Class: Stackup::Stack

Inherits:
Object
  • Object
show all
Includes:
ErrorHandling
Defined in:
lib/stackup/stack.rb

Overview

An abstraction of a CloudFormation stack.

Constant Summary collapse

DEFAULT_WAIT_POLL_INTERVAL =

seconds

5
ALMOST_DEAD_STATUSES =
%w[CREATE_FAILED ROLLBACK_COMPLETE].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ErrorHandling

#handling_cf_errors

Constructor Details

#initialize(name, client = {}, options = {}) ⇒ Stack

Returns a new instance of Stack.



20
21
22
23
24
25
26
27
28
29
# File 'lib/stackup/stack.rb', line 20

def initialize(name, client = {}, options = {})
  client     = Aws::CloudFormation::Client.new(client) if client.is_a?(Hash)
  @name      = name
  @cf_client = client
  @wait      = true
  options.each do |key, value|
    public_send("#{key}=", value)
  end
  @wait_poll_interval ||= DEFAULT_WAIT_POLL_INTERVAL
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



31
32
33
# File 'lib/stackup/stack.rb', line 31

def name
  @name
end

#waitString

Wait until stack reaches a stable state

Returns:

  • (String)

    status, once stable



187
188
189
190
191
# File 'lib/stackup/stack.rb', line 187

def wait
  modify_stack(/./, "failed to stabilize") do
    # nothing
  end
end

#wait_poll_intervalObject

Returns the value of attribute wait_poll_interval.



32
33
34
# File 'lib/stackup/stack.rb', line 32

def wait_poll_interval
  @wait_poll_interval
end

Instance Method Details

#cancel_updateString

Cancel update in-progress.

Returns:

  • (String)

    resulting stack status

Raises:



175
176
177
178
179
180
181
# File 'lib/stackup/stack.rb', line 175

def cancel_update
  modify_stack(/_COMPLETE$/, "update cancel failed") do
    cf_stack.cancel_update
  end
rescue InvalidStateError
  nil
end

#change_set(name) ⇒ ChangeSet

An abstraction of a CloudFormation change-set.

Parameters:

  • name (String)

    change-set name

Returns:

  • (ChangeSet)

    an handle for change-set operations



266
267
268
# File 'lib/stackup/stack.rb', line 266

def change_set(name)
  ChangeSet.new(name, self)
end

#change_set_summariesArray<ChangeSetSummary>

List change-sets.

Returns:

  • (Array<ChangeSetSummary>)

Raises:



255
256
257
258
259
# File 'lib/stackup/stack.rb', line 255

def change_set_summaries
  handling_cf_errors do
    cf_client.list_change_sets(:stack_name => name).summaries
  end
end

#create_or_update(options) ⇒ String Also known as: up

Create or update the stack.

Parameters:

Options Hash (options):

  • :capabilities (Array<String>) — default: CAPABILITY_NAMED_IAM

    list of capabilities required for stack template

  • :disable_rollback (boolean) — default: false

    if true, disable rollback if stack creation fails

  • :notification_arns (String)

    ARNs for the Amazon SNS topics associated with this stack

  • :on_failure (String) — default: ROLLBACK

    if stack creation fails: DO_NOTHING, ROLLBACK, or DELETE

  • :parameters (Hash, Array<Hash>)

    stack parameters, either as a Hash, or an Array of Aws::CloudFormation::Types::Parameter structures

  • :tags (Hash, Array<Hash>)

    stack tags, either as a Hash, or an Array of Aws::CloudFormation::Types::Tag structures

  • :resource_types (Array<String>)

    resource types that you have permissions to work with

  • :stack_policy (Hash)

    stack policy, as Ruby data

  • :stack_policy_body (String)

    stack policy, as JSON

  • :stack_policy_url (String)

    location of stack policy

  • :stack_policy_during_update (Hash)

    temporary stack policy, as Ruby data

  • :stack_policy_during_update_body (String)

    temporary stack policy, as JSON

  • :stack_policy_during_update_url (String)

    location of temporary stack policy

  • :template (Hash)

    stack template, as Ruby data

  • :template_body (String)

    stack template, as JSON or YAML

  • :template_url (String)

    location of stack template

  • :timeout_in_minutes (Integer)

    stack creation timeout

  • :use_previous_template (boolean)

    if true, reuse the existing template

Returns:

  • (String)

    resulting stack status

Raises:



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
# File 'lib/stackup/stack.rb', line 117

def create_or_update(options)
  options = options.dup
  if (template_data = options.delete(:template))
    options[:template_body] = MultiJson.dump(template_data)
  end
  # optionally override template_body with the original template to preserve formatting (& comments in YAML)
  template_orig = options.delete(:template_orig)
  options[:template_body] = template_orig if options.delete(:preserve)
  if (parameters = options[:parameters])
    options[:parameters] = Parameters.new(parameters).to_a
  end
  if (tags = options[:tags])
    options[:tags] = normalize_tags(tags)
  end
  if (policy_data = options.delete(:stack_policy))
    options[:stack_policy_body] = MultiJson.dump(policy_data)
  end
  if (policy_data = options.delete(:stack_policy_during_update))
    options[:stack_policy_during_update_body] = MultiJson.dump(policy_data)
  end
  options[:capabilities] ||= ["CAPABILITY_NAMED_IAM"]
  delete if ALMOST_DEAD_STATUSES.include?(status)
  update(options)
rescue NoSuchStack
  create(options)
end

#deleteString Also known as: down

Delete the stack.

Returns:

  • (String)

    “DELETE_COMPLETE”

Raises:



153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/stackup/stack.rb', line 153

def delete
  begin
    @stack_id = handling_cf_errors do
      cf_stack.stack_id
    end
  rescue NoSuchStack
    return nil
  end
  modify_stack("DELETE_COMPLETE", "stack delete failed") do
    cf_stack.delete
  end
ensure
  @stack_id = nil
end

#exists?boolean

Returns true iff the stack exists.

Returns:

  • (boolean)

    true iff the stack exists



63
64
65
66
67
68
# File 'lib/stackup/stack.rb', line 63

def exists?
  status
  true
rescue NoSuchStack
  false
end

#on_event(event_handler = nil, &block) ⇒ Object

Register a handler for reporting of stack events.

Parameters:

  • event_handler (Proc) (defaults to: nil)

Raises:

  • (ArgumentError)


43
44
45
46
47
48
# File 'lib/stackup/stack.rb', line 43

def on_event(event_handler = nil, &block)
  event_handler ||= block
  raise ArgumentError, "no event_handler provided" if event_handler.nil?

  @event_handler = event_handler
end

#outputsHash<String, String>

Get stack outputs.

Returns:

  • (Hash<String, String>)

    stack outputs

Raises:



236
237
238
# File 'lib/stackup/stack.rb', line 236

def outputs
  extract_hash(:outputs, :output_key, :output_value)
end

#parametersHash

Get the current parameters.

Returns:

  • (Hash)

    current stack parameters

Raises:



218
219
220
# File 'lib/stackup/stack.rb', line 218

def parameters
  extract_hash(:parameters, :parameter_key, :parameter_value)
end

#resourcesHash<String, String>

Get stack outputs.

Returns:

  • (Hash<String, String>)

    mapping of logical resource-name to physical resource-name

Raises:



246
247
248
# File 'lib/stackup/stack.rb', line 246

def resources
  extract_hash(:resource_summaries, :logical_resource_id, :physical_resource_id)
end

#statusString

Returns the current stack status.

Returns:

  • (String)

    the current stack status

Raises:



55
56
57
58
59
# File 'lib/stackup/stack.rb', line 55

def status
  handling_cf_errors do
    cf_stack.stack_status
  end
end

#tagsHash

Get the current tags.

Returns:

  • (Hash)

    current stack tags

Raises:



227
228
229
# File 'lib/stackup/stack.rb', line 227

def tags
  extract_hash(:tags, :key, :value)
end

#templateHash

Get the current template.

Returns:

  • (Hash)

    current stack template, as Ruby data

Raises:



209
210
211
# File 'lib/stackup/stack.rb', line 209

def template
  Stackup::YAML.load(template_body)
end

#template_bodyString

Get the current template body.

Returns:

  • (String)

    current stack template, as JSON or YAML

Raises:



198
199
200
201
202
# File 'lib/stackup/stack.rb', line 198

def template_body
  handling_cf_errors do
    cf_client.get_template(:stack_name => name).template_body
  end
end

#wait?Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/stackup/stack.rb', line 36

def wait?
  @wait
end

#watch(zero = true) {|watcher| ... } ⇒ Object

Yields:

  • (watcher)


270
271
272
273
274
# File 'lib/stackup/stack.rb', line 270

def watch(zero = true)
  watcher = Stackup::StackWatcher.new(cf_stack)
  watcher.zero if zero
  yield watcher
end