Module: KnifeCloudformation::Knife::Stack::InstanceMethods

Defined in:
lib/knife-cloudformation/knife/stack.rb

Constant Summary collapse

UNPACK_NAME_JOINER =

un-packed stack name joiner/identifier

'-sfn-'
MAX_PARAMETER_ATTEMPTS =

maximum number of attempts to get valid parameter value

5

Instance Method Summary collapse

Instance Method Details

#apply_nested_stacks!(remote_stack, stack) ⇒ Miasma::Models::Orchestration::Stack

TODO:

ported from a proto branch and needs to be refactored. this implementation is some what shady

Detect nested stacks and apply

Parameters:

  • remote_stack (Miasma::Models::Orchestration::Stack)

    nested stack

  • stack (Miasma::Models::Orchestration::Stack)

    current stack

Returns:

  • (Miasma::Models::Orchestration::Stack)


43
44
45
46
47
48
49
50
51
52
# File 'lib/knife-cloudformation/knife/stack.rb', line 43

def apply_nested_stacks!(remote_stack, stack)
  remote_stack.resources.all.each do |resource|
    if(resource.type == 'AWS::CloudFormation::Stack')
      nested_stack = provider.connection.stacks.get(resource.id)
      apply_nested_stacks!(nested_stack, stack)
      stack.apply_stack(nested_stack)
    end
  end
  stack
end

#apply_stacks!(stack) ⇒ Miasma::Models::Orchestration::Stack

Apply any defined remote stacks

Parameters:

  • stack (Miasma::Models::Orchestration::Stack)

Returns:

  • (Miasma::Models::Orchestration::Stack)


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/knife-cloudformation/knife/stack.rb', line 20

def apply_stacks!(stack)
  action = self.class.name.downcase.end_with?('create') ? :create : :update
  remote_stacks = Chef::Config[:knife][:cloudformation].
    fetch(action, {}).fetch(:apply_stacks, [])
  remote_stacks.each do |stack_name|
    remote_stack = provider.connection.stacks.get(stack_name)
    apply_nested_stacks!(remote_stack, stack)
    if(remote_stack)
      stack.apply_stack(remote_stack)
    else
      apply_unpacked_stack!(stack_name, stack)
    end
  end
  stack
end

#apply_unpacked_stack!(stack_name, stack) ⇒ Miasma::Models::Orchestration::Stack

Apply all stacks from an unpacked stack

Parameters:

  • stack_name (String)

    name of parent stack

  • stack (Miasma::Models::Orchestration::Stack)

Returns:

  • (Miasma::Models::Orchestration::Stack)


59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/knife-cloudformation/knife/stack.rb', line 59

def apply_unpacked_stack!(stack_name, stack)
  result = provider.connection.stacks.all.find_all do |remote_stack|
    remote_stack.name.start_with?("#{stack_name}#{UNPACK_NAME_JOINER}")
  end.sort_by(&:name).map do |remote_stack|
    stack.apply_stack(remote_stack)
  end
  unless(result.empty?)
    stack
  else
    ui.error "Failed to apply requested stack. Unable to locate. (#{stack_name})"
    exit 1
  end
end

#populate_parameters!(stack, current_params = {}) ⇒ Hash

Prompt for parameter values and store result

Parameters:

  • stack (Hash)

    stack template

Returns:

  • (Hash)


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/knife-cloudformation/knife/stack.rb', line 117

def populate_parameters!(stack, current_params={})
  if(Chef::Config[:knife][:cloudformation][:interactive_parameters])
    if(stack['Parameters'])
      Chef::Config[:knife][:cloudformation][:options][:parameters] ||= Mash.new
      stack.fetch('Parameters', {}).each do |k,v|
        next if Chef::Config[:knife][:cloudformation][:options][:parameters][k]
        attempt = 0
        valid = false
        until(valid)
          attempt += 1
          default = Chef::Config[:knife][:cloudformation][:options][:parameters].fetch(
            k, current_params.fetch(
              k, v['Default']
            )
          )
          answer = ui.ask_question("#{k.split(/([A-Z]+[^A-Z]*)/).find_all{|s|!s.empty?}.join(' ')}: ", :default => default)
          validation = KnifeCloudformation::Utils::StackParameterValidator.validate(answer, v)
          if(validation == true)
            unless(answer == default)
              Chef::Config[:knife][:cloudformation][:options][:parameters][k] = answer
            end
            valid = true
          else
            validation.each do |validation_error|
              ui.error validation_error.last
            end
          end
          if(attempt > MAX_PARAMETER_ATTEMPTS)
            ui.fatal 'Failed to receive allowed parameter!'
            exit 1
          end
        end
      end
    end
  end
  stack
end

#unpack_nesting(name, file, action) ⇒ TrueClass

Unpack nested stack and run action on each stack, applying the previous stacks automatically

Parameters:

  • name (String)

    container stack name

  • file (Hash)

    stack template

  • action (String)

    create or update

Returns:

  • (TrueClass)


80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/knife-cloudformation/knife/stack.rb', line 80

def unpack_nesting(name, file, action)

  # @todo move this init into setup
  Chef::Config[:knife][:cloudformation][action.to_sym] ||= Mash.new
  Chef::Config[:knife][:cloudformation][action.to_sym][:apply_stacks] ||= []

  orig_options = Chef::Config[:knife][:cloudformation][:options].dup
  stack_count = 0

  file['Resources'].each do |stack_resource_name, stack_resource|

    nested_stack_name = "#{name}#{UNPACK_NAME_JOINER}#{Kernel.sprintf('%0.3d', stack_count)}-#{stack_resource_name}"
    nested_stack_template = stack_resource['Properties']['Stack']
    Chef::Config[:knife][:cloudformation][:options] = orig_options.dup

    klass = Chef::Knife.const_get("Cloudformation#{action.to_s.capitalize}")
    nested_stack_runner = klass.new
    nested_stack_runner.config = config.dup
    nested_stack_runner.name_args.push(nested_stack_name)
    Chef::Config[:knife][:cloudformation][:template] = nested_stack_template
    nested_stack_runner.run
    unless(config[:print_only])
      Chef::Config[:knife][:cloudformation][action.to_sym][:apply_stacks].push(nested_stack_name).uniq!
    end
    Chef::Config[:knife][:cloudformation][:template] = nil
    provider.connection.stacks.reload
    stack_count += 1

  end

  true
end