autostacker24 1.0.pre1420195669

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5504eb5540d79a296099f4b7e3e20e8956ffa7f6
4
+ data.tar.gz: 34aa0de0b82ea78c919503c70b44c19a242c97f9
5
+ SHA512:
6
+ metadata.gz: 3339d2f678fd379179aebc52882802061522c57cae23685490e7b70132e500c6a50f025fd284325a38eeb71121b4241525028aefcf971bc19078cc545b3df108
7
+ data.tar.gz: ea14bf541ef75c9e7b8459a3d8c6332d581f5c74578951e412e847a1d4004efa3fdc4496c42ab369c3fea889295eedd090c3fa3cb922b66f0caa47e3a0fdfbb4
@@ -0,0 +1,3 @@
1
+
2
+ require_relative 'autostacker24/service_stack.rb'
3
+ require_relative 'autostacker24/stacker.rb'
@@ -0,0 +1,43 @@
1
+ require 'json'
2
+ require_relative 'stacker.rb'
3
+
4
+ class ServiceStack
5
+
6
+ def initialize(name, version, sandbox = nil, global_stack_name = nil)
7
+ @name = name || fail('mandatory name is not specified')
8
+ @version = version || ENV['VERSION'] || fail('mandatory version is not specified')
9
+ @sandbox = sandbox || ENV['SANDBOX']
10
+ @stack_name = (sandbox ? "#{sandbox}-" : '') + name
11
+ @global_stack_name = global_stack_name || ENV['GLOBAL_STACK_NAME'] || 'global'
12
+ end
13
+
14
+ attr_reader :name, :sandbox, :version, :stack_name, :global_stack_name
15
+
16
+ def create_or_update(template, parameters)
17
+ inputs = JSON(template)['Parameters']
18
+ global_outputs.each{|k, v| parameters[k.to_sym] = v if inputs.has_key?(k.to_s)}
19
+ parameters[:Version] = version
20
+ Stacker.create_or_update_stack(stack_name, template, parameters)
21
+ end
22
+
23
+ def delete
24
+ Stacker.delete_stack(stack_name)
25
+ end
26
+
27
+ def outputs
28
+ @lazy_outputs ||= Stacker.get_stack_outputs(stack_name)
29
+ end
30
+
31
+ def global_outputs
32
+ @lazy_global_outputs ||= Stacker.get_stack_outputs(global_stack_name)
33
+ end
34
+
35
+ def estimate(template, parameters)
36
+ Stacker.estimate_template_cost(template, parameters)
37
+ end
38
+
39
+ end
40
+
41
+ if $0 ==__FILE__ # placeholder for interactive testing
42
+
43
+ end
@@ -0,0 +1,98 @@
1
+ require 'aws-sdk'
2
+
3
+ module Stacker
4
+
5
+ def self.create_or_update_stack(stack_name, template_body, parameters)
6
+ if find_stack(stack_name).nil?
7
+ create_stack(stack_name, template_body, parameters)
8
+ else
9
+ update_stack(stack_name, template_body, parameters)
10
+ end
11
+ end
12
+
13
+ def self.create_stack(stack_name, template_body, parameters)
14
+ cloud_formation.create_stack(stack_name: stack_name,
15
+ template_body: template_body,
16
+ on_failure: 'DELETE',
17
+ parameters: transform_parameters(parameters),
18
+ capabilities: ['CAPABILITY_IAM'])
19
+ wait_for_stack(stack_name, :create)
20
+ end
21
+
22
+ def self.update_stack(stack_name, template_body, parameters)
23
+ begin
24
+ cloud_formation.update_stack(stack_name: stack_name,
25
+ template_body: template_body,
26
+ parameters: transform_parameters(parameters),
27
+ capabilities: ['CAPABILITY_IAM'])
28
+ rescue Aws::CloudFormation::Errors::ValidationError => error
29
+ raise error unless error.message =~ /No updates are to be performed/i # may be flaky, do more research in API
30
+ find_stack(stack_name)
31
+ else
32
+ wait_for_stack(stack_name, :update)
33
+ end
34
+ end
35
+
36
+ def self.delete_stack(stack_name)
37
+ cloud_formation.delete_stack(stack_name: stack_name)
38
+ wait_for_stack(stack_name, :delete)
39
+ end
40
+
41
+ def self.wait_for_stack(stack_name, operation, timeout_in_minutes = 15)
42
+ stop_time = Time.now + timeout_in_minutes * 60
43
+ finished = /(CREATE_COMPLETE|UPDATE_COMPLETE|DELETE_COMPLETE|ROLLBACK_COMPLETE|ROLLBACK_FAILED|CREATE_FAILED|DELETE_FAILED)$/
44
+ while Time.now < stop_time
45
+ stack = find_stack(stack_name)
46
+ status = stack ? stack.stack_status : 'DELETE_COMPLETE'
47
+ expected_status = case operation
48
+ when :create then /CREATE_COMPLETE$/
49
+ when :update then /UPDATE_COMPLETE$/
50
+ when :delete then /DELETE_COMPLETE$/
51
+ end
52
+ return true if status =~ expected_status
53
+ fail "#{stack_name} failed, current status #{status}" if status =~ finished
54
+ puts "waiting for #{stack_name}, current status #{status}"
55
+ sleep(7)
56
+ end
57
+ fail "waiting for stack timeout after #{timeout_in_minutes} minutes"
58
+ end
59
+
60
+ def self.find_stack(stack_name)
61
+ cloud_formation.describe_stacks(stack_name: stack_name).stacks.first
62
+ rescue Aws::CloudFormation::Errors::ValidationError => error
63
+ raise error unless error.message =~ /does not exist/i # may be flaky, do more research in API
64
+ nil
65
+ end
66
+
67
+ def self.estimate_template_cost(template_body, parameters)
68
+ cloud_formation.estimate_template_cost(:template_body => template_body, :parameters => transform_parameters(parameters))
69
+ end
70
+
71
+ def self.get_stack_outputs(stack_name, hash = {})
72
+ stack = find_stack(stack_name)
73
+ fail "stack #{stack_name} not found" unless stack
74
+ transform_outputs(stack.outputs, hash).freeze
75
+ end
76
+
77
+ def self.transform_outputs(outputs, existing_outputs = {})
78
+ outputs.inject(existing_outputs) { |m, o| m.merge(o.output_key.to_sym => o.output_value) }
79
+ end
80
+
81
+ def self.transform_parameters(parameters)
82
+ parameters.inject([]) { |m, kv| m << {parameter_key: kv[0].to_s, parameter_value: kv[1].to_s} }
83
+ end
84
+
85
+ def self.get_stack_resources(stack_name)
86
+ resources = cloud_formation.describe_stack_resources(stack_name: stack_name).data.stack_resources
87
+ resources.inject({}){|map, resource| map.merge(resource.logical_resource_id => resource)}.freeze
88
+ end
89
+
90
+ def self.cloud_formation # lazy CloudFormation client
91
+ @lazy_cloud_formation ||= Aws::CloudFormation::Client.new(region: ENV['AWS_DEFAULT_REGION'] || 'eu-west-1')
92
+ end
93
+
94
+ end
95
+
96
+ if $0 ==__FILE__ # placeholder for interactive testing
97
+
98
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: autostacker24
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.pre1420195669
5
+ platform: ruby
6
+ authors:
7
+ - Johannes Mueller
8
+ - Christian Rodemeyer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-01-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: aws-sdk
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: 2.0.pre
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: 2.0.pre
28
+ description: n/a
29
+ email:
30
+ - jmueller@autoscout24.com
31
+ - crodemeyer@autoscout24.com
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - lib/autostacker24.rb
37
+ - lib/autostacker24/service_stack.rb
38
+ - lib/autostacker24/stacker.rb
39
+ homepage: https://github.com/AutoScout24/autostacker24
40
+ licenses:
41
+ - MIT
42
+ metadata: {}
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - '>'
55
+ - !ruby/object:Gem::Version
56
+ version: 1.3.1
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 2.0.14
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: Library for managing AWS CloudFormation stacks
63
+ test_files: []