eb_deployer 0.3.8 → 0.3.9
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 +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
|