automan 2.3.1 → 2.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|