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.



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

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.



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

def child_stacks
  @child_stacks
end

#stack_nameObject (readonly)

Returns the value of attribute stack_name.



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

def stack_name
  @stack_name
end

Instance Method Details

#create(opts) ⇒ Object

Creates a new stack

Parameters:



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

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



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

def default_config
  Config::CfnClient.new
end

#delete(opts, config) ⇒ Object

Deletes an existing stack



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

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 = nil) ⇒ Object

Get the events from the cfn stack



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

def events(next_token = nil)
  stack.events(next_token: next_token)
end

#exists?Boolean

Returns:

  • (Boolean)


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

def exists?
  stack.exists?
end

#fail_on_noop?Boolean

Returns:

  • (Boolean)


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

def fail_on_noop?
  @config.fail_on_noop
end

#fetch_stack_idObject

Gets stack id from the cfn API



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

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)


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

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)


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

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



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

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)


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

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

#stackObject



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

def stack
  fetch_stack
end

#stack_idObject



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

def stack_id
  @stack_id || @stack_name
end

#succeeded?Boolean

Indicates if the stack is in a successful state

Returns:

  • (Boolean)


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

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

#update(opts) ⇒ Object

Updates an existing stack

Parameters:



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

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



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

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