formatron 0.1.11 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/formatron.gemspec +1 -0
- data/lib/formatron/aws.rb +19 -28
- data/lib/formatron/aws/cloud_formation_stack.rb +144 -0
- data/lib/formatron/version.rb +1 -1
- data/support/cloudformation_stack_events_responses.rb +67 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c47341bd39e30cd27955cba1ae8bab5a79135e6
|
4
|
+
data.tar.gz: 69129c0a0edd68e080e37af928954c4a0ecaae34
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6f0aeebee3996040189a535ddf6144a62f8eb6f6930e2167b7bfabff77cf00e46a8858a2061ffc7ca106586a5c67d303d2ffa2ce53ea5e1096296cbc40e7e8d
|
7
|
+
data.tar.gz: a2dac2aa24c3d8587c654b4d0556f0a60476a47acd36be9c60f82545531f297a1324709ce5b02aeaa4f311c40085eca4840b47e1208b5f7a46a7918ccec8c607
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Formatron
|
2
2
|
|
3
3
|
[](https://travis-ci.org/formatron/formatron?branch=master)
|
4
|
-
[](https://coveralls.io/github/formatron/formatron?branch=master)
|
5
|
+
[](https://gemnasium.com/formatron/formatron)
|
6
6
|
|
7
7
|
Simple AWS CloudFormation configuration with Chef Server
|
8
8
|
|
data/formatron.gemspec
CHANGED
data/lib/formatron/aws.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'aws-sdk'
|
2
|
+
require_relative 'aws/cloud_formation_stack'
|
2
3
|
|
3
4
|
class Formatron
|
4
5
|
# shared AWS clients
|
@@ -102,19 +103,21 @@ class Formatron
|
|
102
103
|
use_previous_value: false
|
103
104
|
}
|
104
105
|
end
|
105
|
-
|
106
|
+
cloud_formation_stack = Formatron::AWS::CloudFormationStack.new(
|
106
107
|
stack_name: stack_name,
|
107
|
-
|
108
|
-
capabilities: CAPABILITIES,
|
109
|
-
on_failure: 'DO_NOTHING',
|
110
|
-
parameters: aws_parameters
|
111
|
-
)
|
112
|
-
rescue Aws::CloudFormation::Errors::AlreadyExistsException
|
113
|
-
_update_stack(
|
114
|
-
stack_name: stack_name,
|
115
|
-
template_url: template_url,
|
116
|
-
parameters: aws_parameters
|
108
|
+
client: @cloudformation_client
|
117
109
|
)
|
110
|
+
if !cloud_formation_stack.exists?
|
111
|
+
cloud_formation_stack.create(
|
112
|
+
template_url: template_url,
|
113
|
+
parameters: aws_parameters
|
114
|
+
)
|
115
|
+
else
|
116
|
+
cloud_formation_stack.update(
|
117
|
+
template_url: template_url,
|
118
|
+
parameters: aws_parameters
|
119
|
+
)
|
120
|
+
end
|
118
121
|
end
|
119
122
|
# rubocop:enable Metrics/MethodLength
|
120
123
|
|
@@ -124,23 +127,12 @@ class Formatron
|
|
124
127
|
).hosted_zone.name.chomp '.'
|
125
128
|
end
|
126
129
|
|
127
|
-
def _update_stack(stack_name:, template_url:, parameters:)
|
128
|
-
@cloudformation_client.update_stack(
|
129
|
-
stack_name: stack_name,
|
130
|
-
template_url: template_url,
|
131
|
-
capabilities: CAPABILITIES,
|
132
|
-
parameters: parameters
|
133
|
-
)
|
134
|
-
rescue Aws::CloudFormation::Errors::ValidationError => error
|
135
|
-
raise error unless error.message.eql?(
|
136
|
-
'No updates are to be performed.'
|
137
|
-
)
|
138
|
-
end
|
139
|
-
|
140
130
|
def delete_stack(stack_name:)
|
141
|
-
|
142
|
-
stack_name: stack_name
|
131
|
+
cloud_formation_stack = Formatron::AWS::CloudFormationStack.new(
|
132
|
+
stack_name: stack_name,
|
133
|
+
client: @cloudformation_client
|
143
134
|
)
|
135
|
+
cloud_formation_stack.delete if cloud_formation_stack.exists?
|
144
136
|
end
|
145
137
|
|
146
138
|
def stack_outputs(stack_name:)
|
@@ -196,8 +188,7 @@ class Formatron
|
|
196
188
|
:_create_aws_credentials,
|
197
189
|
:_create_s3_client,
|
198
190
|
:_create_cloudformation_client,
|
199
|
-
:_create_route53_client
|
200
|
-
:_update_stack
|
191
|
+
:_create_route53_client
|
201
192
|
)
|
202
193
|
end
|
203
194
|
# rubocop:enable Metrics/ClassLength
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
|
3
|
+
class Formatron
|
4
|
+
class AWS
|
5
|
+
# utilities for monitoring CloudFormation stack activities
|
6
|
+
# rubocop:disable Metrics/ClassLength
|
7
|
+
class CloudFormationStack
|
8
|
+
CAPABILITIES = %w(CAPABILITY_IAM)
|
9
|
+
|
10
|
+
CREATE_COMPLETE_STATUS = 'CREATE_COMPLETE'
|
11
|
+
CREATE_FINAL_STATUSES = %W(
|
12
|
+
#{CREATE_COMPLETE_STATUS}
|
13
|
+
CREATE_FAILED
|
14
|
+
ROLLBACK_COMPLETE
|
15
|
+
ROLLBACK_FAILED
|
16
|
+
)
|
17
|
+
|
18
|
+
UPDATE_COMPLETE_STATUS = 'UPDATE_COMPLETE'
|
19
|
+
UPDATE_FINAL_STATUSES = %W(
|
20
|
+
#{UPDATE_COMPLETE_STATUS}
|
21
|
+
UPDATE_ROLLBACK_COMPLETE
|
22
|
+
UPDATE_ROLLBACK_FAILED
|
23
|
+
)
|
24
|
+
|
25
|
+
DELETE_COMPLETE_STATUS = 'DELETE_COMPLETE'
|
26
|
+
DELETE_FINAL_STATUSES = %W(
|
27
|
+
#{DELETE_COMPLETE_STATUS}
|
28
|
+
DELETE_FAILED
|
29
|
+
)
|
30
|
+
|
31
|
+
def initialize(stack_name:, client:)
|
32
|
+
@stack_name = stack_name
|
33
|
+
@client = client
|
34
|
+
@stack = Aws::CloudFormation::Stack.new(
|
35
|
+
stack_name,
|
36
|
+
client: @client
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def exists?
|
41
|
+
@stack.exists?
|
42
|
+
end
|
43
|
+
|
44
|
+
def create(template_url:, parameters:)
|
45
|
+
@client.create_stack(
|
46
|
+
stack_name: @stack_name,
|
47
|
+
template_url: template_url,
|
48
|
+
capabilities: CAPABILITIES,
|
49
|
+
on_failure: 'DO_NOTHING',
|
50
|
+
parameters: parameters
|
51
|
+
)
|
52
|
+
@stack.wait_until_exists
|
53
|
+
status = _wait_for_status statuses: CREATE_FINAL_STATUSES
|
54
|
+
fail status unless status.eql? CREATE_COMPLETE_STATUS
|
55
|
+
end
|
56
|
+
|
57
|
+
def update(template_url:, parameters:)
|
58
|
+
last_event_id = _last_event_id
|
59
|
+
return unless _update_unless_no_changes(
|
60
|
+
template_url: template_url,
|
61
|
+
parameters: parameters
|
62
|
+
)
|
63
|
+
status = _wait_for_status(
|
64
|
+
statuses: UPDATE_FINAL_STATUSES,
|
65
|
+
last_event_id: last_event_id
|
66
|
+
)
|
67
|
+
fail status unless status.eql? UPDATE_COMPLETE_STATUS
|
68
|
+
end
|
69
|
+
|
70
|
+
# rubocop:disable Metrics/MethodLength
|
71
|
+
def _update_unless_no_changes(template_url:, parameters:)
|
72
|
+
@stack.update(
|
73
|
+
template_url: template_url,
|
74
|
+
parameters: parameters,
|
75
|
+
capabilities: CAPABILITIES
|
76
|
+
)
|
77
|
+
true
|
78
|
+
rescue Aws::CloudFormation::Errors::ValidationError => error
|
79
|
+
raise error unless error.message.eql?(
|
80
|
+
'No updates are to be performed.'
|
81
|
+
)
|
82
|
+
Formatron::LOG.info do
|
83
|
+
'No updates are to be performed for CloudFormation stack'
|
84
|
+
end
|
85
|
+
false
|
86
|
+
end
|
87
|
+
# rubocop:enable Metrics/MethodLength
|
88
|
+
|
89
|
+
def delete
|
90
|
+
last_event_id = _last_event_id
|
91
|
+
@stack.delete
|
92
|
+
status = _wait_for_status(
|
93
|
+
statuses: DELETE_FINAL_STATUSES,
|
94
|
+
last_event_id: last_event_id
|
95
|
+
)
|
96
|
+
fail status unless status.eql? DELETE_COMPLETE_STATUS
|
97
|
+
end
|
98
|
+
|
99
|
+
def _last_event_id
|
100
|
+
@stack.events.each do |event|
|
101
|
+
return event.event_id
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# rubocop:disable Metrics/MethodLength
|
106
|
+
# rubocop:disable Metrics/AbcSize
|
107
|
+
def _wait_for_status(statuses:, last_event_id: nil)
|
108
|
+
loop do
|
109
|
+
events = []
|
110
|
+
@stack.events.each do |event|
|
111
|
+
break if event.event_id.eql? last_event_id
|
112
|
+
events.push event
|
113
|
+
end
|
114
|
+
events.reverse!
|
115
|
+
events.each do |event|
|
116
|
+
status = event.resource_status
|
117
|
+
timestamp = event.timestamp
|
118
|
+
type = event.resource_type
|
119
|
+
logical_id = event.logical_resource_id
|
120
|
+
reason = event.resource_status_reason
|
121
|
+
Formatron::LOG.info do
|
122
|
+
"#{timestamp} - #{status} - #{type} - #{logical_id} - #{reason}"
|
123
|
+
end
|
124
|
+
return status if
|
125
|
+
statuses.include?(status) &&
|
126
|
+
logical_id.eql?(@stack_name) &&
|
127
|
+
type.eql?('AWS::CloudFormation::Stack')
|
128
|
+
last_event_id = event.event_id
|
129
|
+
end
|
130
|
+
sleep 1
|
131
|
+
end
|
132
|
+
end
|
133
|
+
# rubocop:enable Metrics/AbcSize
|
134
|
+
# rubocop:enable Metrics/MethodLength
|
135
|
+
|
136
|
+
private(
|
137
|
+
:_update_unless_no_changes,
|
138
|
+
:_last_event_id,
|
139
|
+
:_wait_for_status
|
140
|
+
)
|
141
|
+
end
|
142
|
+
# rubocop:enable Metrics/ClassLength
|
143
|
+
end
|
144
|
+
end
|
data/lib/formatron/version.rb
CHANGED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
|
3
|
+
class Formatron
|
4
|
+
module Support
|
5
|
+
# Stub CloudFormation describe_stacks response class
|
6
|
+
class CloudformationStackEventsResponses
|
7
|
+
include RSpec::Mocks::ExampleMethods
|
8
|
+
|
9
|
+
attr_reader :responses
|
10
|
+
|
11
|
+
# rubocop:disable Metrics/MethodLength
|
12
|
+
def initialize(stack_name:, final_status:)
|
13
|
+
@next_event_id = 0
|
14
|
+
first_response = [
|
15
|
+
event,
|
16
|
+
event,
|
17
|
+
event
|
18
|
+
]
|
19
|
+
second_response = [
|
20
|
+
event,
|
21
|
+
event,
|
22
|
+
event,
|
23
|
+
*first_response
|
24
|
+
]
|
25
|
+
third_response = [
|
26
|
+
event(
|
27
|
+
logical_resource_id: stack_name,
|
28
|
+
resource_status: final_status,
|
29
|
+
resource_type: 'AWS::CloudFormation::Stack'
|
30
|
+
),
|
31
|
+
event,
|
32
|
+
event,
|
33
|
+
*second_response
|
34
|
+
]
|
35
|
+
@responses = [
|
36
|
+
first_response,
|
37
|
+
second_response,
|
38
|
+
third_response
|
39
|
+
]
|
40
|
+
end
|
41
|
+
# rubocop:enable Metrics/MethodLength
|
42
|
+
|
43
|
+
# rubocop:disable Metrics/MethodLength
|
44
|
+
# rubocop:disable Metrics/AbcSize
|
45
|
+
def event(
|
46
|
+
logical_resource_id: 'logical_resource_id',
|
47
|
+
resource_status: 'resource_status',
|
48
|
+
resource_type: 'resource_type'
|
49
|
+
)
|
50
|
+
event = instance_double(Aws::CloudFormation::Event)
|
51
|
+
allow(event).to receive(:logical_resource_id) { logical_resource_id }
|
52
|
+
allow(event).to receive(:resource_status) { resource_status }
|
53
|
+
allow(event).to receive(:resource_type) { resource_type }
|
54
|
+
allow(event).to receive(:timestamp) { 'timestamp' }
|
55
|
+
allow(event).to receive(
|
56
|
+
:resource_status_reason
|
57
|
+
) { 'resource_status_reason' }
|
58
|
+
allow(event).to receive(:event_id) do
|
59
|
+
@next_event_id += 1
|
60
|
+
end
|
61
|
+
event
|
62
|
+
end
|
63
|
+
# rubocop:enable Metrics/AbcSize
|
64
|
+
# rubocop:enable Metrics/MethodLength
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: formatron
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Halliday
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -276,6 +276,20 @@ dependencies:
|
|
276
276
|
- - "~>"
|
277
277
|
- !ruby/object:Gem::Version
|
278
278
|
version: '12.5'
|
279
|
+
- !ruby/object:Gem::Dependency
|
280
|
+
name: net-ssh
|
281
|
+
requirement: !ruby/object:Gem::Requirement
|
282
|
+
requirements:
|
283
|
+
- - "~>"
|
284
|
+
- !ruby/object:Gem::Version
|
285
|
+
version: '2.9'
|
286
|
+
type: :runtime
|
287
|
+
prerelease: false
|
288
|
+
version_requirements: !ruby/object:Gem::Requirement
|
289
|
+
requirements:
|
290
|
+
- - "~>"
|
291
|
+
- !ruby/object:Gem::Version
|
292
|
+
version: '2.9'
|
279
293
|
description: |
|
280
294
|
AWS/Chef deployment tool based around Chef Server and AWS CloudFormation
|
281
295
|
email:
|
@@ -303,6 +317,7 @@ files:
|
|
303
317
|
- formatron.gemspec
|
304
318
|
- lib/formatron.rb
|
305
319
|
- lib/formatron/aws.rb
|
320
|
+
- lib/formatron/aws/cloud_formation_stack.rb
|
306
321
|
- lib/formatron/chef.rb
|
307
322
|
- lib/formatron/chef/berkshelf.rb
|
308
323
|
- lib/formatron/chef/keys.rb
|
@@ -390,6 +405,7 @@ files:
|
|
390
405
|
- lib/formatron/util/vpc.rb
|
391
406
|
- lib/formatron/version.rb
|
392
407
|
- support/cloudformation_describe_stacks_response.rb
|
408
|
+
- support/cloudformation_stack_events_responses.rb
|
393
409
|
- support/dsl_test.rb
|
394
410
|
- support/route53_get_hosted_zone_response.rb
|
395
411
|
- support/s3_get_object_response.rb
|