class Sfn::Command::Update
Update
command
Public Instance Methods
execute!()
click to toggle source
Run the stack update command
# File lib/sfn/command/update.rb, line 13 def execute! name_required! name = name_args.first stack_info = "#{ui.color("Name:", :bold)} #{name}" begin stack = provider.stacks.get(name) rescue Miasma::Error::ApiError::RequestError stack = nil end config[:compile_parameters] ||= Smash.new if config[:file] s_name = [name] c_setter = lambda do |c_stack| if c_stack.outputs compile_params = c_stack.outputs.detect do |output| output.key == "CompileState" end end if compile_params compile_params = MultiJson.load(compile_params.value) c_current = config[:compile_parameters].fetch(s_name.join("__"), Smash.new) config[:compile_parameters][s_name.join("__")] = compile_params.merge(c_current) end c_stack.nested_stacks(false).each do |n_stack| s_name.push(n_stack.data.fetch(:logical_id, n_stack.name)) c_setter.call(n_stack) s_name.pop end end if stack c_setter.call(stack) end ui.debug "Compile parameters - #{config[:compile_parameters]}" file = load_template_file(:stack => stack) stack_info << " #{ui.color("Path:", :bold)} #{config[:file]}" else file = stack.template.dup if config[:plan] end unless stack ui.fatal "Failed to locate requested stack: #{ui.color(name, :red, :bold)}" raise "Failed to locate stack: #{name}" end unless config[:print_only] ui.info "#{ui.color("SparkleFormation:", :bold)} #{ui.color("update", :green)}" end unless file if config[:template] file = config[:template] stack_info << " #{ui.color("(template provided)", :green)}" else stack_info << " #{ui.color("(no template update)", :yellow)}" end end unless config[:print_only] ui.info " -> #{stack_info}" end if file if config[:print_only] ui.puts format_json(parameter_scrub!(template_content(file))) return end original_template = stack.template original_parameters = stack.parameters apply_stacks!(stack) populate_parameters!(file, :current_parameters => stack.root_parameters) update_template = stack.template if config[:plan] begin stack.template = original_template stack.parameters = original_parameters plan = build_planner(stack) if plan result = plan.generate_plan( file.respond_to?(:dump) ? file.dump : file, config_root_parameters ) display_plan_information(result) end rescue => e unless e.message.include?("Confirmation declined") ui.error "Unexpected error when generating plan information: #{e.class} - #{e}" ui.debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}" ui.confirm "Continue with stack update?" unless config[:plan_only] else raise end end if config[:plan_only] ui.info "Plan only mode requested. Exiting." return end end stack.parameters = config_root_parameters if config[:upload_root_template] upload_result = store_template(name, file, Smash.new) stack.template_url = upload_result[:url] else stack.template = parameter_scrub!(template_content(file, :scrub)) end else apply_stacks!(stack) original_parameters = stack.parameters populate_parameters!(stack.template, :current_parameters => stack.root_parameters) stack.parameters = config_root_parameters end # Set options defined within config into stack instance for update request if config[:merge_api_options] config.fetch(:options, Smash.new).each_pair do |key, value| if stack.respond_to?("#{key}=") stack.send("#{key}=", value) end end end begin api_action!(:api_stack => stack) do stack.save if config[:poll] poll_stack(stack.name) if stack.reload.state == :update_complete ui.info "Stack update complete: #{ui.color("SUCCESS", :green)}" namespace.const_get(:Describe).new({:outputs => true}, [name]).execute! else ui.fatal "Update of stack #{ui.color(name, :bold)}: #{ui.color("FAILED", :red, :bold)}" raise "Stack did not reach a successful update completion state." end else ui.warn "Stack state polling has been disabled." ui.info "Stack update initialized for #{ui.color(name, :green)}" end end rescue Miasma::Error::ApiError::RequestError => e if e.message.downcase.include?("no updates") ui.warn "No updates detected for stack (#{stack.name})" else raise end end end