eb_deployer 0.3.8 → 0.3.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/CHANGELOG.md +5 -0
- data/lib/eb_deployer/application.rb +0 -1
- data/lib/eb_deployer/config_loader.rb +1 -0
- data/lib/eb_deployer/deployment_strategy/blue_green.rb +11 -11
- data/lib/eb_deployer/eb_environment.rb +23 -23
- data/lib/eb_deployer/event_poller.rb +9 -9
- data/lib/eb_deployer/version.rb +1 -1
- data/lib/eb_deployer.rb +5 -3
- data/test/aws_driver_stubs.rb +21 -8
- data/test/blue_green_deploy_test.rb +106 -0
- data/test/config_loader_test.rb +13 -0
- data/test/deploy_test.rb +1 -444
- data/test/eb_environment_test.rb +61 -6
- data/test/inplace_update_deploy_test.rb +85 -0
- data/test/legacy_env_migrate_deploy_test.rb +94 -0
- data/test/resources_deploy_test.rb +122 -0
- data/test/tier_setting_deploy_test.rb +19 -0
- data/test/versions_deploy_test.rb +120 -0
- metadata +30 -16
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZTFkZGMyNGQ3YTg2ZjRjMGM1ZTE0OGIwMDk5ZTQ0ZDgwY2MyMWJhNw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YmZkZmQ3MTFiZDQ2YjQxMjg4OWM0NWZmMzk3MzZiOTY2YmM5MzdlZQ==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YTAxZjdhNmEwZTcwMjYyNzA2MzY1Zjg5ZDM2ZDhiNmQzN2M1Y2M0Mjk0ZjQy
|
10
|
+
YTczYzEzNDQ1ODAxMTkwOTVlZTc5YmQwZDkxN2JkY2IwNmVmY2U4MWUzMzEx
|
11
|
+
Y2JlMGJjMmI3ZTJiZjQ1OWM5Yzk3NTcyMTdlNmMzMDYyMGY5NjE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZTE5MjFiODhmNjA0MjFmNmQyMTJhMmYwMWRiYjM1ODdlNWYyOWMxYzExZTZi
|
14
|
+
OTY1ZmI2ZjkyMjA5ZGM0NTQzMTQ1MTkwZjI3MjY5N2UyOTQyNjRiZTc2OTk3
|
15
|
+
ZWVmNDQxNTcxNDk5ZTljMGE5YjdlMDZiM2M4NmQxMmMxYjVjNDM=
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
0.3.9
|
2
|
+
====
|
3
|
+
* Fix hang problem introduced in 0.3.8 when migrating old ElasticBeanstalk environment.
|
4
|
+
* Fix issue #13 (Deployment via S3 object broken since 0.3.7)
|
5
|
+
|
1
6
|
0.3.8
|
2
7
|
=====
|
3
8
|
* Change ElasticBeanstalk environment name pattern. Stop using sufix hash to make eb environment global unique. (Because ElasticBeanstalk does not require environment has globally uniqe name any more.)
|
@@ -36,7 +36,6 @@ module EbDeployer
|
|
36
36
|
|
37
37
|
def delete(env_name=nil)
|
38
38
|
if @eb_driver.application_exists?(@name)
|
39
|
-
env_name = EbEnvironment.unique_ebenv_name(@name, env_name) unless env_name.nil?
|
40
39
|
available_envs = @eb_driver.environment_names_for_application(@name)
|
41
40
|
|
42
41
|
unless env_name.nil? || available_envs.include?(env_name)
|
@@ -6,29 +6,29 @@ module EbDeployer
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def deploy(version_label, env_settings)
|
9
|
-
if !
|
10
|
-
|
9
|
+
if !ebenvs.any?(&method(:active_ebenv?))
|
10
|
+
ebenv('a', @env.cname_prefix).
|
11
11
|
deploy(version_label, env_settings)
|
12
12
|
return
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
active_ebenv = ebenvs.detect(&method(:active_ebenv?))
|
16
|
+
inactive_ebenv = ebenvs.reject(&method(:active_ebenv?)).first
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
inactive_ebenv.deploy(version_label, env_settings)
|
19
|
+
active_ebenv.swap_cname_with(inactive_ebenv)
|
20
20
|
end
|
21
21
|
|
22
22
|
private
|
23
|
-
def
|
24
|
-
|
23
|
+
def active_ebenv?(ebenv)
|
24
|
+
ebenv.cname_prefix == @env.cname_prefix
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
[
|
27
|
+
def ebenvs
|
28
|
+
[ebenv('a'), ebenv('b')]
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
31
|
+
def ebenv(suffix, cname_prefix=nil)
|
32
32
|
@env.new_eb_env(suffix, cname_prefix || inactive_cname_prefix)
|
33
33
|
end
|
34
34
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module EbDeployer
|
2
2
|
class EbEnvironment
|
3
|
-
attr_reader :app, :name
|
3
|
+
attr_reader :app, :name, :legacy_env_name
|
4
4
|
attr_writer :event_poller
|
5
5
|
|
6
6
|
def self.legacy_ebenv_name(app_name, env_name)
|
@@ -13,6 +13,7 @@ module EbDeployer
|
|
13
13
|
@name = name
|
14
14
|
@bs = eb_driver
|
15
15
|
@creation_opts = creation_opts
|
16
|
+
@legacy_env_name = self.class.legacy_ebenv_name(@app, @name)
|
16
17
|
end
|
17
18
|
|
18
19
|
def deploy(version_label, settings={})
|
@@ -24,16 +25,12 @@ module EbDeployer
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def cname_prefix
|
27
|
-
@bs.environment_cname_prefix(@app,
|
28
|
-
end
|
29
|
-
|
30
|
-
def ==(another)
|
31
|
-
self.app == another.app && self.name == another.name
|
28
|
+
@bs.environment_cname_prefix(@app, defactor_env_name)
|
32
29
|
end
|
33
30
|
|
34
31
|
def swap_cname_with(another)
|
35
32
|
log("Swap CNAME with env #{another.name}")
|
36
|
-
@bs.environment_swap_cname(self.app, self.
|
33
|
+
@bs.environment_swap_cname(self.app, self.defactor_env_name, another.defactor_env_name)
|
37
34
|
end
|
38
35
|
|
39
36
|
def log(msg)
|
@@ -41,34 +38,37 @@ module EbDeployer
|
|
41
38
|
end
|
42
39
|
|
43
40
|
def terminate
|
44
|
-
|
41
|
+
env_name = defactor_env_name
|
42
|
+
if @bs.environment_exists?(@app, env_name)
|
43
|
+
with_polling_events(env_name, /terminateEnvironment completed successfully/i) do
|
44
|
+
@bs.delete_environment(@app, env_name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def defactor_env_name
|
50
|
+
@bs.environment_exists?(@app, @legacy_env_name) ? @legacy_env_name : @name
|
45
51
|
end
|
46
52
|
|
47
53
|
private
|
48
54
|
|
49
55
|
def terminate_legacy_env
|
50
|
-
|
51
|
-
|
52
|
-
log("Found legacy environment '#{legacy_env_name}', eb_deployer will terminate it and create new environment following new name pattern.")
|
53
|
-
terminate_environment(legacy_env_name)
|
54
|
-
end
|
55
|
-
end
|
56
|
+
if @bs.environment_exists?(@app, @legacy_env_name)
|
57
|
+
log("Found legacy environment '#{@legacy_env_name}', eb_deployer will terminate it and create new environment following new name pattern as '#{@name}'.")
|
56
58
|
|
57
|
-
|
58
|
-
|
59
|
-
with_polling_events(/terminateEnvironment completed successfully/i) do
|
60
|
-
@bs.delete_environment(@app, env_name)
|
59
|
+
with_polling_events(@legacy_env_name, /terminateEnvironment completed successfully/i) do
|
60
|
+
@bs.delete_environment(@app, @legacy_env_name)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
65
|
def create_or_update_env(version_label, settings)
|
66
66
|
if @bs.environment_exists?(@app, @name)
|
67
|
-
with_polling_events(/Environment update completed successfully/i) do
|
67
|
+
with_polling_events(@name, /Environment update completed successfully/i) do
|
68
68
|
@bs.update_environment(@app, @name, version_label, @creation_opts[:tier], settings)
|
69
69
|
end
|
70
70
|
else
|
71
|
-
with_polling_events(/Successfully launched environment/i) do
|
71
|
+
with_polling_events(@name, /Successfully launched environment/i) do
|
72
72
|
@bs.create_environment(@app, @name, @creation_opts[:solution_stack], @creation_opts[:cname_prefix], version_label, @creation_opts[:tier], settings)
|
73
73
|
end
|
74
74
|
end
|
@@ -79,10 +79,10 @@ module EbDeployer
|
|
79
79
|
SmokeTest.new(@creation_opts[:smoke_test]).run(host_name, self)
|
80
80
|
end
|
81
81
|
|
82
|
-
def with_polling_events(terminate_pattern, &block)
|
82
|
+
def with_polling_events(env_name, terminate_pattern, &block)
|
83
83
|
event_start_time = Time.now
|
84
84
|
yield
|
85
|
-
event_poller.poll(event_start_time) do |event|
|
85
|
+
event_poller.poll(env_name, event_start_time) do |event|
|
86
86
|
if event[:message] =~ /Failed to deploy application/
|
87
87
|
raise event[:message]
|
88
88
|
end
|
@@ -111,7 +111,7 @@ module EbDeployer
|
|
111
111
|
end
|
112
112
|
|
113
113
|
def event_poller
|
114
|
-
@event_poller || EventPoller.new(@app, @
|
114
|
+
@event_poller || EventPoller.new(@app, @bs)
|
115
115
|
end
|
116
116
|
|
117
117
|
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module EbDeployer
|
2
2
|
class EventPoller
|
3
|
-
def initialize(app,
|
4
|
-
@app, @
|
3
|
+
def initialize(app, beanstalk)
|
4
|
+
@app, @beanstalk = app, beanstalk
|
5
5
|
end
|
6
6
|
|
7
|
-
def poll(start_time = Time.now, &block)
|
7
|
+
def poll(eb_env_name, start_time = Time.now, &block)
|
8
8
|
handled = Set.new
|
9
9
|
loop do
|
10
|
-
fetch_events(start_time) do |events|
|
10
|
+
fetch_events(eb_env_name, start_time) do |events|
|
11
11
|
new_events = events.reject { |e| handled.include?(digest(e)) }
|
12
12
|
handle(new_events, &block)
|
13
13
|
handled += new_events.map { |e| digest(e) }
|
@@ -27,14 +27,14 @@ module EbDeployer
|
|
27
27
|
events.reverse.each(&block)
|
28
28
|
end
|
29
29
|
|
30
|
-
def fetch_events(start_time, &block)
|
31
|
-
events, next_token = @beanstalk.fetch_events(@app,
|
30
|
+
def fetch_events(eb_env_name, start_time, &block)
|
31
|
+
events, next_token = @beanstalk.fetch_events(@app, eb_env_name, :start_time => start_time.iso8601)
|
32
32
|
yield(events)
|
33
|
-
fetch_next(next_token, &block) if next_token
|
33
|
+
fetch_next(eb_env_name, next_token, &block) if next_token
|
34
34
|
end
|
35
35
|
|
36
|
-
def fetch_next(next_token, &block)
|
37
|
-
events, next_token = @beanstalk.fetch_events(@app,
|
36
|
+
def fetch_next(eb_env_name, next_token, &block)
|
37
|
+
events, next_token = @beanstalk.fetch_events(@app, eb_env_name, :next_token => next_token)
|
38
38
|
yield(events)
|
39
39
|
fetch_next(next_token, &block) if next_token
|
40
40
|
end
|
data/lib/eb_deployer/version.rb
CHANGED
data/lib/eb_deployer.rb
CHANGED
@@ -223,9 +223,10 @@ module EbDeployer
|
|
223
223
|
end
|
224
224
|
|
225
225
|
app = opts[:application]
|
226
|
-
bs = opts[:bs_driver] || Beanstalk.new
|
227
|
-
s3 = opts[:s3_driver] || S3Driver.new
|
228
|
-
cf = opts[:cf_driver] || CloudFormationDriver.new
|
226
|
+
bs = opts[:bs_driver] || AWSDriver::Beanstalk.new
|
227
|
+
s3 = opts[:s3_driver] || AWSDriver::S3Driver.new
|
228
|
+
cf = opts[:cf_driver] || AWSDriver::CloudFormationDriver.new
|
229
|
+
|
229
230
|
Application.new(app, bs, s3).delete(opts[:environment])
|
230
231
|
end
|
231
232
|
|
@@ -308,6 +309,7 @@ module EbDeployer
|
|
308
309
|
puts "YAML package file format:"
|
309
310
|
puts "s3_bucket: <bucket_name>"
|
310
311
|
puts "s3_key: <object_path>"
|
312
|
+
exit(0)
|
311
313
|
end
|
312
314
|
end
|
313
315
|
end
|
data/test/aws_driver_stubs.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
class EBStub
|
2
|
+
attr_reader :envs
|
2
3
|
def initialize
|
3
4
|
@apps = []
|
4
5
|
@envs = {}
|
@@ -78,16 +79,16 @@ class EBStub
|
|
78
79
|
end
|
79
80
|
|
80
81
|
def fetch_events(app_name, env_name, options={})
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
nil]
|
82
|
+
unless @events # unrestricted mode for testing if no explicit events set
|
83
|
+
return generate_event_from_messages(['Environment update completed successfully',
|
84
|
+
'terminateEnvironment completed successfully',
|
85
|
+
'Successfully launched environment'])
|
86
|
+
end
|
87
|
+
|
88
|
+
@events[env_key(app_name, env_name)]
|
89
89
|
end
|
90
90
|
|
91
|
+
|
91
92
|
def environment_cname_prefix(app_name, env_name)
|
92
93
|
return unless @envs[env_key(app_name, env_name)]
|
93
94
|
@envs[env_key(app_name, env_name)][:cname_prefix] || app_name + "-" + SecureRandom.hex
|
@@ -140,8 +141,20 @@ class EBStub
|
|
140
141
|
@versions_deleted[app_name]
|
141
142
|
end
|
142
143
|
|
144
|
+
def set_events(app_name, env_name, messages)
|
145
|
+
@events ||= {}
|
146
|
+
@events[env_key(app_name, env_name)] = generate_event_from_messages(messages)
|
147
|
+
end
|
148
|
+
|
143
149
|
private
|
144
150
|
|
151
|
+
def generate_event_from_messages(messages)
|
152
|
+
[messages.reverse.map do |m|
|
153
|
+
{:event_date => Time.now.utc,
|
154
|
+
:message => m}
|
155
|
+
end, nil]
|
156
|
+
end
|
157
|
+
|
145
158
|
def env_key(app, name)
|
146
159
|
[app, name].join("-")
|
147
160
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'deploy_test'
|
2
|
+
|
3
|
+
class BlueGreenDeployTest < DeployTest
|
4
|
+
def test_blue_green_deployment_strategy_should_create_blue_env_on_first_deployment
|
5
|
+
deploy(:application => 'simple',
|
6
|
+
:environment => "production",
|
7
|
+
:strategy => 'blue-green',
|
8
|
+
:version_label => 42)
|
9
|
+
|
10
|
+
assert @eb_driver.environment_exists?('simple', 'production-a')
|
11
|
+
assert_equal 'simple-production', @eb_driver.environment_cname_prefix('simple', 'production-a')
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def test_blue_green_deployment_should_create_green_env_if_blue_exists
|
16
|
+
deploy(:application => 'simple',
|
17
|
+
:environment => "production",
|
18
|
+
:strategy => 'blue-green',
|
19
|
+
:version_label => 42)
|
20
|
+
|
21
|
+
deploy(:application => 'simple',
|
22
|
+
:environment => "production",
|
23
|
+
:strategy => 'blue-green',
|
24
|
+
:version_label => 43)
|
25
|
+
|
26
|
+
assert @eb_driver.environment_exists?('simple', 'production-a')
|
27
|
+
assert @eb_driver.environment_exists?('simple', 'production-b')
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def test_blue_green_deployment_should_swap_cname_to_make_active_most_recent_updated_env
|
32
|
+
deploy(:application => 'simple',
|
33
|
+
:environment => "production",
|
34
|
+
:strategy => 'blue-green',
|
35
|
+
:version_label => 42)
|
36
|
+
|
37
|
+
deploy(:application => 'simple',
|
38
|
+
:environment => "production",
|
39
|
+
:strategy => 'blue-green',
|
40
|
+
:version_label => 43)
|
41
|
+
|
42
|
+
assert_match(/simple-production-inactive/, @eb_driver.environment_cname_prefix('simple', 'production-a'))
|
43
|
+
|
44
|
+
assert_equal 'simple-production', @eb_driver.environment_cname_prefix('simple', 'production-b')
|
45
|
+
|
46
|
+
|
47
|
+
deploy(:application => 'simple',
|
48
|
+
:environment => "production",
|
49
|
+
:strategy => 'blue-green',
|
50
|
+
:version_label => 44)
|
51
|
+
|
52
|
+
assert_match(/simple-production-inactive/, @eb_driver.environment_cname_prefix('simple', 'production-b'))
|
53
|
+
|
54
|
+
assert_equal 'simple-production', @eb_driver.environment_cname_prefix('simple', 'production-a')
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def test_blue_green_deploy_should_run_smoke_test_before_cname_switch
|
59
|
+
smoked_host = []
|
60
|
+
smoke_test = lambda { |host| smoked_host << host }
|
61
|
+
[42, 43, 44].each do |version_label|
|
62
|
+
deploy(:application => 'simple',
|
63
|
+
:environment => "production",
|
64
|
+
:strategy => 'blue-green',
|
65
|
+
:smoke_test => smoke_test,
|
66
|
+
:version_label => version_label)
|
67
|
+
end
|
68
|
+
|
69
|
+
assert_equal ['simple-production.elasticbeanstalk.com',
|
70
|
+
'simple-production-inactive.elasticbeanstalk.com',
|
71
|
+
'simple-production-inactive.elasticbeanstalk.com'], smoked_host
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def test_blue_green_deployment_should_delete_and_recreate_inactive_env_if_phoenix_mode_is_enabled
|
76
|
+
deploy(:application => 'simple',
|
77
|
+
:environment => "production",
|
78
|
+
:strategy => 'blue-green',
|
79
|
+
:version_label => 42,
|
80
|
+
:phoenix_mode => true)
|
81
|
+
|
82
|
+
deploy(:application => 'simple',
|
83
|
+
:environment => "production",
|
84
|
+
:strategy => 'blue-green',
|
85
|
+
:version_label => 43,
|
86
|
+
:phoenix_mode => true)
|
87
|
+
|
88
|
+
assert_equal [], @eb_driver.environments_been_deleted('simple')
|
89
|
+
|
90
|
+
inactive_env = 'production-a'
|
91
|
+
assert_match(/inactive/, @eb_driver.environment_cname_prefix('simple', inactive_env))
|
92
|
+
|
93
|
+
|
94
|
+
deploy(:application => 'simple',
|
95
|
+
:environment => "production",
|
96
|
+
:strategy => 'blue-green',
|
97
|
+
:version_label => 44,
|
98
|
+
:phoenix_mode => true)
|
99
|
+
|
100
|
+
assert_equal [inactive_env], @eb_driver.environments_been_deleted('simple')
|
101
|
+
|
102
|
+
assert_equal 'simple-production', @eb_driver.environment_cname_prefix('simple', inactive_env)
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
end
|
data/test/config_loader_test.rb
CHANGED
@@ -25,6 +25,19 @@ YAML
|
|
25
25
|
assert_equal(nil, config[:common])
|
26
26
|
end
|
27
27
|
|
28
|
+
def test_use_package_as_version_label_when_using_s3_obj_as_package
|
29
|
+
config = @loader.load(generate_input(<<-YAML, :package => 'bucket:obj'))
|
30
|
+
application: myapp
|
31
|
+
common:
|
32
|
+
strategy: inplace-update
|
33
|
+
environments:
|
34
|
+
dev:
|
35
|
+
YAML
|
36
|
+
assert_equal('myapp', config[:application])
|
37
|
+
assert_equal('bucket:obj', config[:package])
|
38
|
+
assert_equal('bucket:obj', config[:version_label])
|
39
|
+
end
|
40
|
+
|
28
41
|
def test_common_settings_get_merge_into_the_config
|
29
42
|
config = @loader.load(generate_input(<<-YAML))
|
30
43
|
application: myapp
|