eb_deployer 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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 =~ /\.yml$/
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
- # template outputs and value as elastic beanstalk settings namespace and option_name.
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
- EventPoller.new(@app, @name, @bs).poll(event_start_time) do |event|
80
- raise event[:message] if event[:message] =~ /Failed to deploy application/
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]}"
@@ -1,3 +1,3 @@
1
1
  module EbDeployer
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -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
- env_name, env = pair
123
- memo << env_name if env[:application] == app
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
@@ -13,4 +13,9 @@ class MiniTest::Unit::TestCase
13
13
  File.open(path, 'w') { |f| f << content }
14
14
  path
15
15
  end
16
+
17
+ def eb_envname(app_name, env_name)
18
+ EbDeployer::Environment.unique_ebenv_name(app_name, env_name)
19
+ end
20
+
16
21
  end
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.1
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-05 00:00:00.000000000 Z
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: 1.8.23
89
+ rubygems_version: 2.2.0
93
90
  signing_key:
94
- specification_version: 3
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: