automan 2.3.1 → 2.3.2
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/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/automan.gemspec +3 -3
- data/lib/automan/version.rb +1 -1
- data/spec/beanstalk/application_spec.rb +17 -17
- data/spec/beanstalk/configuration_spec.rb +24 -24
- data/spec/beanstalk/deployer_spec.rb +65 -65
- data/spec/beanstalk/router_spec.rb +18 -18
- data/spec/beanstalk/terminator_spec.rb +16 -16
- data/spec/beanstalk/uploader_spec.rb +13 -13
- data/spec/beanstalk/version_spec.rb +8 -9
- data/spec/cloudformation/launcher_spec.rb +63 -65
- data/spec/cloudformation/replacer_spec.rb +10 -10
- data/spec/cloudformation/terminator_spec.rb +23 -23
- data/spec/cloudformation/uploader_spec.rb +13 -13
- data/spec/ec2/image_spec.rb +55 -55
- data/spec/ec2/instance_spec.rb +17 -17
- data/spec/mixins/aws_caller_spec.rb +9 -9
- data/spec/mixins/utils_spec.rb +27 -28
- data/spec/rds/snapshot_spec.rb +43 -45
- data/templates/stacker/.ruby-version +1 -0
- data/templates/stacker/bin/{launch_%app_name%.sh → launch_%app_name%.sh.tt} +2 -2
- metadata +12 -10
- data/.rvmrc +0 -1
@@ -14,33 +14,33 @@ describe Automan::Beanstalk::Terminator do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
it "returns false if environment does not exist" do
|
17
|
-
resp =
|
17
|
+
resp = subject.eb.stub_for :describe_environments
|
18
18
|
resp.data[:environments] = [{}]
|
19
|
-
|
19
|
+
expect(subject.environment_exists?('foo')).to be_falsey
|
20
20
|
end
|
21
21
|
|
22
22
|
it "returns false if environment is in Terminated state" do
|
23
|
-
resp =
|
23
|
+
resp = subject.eb.stub_for :describe_environments
|
24
24
|
resp.data[:environments] = [{environment_name: 'foo', status: 'Terminated'}]
|
25
|
-
|
25
|
+
expect(subject.environment_exists?('foo')).to be_falsey
|
26
26
|
end
|
27
27
|
|
28
28
|
it "returns false if environment is in Terminating state" do
|
29
|
-
resp =
|
29
|
+
resp = subject.eb.stub_for :describe_environments
|
30
30
|
resp.data[:environments] = [{environment_name: 'foo', status: 'Terminating'}]
|
31
|
-
|
31
|
+
expect(subject.environment_exists?('foo')).to be_falsey
|
32
32
|
end
|
33
33
|
|
34
34
|
it "returns true if environment does exist" do
|
35
|
-
resp =
|
35
|
+
resp = subject.eb.stub_for :describe_environments
|
36
36
|
resp.data[:environments] = [{environment_name: 'foo'}]
|
37
|
-
|
37
|
+
expect(subject.environment_exists?('foo')).to be_truthy
|
38
38
|
end
|
39
39
|
|
40
40
|
it "returns true if environment is in Ready state" do
|
41
|
-
resp =
|
41
|
+
resp = subject.eb.stub_for :describe_environments
|
42
42
|
resp.data[:environments] = [{environment_name: 'foo', status: 'Ready'}]
|
43
|
-
|
43
|
+
expect(subject.environment_exists?('foo')).to be_truthy
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
@@ -53,15 +53,15 @@ describe Automan::Beanstalk::Terminator do
|
|
53
53
|
end
|
54
54
|
|
55
55
|
it 'should call #terminate_environment if the environment exists' do
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
allow(subject).to receive(:environment_exists?).and_return(true)
|
57
|
+
expect(subject).to receive :terminate_environment
|
58
|
+
subject.terminate
|
59
59
|
end
|
60
60
|
|
61
61
|
it 'should not call #terminate_environment if the environment does not exist' do
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
allow(subject).to receive(:environment_exists?).and_return(false)
|
63
|
+
expect(subject).to_not receive :terminate_environment
|
64
|
+
subject.terminate
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
@@ -6,7 +6,7 @@ describe Automan::Beanstalk::Uploader do
|
|
6
6
|
u = Automan::Beanstalk::Uploader.new
|
7
7
|
u.logger = Logger.new('/dev/null')
|
8
8
|
u.template_files = 'foo'
|
9
|
-
u.
|
9
|
+
allow(u).to receive(:config_templates).and_return(['foo'])
|
10
10
|
u
|
11
11
|
end
|
12
12
|
|
@@ -18,36 +18,36 @@ describe Automan::Beanstalk::Uploader do
|
|
18
18
|
describe '#config_templates_valid?' do
|
19
19
|
|
20
20
|
it 'raises error if config templates do not exist' do
|
21
|
-
|
21
|
+
allow(subject).to receive(:config_templates).and_return([])
|
22
22
|
expect {
|
23
|
-
|
23
|
+
subject.config_templates_valid?
|
24
24
|
}.to raise_error(Automan::Beanstalk::NoConfigurationTemplatesError)
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'returns true if config templates are valid json' do
|
28
|
-
|
29
|
-
|
28
|
+
allow(subject).to receive(:read_config_template).and_return('[{}]')
|
29
|
+
expect(subject.config_templates_valid?).to be_truthy
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'returns false if config templates are invalid json' do
|
33
|
-
|
34
|
-
|
33
|
+
allow(subject).to receive(:read_config_template).and_return('@#$%#')
|
34
|
+
expect(subject.config_templates_valid?).to be_falsey
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
describe '#upload_config_templates' do
|
39
39
|
it 'raises error if any config template fails validation' do
|
40
|
-
|
40
|
+
allow(subject).to receive(:config_templates_valid?).and_return(false)
|
41
41
|
expect {
|
42
|
-
|
42
|
+
subject.upload_config_templates
|
43
43
|
}.to raise_error(Automan::Beanstalk::InvalidConfigurationTemplateError)
|
44
44
|
end
|
45
45
|
|
46
46
|
it 'uploads files if they are valid' do
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
47
|
+
allow(subject).to receive(:config_templates).and_return(%w[a b c])
|
48
|
+
allow(subject).to receive(:config_templates_valid?).and_return(true)
|
49
|
+
expect(subject).to receive(:upload_file).exactly(3).times
|
50
|
+
subject.upload_config_templates
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
@@ -21,19 +21,19 @@ describe Automan::Beanstalk::Version do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
it "is true when version exists in response" do
|
24
|
-
resp =
|
24
|
+
resp = subject.eb.stub_for :describe_application_versions
|
25
25
|
resp.data[:application_versions] = [
|
26
|
-
{application_name:
|
26
|
+
{application_name: subject.application, version_label: subject.label}
|
27
27
|
]
|
28
|
-
|
28
|
+
expect(subject.exists?).to be_truthy
|
29
29
|
end
|
30
30
|
|
31
31
|
it "is false when version is not in response" do
|
32
|
-
resp =
|
32
|
+
resp = subject.eb.stub_for :describe_application_versions
|
33
33
|
resp.data[:application_versions] = [
|
34
34
|
{application_name: '', version_label: ''}
|
35
35
|
]
|
36
|
-
|
36
|
+
expect(subject.exists?).to be_falsey
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
@@ -46,11 +46,10 @@ describe Automan::Beanstalk::Version do
|
|
46
46
|
end
|
47
47
|
|
48
48
|
it 'ignores AWS::ElasticBeanstalk::Errors::SourceBundleDeletionFailure' do
|
49
|
-
eb = double(
|
50
|
-
eb.
|
51
|
-
v.eb = eb
|
49
|
+
subject.eb = double()
|
50
|
+
allow(subject.eb).to receive(:delete_application_version).and_raise(AWS::ElasticBeanstalk::Errors::SourceBundleDeletionFailure)
|
52
51
|
expect {
|
53
|
-
|
52
|
+
subject.delete_by_label('foo')
|
54
53
|
}.not_to raise_error
|
55
54
|
end
|
56
55
|
|
@@ -17,30 +17,29 @@ describe Automan::Cloudformation::Launcher do
|
|
17
17
|
it { should respond_to :stack_update_complete? }
|
18
18
|
|
19
19
|
describe '#read_manifest' do
|
20
|
-
subject(
|
20
|
+
subject() do
|
21
21
|
AWS.stub!
|
22
|
-
|
23
|
-
s
|
22
|
+
Automan::Cloudformation::Launcher.new
|
24
23
|
end
|
25
24
|
|
26
25
|
it 'raises MissingManifestError if manifest does not exist' do
|
27
|
-
|
26
|
+
allow(subject).to receive(:manifest_exists?).and_return(false)
|
28
27
|
expect {
|
29
|
-
|
28
|
+
subject.read_manifest
|
30
29
|
}.to raise_error(Automan::Cloudformation::MissingManifestError)
|
31
30
|
end
|
32
31
|
|
33
32
|
it 'merges manifest contents into parameters hash' do
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
allow(subject).to receive(:manifest_exists?).and_return(true)
|
34
|
+
allow(subject).to receive(:s3_read).and_return('{"foo": "bar", "big": "poppa"}')
|
35
|
+
subject.parameters = {'foo'=> 'baz', 'fo'=> 'shizzle'}
|
36
|
+
subject.read_manifest
|
37
|
+
expect(subject.parameters).to eq({'foo' => 'bar', 'fo' => 'shizzle', 'big' => 'poppa'})
|
39
38
|
end
|
40
39
|
end
|
41
40
|
|
42
41
|
describe '#parse_template_parameters' do
|
43
|
-
subject(
|
42
|
+
subject() do
|
44
43
|
AWS.stub!
|
45
44
|
s = Automan::Cloudformation::Launcher.new
|
46
45
|
s.cfn = AWS::CloudFormation.new
|
@@ -49,31 +48,30 @@ describe Automan::Cloudformation::Launcher do
|
|
49
48
|
end
|
50
49
|
|
51
50
|
it "returns a hash" do
|
52
|
-
|
53
|
-
result =
|
54
|
-
result.class.
|
51
|
+
subject.template = File.join(File.dirname(__FILE__), 'templates', 'worker_role.json')
|
52
|
+
result = subject.parse_template_parameters
|
53
|
+
expect(result.class).to eq(Hash)
|
55
54
|
end
|
56
55
|
|
57
56
|
end
|
58
57
|
|
59
58
|
describe '#template_handle' do
|
60
|
-
subject(
|
59
|
+
subject() do
|
61
60
|
AWS.stub!
|
62
|
-
|
63
|
-
s
|
61
|
+
Automan::Cloudformation::Launcher.new
|
64
62
|
end
|
65
63
|
|
66
64
|
it "returns an s3 key if it is an s3 path" do
|
67
|
-
|
65
|
+
expect(subject.template_handle("s3://foo/bar/baz")).to be_a AWS::S3::S3Object
|
68
66
|
end
|
69
67
|
|
70
68
|
it "returns a string if it is a local file" do
|
71
|
-
|
69
|
+
expect(subject.template_handle(__FILE__)).to be_a String
|
72
70
|
end
|
73
71
|
end
|
74
72
|
|
75
73
|
describe '#validate_parameters' do
|
76
|
-
subject(
|
74
|
+
subject() do
|
77
75
|
AWS.stub!
|
78
76
|
s = Automan::Cloudformation::Launcher.new
|
79
77
|
s.logger = Logger.new('/dev/null')
|
@@ -82,99 +80,99 @@ describe Automan::Cloudformation::Launcher do
|
|
82
80
|
end
|
83
81
|
|
84
82
|
it "raises error if no parameters were specified" do
|
85
|
-
|
83
|
+
subject.parameters = nil
|
86
84
|
expect {
|
87
|
-
|
85
|
+
subject.validate_parameters
|
88
86
|
}.to raise_error Automan::Cloudformation::MissingParametersError
|
89
87
|
end
|
90
88
|
|
91
89
|
it "raises error if the template doesn't validate" do
|
92
|
-
|
90
|
+
allow(subject).to receive(:parse_template_parameters).and_return({code: 'foo', message: 'bar'})
|
93
91
|
expect {
|
94
|
-
|
92
|
+
subject.validate_parameters
|
95
93
|
}.to raise_error Automan::Cloudformation::BadTemplateError
|
96
94
|
end
|
97
95
|
|
98
96
|
it "raises error if a required parameter isn't present" do
|
99
|
-
|
97
|
+
allow(subject).to receive(:parse_template_parameters).and_return(parameters: [{parameter_key: 'foo'}])
|
100
98
|
expect {
|
101
|
-
|
99
|
+
subject.validate_parameters
|
102
100
|
}.to raise_error Automan::Cloudformation::MissingParametersError
|
103
101
|
end
|
104
102
|
|
105
103
|
it "raises no error if all required parameters are present" do
|
106
|
-
|
107
|
-
|
104
|
+
allow(subject).to receive(:parse_template_parameters).and_return(parameters: [{parameter_key: 'foo'}])
|
105
|
+
subject.parameters = {'foo' => 'bar'}
|
108
106
|
expect {
|
109
|
-
|
107
|
+
subject.validate_parameters
|
110
108
|
}.not_to raise_error
|
111
109
|
end
|
112
110
|
|
113
111
|
it "raises no error if there are no required parameters" do
|
114
|
-
|
112
|
+
allow(subject).to receive(:parse_template_parameters).and_return(parameters: [{parameter_key: 'foo', default_value: 'bar'}])
|
115
113
|
expect {
|
116
|
-
|
114
|
+
subject.validate_parameters
|
117
115
|
}.not_to raise_error
|
118
116
|
end
|
119
117
|
end
|
120
118
|
|
121
119
|
describe '#update' do
|
122
|
-
subject(
|
120
|
+
subject() do
|
123
121
|
AWS.stub!
|
124
122
|
s = Automan::Cloudformation::Launcher.new
|
125
123
|
s.logger = Logger.new('/dev/null')
|
126
|
-
s.
|
124
|
+
allow(s).to receive(:template_handle).and_return('foo')
|
127
125
|
s
|
128
126
|
end
|
129
127
|
|
130
128
|
it "ignores AWS::CloudFormation::Errors::ValidationError when no updates are to be performed" do
|
131
|
-
|
129
|
+
allow(subject).to receive(:update_stack).and_raise AWS::CloudFormation::Errors::ValidationError.new("No updates are to be performed.")
|
132
130
|
expect {
|
133
|
-
|
131
|
+
subject.update
|
134
132
|
}.to_not raise_error
|
135
133
|
end
|
136
134
|
|
137
135
|
it 're-raises any other ValidationError' do
|
138
|
-
|
136
|
+
allow(subject).to receive(:update_stack).and_raise AWS::CloudFormation::Errors::ValidationError.new("foo")
|
139
137
|
expect {
|
140
|
-
|
138
|
+
subject.update
|
141
139
|
}.to raise_error AWS::CloudFormation::Errors::ValidationError
|
142
140
|
end
|
143
141
|
end
|
144
142
|
|
145
143
|
describe '#launch_or_update' do
|
146
|
-
subject(
|
144
|
+
subject() do
|
147
145
|
AWS.stub!
|
148
146
|
s = Automan::Cloudformation::Launcher.new
|
149
147
|
s.logger = Logger.new('/dev/null')
|
150
|
-
s.
|
148
|
+
allow(s).to receive(:validate_parameters)
|
151
149
|
s
|
152
150
|
end
|
153
151
|
|
154
152
|
it "launches a new stack if it does not exist" do
|
155
|
-
|
156
|
-
|
157
|
-
|
153
|
+
allow(subject).to receive(:stack_exists?).and_return(false)
|
154
|
+
expect(subject).to receive(:launch)
|
155
|
+
subject.launch_or_update
|
158
156
|
end
|
159
157
|
|
160
158
|
it "updates an existing stack if update is enabled" do
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
159
|
+
allow(subject).to receive(:stack_exists?).and_return(true)
|
160
|
+
allow(subject).to receive(:enable_update).and_return(true)
|
161
|
+
expect(subject).to receive(:update)
|
162
|
+
subject.launch_or_update
|
165
163
|
end
|
166
164
|
|
167
165
|
it "raises an error when updating an existing stack w/o update enabled" do
|
168
|
-
|
169
|
-
|
166
|
+
allow(subject).to receive(:stack_exists?).and_return(true)
|
167
|
+
allow(subject).to receive(:enable_update).and_return(false)
|
170
168
|
expect {
|
171
|
-
|
169
|
+
subject.launch_or_update
|
172
170
|
}.to raise_error Automan::Cloudformation::StackExistsError
|
173
171
|
end
|
174
172
|
end
|
175
173
|
|
176
174
|
describe '#stack_launch_complete?' do
|
177
|
-
subject(
|
175
|
+
subject() do
|
178
176
|
AWS.stub!
|
179
177
|
s = Automan::Cloudformation::Launcher.new
|
180
178
|
s.logger = Logger.new('/dev/null')
|
@@ -182,35 +180,35 @@ describe Automan::Cloudformation::Launcher do
|
|
182
180
|
end
|
183
181
|
|
184
182
|
it 'returns true when the stack completes' do
|
185
|
-
|
186
|
-
|
183
|
+
allow(subject).to receive(:stack_status).and_return('CREATE_COMPLETE')
|
184
|
+
expect(subject.stack_launch_complete?).to be_truthy
|
187
185
|
end
|
188
186
|
|
189
187
|
it 'raises an error when the stack fails' do
|
190
|
-
|
188
|
+
allow(subject).to receive(:stack_status).and_return('CREATE_FAILED')
|
191
189
|
expect {
|
192
|
-
|
190
|
+
subject.stack_launch_complete?
|
193
191
|
}.to raise_error Automan::Cloudformation::StackCreationError
|
194
192
|
end
|
195
193
|
|
196
194
|
rollback_states = %w[ROLLBACK_COMPLETE ROLLBACK_FAILED ROLLBACK_IN_PROGRESS]
|
197
195
|
rollback_states.each do |state|
|
198
196
|
it "raises an error when the stack goes into #{state} state" do
|
199
|
-
|
197
|
+
allow(subject).to receive(:stack_status).and_return(state)
|
200
198
|
expect {
|
201
|
-
|
199
|
+
subject.stack_launch_complete?
|
202
200
|
}.to raise_error Automan::Cloudformation::StackCreationError
|
203
201
|
end
|
204
202
|
end
|
205
203
|
|
206
204
|
it 'returns false for any other state' do
|
207
|
-
|
208
|
-
|
205
|
+
allow(subject).to receive(:stack_status).and_return('foo')
|
206
|
+
expect(subject.stack_launch_complete?).to be_falsey
|
209
207
|
end
|
210
208
|
end
|
211
209
|
|
212
210
|
describe '#stack_update_complete?' do
|
213
|
-
subject(
|
211
|
+
subject() do
|
214
212
|
AWS.stub!
|
215
213
|
s = Automan::Cloudformation::Launcher.new
|
216
214
|
s.logger = Logger.new('/dev/null')
|
@@ -218,23 +216,23 @@ describe Automan::Cloudformation::Launcher do
|
|
218
216
|
end
|
219
217
|
|
220
218
|
it 'returns true when the stack completes' do
|
221
|
-
|
222
|
-
|
219
|
+
allow(subject).to receive(:stack_status).and_return('UPDATE_COMPLETE')
|
220
|
+
expect(subject.stack_update_complete?).to be_truthy
|
223
221
|
end
|
224
222
|
|
225
223
|
rollback_states = %w[UPDATE_ROLLBACK_COMPLETE UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS UPDATE_ROLLBACK_FAILED UPDATE_ROLLBACK_IN_PROGRESS]
|
226
224
|
rollback_states.each do |state|
|
227
225
|
it "raises an error when the stack enters #{state} state" do
|
228
|
-
|
226
|
+
allow(subject).to receive(:stack_status).and_return(state)
|
229
227
|
expect {
|
230
|
-
|
228
|
+
subject.stack_update_complete?
|
231
229
|
}.to raise_error Automan::Cloudformation::StackUpdateError
|
232
230
|
end
|
233
231
|
end
|
234
232
|
|
235
233
|
it 'returns false for any other state' do
|
236
|
-
|
237
|
-
|
234
|
+
allow(subject).to receive(:stack_status).and_return('foo')
|
235
|
+
expect(subject.stack_update_complete?).to be_falsey
|
238
236
|
end
|
239
237
|
end
|
240
238
|
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
require 'automan'
|
2
2
|
|
3
3
|
describe Automan::Cloudformation::Replacer do
|
4
|
-
it {
|
5
|
-
it {
|
6
|
-
it {
|
7
|
-
it {
|
4
|
+
it { is_expected.to respond_to :name }
|
5
|
+
it { is_expected.to respond_to :replace_instances }
|
6
|
+
it { is_expected.to respond_to :ok_to_replace_instances? }
|
7
|
+
it { is_expected.to respond_to :stack_exists? }
|
8
8
|
|
9
9
|
describe '#ok_to_replace_instances?' do
|
10
|
-
subject(
|
10
|
+
subject() do
|
11
11
|
AWS.stub!
|
12
|
-
|
12
|
+
Automan::Cloudformation::Replacer.new
|
13
13
|
end
|
14
14
|
|
15
15
|
good_states = %w[UPDATE_COMPLETE]
|
@@ -30,28 +30,28 @@ describe Automan::Cloudformation::Replacer do
|
|
30
30
|
|
31
31
|
good_states.each do |state|
|
32
32
|
it "returns true when stack is in the right state (state: #{state})" do
|
33
|
-
|
33
|
+
expect(subject.ok_to_replace_instances?(state, Time.now)).to be_truthy
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
37
|
good_states.each do |state|
|
38
38
|
it "returns false when stack is in the right state but has not been updated in the last 5m" do
|
39
39
|
last_updated = Time.now - (5 * 60 + 1)
|
40
|
-
|
40
|
+
expect(subject.ok_to_replace_instances?(state, last_updated)).to be_falsey
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
44
|
bad_states.each do |state|
|
45
45
|
it "raises error when stack is borked (state: #{state})" do
|
46
46
|
expect {
|
47
|
-
|
47
|
+
subject.ok_to_replace_instances?(state, Time.now)
|
48
48
|
}.to raise_error Automan::Cloudformation::StackBrokenError
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
52
|
wait_states.each do |state|
|
53
53
|
it "returns false when it is not yet ok to replace (state: #{state})" do
|
54
|
-
|
54
|
+
expect(subject.ok_to_replace_instances?(state, Time.now)).to be_falsey
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|