class ServerBackup::BackupRestore
Constants
- COMPONENTS
Public Instance Methods
run()
click to toggle source
# File lib/chef/knife/backup_restore.rb, line 54 def run ui.warn "This will overwrite existing data!" ui.warn "Backup is at least 1 day old" if (Time.now - File.atime(config[:backup_dir])) > 86400 ui.confirm "Do you want to restore backup, possibly overwriting existing data" validate! components = name_args.empty? ? COMPONENTS : name_args Array(components).each { |component| self.send(component) } end
Private Instance Methods
clients()
click to toggle source
# File lib/chef/knife/backup_restore.rb, line 123 def clients JSON.create_id = "no_thanks" ui.info "=== Restoring clients ===" clients = Dir.glob(File.join(config[:backup_dir], "clients", "*.json")) clients.each do |file| ui.info "Restoring clients from #{file}" client = JSON.parse(IO.read(file)) begin rest.post_rest("clients", { :name => client['name'], :public_key => client['public_key'], :admin => client['admin'], :validator => client['validator'] }) rescue Net::HTTPServerException => e handle_error 'client', client['name'], e end end end
cookbooks()
click to toggle source
# File lib/chef/knife/backup_restore.rb, line 168 def cookbooks count = 0 ui.info "=== Restoring cookbooks ===" cookbooks = Dir.glob(File.join(config[:backup_dir], "cookbooks", '*')) #Make tmp dir FileUtils.rm_rf(config[:backup_dir] + "/tmp") Dir.mkdir config[:backup_dir] + "/tmp" cookbooks.each do |cb| full_cb = File.expand_path(cb) cb_name = File.basename(cb) cookbook = cb_name.reverse.split('-',2).last.reverse full_path = File.join(config[:backup_dir] + "/tmp", cookbook) begin count += 1 if Chef::Platform.windows? Dir.mkdir config[:backup_dir] + "/tmp/#{cb_name}" full_path = File.join(config[:backup_dir] + "/tmp/#{cb_name}", cookbook) ui.info "Copy cookbook #{full_cb} to #{full_path}" FileUtils.copy_entry(full_cb, full_path) else full_path = File.join(config[:backup_dir] + "/tmp", cookbook) File.symlink(full_cb, full_path) end cbu = Chef::Knife::CookbookUpload.new Chef::Knife::CookbookUpload.load_deps cbu.name_args = [ cookbook ] cbu.config[:cookbook_path] = File.dirname(full_path) ui.info "Restoring cookbook #{cbu.name_args}" cbu.run rescue Net::HTTPServerException => e handle_error 'cookbook', cb_name, e rescue Chef::Exceptions::JSON::ParseError => e handle_error 'cookbook', cb_name, e throw e unless config[:ignore_metadata_errors] ensure if Chef::Platform.windows? rm_path = config[:backup_dir] + "/tmp/#{cb_name}" ui.info "remove dir #{rm_path}" FileUtils.remove_dir(rm_path, force = true) else File.unlink(full_path) end end end ui.info "Uploaded #{count} Cookbooks" FileUtils.rm_rf(config[:backup_dir] + "/tmp") end
data_bags()
click to toggle source
# File lib/chef/knife/backup_restore.rb, line 86 def data_bags ui.info "=== Restoring data bags ===" loader = Chef::Knife::Core::ObjectLoader.new(Chef::DataBagItem, ui) dbags = Dir.glob(File.join(config[:backup_dir], "data_bags", '*')) dbags.each do |bag| bag_name = File.basename(bag) ui.info "Restoring data_bag[#{bag_name}]" begin rest.post_rest("data", { "name" => bag_name}) rescue Net::HTTPServerException => e handle_error 'data_bag', bag_name, e end dbag_items = Dir.glob(File.join(bag, "*")) dbag_items.each do |item_path| item_name = File.basename(item_path, '.json') ui.info "Restoring data_bag_item[#{bag_name}::#{item_name}]" item = loader.load_from("data_bags", bag_name, item_path) dbag = Chef::DataBagItem.new dbag.data_bag(bag_name) dbag.raw_data = item dbag.save end end end
environments()
click to toggle source
# File lib/chef/knife/backup_restore.rb, line 82 def environments restore_standard("environments", Chef::Environment) end
handle_error(type, name, error)
click to toggle source
# File lib/chef/knife/backup_restore.rb, line 216 def handle_error(type, name, error) thing = "#{type}[#{name}]" return ui.error "Error parsing JSON for: #{thing}" if error.kind_of?(Chef::Exceptions::JSON::ParseError) case error.response when Net::HTTPConflict # 409 ui.warn "#{thing} already exists; skipping" when Net::HTTPClientError # 4xx Catch All ui.error "Failed to create #{thing}: #{error.response}; skipping" else ui.error "Failed to create #{thing}: #{error.response}; skipping" end end
nodes()
click to toggle source
# File lib/chef/knife/backup_restore.rb, line 74 def nodes restore_standard("nodes", Chef::Node) end
restore_standard(component, klass)
click to toggle source
# File lib/chef/knife/backup_restore.rb, line 112 def restore_standard(component, klass) loader = Chef::Knife::Core::ObjectLoader.new(klass, ui) ui.info "=== Restoring #{component} ===" files = Dir.glob(File.join(config[:backup_dir], component, "*.json")) files.each do |f| ui.info "Restoring #{component} from #{f}" updated = loader.load_from(component, f) updated.save end end
roles()
click to toggle source
# File lib/chef/knife/backup_restore.rb, line 78 def roles restore_standard("roles", Chef::Role) end
users()
click to toggle source
# File lib/chef/knife/backup_restore.rb, line 143 def users JSON.create_id = "no_thanks" ui.info "=== Restoring users ===" users = Dir.glob(File.join(config[:backup_dir], "users", "*.json")) if !users.empty? and Chef::VERSION !~ /^11\./ ui.warn "users restore only supported on chef == 11" return end users.each do |file| user = JSON.parse(IO.read(file)) password = SecureRandom.hex[0..7] begin rest.post_rest("users", { :name => user['name'], :public_key => user['public_key'], :admin => user['admin'], :password => password }) ui.info "Set password for #{user['name']} to #{password}, please update" rescue Net::HTTPServerException => e handle_error 'user', user['name'], e end end end
validate!()
click to toggle source
# File lib/chef/knife/backup_restore.rb, line 66 def validate! bad_names = name_args - COMPONENTS unless bad_names.empty? ui.error "Component types #{bad_names.join(",")} are not valid." exit 1 end end