Module: Sfn::CommandModule::Stack::InstanceMethods

Defined in:
lib/sfn/command_module/stack.rb

Constant Summary collapse

UNPACK_NAME_JOINER =

unpacked 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

Detect nested stacks and apply

Parameters:

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

    stack to inspect for nested stacks

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

    current stack

Returns:

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


39
40
41
42
43
44
45
46
47
48
# File 'lib/sfn/command_module/stack.rb', line 39

def apply_nested_stacks!(remote_stack, stack)
  remote_stack.resources.all.each do |resource|
    if(resource.type == 'AWS::CloudFormation::Stack')
      nested_stack = resource.expand
      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
# File 'lib/sfn/command_module/stack.rb', line 20

def apply_stacks!(stack)
  remote_stacks = [config[:apply_stack]].flatten.compact
  remote_stacks.each do |stack_name|
    remote_stack = provider.connection.stacks.get(stack_name)
    if(remote_stack)
      apply_nested_stacks!(remote_stack, 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)


55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/sfn/command_module/stack.rb', line 55

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})"
    raise "Failed to locate stack: #{stack_name}"
  end
end

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

Prompt for parameter values and store result

Parameters:

  • stack (Hash)

    stack template

Returns:

  • (Hash)


109
110
111
112
113
114
115
116
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
154
155
156
157
158
# File 'lib/sfn/command_module/stack.rb', line 109

def populate_parameters!(stack, current_params={})
  if(stack['Parameters'])
    if(config.get(:parameter).is_a?(Array))
      config[:parameter] = Smash[
        *config.get(:parameter).map(&:to_a)
      ]
    end
    if(config.get(:parameters))
      config.set(:parameters,
        config.get(:parameters).merge(config[:parameter])
      )
    else
      config.set(:parameters, config.fetch(:parameter, Smash.new))
    end
    stack.fetch('Parameters', {}).each do |k,v|
      next if config[:parameters][k]
      attempt = 0
      valid = false
      until(valid)
        attempt += 1
        default = config[:parameters].fetch(
          k, current_params.fetch(
            k, v['Default']
          )
        )
        if(config[:interactive_parameters])
          answer = ui.ask_question("#{k.split(/([A-Z]+[^A-Z]*)/).find_all{|s|!s.empty?}.join(' ')}", :default => default)
        else
          answer = default
        end
        validation = Sfn::Utils::StackParameterValidator.validate(answer, v)
        if(validation == true)
          unless(answer == v['Default'])
            config[: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
  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)


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
101
102
103
# File 'lib/sfn/command_module/stack.rb', line 76

def unpack_nesting(name, file, action)
  config[:apply_stacks] ||= []
  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']

    namespace.const_get(action.to_s.capitalize).new(
      Smash.new(
        :print_only => config[:print_only],
        :template => nested_stack_template,
        :parameters => config.fetch(:parameters, Smash.new).to_smash,
        :apply_stacks => config[:apply_stacks],
        :options => config[:options]
      ),
      [nested_stack_name]
    ).execute!
    unless(config[:print_only])
      config[:apply_stacks].push(nested_stack_name).uniq!
    end
    config[:template] = nil
    provider.connection.stacks.reload
    stack_count += 1
  end

  true
end