class CfnEvents::Runner
Public Class Methods
new(config)
click to toggle source
# File lib/cfn-events/runner.rb, line 7 def initialize(config) @config = config @config.cfn_client ||= begin effective_options = CfnEvents::Client.core_v2_options.merge(config.client_options) Aws::CloudFormation::Client.new(effective_options) end end
Public Instance Methods
all_events_so_far()
click to toggle source
# File lib/cfn-events/runner.rb, line 24 def all_events_so_far r = @config.cfn_client.describe_stack_events(stack_name: @stack_id) events = r.each_page.flat_map {|page| page.stack_events}.reverse if events.empty? raise "Stack has no events! Please raise this as a cfn-events bug." end [ events, events.last ] end
events_since_event(since_event)
click to toggle source
# File lib/cfn-events/runner.rb, line 64 def events_since_event(since_event) r = @config.cfn_client.describe_stack_events(stack_name: @stack_id) # Sort of a special case: no new events if r.stack_events.first.event_id == since_event.event_id return [ [], since_event ] end events = [] r.each_page do |page| cutoff = page.stack_events.index {|e| e.event_id == since_event.event_id} if cutoff events.concat page.stack_events[0..cutoff-1] return [ events.reverse, events.first ] end events.concat r.stack_events end # Unable to join what we've seen so far to what we can see now $stderr.puts "Last-seen stack event is no longer returned by AWS. Please raise this as a cfn-events bug." return [ events.reverse, events.first ] end
events_since_time(t)
click to toggle source
# File lib/cfn-events/runner.rb, line 35 def events_since_time(t) r = @config.cfn_client.describe_stack_events(stack_name: @stack_id) # If there are no events since the given time, show none, and return the # most recent event. Sort of an edge case. if r.stack_events.first.timestamp <= t return [ [], r.stack_events.first ] end events = [] loop do cutoff = r.stack_events.index {|event| event.timestamp <= t} if cutoff # We can stop looking events.concat r.stack_events[0..cutoff-1] events.reverse! return [ events, events.last ] end events.concat r.stack_events r.next_page? or break r = r.next_page end # ALL the available events are since the given time events.reverse! return [ events, events.last ] end
resolve_stack(stack_name_or_id)
click to toggle source
# File lib/cfn-events/runner.rb, line 16 def resolve_stack(stack_name_or_id) ans = @config.cfn_client.describe_stacks(stack_name: stack_name_or_id).stacks[0].stack_id if ans != stack_name_or_id $stderr.puts "Resolved #{stack_name_or_id} to #{ans}" end ans end
run()
click to toggle source
Calls $stdout.sync. Returns 0/1/2, like the command line exit code.
# File lib/cfn-events/runner.rb, line 112 def run @stack_id = resolve_stack(@config.stack_name_or_id) # An assumption to make the logic easier: # - there can never be zero events # (The closest we seem to get to this is if a stack is created via a # change set, then the stack entity is created with a single event, # "AWS::CloudFormation::Stack <the stack name> REVIEW_IN_PROGRESS"). # Therefore there is always a most_recent_event. events_to_show, most_recent_event = if @config.since events_since_time @config.since else all_events_so_far end show_events events_to_show return 0 unless @config.forever or @config.wait while @config.forever or not steady_state?(most_recent_event) $stdout.sync sleep @config.poll_seconds events_to_show, most_recent_event = events_since_event most_recent_event show_events events_to_show end return 2 if most_recent_event.resource_status.match /FAILED/ return 1 if most_recent_event.resource_status.match /ROLLBACK/ return 0 end
show_events(events)
click to toggle source
# File lib/cfn-events/runner.rb, line 90 def show_events(events) events.each do |e| if @config.output_json puts JSON.generate(e.to_h) else puts [ e.timestamp.utc.strftime('%Y-%m-%dT%H:%M:%SZ'), e.resource_type, e.resource_status, e.logical_resource_id, e.physical_resource_id, e.resource_status_reason, ].join " " end end end
steady_state?(e)
click to toggle source
# File lib/cfn-events/runner.rb, line 107 def steady_state?(e) e.resource_type == "AWS::CloudFormation::Stack" and not e.resource_status.match(/IN_PROGRESS/) end