Class: Automan::Cloudformation::Replacer

Inherits:
Base
  • Object
show all
Defined in:
lib/automan/cloudformation/replacer.rb

Constant Summary

Constants included from Mixins::AwsCaller

Mixins::AwsCaller::S3_PROTO

Instance Attribute Summary

Attributes inherited from Base

#logger, #wait

Attributes included from Mixins::AwsCaller

#as, #cfn, #eb, #ec, #ec2, #elb, #r53, #rds, #s3

Instance Method Summary collapse

Methods inherited from Base

add_option, #log_options, #wait_until

Methods included from Mixins::AwsCaller

#account, #configure_aws, #looks_like_s3_path?, #parse_s3_path, #s3_object_exists?, #s3_read

Constructor Details

#initialize(options = {}) ⇒ Replacer

Returns a new instance of Replacer.



8
9
10
11
12
13
14
15
16
17
# File 'lib/automan/cloudformation/replacer.rb', line 8

def initialize(options={})
  super
  @wait = Wait.new({
    delay: 60,
    attempts: 20, # 20 x 60s == 20m
    debug: true,
    rescuer:  WaitRescuer.new,
    logger:   @logger
  })
end

Instance Method Details

#ok_to_replace_instances?(stack_status, last_mod_time) ⇒ Boolean

so we want: when CREATE_COMPLETE | UPDATE_COMPLETE then continue when CREATE_FAILED | .ROLLBACK_. | ^DELETE_.* then raise error else try again

Returns:

  • (Boolean)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/automan/cloudformation/replacer.rb', line 32

def ok_to_replace_instances?(stack_status, last_mod_time)
  case stack_status
  when 'UPDATE_COMPLETE'
    if (Time.now - last_mod_time) <= (5*60)
      true
    else
      false
    end
  when 'CREATE_FAILED', /^.*ROLLBACK.*$/, /^DELETE.*/
    raise StackBrokenError, "Stack is in broken state #{stack_status}"
  else
    false
  end
end

#replace_instancesObject

terminate all running instances in the ASG so that new machines with the latest build will be started



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/automan/cloudformation/replacer.rb', line 67

def replace_instances
  log_options

  unless stack_exists?(name)
    raise StackDoesNotExistError, "Stack #{name} does not exist."
  end

  stack = cfn.stacks[name]
  unless stack_was_just_updated?(stack)
    logger.info "stack was not updated recently, not replacing instances."
    return
  end

  ex = WaitTimedOutError.new "Timed out waiting to replace instances."
  wait_until(ex) do
    ok_to_replace_instances?(stack.status, stack.last_updated_time)
  end

  logger.info "replacing all auto-scaling instances in #{name}"

  if stack_asg.nil?
    raise MissingAutoScalingGroupError, "No ASG found for stack #{name}"
  end

  stack_asg.ec2_instances.each do |i|
    if i.status == :running
      logger.info "terminating instance #{i.id}"
      i.terminate
    else
      logger.info "Not terminating #{i.id} due to status: #{i.status}"
    end
  end
end

#stack_asgObject



51
52
53
54
55
56
57
58
59
# File 'lib/automan/cloudformation/replacer.rb', line 51

def stack_asg
  resources = cfn.stacks[name].resources
  asgs = resources.select {|i| i.resource_type == "AWS::AutoScaling::AutoScalingGroup"}
  if asgs.nil? || asgs.empty?
    return nil
  end
  asg_id = asgs.first.physical_resource_id
  as.groups[asg_id]
end

#stack_exists?(stack_name) ⇒ Boolean

Returns:

  • (Boolean)


47
48
49
# File 'lib/automan/cloudformation/replacer.rb', line 47

def stack_exists?(stack_name)
  cfn.stacks[stack_name].exists?
end

#stack_was_just_updated?(stack) ⇒ Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/automan/cloudformation/replacer.rb', line 61

def stack_was_just_updated?(stack)
  stack.status == 'UPDATE_COMPLETE' && (Time.now - stack.last_updated_time) <= (5*60)
end