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 +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/eb_deployer.rb +13 -5
- data/lib/eb_deployer/aws_driver/beanstalk.rb +12 -7
- data/lib/eb_deployer/cloud_formation_provisioner.rb +19 -12
- data/lib/eb_deployer/default_config.yml +3 -0
- data/lib/eb_deployer/eb_environment.rb +8 -2
- data/lib/eb_deployer/version.rb +1 -1
- data/lib/generators/eb_deployer/install/templates/eb_deployer.yml.erb +3 -0
- data/test/aws_driver_stubs.rb +9 -4
- data/test/resources_deploy_test.rb +55 -0
- data/test/template_deploy_test.rb +13 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61bce2cf3c9e823994645f76257fe43b360f3dfa
|
4
|
+
data.tar.gz: 0446b95ef9b12a138b495fd847118981c22452cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
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
|
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
|
168
|
-
# that
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
70
|
-
|
71
|
-
|
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
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
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
|
|
data/lib/eb_deployer/version.rb
CHANGED
@@ -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
|
data/test/aws_driver_stubs.rb
CHANGED
@@ -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.
|
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-
|
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
|