Class: CfnCli::Stack

Inherits:
Object
  • Object
show all
Includes:
CfnClient, CfnStates, Loggable
Defined in:
lib/cfncli/stack.rb

Defined Under Namespace

Classes: StackNotFoundError

Instance Attribute Summary collapse

Attributes included from CfnClient

#retry_backoff, #retry_limit, #stub_responses

Instance Method Summary collapse

Methods included from Loggable

#log_level, #log_level=, #logger, #logger=

Methods included from CfnStates

#failed?, #failed_states, #finished_states, #states, #success_states, #transitive_states

Methods included from CfnClient

#cfn, #cfn_client

Constructor Details

#initialize(stack_name, config = nil) ⇒ Stack

Returns a new instance of Stack.



22
23
24
25
26
27
28
29
30
31
# File 'lib/cfncli/stack.rb', line 22

def initialize(stack_name, config = nil)
  @stack = nil
  @stack_id = nil
  @stack_name = stack_name
  @config = config || default_config
  @child_stacks = Concurrent::Array.new

  @retry_limit = @config.aws_retry_limit
  @retry_backoff = @config.aws_retry_backoff
end

Instance Attribute Details

#child_stacksObject (readonly)

Returns the value of attribute child_stacks.



18
19
20
# File 'lib/cfncli/stack.rb', line 18

def child_stacks
  @child_stacks
end

#stack_nameObject (readonly)

Returns the value of attribute stack_name.



17
18
19
# File 'lib/cfncli/stack.rb', line 17

def stack_name
  @stack_name
end

Instance Method Details

#create(opts) ⇒ Object

Creates a new stack

Parameters:



56
57
58
59
60
61
# File 'lib/cfncli/stack.rb', line 56

def create(opts)
  logger.debug "Creating stack #{stack_name} (#{opts.inspect})"
  @stack = cfn.create_stack(opts)
  stack.wait_until_exists
  @stack_id = stack.stack_id
end

#default_configObject



33
34
35
# File 'lib/cfncli/stack.rb', line 33

def default_config
  Config::CfnClient.new
end

#delete(opts, config) ⇒ Object

Deletes an existing stack



77
78
79
80
81
82
# File 'lib/cfncli/stack.rb', line 77

def delete(opts, config)
  logger.debug "Deleting stack #{opts.inspect}"
  # Always use the real stack ID as the stack won't be available once deleted
  id = fetch_stack_id
  cfn.client.delete_stack(stack_name: id)
end

#events(next_token) ⇒ Object

Get the events from the cfn stack



111
112
113
# File 'lib/cfncli/stack.rb', line 111

def events(next_token)
  stack.events(next_token)
end

#exists?Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/cfncli/stack.rb', line 49

def exists?
  stack.exists?
end

#fail_on_noop?Boolean

Returns:

  • (Boolean)


37
38
39
# File 'lib/cfncli/stack.rb', line 37

def fail_on_noop?
  @config.fail_on_noop
end

#fetch_stack_idObject

Gets stack id from the cfn API



140
141
142
143
144
# File 'lib/cfncli/stack.rb', line 140

def fetch_stack_id
  @stack = cfn.stack(stack_id)
  @stack_id = @stack.stack_id
  @stack_id
end

#finished?Boolean

Indicates if the stack is in a finished state

Returns:

  • (Boolean)


121
122
123
124
# File 'lib/cfncli/stack.rb', line 121

def finished?
  return false if stack.nil?
  finished_states.include?(stack.stack_status)
end

#in_progress?Boolean

Indicates if the stack is in a transition state

Returns:

  • (Boolean)


134
135
136
137
# File 'lib/cfncli/stack.rb', line 134

def in_progress?
  return false if stack.nil?
  transitive_states.include? stack.stack_status
end

#list_events(poller, streamer = nil, config = nil, event_prefix = nil, list_nested_events = true) ⇒ Object

List all events in real time

Parameters:

  • poller (CfnCli::Poller)

    Poller class to display events



98
99
100
101
102
103
104
105
106
107
108
# File 'lib/cfncli/stack.rb', line 98

def list_events(poller, streamer = nil, config = nil, event_prefix = nil, list_nested_events = true)
  @event_listing_thread = Thread.new do
    streamer ||= EventStreamer.new(self, config)
    streamer.each_event do |event|
      if list_nested_events && Event.new(event).child_stack_create_event?
        track_child_stack(event.physical_resource_id, event.logical_resource_id, poller)
      end
      poller.event(event, event_prefix)
    end
  end
end

#listing_events?Boolean

Is this stack currently listing events

Returns:

  • (Boolean)


116
117
118
# File 'lib/cfncli/stack.rb', line 116

def listing_events?
  !@event_listing_thread.nil? && @event_listing_thread.alive?
end

#stackObject



45
46
47
# File 'lib/cfncli/stack.rb', line 45

def stack
  fetch_stack
end

#stack_idObject



41
42
43
# File 'lib/cfncli/stack.rb', line 41

def stack_id
  @stack_id || @stack_name
end

#succeeded?Boolean

Indicates if the stack is in a successful state

Returns:

  • (Boolean)


127
128
129
130
131
# File 'lib/cfncli/stack.rb', line 127

def succeeded?
  res = success_states.include? stack.stack_status
  return false if stack.nil?
  res
end

#update(opts) ⇒ Object

Updates an existing stack

Parameters:



66
67
68
69
70
71
72
73
74
# File 'lib/cfncli/stack.rb', line 66

def update(opts)
  logger.debug "Updating stack #{stack_name} (#{opts.inspect})"
  resp = cfn.client.update_stack(opts)
  @stack_id = resp.stack_id
rescue Aws::CloudFormation::Errors::ValidationError => e
  unless !fail_on_noop? && e.message.include?('No updates are to be performed')
    raise e
  end
end

#wait_for_completionObject

Waits for a stack to be in a finished state

Returns:

  • A boolean indicating if the operation was succesful



86
87
88
89
90
91
92
93
94
# File 'lib/cfncli/stack.rb', line 86

def wait_for_completion
  Waiting.wait(max_attempts: @config.retries, interval: @config.interval) do |waiter|
    waiter.done if finished?
  end
  succeeded?
rescue Waiting::TimedOutError => e
  logger.error "Timed out while waiting for the stack #{inspect} to be created(#{e.message})"
  false
end