cf_deployer 1.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +29 -0
  3. data/ChangeLog.md +16 -0
  4. data/DETAILS.md +268 -0
  5. data/FAQ.md +61 -0
  6. data/Gemfile +10 -0
  7. data/Gemfile.lock +51 -0
  8. data/LICENSE +22 -0
  9. data/QUICKSTART.md +96 -0
  10. data/README.md +36 -0
  11. data/Rakefile +32 -0
  12. data/bin/cf_deploy +10 -0
  13. data/cf_deployer.gemspec +23 -0
  14. data/lib/cf_deployer/application.rb +74 -0
  15. data/lib/cf_deployer/application_error.rb +4 -0
  16. data/lib/cf_deployer/aws_constants.rb +3 -0
  17. data/lib/cf_deployer/cli.rb +111 -0
  18. data/lib/cf_deployer/component.rb +103 -0
  19. data/lib/cf_deployer/config_loader.rb +189 -0
  20. data/lib/cf_deployer/config_validation.rb +138 -0
  21. data/lib/cf_deployer/defaults.rb +10 -0
  22. data/lib/cf_deployer/deployment_strategy/auto_scaling_group_swap.rb +102 -0
  23. data/lib/cf_deployer/deployment_strategy/base.rb +88 -0
  24. data/lib/cf_deployer/deployment_strategy/blue_green.rb +70 -0
  25. data/lib/cf_deployer/deployment_strategy/cname_swap.rb +108 -0
  26. data/lib/cf_deployer/deployment_strategy/create_or_update.rb +57 -0
  27. data/lib/cf_deployer/driver/auto_scaling_group.rb +86 -0
  28. data/lib/cf_deployer/driver/cloud_formation_driver.rb +85 -0
  29. data/lib/cf_deployer/driver/dry_run.rb +27 -0
  30. data/lib/cf_deployer/driver/elb_driver.rb +17 -0
  31. data/lib/cf_deployer/driver/instance.rb +29 -0
  32. data/lib/cf_deployer/driver/route53_driver.rb +79 -0
  33. data/lib/cf_deployer/driver/verisign_driver.rb +21 -0
  34. data/lib/cf_deployer/hook.rb +32 -0
  35. data/lib/cf_deployer/logger.rb +34 -0
  36. data/lib/cf_deployer/stack.rb +154 -0
  37. data/lib/cf_deployer/status_presenter.rb +195 -0
  38. data/lib/cf_deployer/version.rb +3 -0
  39. data/lib/cf_deployer.rb +97 -0
  40. data/spec/fakes/instance.rb +32 -0
  41. data/spec/fakes/route53_client.rb +23 -0
  42. data/spec/fakes/stack.rb +65 -0
  43. data/spec/functional/deploy_spec.rb +73 -0
  44. data/spec/functional/kill_inactive_spec.rb +57 -0
  45. data/spec/functional_spec_helper.rb +3 -0
  46. data/spec/spec_helper.rb +8 -0
  47. data/spec/unit/application_spec.rb +191 -0
  48. data/spec/unit/component_spec.rb +142 -0
  49. data/spec/unit/config_loader_spec.rb +356 -0
  50. data/spec/unit/config_validation_spec.rb +480 -0
  51. data/spec/unit/deployment_strategy/auto_scaling_group_swap_spec.rb +435 -0
  52. data/spec/unit/deployment_strategy/base_spec.rb +44 -0
  53. data/spec/unit/deployment_strategy/cname_swap_spec.rb +294 -0
  54. data/spec/unit/deployment_strategy/create_or_update_spec.rb +113 -0
  55. data/spec/unit/deployment_strategy/deployment_strategy_spec.rb +29 -0
  56. data/spec/unit/driver/auto_scaling_group_spec.rb +127 -0
  57. data/spec/unit/driver/cloud_formation_spec.rb +32 -0
  58. data/spec/unit/driver/elb_spec.rb +11 -0
  59. data/spec/unit/driver/instance_spec.rb +30 -0
  60. data/spec/unit/driver/route53_spec.rb +85 -0
  61. data/spec/unit/driver/verisign_spec.rb +18 -0
  62. data/spec/unit/hook_spec.rb +64 -0
  63. data/spec/unit/stack_spec.rb +150 -0
  64. data/spec/unit/status_presenter_spec.rb +108 -0
  65. metadata +197 -0
@@ -0,0 +1,102 @@
1
+ module CfDeployer
2
+ module DeploymentStrategy
3
+ class AutoScalingGroupSwap < BlueGreen
4
+
5
+
6
+ def deploy
7
+ check_blue_green_not_both_active 'Deployment'
8
+ Log.info "Found active stack #{active_stack.name}" if active_stack
9
+ delete_stack inactive_stack
10
+ create_inactive_stack
11
+ swap_group
12
+ run_hook(:'after-swap')
13
+ Log.info "Active stack has been set to #{inactive_stack.name}"
14
+ delete_stack(active_stack) if active_stack && !keep_previous_stack
15
+ Log.info "#{component_name} deployed successfully"
16
+ end
17
+
18
+
19
+ def kill_inactive
20
+ check_blue_green_not_both_active 'Kill Inactive'
21
+ raise ApplicationError.new('Only one color stack exists, cannot kill a non-existant version!') unless both_stacks_exist?
22
+ delete_stack inactive_stack
23
+ end
24
+
25
+ def switch
26
+ check_blue_green_not_both_active 'Switch'
27
+ raise ApplicationError.new('Only one color stack exists, cannot switch to a non-existent version!') unless both_stacks_exist?
28
+ warm_up_cooled = true
29
+ swap_group warm_up_cooled
30
+ end
31
+
32
+ private
33
+
34
+
35
+ def check_blue_green_not_both_active action
36
+ active_stacks = get_active_asg(active_stack) + get_active_asg(inactive_stack)
37
+ raise BothStacksActiveError.new("Found both auto-scaling-groups, #{active_stacks}, in green and blue stacks are active. #{action} aborted!") if both_stacks_active?
38
+ end
39
+
40
+ def swap_group is_switching_to_cooled = false
41
+ is_switching_to_cooled ? warm_up_cooled_stack : warm_up_inactive_stack
42
+ cool_down_active_stack if active_stack && (is_switching_to_cooled || keep_previous_stack)
43
+ end
44
+
45
+ def keep_previous_stack
46
+ context[:settings][:'keep-previous-stack']
47
+ end
48
+
49
+ def create_inactive_stack
50
+ inactive_stack.deploy
51
+ get_parameters_outputs(inactive_stack)
52
+ run_hook(:'after-create')
53
+ end
54
+
55
+ def both_stacks_active?
56
+ active_stack && stack_active?(inactive_stack)
57
+ end
58
+
59
+
60
+ def warm_up_cooled_stack
61
+ group_ids(active_stack).each_with_index do |id, index|
62
+ min_max_desired = asg_driver(id).describe
63
+ asg_driver(group_ids(inactive_stack)[index]).warm_up_cooled_group min_max_desired
64
+ end
65
+ end
66
+
67
+ def cool_down_active_stack
68
+ group_ids(active_stack).each do |id|
69
+ asg_driver(id).cool_down
70
+ end
71
+
72
+ end
73
+
74
+
75
+ def stack_active?(stack)
76
+ return false unless stack.exists?
77
+ get_active_asg(stack).any?
78
+ end
79
+
80
+
81
+
82
+ def get_active_asg stack
83
+ return [] unless stack && stack.exists?
84
+ group_ids(stack).select do |id|
85
+ result = asg_driver(id).describe
86
+ result[:min] > 0 && result[:max] > 0 && result[:desired] > 0
87
+ end
88
+ end
89
+
90
+ def asg_driver name
91
+ @auto_scaling_group_drivers[name] ||= CfDeployer::Driver::AutoScalingGroup.new name
92
+ end
93
+
94
+ def asg_id_outputs
95
+ @context[:settings][:'auto-scaling-group-name-output']
96
+ end
97
+
98
+ class BothStacksActiveError < ApplicationError
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,88 @@
1
+
2
+ module CfDeployer
3
+ module DeploymentStrategy
4
+
5
+ def self.create application_name, environment_name, component_name, context
6
+ context[:'deployment-strategy'] ||= 'create-or-update'
7
+ strategy_class_name = 'CfDeployer::DeploymentStrategy::' + context[:'deployment-strategy'].split('-').map(&:capitalize).join
8
+ begin
9
+ eval(strategy_class_name).new application_name, component_name, environment_name, context
10
+ rescue
11
+ raise ApplicationError.new 'strategy_name: ' + strategy_class_name + ' not supported'
12
+ end
13
+ end
14
+
15
+ class Base
16
+ BLUE_GREEN_STRATEGY = true
17
+
18
+ attr_reader :context, :component_name, :application_name, :environment_name
19
+ def initialize(application_name, component_name, environment_name, context)
20
+ @application_name = application_name
21
+ @component_name = component_name
22
+ @environment_name = environment_name
23
+ @context = context
24
+ @auto_scaling_group_drivers = {}
25
+ end
26
+
27
+ def blue_green_strategy?
28
+ BLUE_GREEN_STRATEGY
29
+ end
30
+
31
+ protected
32
+
33
+ def stack_prefix
34
+ "#{@application_name}-#{@environment_name}-#{@component_name}"
35
+ end
36
+
37
+ def delete_stack(stack)
38
+ # Should this be stack.ready? Outputs won't exist if the stack is still starting.
39
+ unless stack.exists?
40
+ CfDeployer::Log.info "Skipping deleting stack #{stack.name} since it doesn't exist."
41
+ return
42
+ end
43
+ get_parameters_outputs stack
44
+ run_hook :'before-destroy'
45
+ stack.delete
46
+ end
47
+
48
+ def run_hook(hook_name)
49
+ CfDeployer::Driver::DryRun.guard "Skipping hook #{hook_name}" do
50
+ hook = Hook.new hook_name, context[hook_name]
51
+ hook.run context
52
+ end
53
+ end
54
+
55
+ def get_parameters_outputs(stack)
56
+ CfDeployer::Driver::DryRun.guard "Skipping get_parameters_outputs" do
57
+ context[:parameters] = stack.parameters
58
+ context[:outputs] = stack.outputs
59
+ end
60
+ end
61
+
62
+ def warm_up_inactive_stack
63
+ group_ids(inactive_stack).each_with_index do |id, index|
64
+ asg_driver(id).warm_up get_desired(id, index)
65
+ end
66
+ end
67
+
68
+ def get_desired(id, index)
69
+ group_id = active_stack ? group_ids(active_stack)[index] : id
70
+ asg_driver(group_id).describe[:desired]
71
+ end
72
+
73
+ def group_ids(stack)
74
+ return [] unless asg_id_outputs
75
+ asg_id_outputs.map { |id| stack.output id }
76
+ end
77
+
78
+ def asg_driver name
79
+ @auto_scaling_group_drivers[name] ||= CfDeployer::Driver::AutoScalingGroup.new name
80
+ end
81
+
82
+ def asg_id_outputs
83
+ @context[:settings][:'auto-scaling-group-name-output']
84
+ end
85
+
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,70 @@
1
+ module CfDeployer
2
+ module DeploymentStrategy
3
+ class BlueGreen < Base
4
+
5
+ def exists?
6
+ green_stack.exists? || blue_stack.exists?
7
+ end
8
+
9
+ def destroy
10
+ delete_stack green_stack
11
+ delete_stack blue_stack
12
+ end
13
+
14
+
15
+ def output_value(key)
16
+ active_stack ? active_stack.output(key) : "The value will be referenced from the output #{key} of undeployed component #{component_name}"
17
+ end
18
+
19
+ def status get_resource_statuses = false
20
+ my_status = {}
21
+ [blue_stack, green_stack].each do |the_stack|
22
+ my_status[the_stack.name] = {}
23
+ my_status[the_stack.name][:active] = stack_active?(the_stack)
24
+ my_status[the_stack.name][:status] = the_stack.status
25
+ my_status[the_stack.name][:resources] = the_stack.resource_statuses if the_stack.exists? && get_resource_statuses
26
+ end
27
+ my_status
28
+ end
29
+
30
+ private
31
+
32
+ def blue_stack
33
+ name = "#{stack_prefix}-B"
34
+ Stack.new(name, component_name, context)
35
+ end
36
+
37
+ def green_stack
38
+ name = "#{stack_prefix}-G"
39
+ Stack.new(name, component_name, context)
40
+ end
41
+
42
+ def both_stacks_exist?
43
+ blue_stack.exists? && green_stack.exists?
44
+ end
45
+
46
+ def active_stack
47
+ @active_stack = get_active_stack unless @active_stack_checked
48
+ @active_stack
49
+ end
50
+
51
+ def inactive_stack
52
+ @inactive_stack ||= get_inactive_stack
53
+ end
54
+
55
+ def get_inactive_stack
56
+ return blue_stack unless active_stack
57
+ stack_active?(green_stack) ? blue_stack : green_stack
58
+ end
59
+
60
+ def get_active_stack
61
+ @active_stack_checked = true
62
+ return green_stack if stack_active?(green_stack)
63
+ return blue_stack if stack_active?(blue_stack)
64
+ nil
65
+ end
66
+
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,108 @@
1
+ module CfDeployer
2
+ module DeploymentStrategy
3
+ class CnameSwap < BlueGreen
4
+
5
+ def deploy
6
+ Log.info "Found active stack #{active_stack.name}" if active_stack
7
+ delete_stack inactive_stack
8
+ create_inactive_stack
9
+ warm_up_inactive_stack
10
+ swap_cname
11
+ Kernel.sleep 60
12
+ run_hook(:'after-swap')
13
+ Log.info "Active stack has been set to #{inactive_stack.name}"
14
+ delete_stack(active_stack) if active_stack && !settings[:'keep-previous-stack']
15
+ Log.info "#{component_name} deployed successfully"
16
+ end
17
+
18
+
19
+ def kill_inactive
20
+ raise ApplicationError.new("Stack: #{inactive_stack.name} does not exist, cannot kill it.") unless inactive_stack.exists?
21
+ delete_stack inactive_stack
22
+ end
23
+
24
+ def switch
25
+ raise ApplicationError.new('There is only one color stack active, you cannot switch back to a non-existent version') unless both_stacks_exist?
26
+ swap_cname
27
+ Log.info "Active stack has been set to #{inactive_stack.name}"
28
+ Log.info "#{component_name} switched successfully"
29
+ end
30
+
31
+ private
32
+
33
+
34
+ def active_cname
35
+ @active_cname ||= get_active_cname
36
+ end
37
+
38
+
39
+
40
+ def create_inactive_stack
41
+ inactive_stack.deploy
42
+ get_parameters_outputs(inactive_stack)
43
+ run_hook(:'after-create')
44
+ end
45
+
46
+ def swap_cname
47
+ set_cname_to(inactive_stack)
48
+ end
49
+
50
+ def set_cname_to(stack)
51
+ cname, zone_id = find_elb_cname_for_stack(stack, elb_output_key)
52
+ dns_driver.set_alias_target(dns_zone, dns_fqdn, zone_id, cname)
53
+ end
54
+
55
+
56
+ def stack_active?(stack)
57
+ return false unless stack.exists?
58
+ return false unless active_cname.length > 0
59
+ cname, zone_id = find_elb_cname_for_stack(stack, elb_output_key)
60
+ active_cname.downcase == cname.downcase
61
+ end
62
+
63
+
64
+ def get_active_cname
65
+ dns_driver.find_alias_target(dns_zone, dns_fqdn) || ""
66
+ end
67
+
68
+
69
+ def elb_output_key
70
+ settings[:'elb-name-output']
71
+ end
72
+
73
+ def dns_fqdn
74
+ settings[:'dns-fqdn']
75
+ end
76
+
77
+ def dns_zone
78
+ settings[:'dns-zone']
79
+ end
80
+
81
+ def dns_driver
82
+ context[:dns_driver] || string_to_class(settings[:'dns-driver'])
83
+ end
84
+
85
+ def elb_driver
86
+ context[:elb_driver] || CfDeployer::Driver::Elb.new
87
+ end
88
+
89
+ def settings
90
+ context[:settings]
91
+ end
92
+
93
+ def find_elb_cname_for_stack(stack, elb_name_output_key)
94
+ return ['', ''] unless stack.exists?
95
+ elb_id = stack.output(elb_name_output_key)
96
+ attrs = elb_driver.find_dns_and_zone_id(elb_id)
97
+ [attrs[:dns_name] || '', attrs[:canonical_hosted_zone_name_id] || '']
98
+ end
99
+
100
+ def string_to_class class_string
101
+ class_string.split('::').inject(Object) do |mod, class_name|
102
+ mod.const_get(class_name)
103
+ end.new
104
+ end
105
+
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,57 @@
1
+ module CfDeployer
2
+ module DeploymentStrategy
3
+ class CreateOrUpdate < Base
4
+ BLUE_GREEN_STRATEGY = false
5
+
6
+ def exists?
7
+ stack.exists?
8
+ end
9
+
10
+ def status get_resource_statuses = false
11
+ my_status = {}
12
+ my_status[stack.name] = {}
13
+ my_status[stack.name][:status] = stack.status
14
+ my_status[stack.name][:resources] = stack.resource_statuses if stack.exists? && get_resource_statuses
15
+ my_status
16
+ end
17
+
18
+
19
+ def deploy
20
+ stack.deploy
21
+ warm_up_inactive_stack
22
+ get_parameters_outputs(inactive_stack)
23
+ run_hook(:'after-create')
24
+ end
25
+
26
+ def output_value(key)
27
+ exists? ? stack.output(key) : "The value will be referenced from the output #{key} of undeployed component #{component_name}"
28
+ end
29
+
30
+ def destroy
31
+ delete_stack stack
32
+ end
33
+
34
+ def kill_inactive
35
+ raise ApplicationError.new('There is no inactive version to kill for Create or Update Deployments.')
36
+ end
37
+
38
+ def switch
39
+ raise ApplicationError.new('There is no inactive version to switch to for Create or Update Deployments. Redeploy the version you want')
40
+ end
41
+
42
+ private
43
+
44
+ def stack
45
+ Stack.new(stack_prefix, @component_name, @context)
46
+ end
47
+
48
+ def inactive_stack
49
+ stack
50
+ end
51
+
52
+ def active_stack
53
+ nil
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,86 @@
1
+ module CfDeployer
2
+ module Driver
3
+ class AutoScalingGroup
4
+ extend Forwardable
5
+
6
+ def_delegators :aws_group, :auto_scaling_instances, :ec2_instances, :load_balancers
7
+
8
+ attr_reader :group_name, :group
9
+
10
+ def initialize name, timeout = CfDeployer::Defaults::Timeout
11
+ @group_name = name
12
+ @timeout = timeout
13
+ end
14
+
15
+ def describe
16
+ { desired: aws_group.desired_capacity, min: aws_group.min_size, max: aws_group.max_size }
17
+ end
18
+
19
+ def warm_up desired
20
+ return if desired < aws_group.min_size
21
+ desired = aws_group.max_size if desired > aws_group.max_size
22
+ Log.info "warming up auto scaling group #{group_name} to #{desired}"
23
+
24
+ CfDeployer::Driver::DryRun.guard "Skipping ASG warmup" do
25
+ aws_group.set_desired_capacity desired
26
+ wait_for_healthy_instance desired
27
+ end
28
+ end
29
+
30
+ def warm_up_cooled_group options
31
+ CfDeployer::Driver::DryRun.guard 'Skipping update of ASG min & max instance count' do
32
+ aws_group.update :min_size => options[:min], :max_size => options[:max]
33
+ end
34
+ warm_up options[:desired]
35
+ end
36
+
37
+ def cool_down
38
+ Log.info "Cooling down #{group_name}"
39
+ CfDeployer::Driver::DryRun.guard "Skipping ASG cooldown" do
40
+ aws_group.update :min_size => 0, :max_size => 0
41
+ aws_group.set_desired_capacity 0
42
+ end
43
+ end
44
+
45
+ def instance_statuses
46
+ instance_info = {}
47
+ ec2_instances.each do |instance|
48
+ instance_info[instance.id] = CfDeployer::Driver::Instance.new(instance).status
49
+ end
50
+ instance_info
51
+ end
52
+
53
+ private
54
+
55
+ def healthy_instance_count
56
+ count = auto_scaling_instances.count do |instance|
57
+ instance.health_status == 'HEALTHY' && (load_balancers.empty? || instance_in_service?( instance.ec2_instance ))
58
+ end
59
+ Log.info "Healthy instance count: #{count}"
60
+ count
61
+ end
62
+
63
+ def instance_in_service? instance
64
+ load_balancers.all? do |load_balancer|
65
+ load_balancer.instances.health.any? do |health|
66
+ health[:instance] == instance ? health[:state] == 'InService' : false
67
+ end
68
+ end
69
+ end
70
+
71
+ def wait_for_healthy_instance number
72
+ Timeout::timeout(@timeout){
73
+ while healthy_instance_count != number
74
+ sleep 15
75
+ end
76
+ }
77
+ end
78
+
79
+
80
+ def aws_group
81
+ @my_group ||= AWS::AutoScaling.new.groups[group_name]
82
+ end
83
+
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,85 @@
1
+ module CfDeployer
2
+ module Driver
3
+ class CloudFormation
4
+
5
+ def initialize stack_name
6
+ @stack_name = stack_name
7
+ end
8
+
9
+ def stack_exists?
10
+ aws_stack.exists?
11
+ end
12
+
13
+ def create_stack template, opts
14
+ CfDeployer::Driver::DryRun.guard "Skipping create_stack" do
15
+ cloud_formation.stacks.create @stack_name, template, opts
16
+ end
17
+ end
18
+
19
+ def update_stack template, opts
20
+ begin
21
+ CfDeployer::Driver::DryRun.guard "Skipping update_stack" do
22
+ aws_stack.update opts.merge(:template => template)
23
+ end
24
+ rescue AWS::CloudFormation::Errors::ValidationError => e
25
+ if e.message =~ /No updates are to be performed/
26
+ Log.info e.message
27
+ else
28
+ raise
29
+ end
30
+ end
31
+ end
32
+
33
+ def stack_status
34
+ aws_stack.status.downcase.to_sym
35
+ end
36
+
37
+ def outputs
38
+ aws_stack.outputs.inject({}) do |memo, o|
39
+ memo[o.key] = o.value
40
+ memo
41
+ end
42
+ end
43
+
44
+ def parameters
45
+ aws_stack.parameters
46
+ end
47
+
48
+ def query_output key
49
+ output = aws_stack.outputs.find { |o| o.key == key }
50
+ output && output.value
51
+ end
52
+
53
+ def delete_stack
54
+ if stack_exists?
55
+ CfDeployer::Driver::DryRun.guard "Skipping create_stack" do
56
+ aws_stack.delete
57
+ end
58
+ else
59
+ Log.info "Stack #{@stack_name} does not exist!"
60
+ end
61
+ end
62
+
63
+ def resource_statuses
64
+ resources = {}
65
+ aws_stack.resource_summaries.each do |rs|
66
+ resources[rs[:resource_type]] ||= {}
67
+ resources[rs[:resource_type]][rs[:physical_resource_id]] = rs[:resource_status]
68
+ end
69
+ resources
70
+ end
71
+
72
+ private
73
+
74
+ def cloud_formation
75
+ AWS::CloudFormation.new
76
+ end
77
+
78
+ def aws_stack
79
+ cloud_formation.stacks[@stack_name]
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,27 @@
1
+ module CfDeployer
2
+ module Driver
3
+ class DryRun
4
+
5
+ @@enabled = false
6
+
7
+ def self.enable
8
+ CfDeployer::Log.info "Enabling Dry-Run Mode"
9
+ @@enabled = true
10
+ end
11
+
12
+ def self.disable
13
+ CfDeployer::Log.info "Disabling Dry-Run Mode"
14
+ @@enabled = false
15
+ end
16
+
17
+ def self.guard description
18
+ if @@enabled
19
+ CfDeployer::Log.info "<Dry Run Enabled> #{description}"
20
+ else
21
+ yield
22
+ end
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ module CfDeployer
2
+ module Driver
3
+ class Elb
4
+ def find_dns_and_zone_id elb_id
5
+ elb = elb_driver.load_balancers[elb_id]
6
+ { :canonical_hosted_zone_name_id => elb.canonical_hosted_zone_name_id, :dns_name => elb.dns_name }
7
+ end
8
+
9
+ private
10
+
11
+ def elb_driver
12
+ AWS::ELB.new
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ module CfDeployer
2
+ module Driver
3
+ class Instance
4
+
5
+ GOOD_STATUSES = [ :running, :pending ]
6
+
7
+ def initialize instance_obj_or_id
8
+ if instance_obj_or_id.is_a?(String)
9
+ @id = instance_obj_or_id
10
+ else
11
+ @instance_obj = instance_obj_or_id
12
+ end
13
+ end
14
+
15
+ def status
16
+ instance_info = { }
17
+ [:status, :public_ip_address, :private_ip_address, :image_id].each do |stat|
18
+ instance_info[stat] = aws_instance.send(stat)
19
+ end
20
+ instance_info[:key_pair] = aws_instance.key_pair.name
21
+ instance_info
22
+ end
23
+
24
+ def aws_instance
25
+ @instance_obj ||= AWS::EC2.new.instances[@id]
26
+ end
27
+ end
28
+ end
29
+ end