eb_deployer 0.3.1 → 0.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 +7 -0
- data/lib/eb_deployer.rb +7 -2
- data/lib/eb_deployer/application.rb +1 -1
- data/lib/eb_deployer/default_config.yml +2 -3
- data/lib/eb_deployer/environment.rb +17 -12
- data/lib/eb_deployer/version.rb +1 -1
- data/test/aws_driver_stubs.rb +9 -3
- data/test/deploy_test.rb +11 -5
- data/test/environment_test.rb +83 -0
- data/test/test_helper.rb +5 -0
- metadata +14 -17
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8ff8dea9ecf894a081eabd4d8e790706b7f6f699
|
4
|
+
data.tar.gz: 32fb41ec3baa8c2a40d73cf7a7c69820a645bbc5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 52589f810e24608c3978a47eadfe5d8a1cd759c025418ea0af29553accabcc0c9ed796b59026e01d6b3083bfd5205f15a5d0b484f5a97352caac7edac0f813de
|
7
|
+
data.tar.gz: ca45f1540987043188a8746ce510c59e6c9dd4f466506f9202b87d557875018a0506349d23b689a8d8d54994ca901bf6c3a853525f31a0a68961054f22b59c8e
|
data/lib/eb_deployer.rb
CHANGED
@@ -34,7 +34,6 @@ module EbDeployer
|
|
34
34
|
# @option opts [Symbol] :region AWS Region (e.g. "us-west-2", "us-east-1")
|
35
35
|
#
|
36
36
|
def self.query_resource_output(key, opts)
|
37
|
-
# AWS.config(:logger => Logger.new($stdout))
|
38
37
|
if region = opts[:region]
|
39
38
|
AWS.config(:region => region)
|
40
39
|
end
|
@@ -162,7 +161,6 @@ module EbDeployer
|
|
162
161
|
# If specified as zero or not specified, all versions will be kept. If a
|
163
162
|
# version_prefix is given, only removes version starting with the prefix.
|
164
163
|
def self.deploy(opts)
|
165
|
-
# AWS.config(:logger => Logger.new($stdout))
|
166
164
|
if region = opts[:region]
|
167
165
|
AWS.config(:region => region)
|
168
166
|
end
|
@@ -278,6 +276,13 @@ module EbDeployer
|
|
278
276
|
exit(0)
|
279
277
|
end
|
280
278
|
|
279
|
+
opts.on("--debug", "Output AWS debug log") do |d|
|
280
|
+
require 'logger'
|
281
|
+
logger = Logger.new($stdout)
|
282
|
+
logger.level = Logger::DEBUG
|
283
|
+
AWS.config(:logger => logger)
|
284
|
+
end
|
285
|
+
|
281
286
|
opts.on("-h", "--help", "help") do
|
282
287
|
puts opts
|
283
288
|
puts ""
|
@@ -11,7 +11,7 @@ module EbDeployer
|
|
11
11
|
def create_version(version_label, package)
|
12
12
|
create_application_if_not_exists
|
13
13
|
|
14
|
-
source_bundle = if package
|
14
|
+
source_bundle = if File.extname(package) == '.yml'
|
15
15
|
YAML.load(File.read(package))
|
16
16
|
else
|
17
17
|
package = Package.new(package, @bucket + ".packages", @s3_driver)
|
@@ -102,9 +102,8 @@ common:
|
|
102
102
|
# keys:
|
103
103
|
# template => CloudFormation template file with JSON format
|
104
104
|
# inputs => A Hash, input values for the CloudFormation template
|
105
|
-
# outputs => A Hash with key map to your CloudFormation
|
106
|
-
#
|
107
|
-
# :capabilities => An array. You need set it to ['CAPABILITY_IAM'] if the
|
105
|
+
# outputs => A Hash with key map to your CloudFormation template outputs and value as elastic beanstalk settings namespace and option_name.
|
106
|
+
# capabilities => An array. You need set it to ['CAPABILITY_IAM'] if the
|
108
107
|
# template include IAM Instance Profile.
|
109
108
|
resources:
|
110
109
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module EbDeployer
|
2
2
|
class Environment
|
3
3
|
attr_reader :app, :name
|
4
|
+
attr_writer :event_poller
|
4
5
|
|
5
6
|
def self.unique_ebenv_name(app_name, env_name)
|
6
7
|
raise "Environment name #{env_name} is too long, it must be under 15 chars" if env_name.size > 15
|
@@ -15,7 +16,7 @@ module EbDeployer
|
|
15
16
|
@creation_opts = creation_opts
|
16
17
|
end
|
17
18
|
|
18
|
-
def deploy(version_label, settings)
|
19
|
+
def deploy(version_label, settings={})
|
19
20
|
terminate if @creation_opts[:phoenix_mode]
|
20
21
|
create_or_update_env(version_label, settings)
|
21
22
|
smoke_test
|
@@ -39,15 +40,6 @@ module EbDeployer
|
|
39
40
|
puts "[#{Time.now.utc}][environment:#{@name}] #{msg}"
|
40
41
|
end
|
41
42
|
|
42
|
-
private
|
43
|
-
|
44
|
-
def shorten(str, max_length, digest_length=5)
|
45
|
-
raise "max length (#{max_length}) should be larger than digest_length (#{digest_length})" if max_length < digest_length
|
46
|
-
return self if str.size <= max_length
|
47
|
-
sha1 = Digest::SHA1.hexdigest(str)
|
48
|
-
sha1[0..(digest_length - 1)] + str[(max_length - digest_length - 1)..-1]
|
49
|
-
end
|
50
|
-
|
51
43
|
def terminate
|
52
44
|
if @bs.environment_exists?(@app, @name)
|
53
45
|
with_polling_events(/terminateEnvironment completed successfully/i) do
|
@@ -56,6 +48,9 @@ module EbDeployer
|
|
56
48
|
end
|
57
49
|
end
|
58
50
|
|
51
|
+
|
52
|
+
private
|
53
|
+
|
59
54
|
def create_or_update_env(version_label, settings)
|
60
55
|
if @bs.environment_exists?(@app, @name)
|
61
56
|
with_polling_events(/Environment update completed successfully/i) do
|
@@ -76,8 +71,14 @@ module EbDeployer
|
|
76
71
|
def with_polling_events(terminate_pattern, &block)
|
77
72
|
event_start_time = Time.now
|
78
73
|
yield
|
79
|
-
|
80
|
-
|
74
|
+
event_poller.poll(event_start_time) do |event|
|
75
|
+
if event[:message] =~ /Failed to deploy application/
|
76
|
+
raise event[:message]
|
77
|
+
end
|
78
|
+
|
79
|
+
if event[:message] =~ /Command failed on instance/
|
80
|
+
raise "Elasticbeanstalk instance provision failed (maybe a problem with your .ebextension files). The original message: #{event[:message]}"
|
81
|
+
end
|
81
82
|
|
82
83
|
log_event(event)
|
83
84
|
break if event[:message] =~ terminate_pattern
|
@@ -98,6 +99,10 @@ module EbDeployer
|
|
98
99
|
end
|
99
100
|
end
|
100
101
|
|
102
|
+
def event_poller
|
103
|
+
@event_poller || EventPoller.new(@app, @name, @bs)
|
104
|
+
end
|
105
|
+
|
101
106
|
|
102
107
|
def log_event(event)
|
103
108
|
puts "[#{event[:event_date]}][environment:#{@name}] #{event[:message]}"
|
data/lib/eb_deployer/version.rb
CHANGED
data/test/aws_driver_stubs.rb
CHANGED
@@ -26,6 +26,7 @@ class EBStub
|
|
26
26
|
raise "env name #{env} is longer than 23 chars" if env.size > 23
|
27
27
|
raise "app not exists" unless application_exists?(app)
|
28
28
|
@envs[env_key(app, env)] = {
|
29
|
+
:name => env,
|
29
30
|
:application => app,
|
30
31
|
:solution_stack => solution_stack,
|
31
32
|
:version => version,
|
@@ -34,7 +35,7 @@ class EBStub
|
|
34
35
|
end
|
35
36
|
|
36
37
|
def delete_environment(app, env)
|
37
|
-
@envs.delete(env)
|
38
|
+
@envs.delete(env_key(app, env))
|
38
39
|
@envs_been_deleted[app] ||= []
|
39
40
|
@envs_been_deleted[app] << env
|
40
41
|
end
|
@@ -119,8 +120,8 @@ class EBStub
|
|
119
120
|
|
120
121
|
def environment_names_for_application(app)
|
121
122
|
@envs.inject([]) do |memo, pair|
|
122
|
-
|
123
|
-
memo <<
|
123
|
+
key, env = pair
|
124
|
+
memo << env[:name] if env[:application] == app
|
124
125
|
memo
|
125
126
|
end
|
126
127
|
end
|
@@ -154,6 +155,10 @@ class S3Stub
|
|
154
155
|
@buckets.has_key?(bucket_name)
|
155
156
|
end
|
156
157
|
|
158
|
+
def objects(bucket_name)
|
159
|
+
@buckets[bucket_name]
|
160
|
+
end
|
161
|
+
|
157
162
|
def object_length(bucket_name, obj_name)
|
158
163
|
@buckets[bucket_name][obj_name] && File.size(@buckets[bucket_name][obj_name])
|
159
164
|
end
|
@@ -161,6 +166,7 @@ class S3Stub
|
|
161
166
|
def upload_file(bucket_name, obj_name, file)
|
162
167
|
@buckets[bucket_name][obj_name] = file
|
163
168
|
end
|
169
|
+
|
164
170
|
end
|
165
171
|
|
166
172
|
class CFStub
|
data/test/deploy_test.rb
CHANGED
@@ -392,6 +392,17 @@ class DeployTest < MiniTest::Unit::TestCase
|
|
392
392
|
assert_equal 'simple-production', @eb_driver.environment_cname_prefix('simple', inactive_env)
|
393
393
|
end
|
394
394
|
|
395
|
+
def test_pass_pathname_as_package_file
|
396
|
+
deploy(:package => Pathname.new(@sample_package),
|
397
|
+
:application => 'simple',
|
398
|
+
:environment => "production",
|
399
|
+
:package_bucket => 'thoughtworks.simple')
|
400
|
+
|
401
|
+
s3_objects = @s3_driver.objects('thoughtworks.simple.packages')
|
402
|
+
assert_equal 1, s3_objects.size
|
403
|
+
assert_equal @sample_package, s3_objects.values.first.to_s
|
404
|
+
end
|
405
|
+
|
395
406
|
private
|
396
407
|
|
397
408
|
def temp_file(content)
|
@@ -400,10 +411,6 @@ class DeployTest < MiniTest::Unit::TestCase
|
|
400
411
|
f
|
401
412
|
end
|
402
413
|
|
403
|
-
def eb_envname(app_name, env_name)
|
404
|
-
EbDeployer::Environment.unique_ebenv_name(app_name, env_name)
|
405
|
-
end
|
406
|
-
|
407
414
|
def query_resource_output(key, opts)
|
408
415
|
EbDeployer.query_resource_output(key, {:bs_driver => @eb_driver,
|
409
416
|
:s3_driver => @s3_driver,
|
@@ -420,7 +427,6 @@ class DeployTest < MiniTest::Unit::TestCase
|
|
420
427
|
EbDeployer.destroy(opts.merge(stubs))
|
421
428
|
end
|
422
429
|
|
423
|
-
|
424
430
|
def stubs
|
425
431
|
{ :bs_driver => @eb_driver,
|
426
432
|
:s3_driver => @s3_driver,
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class EnvironmentTest < MiniTest::Unit::TestCase
|
4
|
+
class PollerStub
|
5
|
+
class Deadloop < StandardError; end
|
6
|
+
|
7
|
+
def initialize(messages)
|
8
|
+
start_time = Time.now.utc
|
9
|
+
@events = messages.map do |message|
|
10
|
+
start_time += 1
|
11
|
+
{:event_date => start_time, :message => message}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def poll(start_time = Time.now, &block)
|
17
|
+
@events.each(&block)
|
18
|
+
raise Deadloop.new('poll will never terminate if you do not set a break in the block')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def setup
|
23
|
+
@eb_driver = EBStub.new
|
24
|
+
@eb_driver.create_application("myapp")
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_deploy_should_create_corresponding_eb_env
|
28
|
+
env = EbDeployer::Environment.new("myapp", "production", @eb_driver)
|
29
|
+
env.deploy("version1")
|
30
|
+
assert @eb_driver.environment_exists?('myapp', eb_envname('myapp', 'production'))
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_deploy_again_should_update_environment
|
34
|
+
env = EbDeployer::Environment.new("myapp", "production", @eb_driver)
|
35
|
+
env.deploy("version1")
|
36
|
+
env.deploy("version2")
|
37
|
+
assert @eb_driver.environment_exists?('myapp', eb_envname('myapp', 'production'))
|
38
|
+
assert_equal 'version2', @eb_driver.environment_verion_label('myapp', eb_envname('myapp', 'production'))
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_option_setttings_get_set_on_eb_env
|
42
|
+
env = EbDeployer::Environment.new("myapp", "production", @eb_driver)
|
43
|
+
env.deploy("version1", {s1: 'v1'})
|
44
|
+
assert_equal({s1: 'v1' }, @eb_driver.environment_settings('myapp', eb_envname('myapp', 'production')))
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_should_run_smoke_test_after_deploy
|
48
|
+
smoked_host = nil
|
49
|
+
env = EbDeployer::Environment.new("myapp", "production", @eb_driver, :smoke_test => Proc.new { |host| smoked_host = host })
|
50
|
+
env.deploy("version1")
|
51
|
+
|
52
|
+
assert !smoked_host.nil?
|
53
|
+
assert_match( /myapp.*\.elasticbeanstalk\.com/, smoked_host)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_should_raise_runtime_error_when_deploy_failed
|
57
|
+
env = EbDeployer::Environment.new("myapp", "production", @eb_driver)
|
58
|
+
env.event_poller = PollerStub.new(["start deploying", "Failed to deploy application"])
|
59
|
+
assert_raises(RuntimeError) { env.deploy("version 1") }
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_should_raise_runtime_error_when_eb_extension_execution_failed
|
63
|
+
env = EbDeployer::Environment.new("myapp", "production", @eb_driver)
|
64
|
+
|
65
|
+
env.event_poller = PollerStub.new(["start deploying",
|
66
|
+
"create environment",
|
67
|
+
"Command failed on instance. Return code: 1 Output: Error occurred during build: Command hooks failed",
|
68
|
+
"Successfully launched environment"])
|
69
|
+
|
70
|
+
assert_raises(RuntimeError) { env.deploy("version 1") }
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def test_terminate_should_delete_environment
|
75
|
+
env = EbDeployer::Environment.new("myapp", "production", @eb_driver)
|
76
|
+
env.deploy("version1")
|
77
|
+
env.terminate
|
78
|
+
assert !@eb_driver.environment_exists?('myapp', eb_envname('myapp', 'production'))
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eb_deployer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
5
|
-
prerelease:
|
4
|
+
version: 0.3.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- wpc
|
@@ -10,22 +9,20 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date: 2014-02-
|
12
|
+
date: 2014-02-14 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: aws-sdk
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
|
-
- -
|
18
|
+
- - ">="
|
21
19
|
- !ruby/object:Gem::Version
|
22
20
|
version: '0'
|
23
21
|
type: :runtime
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
|
-
- -
|
25
|
+
- - ">="
|
29
26
|
- !ruby/object:Gem::Version
|
30
27
|
version: '0'
|
31
28
|
description: For automate blue green deployment flow on Elasti Beanstalk.
|
@@ -37,9 +34,9 @@ executables:
|
|
37
34
|
extensions: []
|
38
35
|
extra_rdoc_files: []
|
39
36
|
files:
|
40
|
-
- .gitignore
|
41
|
-
- .ruby-gemset
|
42
|
-
- .ruby-version
|
37
|
+
- ".gitignore"
|
38
|
+
- ".ruby-gemset"
|
39
|
+
- ".ruby-version"
|
43
40
|
- Gemfile
|
44
41
|
- LICENSE
|
45
42
|
- README.md
|
@@ -66,32 +63,32 @@ files:
|
|
66
63
|
- test/cloud_formation_provisioner_test.rb
|
67
64
|
- test/config_loader_test.rb
|
68
65
|
- test/deploy_test.rb
|
66
|
+
- test/environment_test.rb
|
69
67
|
- test/smoke_test_test.rb
|
70
68
|
- test/test_helper.rb
|
71
69
|
homepage: https://github.com/ThoughtWorksStudios/eb_deployer
|
72
70
|
licenses:
|
73
71
|
- MIT
|
72
|
+
metadata: {}
|
74
73
|
post_install_message:
|
75
74
|
rdoc_options: []
|
76
75
|
require_paths:
|
77
76
|
- lib
|
78
77
|
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
-
none: false
|
80
78
|
requirements:
|
81
|
-
- -
|
79
|
+
- - ">="
|
82
80
|
- !ruby/object:Gem::Version
|
83
81
|
version: '0'
|
84
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
-
none: false
|
86
83
|
requirements:
|
87
|
-
- -
|
84
|
+
- - ">="
|
88
85
|
- !ruby/object:Gem::Version
|
89
86
|
version: '0'
|
90
87
|
requirements: []
|
91
88
|
rubyforge_project:
|
92
|
-
rubygems_version:
|
89
|
+
rubygems_version: 2.2.0
|
93
90
|
signing_key:
|
94
|
-
specification_version:
|
91
|
+
specification_version: 4
|
95
92
|
summary: Low friction deployments should be a breeze. Elastic Beanstalk provides a
|
96
93
|
great foundation for performing Blue-Green deployments, and EbDeployer add a missing
|
97
94
|
top to automate the whole flow out of box.
|
@@ -100,6 +97,6 @@ test_files:
|
|
100
97
|
- test/cloud_formation_provisioner_test.rb
|
101
98
|
- test/config_loader_test.rb
|
102
99
|
- test/deploy_test.rb
|
100
|
+
- test/environment_test.rb
|
103
101
|
- test/smoke_test_test.rb
|
104
102
|
- test/test_helper.rb
|
105
|
-
has_rdoc:
|