Class: Lono::Cfn::Preview::Changeset

Inherits:
Base show all
Defined in:
lib/lono/cfn/preview/changeset.rb

Instance Method Summary collapse

Methods inherited from Base

#capabilities, #check_registration, #command_with_iam, #continue_update_rollback, #continue_update_rollback_sure?, #delete_rollback_stack, #exit_unless_updatable!, #generate_all, #pretty_path, #prompt_for_iam, #quit, #rerun_with_iam?, #set_template_url!, #show_options, #stack_status, #starting_message, #status, #tags

Methods included from Utils::Sure

#sure?

Methods included from AwsServices

#cfn, #ec2, #iam, #s3, #s3_presigner, #s3_resource, #sts

Methods included from AwsServices::Helper

#rollback_complete?, #testing_update?

Methods included from AwsServices::StackSet

#find_stack_set, #stack_set_exists?

Methods included from AwsServices::Stack

#find_stack, #stack_exists?

Methods inherited from AbstractBase

#initialize, #reinitialize, #template_path

Methods included from Blueprint::Root

#find_blueprint_root, #set_blueprint_root

Constructor Details

This class inherits a constructor from Lono::AbstractBase

Instance Method Details

#change_set_nameObject

generates a change set name



117
118
119
# File 'lib/lono/cfn/preview/changeset.rb', line 117

def change_set_name
  @change_set_name ||= "changeset-#{Time.now.strftime("%Y%d%m%H%M%S")}"
end

#create_change_set(parameters) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/lono/cfn/preview/changeset.rb', line 22

def create_change_set(parameters)
  unless stack_exists?(@stack)
    puts "WARN: Cannot create a change set for the stack because the #{@stack} does not exists.".color(:yellow)
    return false
  end
  exit_unless_updatable!

  options = {
    change_set_name: change_set_name,
    stack_name: @stack,
    parameters: parameters,
  }
  options[:tags] = tags unless tags.empty?
  set_template_url!(options)
  show_options(options, "cfn.create_change_set")
  begin
    # Tricky for preview need to set capabilities so that it gets updated. For Base#run save within the begin block already.
    options[:capabilities] = capabilities # ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
    cfn.create_change_set(options)
  rescue Aws::CloudFormation::Errors::InsufficientCapabilitiesException => e
    # If coming from cfn_preview_command automatically add iam capabilities
    cfn_preview_command = ARGV.join(" ").include?("cfn preview")
    if cfn_preview_command
      # e.message is "Requires capabilities : [CAPABILITY_IAM]"
      # grab CAPABILITY_IAM with regexp
      capabilities = e.message.match(/\[(.*)\]/)[1]
      @options.merge!(capabilities: [capabilities])
      retry
    end
    yes = rerun_with_iam?(e)
    retry if yes
  rescue Aws::CloudFormation::Errors::ValidationError => e
    handle_error(e)
  end
  true
end

#delete_change_setObject



102
103
104
105
106
107
# File 'lib/lono/cfn/preview/changeset.rb', line 102

def delete_change_set
  cfn.delete_change_set(
    change_set_name: change_set_name,
    stack_name: @stack
  )
end

#display_change_setObject



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/lono/cfn/preview/changeset.rb', line 74

def display_change_set
  print "Generating CloudFormation Change Set for preview.."
  change_set = describe_change_set
  until change_set_finished?(change_set) do
    change_set = describe_change_set
    sleep 1
    print '.'
  end
  puts

  case change_set.status
  when "CREATE_COMPLETE"
    puts "CloudFormation preview for '#{@stack}' stack update. Changes:"
    changes = change_set.changes.sort_by do |change|
      change["resource_change"]["action"]
    end
    changes.each do |change|
      display_change(change)
    end
  when "FAILED"
    puts "WARN: Fail to create a CloudFormation preview for '#{@stack}' stack update. Reason:".color(:yellow)
    puts change_set.status_reason
    quit(0)
  else
    raise "hell: never come here"
  end
end

#execute_change_setObject



109
110
111
112
113
114
# File 'lib/lono/cfn/preview/changeset.rb', line 109

def execute_change_set
  cfn.execute_change_set(
    change_set_name: change_set_name,
    stack_name: @stack
  )
end

#handle_error(e) ⇒ Object

Example errors: “Template error: variable names in Fn::Sub syntax must contain only alphanumeric characters, underscores, periods, and colons”



61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/lono/cfn/preview/changeset.rb', line 61

def handle_error(e)
  raise if ENV['FULL_BACKTRACE']

  if e.message =~ /^Parameters: / || e.message =~ /^Template error: /
    puts "Error creating CloudFormation preview because invalid CloudFormation parameters. Full error message:".color(:red)
    puts e.message
    puts "For full backtrace run command again with FULL_BACKTRACE=1"
    quit(1)
  else
    raise
  end
end

#preview_change_set(parameters) ⇒ Object



17
18
19
20
# File 'lib/lono/cfn/preview/changeset.rb', line 17

def preview_change_set(parameters)
  success = create_change_set(parameters)
  display_change_set if success
end

#runObject

Override run from Base superclass, the run method is different enough with Preview



4
5
6
7
8
9
10
11
12
13
14
15
# File 'lib/lono/cfn/preview/changeset.rb', line 4

def run
  puts "Changeset Preview:".color(:green)

  if @options[:noop]
    puts "NOOP CloudFormation preview for #{@stack} update"
    return
  end

  parameters = generate_all
  success = preview_change_set(parameters)
  delete_change_set if success && !@options[:keep] # Clean up and delete the change set
end