Skip to content

Commit

Permalink
Add also restore script to backup, so it remove newly added stuff and
Browse files Browse the repository at this point in the history
fix permission of tarball
  • Loading branch information
jreidinger committed Jun 30, 2014
1 parent 1b96e00 commit 8347a4c
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 18 deletions.
68 changes: 50 additions & 18 deletions src/modules/Update.rb
Original file line number Diff line number Diff line change
Expand Up @@ -842,25 +842,12 @@ def installed_product
def create_backup(name, paths)
mounted_root = Installation.destdir

# tar reports an error if a file does not exist.
# So we have to check this before.
existing_paths = paths.select { |p| File.exist?(File.join(mounted_root, p)) }

# ensure directory exists
::FileUtils.mkdir_p(File.join(mounted_root, BACKUP_DIR))

target_file = File.join(mounted_root, BACKUP_DIR, "#{name}.tar.bz2")

paths_without_prefix = existing_paths.map {|p| p.start_with?("/") ? p[1..-1] : p }

command = "tar cjvf '#{target_file}'"
command << " -C '#{mounted_root}'"
# no shell escaping here, but we backup reasonable files and want to allow globs
command << " " + paths_without_prefix.join(" ")
res = SCR.Execute(path(".target.bash_output"), command)
log.info "backup created with '#{command}' result: #{res}"
tarball_path = File.join(BACKUP_DIR, "#{name}.tar.bz2")
root_tarball_path = File.join(mounted_root, tarball_path)
create_tarball(root_tarball_path, mounted_root, paths)

raise "Failed to create backup" if res["exit"] != 0
script_path = File.join(mounted_root, BACKUP_DIR, "restore-#{name}.sh")
create_restore_script(script_path, tarball_path, paths)
end

publish :variable => :packages_to_install, :type => "integer"
Expand Down Expand Up @@ -900,6 +887,51 @@ def create_backup(name, paths)

private

def create_tarball(tarball_path, root, paths)
# tar reports an error if a file does not exist.
# So we have to check this before.
existing_paths = paths.select { |p| File.exist?(File.join(root, p)) }

# ensure directory exists
::FileUtils.mkdir_p(File.dirname(tarball_path))

paths_without_prefix = existing_paths.map {|p| p.start_with?("/") ? p[1..-1] : p }

command = "tar cjvf '#{tarball_path}'"
command << " -C '#{root}'"
# no shell escaping here, but we backup reasonable files and want to allow globs
command << " " + paths_without_prefix.join(" ")
res = SCR.Execute(path(".target.bash_output"), command)
log.info "backup created with '#{command}' result: #{res}"

raise "Failed to create backup" if res["exit"] != 0

# tarball can contain sensitive data, so prevent read to non-root
::FileUtils.chmod(0600, tarball_path)
end

def create_restore_script(script_path, tarball_path, paths)
paths_without_prefix = paths.map {|p| p.start_with?("/") ? p[1..-1] : p }

# remove leading "/" from tarball to allow to run it from different root
tarball_path = tarball_path[1..-1] if tarball_path.start_with?("/")
script_content = <<EOF
#! /bin/sh
# change root to first parameter or use / as default
# it is needed to allow restore in installation
cd ${1:-/}
#{paths_without_prefix.map{ |p| "rm -rf #{p}" }.join("\n")}
tar xvf #{tarball_path} --overwrite
# return back to original dir
cd -
EOF

File.write(script_path, script_content)
# allow execution of script
::FileUtils.chmod(0744, script_path)
end

# Reads the currently selected default desktop from sysconfig
# and returns it
#
Expand Down
30 changes: 30 additions & 0 deletions test/update_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ def default_SetDesktopPattern_stubs
before(:each) do
allow(Yast::Installation).to receive(:destdir).and_return("/mnt")
allow(::FileUtils).to receive(:mkdir_p)
allow(::File).to receive(:write)
allow(::FileUtils).to receive(:chmod)
allow(::File).to receive(:exist?).and_return(true)
allow(Yast::SCR).to receive(:Execute).with(Yast::Path.new(".target.bash_output"), /^tar /).
and_return({"exit" => 0})
end

it "create tarball including given name with all paths added" do
Expand All @@ -86,13 +91,38 @@ def default_SetDesktopPattern_stubs
Yast::Update.create_backup(name, paths)
end

it "change permission of tarball to be readable only for creator" do
name = "test-backup"
paths = ["a", "b"]
expect(::FileUtils).to receive(:chmod).with(0600, /test-backup\.tar.bz2/)

Yast::Update.create_backup(name, paths)
end

it "raise exception if creating tarball failed" do
name = "test-backup"
paths = ["/path_with_slash"]
expect(Yast::SCR).to receive(:Execute).with(Yast::Path.new(".target.bash_output"), /tar/).
and_return({"exit" => 1})
expect{Yast::Update.create_backup(name, paths)}.to raise_error
end

it "create restore script" do
name = "test-backup"
paths = ["a", "b"]
expect(File).to receive(:write)

Yast::Update.create_backup(name, paths)
end

it "set executable permission on restore script" do
name = "test-backup"
paths = ["a", "b"]

expect(::FileUtils).to receive(:chmod).with(0744, /restore-test-backup\.sh/)

Yast::Update.create_backup(name, paths)
end
end

describe "#SetDesktopPattern" do
Expand Down

0 comments on commit 8347a4c

Please sign in to comment.