lib/chef-cli/command/undelete.rb
# # Copyright:: Copyright (c) 2015-2019 Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "base" require_relative "../ui" require_relative "../configurable" require_relative "../policyfile_services/undelete" require_relative "../dist" module ChefCLI module Command class Undelete < Base banner(<<~BANNER) Usage: #{ChefCLI::Dist::EXEC} undelete [--list | --id ID] [options] `#{ChefCLI::Dist::EXEC} undelete` helps you recover quickly if you've deleted a policy or policy group in error. When run with no arguements, it lists the available undo operations. To undo the last delete operation, use `chef undelete --last`. CAVEATS: `#{ChefCLI::Dist::EXEC} undelete` doesn't detect conflicts. If a deleted item has been recreated, running `chef undelete` will overwrite it. Undo information does not include cookbooks that might be referenced by policies. If you have cleaned the policy cookbooks after the delete operation you want to reverse, `chef undelete` may not be able to fully restore the previous state. The delete commands also do not store access control data, so you may have to manually reapply any ACL customizations you have made. See our detailed README for more information: https://docs.chef.io/policyfile/ Options: BANNER option :undo_last, short: "-l", long: "--last", description: "Undo the most recent delete operation" option :undo_record_id, short: "-i ID", long: "--id ID", description: "Undo the delete operation with the given ID" option :config_file, short: "-c CONFIG_FILE", long: "--config CONFIG_FILE", description: "Path to configuration file" option :debug, short: "-D", long: "--debug", description: "Enable stacktraces and other debug output", default: false include Configurable attr_accessor :ui attr_reader :undo_record_id def initialize(*args) super @list_undo_records = false @undo_record_id = nil @ui = UI.new end def run(params) return 1 unless apply_params!(params) if list_undo_records? undelete_service.list else undelete_service.run end 0 rescue PolicyfileServiceError => e handle_error(e) 1 end def undelete_service @undelete_service ||= PolicyfileServices::Undelete.new(config: chef_config, ui: ui, undo_record_id: undo_record_id) end def debug? !!config[:debug] end def list_undo_records? @list_undo_records end def handle_error(error) ui.err("Error: #{error.message}") if error.respond_to?(:reason) ui.err("Reason: #{error.reason}") ui.err("") ui.err(error.extended_error_info) if debug? ui.err(error.cause.backtrace.join("\n")) if debug? end end def apply_params!(params) remaining_args = parse_options(params) if !remaining_args.empty? ui.err("Too many arguments") ui.err("") ui.err(opt_parser) false elsif config[:undo_record_id].nil? && config[:undo_last].nil? @list_undo_records = true true elsif config[:undo_record_id] && config[:undo_last] ui.err("Error: options --last and --id cannot both be given.") ui.err("") ui.err(opt_parser) false elsif config[:undo_record_id] @undo_record_id = config[:undo_record_id] true elsif config[:undo_last] @undo_record_id = nil true end end end end end