eb_deployer 0.6.5 → 0.6.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8a3bf432fbdd44e7326eaf9e78be738e88e9f3e4
4
- data.tar.gz: 2098b1afc36775fde413f58dd89aabd885e12dd3
3
+ metadata.gz: 61bce2cf3c9e823994645f76257fe43b360f3dfa
4
+ data.tar.gz: 0446b95ef9b12a138b495fd847118981c22452cf
5
5
  SHA512:
6
- metadata.gz: 1de31e8970e914b8cea087335e455356294144327b4d905b2ad1f5fe28cbfafb62134b1b2408a8178927f7dfd99880aba589d05092a0b0df7cb9b05fae3fac77
7
- data.tar.gz: 3faefb2b6faf8ec5caec1ac861828fe95394f81dce54d4ff94b1cec3b02d7275c86872da33e2908f5206ace6868c3b2fa2a56e4f911b48d675709377ad21660a
6
+ metadata.gz: 86ab2af9a6e5beaa906486a9929f75914a4f425169d39dd32c077ea63310951ea7c83ca93ff4e3c7aec11fe4bcf00b7ee5b0e5675bc1b01175776eaa6021d8ee
7
+ data.tar.gz: a699f697841d6e07c2d1b0ee7b682d65431f2d24b1e26a4602e7bb72303eead2866ce9e7014e7652052005a9b30d151481c4909f290e2d97e9b8f63f16777d53
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ 0.6.6
2
+ =====
3
+
4
+ * Add support for specifying (and overriding) a [stack policy](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html) for the CloudFormation resource stack
5
+ * Fix issue where deployment hangs if resource stack update fails and stack is rolled back, deployment will now fail when the resource stack update fails
6
+
1
7
  0.6.5
2
8
  =====
3
9
 
data/lib/eb_deployer.rb CHANGED
@@ -56,7 +56,7 @@ module EbDeployer
56
56
 
57
57
 
58
58
  #
59
- # Deploy a package to specfied environments on elastic beanstalk
59
+ # Deploy a package to specified environments on elastic beanstalk
60
60
  #
61
61
  # @param [Hash] opts
62
62
  #
@@ -101,7 +101,7 @@ module EbDeployer
101
101
  # deploy. For blue-green deployment it terminate the inactive environment
102
102
  # first then recreate it. This is useful to avoiding configuration drift and
103
103
  # accumulating state on the EC2 instances. Also it has the benefit of keeping
104
- # your EC2 instance system package upto date, because everytime EC2 instance
104
+ # your EC2 instance system package upto date, because every time EC2 instance
105
105
  # boot up from AMI it does a system update.
106
106
  #
107
107
  #
@@ -116,6 +116,10 @@ module EbDeployer
116
116
  # following keys:
117
117
  #
118
118
  # :template => CloudFormation template file with JSON format
119
+ # :policy => CloudFormation policy file with JSON format
120
+ # :override_policy => (false) If override_policy is true and a policy file is provided then the
121
+ # policy will temporarily override any existing policy on the resource stack during this update,
122
+ # otherwise the provided policy will replace any existing policy on the resource stack
119
123
  # :parameters (or :inputs) => A Hash, input values for the CloudFormation template
120
124
  # :transforms => A Hash with key map to your CloudFormation
121
125
  # template outputs and value as lambda that return a single or array of
@@ -151,7 +155,7 @@ module EbDeployer
151
155
  #
152
156
  # @option opts [Symbol] :strategy (:blue-green) There are two options:
153
157
  # blue-green or inplace-update. Blue green keep two elastic beanstalk
154
- # environments and always deploy to inactive one, to achive zero downtime.
158
+ # environments and always deploy to inactive one, to achieve zero downtime.
155
159
  # inplace-update strategy will only keep one environment, and update the
156
160
  # version inplace on deploy. this will save resources but will have downtime.
157
161
  #
@@ -164,8 +168,8 @@ module EbDeployer
164
168
  # @option opts [Symbol] :version_label *required*. Version label give the
165
169
  # package uploaded a unique identifier. Should use something related to
166
170
  # pipeline counter if you have build pipeline setup to build the installer.
167
- # For the convient of dev we recommend use md5 digest of the installer so
168
- # that everytime you upload new installer it forms a new version. e.g.
171
+ # For the convenience of dev we recommend use md5 digest of the installer so
172
+ # that every time you upload new installer it forms a new version. e.g.
169
173
  #
170
174
  # :version_label => ENV['MY_PIPELINE_COUNTER']
171
175
  # || "dev-" + Digest::MD5.file(my_package).hexdigest
@@ -178,6 +182,9 @@ module EbDeployer
178
182
  # keep. Older versions are removed and deleted from the S3 source bucket as well.
179
183
  # If specified as zero or not specified, all versions will be kept. If a
180
184
  # version_prefix is given, only removes version starting with the prefix.
185
+ #
186
+ # @option opts [Symbol] :template_name. Specifies the environement template you wish
187
+ # to use to build your environment.
181
188
  def self.deploy(opts)
182
189
  if region = opts[:region]
183
190
  Aws.config.update(:region => region)
@@ -205,6 +212,7 @@ module EbDeployer
205
212
  env.settings = opts[:option_settings] || opts[:settings] || []
206
213
  env.inactive_settings = opts[:inactive_settings] || []
207
214
  env.creation_opts = {
215
+ :template_name => opts[:template_name],
208
216
  :solution_stack => opts[:solution_stack_name],
209
217
  :cname_prefix => opts[:cname_prefix],
210
218
  :smoke_test => opts[:smoke_test],
@@ -25,12 +25,16 @@ module EbDeployer
25
25
  @client.update_environment(:environment_id => env_id, :option_settings => settings)
26
26
  end
27
27
 
28
- def update_environment(app_name, env_name, version, tier, settings)
28
+ def update_environment(app_name, env_name, version, tier, settings, template_name)
29
29
  env_id = convert_env_name_to_id(app_name, [env_name]).first
30
- @client.update_environment(:environment_id => env_id,
31
- :version_label => version,
32
- :option_settings => settings,
33
- :tier => environment_tier(tier))
30
+ request = reject_nil({
31
+ :environment_id => env_id,
32
+ :version_label => version,
33
+ :option_settings => settings,
34
+ :tier => environment_tier(tier),
35
+ :template_name => template_name
36
+ })
37
+ @client.update_environment(request)
34
38
  end
35
39
 
36
40
  def environment_exists?(app_name, env_name)
@@ -41,7 +45,7 @@ module EbDeployer
41
45
  alive_envs(app_name).collect { |env| env[:environment_name] }
42
46
  end
43
47
 
44
- def create_environment(app_name, env_name, stack_name, cname_prefix, version, tier, tags, settings)
48
+ def create_environment(app_name, env_name, stack_name, cname_prefix, version, tier, tags, settings, template_name)
45
49
  request = reject_nil({
46
50
  :application_name => app_name,
47
51
  :environment_name => env_name,
@@ -50,7 +54,8 @@ module EbDeployer
50
54
  :option_settings => settings,
51
55
  :tier => environment_tier(tier),
52
56
  :cname_prefix => cname_prefix,
53
- :tags => tags
57
+ :tags => tags,
58
+ :template_name => template_name
54
59
  })
55
60
  @client.create_environment(request)
56
61
  end
@@ -4,7 +4,7 @@ module EbDeployer
4
4
 
5
5
  class CloudFormationProvisioner
6
6
  SUCCESS_STATS = ["CREATE_COMPLETE", "UPDATE_COMPLETE"]
7
- FAILED_STATS = ["CREATE_FAILED", "UPDATE_FAILED"]
7
+ FAILED_STATS = ["CREATE_FAILED", "UPDATE_FAILED", "UPDATE_ROLLBACK_COMPLETE"]
8
8
 
9
9
  def initialize(stack_name, cf_driver)
10
10
  @stack_name = stack_name
@@ -17,13 +17,15 @@ module EbDeployer
17
17
  template = File.read(resources[:template])
18
18
  capabilities = resources[:capabilities] || []
19
19
  params = resources[:inputs] || resources[:parameters] || {}
20
+ policy = File.read(resources[:policy]) if resources[:policy]
21
+ override_policy = resources[:override_policy] || false
20
22
  anchor = nil
21
23
  begin
22
24
  if stack_exists?
23
25
  anchor = @poller.get_anchor
24
- update_stack(template, params, capabilities)
26
+ update_stack(template, params, capabilities, policy, override_policy)
25
27
  else
26
- create_stack(template, params, capabilities)
28
+ create_stack(template, params, capabilities, policy)
27
29
  end
28
30
  rescue Aws::CloudFormation::Errors::ValidationError => e
29
31
  if e.message =~ /No updates are to be performed/
@@ -65,21 +67,26 @@ module EbDeployer
65
67
  end
66
68
  end
67
69
 
68
- def update_stack(template, params, capabilities)
69
- @cf_driver.update_stack(@stack_name, template,
70
- :capabilities => capabilities,
71
- :parameters => params)
70
+ def update_stack(template, params, capabilities, policy, override_policy)
71
+ opts = {:capabilities => capabilities, :parameters => params}
72
+ if (policy)
73
+ opts[:stack_policy_during_update_body] = policy if override_policy
74
+ log("Using temporary stack policy to apply resource stack updates") if override_policy
75
+ opts[:stack_policy_body] = policy unless override_policy
76
+ log("Applying new stack policy to existing resource stack") unless override_policy
77
+ end
78
+ @cf_driver.update_stack(@stack_name, template, opts)
72
79
  end
73
80
 
74
81
  def stack_exists?
75
82
  @cf_driver.stack_exists?(@stack_name)
76
83
  end
77
84
 
78
- def create_stack(template, params, capabilities)
79
- @cf_driver.create_stack(@stack_name, template,
80
- :disable_rollback => true,
81
- :capabilities => capabilities,
82
- :parameters => params)
85
+ def create_stack(template, params, capabilities, policy)
86
+ opts = {:disable_rollback => true, :capabilities => capabilities, :parameters => params}
87
+ opts[:stack_policy_body] = policy if policy
88
+ log("Applying stack policy to new resource stack") if policy
89
+ @cf_driver.create_stack(@stack_name, template, opts)
83
90
  end
84
91
 
85
92
  def transform_output_to_settings(transforms)
@@ -122,6 +122,9 @@ common:
122
122
  # options settings.
123
123
  # keys:
124
124
  # template => CloudFormation template file with JSON format
125
+ # policy => CloudFormation policy file with JSON format
126
+ # override_policy => (false) If override_policy is true and a policy file is provided then the policy will temporarily override any existing policy on the resource stack during this update,
127
+ # otherwise the provided policy will replace any existing policy on the resource stack
125
128
  # inputs => A Hash, input values for the CloudFormation template
126
129
  # outputs => A Hash with key map to your CloudFormation template outputs and value as elastic beanstalk settings namespace and option_name.
127
130
  # capabilities => An array. You need set it to ['CAPABILITY_IAM'] if the
@@ -73,6 +73,10 @@ module EbDeployer
73
73
  @creation_opts[:tier]
74
74
  end
75
75
 
76
+ def template_name
77
+ @creation_opts[:template_name]
78
+ end
79
+
76
80
  def has_cname?
77
81
  !configured_tier || configured_tier.downcase == 'webserver'
78
82
  end
@@ -93,7 +97,8 @@ module EbDeployer
93
97
  version_label,
94
98
  configured_tier,
95
99
  tags,
96
- settings)
100
+ settings,
101
+ template_name)
97
102
  end
98
103
  end
99
104
 
@@ -103,7 +108,8 @@ module EbDeployer
103
108
  @name,
104
109
  version_label,
105
110
  configured_tier,
106
- settings)
111
+ settings,
112
+ template_name)
107
113
  end
108
114
  end
109
115
 
@@ -1,3 +1,3 @@
1
1
  module EbDeployer
2
- VERSION = "0.6.5"
2
+ VERSION = "0.6.6"
3
3
  end
@@ -137,6 +137,9 @@ common:
137
137
  # options settings.
138
138
  # keys:
139
139
  # template => CloudFormation template file with JSON format
140
+ # policy => CloudFormation policy file with JSON format
141
+ # override_policy => (false) If override_policy is true and a policy file is provided then the policy will temporarily override any existing policy on the resource stack during this update,
142
+ # otherwise the provided policy will replace any existing policy on the resource stack
140
143
  # inputs => A Hash, input values for the CloudFormation template
141
144
  # outputs => A Hash with key map to your CloudFormation template outputs and value as elastic beanstalk settings namespace and option_name.
142
145
  # capabilities => An array. You need set it to ['CAPABILITY_IAM'] if the
@@ -24,7 +24,7 @@ class EBStub
24
24
  @apps.include?(app)
25
25
  end
26
26
 
27
- def create_environment(app, env, solution_stack, cname_prefix, version, tier, tags, settings)
27
+ def create_environment(app, env, solution_stack, cname_prefix, version, tier, tags, settings, template_name)
28
28
  raise 'cname prefix is not avaible' if @envs.values.detect { |env| env[:cname_prefix] == cname_prefix }
29
29
  raise "env name #{env} is longer than 23 chars" if env.size > 23
30
30
  raise "app not exists" unless application_exists?(app)
@@ -36,7 +36,8 @@ class EBStub
36
36
  :cname_prefix => cname_prefix,
37
37
  :tier => tier,
38
38
  :tags => tags,
39
- :settings => settings }
39
+ :settings => settings,
40
+ :template_name => template_name }
40
41
  set_env_ready(app, env, false)
41
42
  end
42
43
 
@@ -52,9 +53,9 @@ class EBStub
52
53
  end
53
54
 
54
55
 
55
- def update_environment(app, env, version, tier, settings)
56
+ def update_environment(app, env, version, tier, settings, template_name)
56
57
  raise "not in ready state, consider waiting for previous action finish by pulling envents" unless env_ready?(app, env)
57
- @envs[env_key(app, env)].merge!(:version => version, :settings => settings, :tier => tier)
58
+ @envs[env_key(app, env)].merge!(:version => version, :settings => settings, :tier => tier, :template_name => template_name)
58
59
  set_env_ready(app, env, false)
59
60
  end
60
61
 
@@ -220,6 +221,10 @@ class EBStub
220
221
  @versions_deleted[app_name]
221
222
  end
222
223
 
224
+ def template_name(app_name, env_name)
225
+ @envs[env_key(app_name, env_name)][:template_name]
226
+ end
227
+
223
228
  private
224
229
 
225
230
  def set_env_ready(app, env, ready)
@@ -11,6 +11,61 @@ class ResourcesDeployTest < DeployTest
11
11
  assert @cf_driver.stack_exists?('simple-production')
12
12
  assert_equal({}, @cf_driver.stack_config('simple-production')[:parameters])
13
13
  assert_equal([], @cf_driver.stack_config('simple-production')[:capabilities])
14
+ assert_nil(@cf_driver.stack_config('simple-production')[:stack_policy_body])
15
+ end
16
+
17
+ def test_deploy_with_resources_declared_will_create_a_cf_stack_for_env_with_policy
18
+ cf_template = temp_file(JSON.dump({'Resources' => {'R1' => {}}}))
19
+ cf_policy = sample_file("sample_policy.json", JSON.dump({'Policy' => {'P1' => {}}}))
20
+ deploy(:application => 'simple', :environment => "production",
21
+ :resources => {
22
+ :template => cf_template,
23
+ :policy => cf_policy
24
+ })
25
+ assert @cf_driver.stack_exists?('simple-production')
26
+ assert_equal({}, @cf_driver.stack_config('simple-production')[:parameters])
27
+ assert_equal([], @cf_driver.stack_config('simple-production')[:capabilities])
28
+ assert_equal("{\"Policy\":{\"P1\":{}}}", @cf_driver.stack_config('simple-production')[:stack_policy_body])
29
+ end
30
+
31
+ def test_deploy_with_resources_declared_will_update_a_cf_stack_for_env_with_policy
32
+ cf_template = temp_file(JSON.dump({'Resources' => {'R1' => {}}}))
33
+ cf_policy = sample_file("sample_policy.json", JSON.dump({'Policy' => {'P1' => {}}}))
34
+ deploy(:application => 'simple', :environment => "production",
35
+ :resources => {
36
+ :template => cf_template,
37
+ :policy => cf_policy
38
+ })
39
+ assert @cf_driver.stack_exists?('simple-production')
40
+ deploy(:application => 'simple', :environment => "production",
41
+ :resources => {
42
+ :template => cf_template,
43
+ :policy => cf_policy,
44
+ :override_policy => false
45
+ })
46
+ assert_equal({}, @cf_driver.stack_config('simple-production')[:parameters])
47
+ assert_equal([], @cf_driver.stack_config('simple-production')[:capabilities])
48
+ assert_equal("{\"Policy\":{\"P1\":{}}}", @cf_driver.stack_config('simple-production')[:stack_policy_body])
49
+ end
50
+
51
+ def test_deploy_with_resources_declared_will_update_a_cf_stack_for_env_with_temp_policy
52
+ cf_template = temp_file(JSON.dump({'Resources' => {'R1' => {}}}))
53
+ cf_policy = sample_file("sample_policy.json", JSON.dump({'Policy' => {'P1' => {}}}))
54
+ deploy(:application => 'simple', :environment => "production",
55
+ :resources => {
56
+ :template => cf_template,
57
+ :policy => cf_policy
58
+ })
59
+ assert @cf_driver.stack_exists?('simple-production')
60
+ deploy(:application => 'simple', :environment => "production",
61
+ :resources => {
62
+ :template => cf_template,
63
+ :policy => cf_policy,
64
+ :override_policy => true
65
+ })
66
+ assert_equal({}, @cf_driver.stack_config('simple-production')[:parameters])
67
+ assert_equal([], @cf_driver.stack_config('simple-production')[:capabilities])
68
+ assert_equal("{\"Policy\":{\"P1\":{}}}", @cf_driver.stack_config('simple-production')[:stack_policy_during_update_body])
14
69
  end
15
70
 
16
71
  def test_provision_resources_with_capacities
@@ -0,0 +1,13 @@
1
+ require 'deploy_test'
2
+
3
+ class TemplateDeployTest < DeployTest
4
+ def test_default_no_template
5
+ deploy(:application => 'simple', :environment => "production")
6
+ assert_equal nil, @eb.template_name('simple', t('production', 'simple'))
7
+ end
8
+
9
+ def test_can_set_a_template
10
+ deploy(:application => 'simple', :environment => "production", :template_name => 'SomeTemplate')
11
+ assert_equal 'SomeTemplate', @eb.template_name('simple', t('production', 'simple'))
12
+ end
13
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eb_deployer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.5
4
+ version: 0.6.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - wpc
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-02-22 00:00:00.000000000 Z
13
+ date: 2016-03-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: aws-sdk
@@ -103,6 +103,7 @@ files:
103
103
  - test/rails_generators_test.rb
104
104
  - test/resources_deploy_test.rb
105
105
  - test/smoke_test_test.rb
106
+ - test/template_deploy_test.rb
106
107
  - test/test_helper.rb
107
108
  - test/tier_setting_deploy_test.rb
108
109
  - test/versions_deploy_test.rb
@@ -148,6 +149,7 @@ test_files:
148
149
  - test/rails_generators_test.rb
149
150
  - test/resources_deploy_test.rb
150
151
  - test/smoke_test_test.rb
152
+ - test/template_deploy_test.rb
151
153
  - test/test_helper.rb
152
154
  - test/tier_setting_deploy_test.rb
153
155
  - test/versions_deploy_test.rb