eb_deployer 0.3.6 → 0.3.7
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.
- data/.ruby-version +1 -1
- data/.travis.yml +10 -0
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/lib/eb_deployer/application.rb +7 -1
- data/lib/eb_deployer/aws_driver/beanstalk.rb +127 -0
- data/lib/eb_deployer/aws_driver/cloud_formation_driver.rb +49 -0
- data/lib/eb_deployer/aws_driver/s3_driver.rb +35 -0
- data/lib/eb_deployer/aws_driver.rb +8 -0
- data/lib/eb_deployer/config_loader.rb +0 -1
- data/lib/eb_deployer/deployment_strategy/blue_green.rb +40 -0
- data/lib/eb_deployer/deployment_strategy/inplace_update.rb +13 -0
- data/lib/eb_deployer/deployment_strategy.rb +6 -61
- data/lib/eb_deployer/eb_environment.rb +111 -0
- data/lib/eb_deployer/environment.rb +21 -87
- data/lib/eb_deployer/resource_stacks.rb +19 -0
- data/lib/eb_deployer/version.rb +1 -1
- data/lib/eb_deployer.rb +35 -41
- data/test/config_loader_test.rb +0 -13
- data/test/deploy_test.rb +11 -0
- data/test/{environment_test.rb → eb_environment_test.rb} +8 -8
- data/test/test_helper.rb +1 -1
- metadata +20 -8
- data/lib/eb_deployer/beanstalk.rb +0 -126
- data/lib/eb_deployer/cloud_formation_driver.rb +0 -48
- data/lib/eb_deployer/s3_driver.rb +0 -33
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.9.3-
|
1
|
+
1.9.3-p484
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# EbDeployer
|
1
|
+
# EbDeployer [](https://travis-ci.org/ThoughtWorksStudios/eb_deployer)
|
2
2
|
|
3
3
|
Low friction deployments should be a breeze. Elastic Beanstalk provides a great foundation for performing Blue-Green deployments, and EbDeployer add a missing link to automate the whole flow out of box.
|
4
4
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module EbDeployer
|
2
2
|
class Application
|
3
|
+
attr_reader :name
|
4
|
+
|
3
5
|
def initialize(name, eb_driver, s3_driver, bucket = nil)
|
4
6
|
@name = name
|
5
7
|
@eb_driver = eb_driver
|
@@ -34,7 +36,7 @@ module EbDeployer
|
|
34
36
|
|
35
37
|
def delete(env_name=nil)
|
36
38
|
if @eb_driver.application_exists?(@name)
|
37
|
-
env_name =
|
39
|
+
env_name = EbEnvironment.unique_ebenv_name(@name, env_name) unless env_name.nil?
|
38
40
|
available_envs = @eb_driver.environment_names_for_application(@name)
|
39
41
|
|
40
42
|
unless env_name.nil? || available_envs.include?(env_name)
|
@@ -75,6 +77,10 @@ module EbDeployer
|
|
75
77
|
end
|
76
78
|
end
|
77
79
|
|
80
|
+
def clean_versions(version_prefix, retentions)
|
81
|
+
VersionCleaner.new(self, retentions).clean(version_prefix)
|
82
|
+
end
|
83
|
+
|
78
84
|
private
|
79
85
|
|
80
86
|
def create_application_if_not_exists
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module EbDeployer
|
2
|
+
module AWSDriver
|
3
|
+
class Beanstalk
|
4
|
+
attr_reader :client
|
5
|
+
|
6
|
+
def initialize(client=AWS::ElasticBeanstalk.new.client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_application(app)
|
11
|
+
@client.create_application(:application_name => app)
|
12
|
+
end
|
13
|
+
|
14
|
+
def delete_application(app)
|
15
|
+
@client.delete_application(:application_name => app)
|
16
|
+
end
|
17
|
+
|
18
|
+
def application_exists?(app)
|
19
|
+
@client.describe_applications(:application_names => [app])[:applications].any?
|
20
|
+
end
|
21
|
+
|
22
|
+
def update_environment(app_name, env_name, version, tier, settings)
|
23
|
+
env_id = convert_env_name_to_id(app_name, [env_name]).first
|
24
|
+
request = {
|
25
|
+
:environment_id => env_id,
|
26
|
+
:version_label => version,
|
27
|
+
:option_settings => settings,
|
28
|
+
:tier => tier
|
29
|
+
}
|
30
|
+
|
31
|
+
@client.update_environment(request)
|
32
|
+
end
|
33
|
+
|
34
|
+
def environment_exists?(app_name, env_name)
|
35
|
+
alive_envs(app_name, [env_name]).any?
|
36
|
+
end
|
37
|
+
|
38
|
+
def environment_names_for_application(app_name)
|
39
|
+
alive_envs(app_name).collect { |env| env[:environment_name] }
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_environment(app_name, env_name, stack_name, cname_prefix, version, tier, settings)
|
43
|
+
request = {
|
44
|
+
:application_name => app_name,
|
45
|
+
:environment_name => env_name,
|
46
|
+
:solution_stack_name => stack_name,
|
47
|
+
:version_label => version,
|
48
|
+
:option_settings => settings,
|
49
|
+
:tier => tier,
|
50
|
+
:cname_prefix => cname_prefix
|
51
|
+
}
|
52
|
+
|
53
|
+
@client.create_environment(request)
|
54
|
+
end
|
55
|
+
|
56
|
+
def delete_environment(app_name, env_name)
|
57
|
+
@client.terminate_environment(:environment_name => env_name)
|
58
|
+
end
|
59
|
+
|
60
|
+
def delete_application_version(app_name, version, delete_source_bundle)
|
61
|
+
request = {
|
62
|
+
:application_name => app_name,
|
63
|
+
:version_label => version,
|
64
|
+
:delete_source_bundle => delete_source_bundle
|
65
|
+
}
|
66
|
+
@client.delete_application_version(request)
|
67
|
+
end
|
68
|
+
|
69
|
+
def create_application_version(app_name, version_label, source_bundle)
|
70
|
+
@client.create_application_version(:application_name => app_name,
|
71
|
+
:source_bundle => source_bundle,
|
72
|
+
:version_label => version_label)
|
73
|
+
end
|
74
|
+
|
75
|
+
def application_version_labels(app_name)
|
76
|
+
application_versions(app_name).map { |apv| apv[:version_label] }
|
77
|
+
end
|
78
|
+
|
79
|
+
def application_versions(app_name)
|
80
|
+
request = { :application_name => app_name }
|
81
|
+
@client.describe_application_versions(request)[:application_versions]
|
82
|
+
end
|
83
|
+
|
84
|
+
def fetch_events(app_name, env_name, params, &block)
|
85
|
+
response = @client.describe_events(params.merge(:application_name => app_name,
|
86
|
+
:environment_name => env_name))
|
87
|
+
return [response[:events], response[:next_token]]
|
88
|
+
end
|
89
|
+
|
90
|
+
def environment_cname_prefix(app_name, env_name)
|
91
|
+
cname = environment_cname(app_name, env_name)
|
92
|
+
if cname =~ /^(.+)\.elasticbeanstalk\.com/
|
93
|
+
$1
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def environment_cname(app_name, env_name)
|
98
|
+
env = alive_envs(app_name, [env_name]).first
|
99
|
+
env && env[:cname]
|
100
|
+
end
|
101
|
+
|
102
|
+
def environment_health_state(app_name, env_name)
|
103
|
+
env = alive_envs(app_name, [env_name]).first
|
104
|
+
env && env[:health]
|
105
|
+
end
|
106
|
+
|
107
|
+
def environment_swap_cname(app_name, env1, env2)
|
108
|
+
env1_id, env2_id = convert_env_name_to_id(app_name, [env1, env2])
|
109
|
+
@client.swap_environment_cnam_es(:source_environment_id => env1_id,
|
110
|
+
:destination_environment_id => env2_id)
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def convert_env_name_to_id(app_name, env_names)
|
116
|
+
envs = alive_envs(app_name, env_names)
|
117
|
+
envs.map { |env| env[:environment_id] }
|
118
|
+
end
|
119
|
+
|
120
|
+
def alive_envs(app_name, env_names=[])
|
121
|
+
envs = @client.describe_environments(:application_name => app_name, :environment_names => env_names)[:environments]
|
122
|
+
|
123
|
+
envs.select {|e| e[:status] != 'Terminated' }
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module EbDeployer
|
2
|
+
module AWSDriver
|
3
|
+
class CloudFormationDriver
|
4
|
+
|
5
|
+
def stack_exists?(name)
|
6
|
+
stack(name).exists?
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_stack(name, template, opts)
|
10
|
+
cloud_formation.stacks.create(name, template, opts)
|
11
|
+
end
|
12
|
+
|
13
|
+
def update_stack(name, template, opts)
|
14
|
+
begin
|
15
|
+
stack(name).update(opts.merge(:template => template))
|
16
|
+
rescue AWS::CloudFormation::Errors::ValidationError => e
|
17
|
+
if e.message =~ /No updates are to be performed/
|
18
|
+
log(e.message)
|
19
|
+
else
|
20
|
+
raise
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def stack_status(name)
|
26
|
+
stack(name).status.downcase.to_sym
|
27
|
+
end
|
28
|
+
|
29
|
+
def query_output(name, key)
|
30
|
+
output = stack(name).outputs.find { |o| o.key == key }
|
31
|
+
output && output.value
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def cloud_formation
|
37
|
+
AWS::CloudFormation.new
|
38
|
+
end
|
39
|
+
|
40
|
+
def stack(name)
|
41
|
+
cloud_formation.stacks[name]
|
42
|
+
end
|
43
|
+
|
44
|
+
def log(msg)
|
45
|
+
puts "[#{Time.now.utc}][cloud_formation_driver] #{msg}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module EbDeployer
|
2
|
+
module AWSDriver
|
3
|
+
class S3Driver
|
4
|
+
def create_bucket(bucket_name)
|
5
|
+
buckets.create(bucket_name)
|
6
|
+
end
|
7
|
+
|
8
|
+
def bucket_exists?(bucket_name)
|
9
|
+
buckets[bucket_name].exists?
|
10
|
+
end
|
11
|
+
|
12
|
+
def object_length(bucket_name, obj_name)
|
13
|
+
obj(bucket_name, obj_name).content_length rescue nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def upload_file(bucket_name, obj_name, file)
|
17
|
+
o = obj(bucket_name, obj_name)
|
18
|
+
File.open(file) { |f| o.write(f) }
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def s3
|
23
|
+
AWS::S3.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def obj(bucket_name, obj_name)
|
27
|
+
buckets[bucket_name].objects[obj_name]
|
28
|
+
end
|
29
|
+
|
30
|
+
def buckets
|
31
|
+
s3.buckets
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module EbDeployer
|
2
|
+
module DeploymentStrategy
|
3
|
+
class BlueGreen
|
4
|
+
def initialize(env)
|
5
|
+
@env = env
|
6
|
+
end
|
7
|
+
|
8
|
+
def deploy(version_label, env_settings)
|
9
|
+
if !envs.any?(&method(:active_env?))
|
10
|
+
env('a', @env.cname_prefix).
|
11
|
+
deploy(version_label, env_settings)
|
12
|
+
return
|
13
|
+
end
|
14
|
+
|
15
|
+
active_env = envs.detect(&method(:active_env?))
|
16
|
+
inactive_env = envs.reject(&method(:active_env?)).first
|
17
|
+
|
18
|
+
inactive_env.deploy(version_label, env_settings)
|
19
|
+
active_env.swap_cname_with(inactive_env)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def active_env?(env)
|
24
|
+
env.cname_prefix == @env.cname_prefix
|
25
|
+
end
|
26
|
+
|
27
|
+
def envs
|
28
|
+
[env('a'), env('b')]
|
29
|
+
end
|
30
|
+
|
31
|
+
def env(suffix, cname_prefix=nil)
|
32
|
+
@env.new_eb_env(suffix, cname_prefix || inactive_cname_prefix)
|
33
|
+
end
|
34
|
+
|
35
|
+
def inactive_cname_prefix
|
36
|
+
"#{@env.cname_prefix}-inactive"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,72 +1,17 @@
|
|
1
|
+
require 'eb_deployer/deployment_strategy/inplace_update'
|
2
|
+
require 'eb_deployer/deployment_strategy/blue_green'
|
3
|
+
|
1
4
|
module EbDeployer
|
2
5
|
module DeploymentStrategy
|
3
|
-
|
4
|
-
def initialize(app, env_name, eb_driver, env_creation_opts)
|
5
|
-
@app = app
|
6
|
-
@env_name = env_name
|
7
|
-
@eb_driver = eb_driver
|
8
|
-
@env_creation_opts = env_creation_opts
|
9
|
-
end
|
10
|
-
|
11
|
-
def deploy(version_label, env_settings)
|
12
|
-
Environment.new(@app, @env_name, @eb_driver, @env_creation_opts).
|
13
|
-
deploy(version_label, env_settings)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class BlueGreen
|
18
|
-
def initialize(app, env_name, eb_driver, env_creation_opts)
|
19
|
-
@app = app
|
20
|
-
@env_name = env_name
|
21
|
-
@eb_driver = eb_driver
|
22
|
-
@env_creation_opts = env_creation_opts
|
23
|
-
@major_cname_prefix = env_creation_opts[:cname_prefix]
|
24
|
-
end
|
25
|
-
|
26
|
-
def deploy(version_label, env_settings)
|
27
|
-
if !envs.any?(&method(:active_env?))
|
28
|
-
env('a', @major_cname_prefix).
|
29
|
-
deploy(version_label, env_settings)
|
30
|
-
return
|
31
|
-
end
|
32
|
-
|
33
|
-
active_env = envs.detect(&method(:active_env?))
|
34
|
-
inactive_env = envs.reject(&method(:active_env?)).first
|
35
|
-
|
36
|
-
inactive_env.deploy(version_label, env_settings)
|
37
|
-
active_env.swap_cname_with(inactive_env)
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
def active_env?(env)
|
42
|
-
env.cname_prefix == @major_cname_prefix
|
43
|
-
end
|
44
|
-
|
45
|
-
def envs
|
46
|
-
[env('a'), env('b')]
|
47
|
-
end
|
48
|
-
|
49
|
-
def env(suffix, cname_prefix=nil)
|
50
|
-
Environment.new(@app, @env_name + '-' + suffix,
|
51
|
-
@eb_driver,
|
52
|
-
@env_creation_opts.merge({:cname_prefix => cname_prefix || inactive_cname_prefix}))
|
53
|
-
end
|
54
|
-
|
55
|
-
def inactive_cname_prefix
|
56
|
-
"#{@app}-#{@env_name}-inactive"
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.create(strategy_name, app, env_name, eb_driver, env_creation_opts={})
|
6
|
+
def self.create(env, strategy_name)
|
61
7
|
case strategy_name.to_s
|
62
8
|
when 'inplace_update', 'inplace-update'
|
63
|
-
InplaceUpdate.new(
|
9
|
+
InplaceUpdate.new(env)
|
64
10
|
when 'blue_green', 'blue-green'
|
65
|
-
BlueGreen.new(
|
11
|
+
BlueGreen.new(env)
|
66
12
|
else
|
67
13
|
raise 'strategy_name: ' + strategy_name.to_s + ' not supported'
|
68
14
|
end
|
69
|
-
|
70
15
|
end
|
71
16
|
end
|
72
17
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module EbDeployer
|
2
|
+
class EbEnvironment
|
3
|
+
attr_reader :app, :name
|
4
|
+
attr_writer :event_poller
|
5
|
+
|
6
|
+
def self.unique_ebenv_name(app_name, env_name)
|
7
|
+
raise "Environment name #{env_name} is too long, it must be under 15 chars" if env_name.size > 15
|
8
|
+
digest = Digest::SHA1.hexdigest(app_name + '-' + env_name)[0..6]
|
9
|
+
"#{env_name}-#{digest}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(app, env_name, eb_driver, creation_opts={})
|
13
|
+
@app = app
|
14
|
+
@name = self.class.unique_ebenv_name(app, env_name)
|
15
|
+
@bs = eb_driver
|
16
|
+
@creation_opts = creation_opts
|
17
|
+
end
|
18
|
+
|
19
|
+
def deploy(version_label, settings={})
|
20
|
+
terminate if @creation_opts[:phoenix_mode]
|
21
|
+
create_or_update_env(version_label, settings)
|
22
|
+
smoke_test
|
23
|
+
wait_for_env_become_healthy
|
24
|
+
end
|
25
|
+
|
26
|
+
def cname_prefix
|
27
|
+
@bs.environment_cname_prefix(@app, @name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def ==(another)
|
31
|
+
self.app == another.app && self.name == another.name
|
32
|
+
end
|
33
|
+
|
34
|
+
def swap_cname_with(another)
|
35
|
+
log("Swap CNAME with env #{another.name}")
|
36
|
+
@bs.environment_swap_cname(self.app, self.name, another.name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def log(msg)
|
40
|
+
puts "[#{Time.now.utc}][environment:#{@name}] #{msg}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def terminate
|
44
|
+
if @bs.environment_exists?(@app, @name)
|
45
|
+
with_polling_events(/terminateEnvironment completed successfully/i) do
|
46
|
+
@bs.delete_environment(@app, @name)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def create_or_update_env(version_label, settings)
|
55
|
+
if @bs.environment_exists?(@app, @name)
|
56
|
+
with_polling_events(/Environment update completed successfully/i) do
|
57
|
+
@bs.update_environment(@app, @name, version_label, @creation_opts[:tier], settings)
|
58
|
+
end
|
59
|
+
else
|
60
|
+
with_polling_events(/Successfully launched environment/i) do
|
61
|
+
@bs.create_environment(@app, @name, @creation_opts[:solution_stack], @creation_opts[:cname_prefix], version_label, @creation_opts[:tier], settings)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def smoke_test
|
67
|
+
host_name = @bs.environment_cname(@app, @name)
|
68
|
+
SmokeTest.new(@creation_opts[:smoke_test]).run(host_name, self)
|
69
|
+
end
|
70
|
+
|
71
|
+
def with_polling_events(terminate_pattern, &block)
|
72
|
+
event_start_time = Time.now
|
73
|
+
yield
|
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
|
82
|
+
|
83
|
+
log_event(event)
|
84
|
+
break if event[:message] =~ terminate_pattern
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def wait_for_env_become_healthy
|
89
|
+
Timeout.timeout(600) do
|
90
|
+
current_health_status = @bs.environment_health_state(@app, @name)
|
91
|
+
|
92
|
+
while current_health_status != 'Green'
|
93
|
+
log("health status: #{current_health_status}")
|
94
|
+
sleep 15
|
95
|
+
current_health_status = @bs.environment_health_state(@app, @name)
|
96
|
+
end
|
97
|
+
|
98
|
+
log("health status: #{current_health_status}")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def event_poller
|
103
|
+
@event_poller || EventPoller.new(@app, @name, @bs)
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
def log_event(event)
|
108
|
+
puts "[#{event[:event_date]}][environment:#{@name}] #{event[:message]}"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -1,111 +1,45 @@
|
|
1
1
|
module EbDeployer
|
2
2
|
class Environment
|
3
|
-
attr_reader :app, :name
|
4
|
-
attr_writer :event_poller
|
5
3
|
|
6
|
-
def
|
7
|
-
raise "Environment name #{env_name} is too long, it must be under 15 chars" if env_name.size > 15
|
8
|
-
digest = Digest::SHA1.hexdigest(app_name + '-' + env_name)[0..6]
|
9
|
-
"#{env_name}-#{digest}"
|
10
|
-
end
|
11
|
-
|
12
|
-
def initialize(app, env_name, eb_driver, creation_opts={})
|
4
|
+
def initialize(app, name, resource_stacks, settings, creation_opts, bs_driver)
|
13
5
|
@app = app
|
14
|
-
@name =
|
15
|
-
@
|
6
|
+
@name = name
|
7
|
+
@resource_stacks = resource_stacks
|
8
|
+
@settings = settings
|
16
9
|
@creation_opts = creation_opts
|
17
|
-
|
18
|
-
|
19
|
-
def deploy(version_label, settings={})
|
20
|
-
terminate if @creation_opts[:phoenix_mode]
|
21
|
-
create_or_update_env(version_label, settings)
|
22
|
-
smoke_test
|
23
|
-
wait_for_env_become_healthy
|
10
|
+
@bs_driver = bs_driver
|
24
11
|
end
|
25
12
|
|
26
13
|
def cname_prefix
|
27
|
-
@
|
28
|
-
end
|
29
|
-
|
30
|
-
def ==(another)
|
31
|
-
self.app == another.app && self.name == another.name
|
32
|
-
end
|
33
|
-
|
34
|
-
def swap_cname_with(another)
|
35
|
-
log("Swap CNAME with env #{another.name}")
|
36
|
-
@bs.environment_swap_cname(self.app, self.name, another.name)
|
14
|
+
@creation_opts[:cname_prefix] || default_cname_prefix
|
37
15
|
end
|
38
16
|
|
39
|
-
def
|
40
|
-
|
17
|
+
def deploy(version_label, strategy_name)
|
18
|
+
strategy = create_strategy(strategy_name)
|
19
|
+
strategy.deploy(version_label,
|
20
|
+
@settings + @resource_stacks.provision(resource_stack_name))
|
41
21
|
end
|
42
22
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
23
|
+
def new_eb_env(suffix=nil, cname_prefix_overriding=nil)
|
24
|
+
EbEnvironment.new(@app.name,
|
25
|
+
[@name, suffix].compact.join('-'),
|
26
|
+
@bs_driver,
|
27
|
+
@creation_opts.merge(:cname_prefix => cname_prefix_overriding || cname_prefix))
|
49
28
|
end
|
50
29
|
|
51
|
-
|
52
30
|
private
|
53
31
|
|
54
|
-
def
|
55
|
-
|
56
|
-
with_polling_events(/Environment update completed successfully/i) do
|
57
|
-
@bs.update_environment(@app, @name, version_label, @creation_opts[:tier], settings)
|
58
|
-
end
|
59
|
-
else
|
60
|
-
with_polling_events(/Successfully launched environment/i) do
|
61
|
-
@bs.create_environment(@app, @name, @creation_opts[:solution_stack], @creation_opts[:cname_prefix], version_label, @creation_opts[:tier], settings)
|
62
|
-
end
|
63
|
-
end
|
32
|
+
def default_cname_prefix
|
33
|
+
[@app.name, @name].join('-')
|
64
34
|
end
|
65
35
|
|
66
|
-
def smoke_test
|
67
|
-
host_name = @bs.environment_cname(@app, @name)
|
68
|
-
SmokeTest.new(@creation_opts[:smoke_test]).run(host_name, self)
|
69
|
-
end
|
70
36
|
|
71
|
-
def
|
72
|
-
|
73
|
-
yield
|
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
|
82
|
-
|
83
|
-
log_event(event)
|
84
|
-
break if event[:message] =~ terminate_pattern
|
85
|
-
end
|
37
|
+
def create_strategy(strategy_name)
|
38
|
+
DeploymentStrategy.create(self, strategy_name)
|
86
39
|
end
|
87
40
|
|
88
|
-
def
|
89
|
-
|
90
|
-
current_health_status = @bs.environment_health_state(@app, @name)
|
91
|
-
|
92
|
-
while current_health_status != 'Green'
|
93
|
-
log("health status: #{current_health_status}")
|
94
|
-
sleep 15
|
95
|
-
current_health_status = @bs.environment_health_state(@app, @name)
|
96
|
-
end
|
97
|
-
|
98
|
-
log("health status: #{current_health_status}")
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def event_poller
|
103
|
-
@event_poller || EventPoller.new(@app, @name, @bs)
|
104
|
-
end
|
105
|
-
|
106
|
-
|
107
|
-
def log_event(event)
|
108
|
-
puts "[#{event[:event_date]}][environment:#{@name}] #{event[:message]}"
|
41
|
+
def resource_stack_name
|
42
|
+
"#{@app.name}-#{@name}"
|
109
43
|
end
|
110
44
|
end
|
111
45
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module EbDeployer
|
2
|
+
class ResourceStacks
|
3
|
+
def initialize(resources, cf_driver, skip_provision=false)
|
4
|
+
@resources = resources
|
5
|
+
@cf_driver = cf_driver
|
6
|
+
@skip_provision = skip_provision
|
7
|
+
end
|
8
|
+
|
9
|
+
def provision(stack_name)
|
10
|
+
provisioner = CloudFormationProvisioner.new(stack_name, @cf_driver)
|
11
|
+
if @resources
|
12
|
+
provisioner.provision(@resources) unless @skip_provision
|
13
|
+
provisioner.transform_outputs(@resources)
|
14
|
+
else
|
15
|
+
[]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/eb_deployer/version.rb
CHANGED
data/lib/eb_deployer.rb
CHANGED
@@ -1,17 +1,3 @@
|
|
1
|
-
require "eb_deployer/version"
|
2
|
-
require "eb_deployer/deployment_strategy"
|
3
|
-
require "eb_deployer/beanstalk"
|
4
|
-
require "eb_deployer/cloud_formation_provisioner"
|
5
|
-
require 'eb_deployer/application'
|
6
|
-
require "eb_deployer/environment"
|
7
|
-
require "eb_deployer/event_poller"
|
8
|
-
require "eb_deployer/package"
|
9
|
-
require 'eb_deployer/s3_driver'
|
10
|
-
require 'eb_deployer/cloud_formation_driver'
|
11
|
-
require 'eb_deployer/config_loader'
|
12
|
-
require 'eb_deployer/default_config'
|
13
|
-
require 'eb_deployer/smoke_test'
|
14
|
-
require 'eb_deployer/version_cleaner'
|
15
1
|
require 'digest'
|
16
2
|
require 'set'
|
17
3
|
require 'time'
|
@@ -22,6 +8,21 @@ require 'optparse'
|
|
22
8
|
require 'erb'
|
23
9
|
require 'fileutils'
|
24
10
|
|
11
|
+
require 'eb_deployer/version'
|
12
|
+
require 'eb_deployer/aws_driver'
|
13
|
+
require 'eb_deployer/deployment_strategy'
|
14
|
+
require 'eb_deployer/cloud_formation_provisioner'
|
15
|
+
require 'eb_deployer/application'
|
16
|
+
require 'eb_deployer/resource_stacks'
|
17
|
+
require 'eb_deployer/eb_environment'
|
18
|
+
require 'eb_deployer/environment'
|
19
|
+
require 'eb_deployer/event_poller'
|
20
|
+
require 'eb_deployer/package'
|
21
|
+
require 'eb_deployer/config_loader'
|
22
|
+
require 'eb_deployer/default_config'
|
23
|
+
require 'eb_deployer/smoke_test'
|
24
|
+
require 'eb_deployer/version_cleaner'
|
25
|
+
|
25
26
|
module EbDeployer
|
26
27
|
|
27
28
|
TIERS = [
|
@@ -48,7 +49,7 @@ module EbDeployer
|
|
48
49
|
end
|
49
50
|
app = opts[:application]
|
50
51
|
env_name = opts[:environment]
|
51
|
-
cf = opts[:cf_driver] || CloudFormationDriver.new
|
52
|
+
cf = opts[:cf_driver] || AWSDriver::CloudFormationDriver.new
|
52
53
|
provisioner = CloudFormationProvisioner.new("#{app}-#{env_name}", cf)
|
53
54
|
provisioner.output(key)
|
54
55
|
end
|
@@ -177,9 +178,9 @@ module EbDeployer
|
|
177
178
|
AWS.config(:region => region)
|
178
179
|
end
|
179
180
|
|
180
|
-
bs = opts[:bs_driver] || Beanstalk.new
|
181
|
-
s3 = opts[:s3_driver] || S3Driver.new
|
182
|
-
cf = opts[:cf_driver] || CloudFormationDriver.new
|
181
|
+
bs = opts[:bs_driver] || AWSDriver::Beanstalk.new
|
182
|
+
s3 = opts[:s3_driver] || AWSDriver::S3Driver.new
|
183
|
+
cf = opts[:cf_driver] || AWSDriver::CloudFormationDriver.new
|
183
184
|
stack_name = opts[:solution_stack_name] || "64bit Amazon Linux 2013.09 running Tomcat 7 Java 7"
|
184
185
|
app = opts[:application]
|
185
186
|
env_name = opts[:environment]
|
@@ -188,7 +189,7 @@ module EbDeployer
|
|
188
189
|
cname = opts[:cname]
|
189
190
|
env_settings = opts[:option_settings] || opts[:settings] || []
|
190
191
|
strategy_name = opts[:strategy] || :blue_green
|
191
|
-
cname_prefix = opts[:cname_prefix]
|
192
|
+
cname_prefix = opts[:cname_prefix]
|
192
193
|
smoke_test = opts[:smoke_test] || Proc.new {}
|
193
194
|
phoenix_mode = opts[:phoenix_mode]
|
194
195
|
bucket = opts[:package_bucket] || app
|
@@ -196,30 +197,24 @@ module EbDeployer
|
|
196
197
|
keep_latest = opts[:keep_latest].to_i || 0
|
197
198
|
app_tier = self.environment_tier(opts[:tier] || 'WebServer')
|
198
199
|
|
200
|
+
resource_stacks = ResourceStacks.new(opts[:resources], cf, skip_resource)
|
199
201
|
application = Application.new(app, bs, s3, bucket)
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
cleaner = VersionCleaner.new(application, keep_latest)
|
214
|
-
|
215
|
-
if resources = opts[:resources]
|
216
|
-
cf.provision(resources) unless skip_resource
|
217
|
-
env_settings += cf.transform_outputs(resources)
|
218
|
-
end
|
202
|
+
environment = Environment.new(application,
|
203
|
+
env_name,
|
204
|
+
resource_stacks,
|
205
|
+
env_settings,
|
206
|
+
{
|
207
|
+
:solution_stack => stack_name,
|
208
|
+
:cname_prefix => cname_prefix,
|
209
|
+
:smoke_test => smoke_test,
|
210
|
+
:phoenix_mode => phoenix_mode,
|
211
|
+
:tier => app_tier
|
212
|
+
},
|
213
|
+
bs)
|
219
214
|
|
220
215
|
application.create_version(version_label, opts[:package])
|
221
|
-
|
222
|
-
|
216
|
+
environment.deploy(version_label, strategy_name)
|
217
|
+
application.clean_versions(version_prefix, keep_latest)
|
223
218
|
end
|
224
219
|
|
225
220
|
def self.destroy(opts)
|
@@ -313,7 +308,6 @@ module EbDeployer
|
|
313
308
|
puts "YAML package file format:"
|
314
309
|
puts "s3_bucket: <bucket_name>"
|
315
310
|
puts "s3_key: <object_path>"
|
316
|
-
exit(0)
|
317
311
|
end
|
318
312
|
end
|
319
313
|
end
|
data/test/config_loader_test.rb
CHANGED
@@ -25,19 +25,6 @@ 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
|
-
|
41
28
|
def test_common_settings_get_merge_into_the_config
|
42
29
|
config = @loader.load(generate_input(<<-YAML))
|
43
30
|
application: myapp
|
data/test/deploy_test.rb
CHANGED
@@ -432,6 +432,17 @@ class DeployTest < MiniTest::Unit::TestCase
|
|
432
432
|
assert_equal({'s3_bucket' => 'test-bucket', 's3_key' => 'test-mingle.war'}, last_version[:source_bundle])
|
433
433
|
end
|
434
434
|
|
435
|
+
=begin
|
436
|
+
def test_deploy_with_components
|
437
|
+
deploy(:application => 'simple',
|
438
|
+
:environment => 'production',
|
439
|
+
:components => [{ :name => 'web' }])
|
440
|
+
|
441
|
+
assert !@eb_driver.environment_exists?('simple', eb_envname('simple', 'production'))
|
442
|
+
|
443
|
+
end
|
444
|
+
=end
|
445
|
+
|
435
446
|
private
|
436
447
|
|
437
448
|
def temp_file(content)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
class
|
3
|
+
class EbEnvironmentTest < MiniTest::Unit::TestCase
|
4
4
|
class PollerStub
|
5
5
|
class Deadloop < StandardError; end
|
6
6
|
|
@@ -25,13 +25,13 @@ class EnvironmentTest < MiniTest::Unit::TestCase
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def test_deploy_should_create_corresponding_eb_env
|
28
|
-
env = EbDeployer::
|
28
|
+
env = EbDeployer::EbEnvironment.new("myapp", "production", @eb_driver)
|
29
29
|
env.deploy("version1")
|
30
30
|
assert @eb_driver.environment_exists?('myapp', eb_envname('myapp', 'production'))
|
31
31
|
end
|
32
32
|
|
33
33
|
def test_deploy_again_should_update_environment
|
34
|
-
env = EbDeployer::
|
34
|
+
env = EbDeployer::EbEnvironment.new("myapp", "production", @eb_driver)
|
35
35
|
env.deploy("version1")
|
36
36
|
env.deploy("version2")
|
37
37
|
assert @eb_driver.environment_exists?('myapp', eb_envname('myapp', 'production'))
|
@@ -39,14 +39,14 @@ class EnvironmentTest < MiniTest::Unit::TestCase
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def test_option_setttings_get_set_on_eb_env
|
42
|
-
env = EbDeployer::
|
42
|
+
env = EbDeployer::EbEnvironment.new("myapp", "production", @eb_driver)
|
43
43
|
env.deploy("version1", {s1: 'v1'})
|
44
44
|
assert_equal({s1: 'v1' }, @eb_driver.environment_settings('myapp', eb_envname('myapp', 'production')))
|
45
45
|
end
|
46
46
|
|
47
47
|
def test_should_run_smoke_test_after_deploy
|
48
48
|
smoked_host = nil
|
49
|
-
env = EbDeployer::
|
49
|
+
env = EbDeployer::EbEnvironment.new("myapp", "production", @eb_driver, :smoke_test => Proc.new { |host| smoked_host = host })
|
50
50
|
env.deploy("version1")
|
51
51
|
|
52
52
|
assert !smoked_host.nil?
|
@@ -54,13 +54,13 @@ class EnvironmentTest < MiniTest::Unit::TestCase
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def test_should_raise_runtime_error_when_deploy_failed
|
57
|
-
env = EbDeployer::
|
57
|
+
env = EbDeployer::EbEnvironment.new("myapp", "production", @eb_driver)
|
58
58
|
env.event_poller = PollerStub.new(["start deploying", "Failed to deploy application"])
|
59
59
|
assert_raises(RuntimeError) { env.deploy("version 1") }
|
60
60
|
end
|
61
61
|
|
62
62
|
def test_should_raise_runtime_error_when_eb_extension_execution_failed
|
63
|
-
env = EbDeployer::
|
63
|
+
env = EbDeployer::EbEnvironment.new("myapp", "production", @eb_driver)
|
64
64
|
|
65
65
|
env.event_poller = PollerStub.new(["start deploying",
|
66
66
|
"create environment",
|
@@ -72,7 +72,7 @@ class EnvironmentTest < MiniTest::Unit::TestCase
|
|
72
72
|
|
73
73
|
|
74
74
|
def test_terminate_should_delete_environment
|
75
|
-
env = EbDeployer::
|
75
|
+
env = EbDeployer::EbEnvironment.new("myapp", "production", @eb_driver)
|
76
76
|
env.deploy("version1")
|
77
77
|
env.terminate
|
78
78
|
assert !@eb_driver.environment_exists?('myapp', eb_envname('myapp', 'production'))
|
data/test/test_helper.rb
CHANGED
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.3.
|
4
|
+
version: 0.3.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-03-
|
13
|
+
date: 2014-03-26 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: aws-sdk
|
@@ -40,6 +40,7 @@ files:
|
|
40
40
|
- .gitignore
|
41
41
|
- .ruby-gemset
|
42
42
|
- .ruby-version
|
43
|
+
- .travis.yml
|
43
44
|
- Gemfile
|
44
45
|
- LICENSE
|
45
46
|
- README.md
|
@@ -48,17 +49,22 @@ files:
|
|
48
49
|
- eb_deployer.gemspec
|
49
50
|
- lib/eb_deployer.rb
|
50
51
|
- lib/eb_deployer/application.rb
|
51
|
-
- lib/eb_deployer/
|
52
|
-
- lib/eb_deployer/
|
52
|
+
- lib/eb_deployer/aws_driver.rb
|
53
|
+
- lib/eb_deployer/aws_driver/beanstalk.rb
|
54
|
+
- lib/eb_deployer/aws_driver/cloud_formation_driver.rb
|
55
|
+
- lib/eb_deployer/aws_driver/s3_driver.rb
|
53
56
|
- lib/eb_deployer/cloud_formation_provisioner.rb
|
54
57
|
- lib/eb_deployer/config_loader.rb
|
55
58
|
- lib/eb_deployer/default_config.rb
|
56
59
|
- lib/eb_deployer/default_config.yml
|
57
60
|
- lib/eb_deployer/deployment_strategy.rb
|
61
|
+
- lib/eb_deployer/deployment_strategy/blue_green.rb
|
62
|
+
- lib/eb_deployer/deployment_strategy/inplace_update.rb
|
63
|
+
- lib/eb_deployer/eb_environment.rb
|
58
64
|
- lib/eb_deployer/environment.rb
|
59
65
|
- lib/eb_deployer/event_poller.rb
|
60
66
|
- lib/eb_deployer/package.rb
|
61
|
-
- lib/eb_deployer/
|
67
|
+
- lib/eb_deployer/resource_stacks.rb
|
62
68
|
- lib/eb_deployer/smoke_test.rb
|
63
69
|
- lib/eb_deployer/version.rb
|
64
70
|
- lib/eb_deployer/version_cleaner.rb
|
@@ -66,7 +72,7 @@ files:
|
|
66
72
|
- test/cloud_formation_provisioner_test.rb
|
67
73
|
- test/config_loader_test.rb
|
68
74
|
- test/deploy_test.rb
|
69
|
-
- test/
|
75
|
+
- test/eb_environment_test.rb
|
70
76
|
- test/smoke_test_test.rb
|
71
77
|
- test/test_helper.rb
|
72
78
|
homepage: https://github.com/ThoughtWorksStudios/eb_deployer
|
@@ -82,15 +88,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
82
88
|
- - ! '>='
|
83
89
|
- !ruby/object:Gem::Version
|
84
90
|
version: '0'
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
hash: 1041206842017006108
|
85
94
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
95
|
none: false
|
87
96
|
requirements:
|
88
97
|
- - ! '>='
|
89
98
|
- !ruby/object:Gem::Version
|
90
99
|
version: '0'
|
100
|
+
segments:
|
101
|
+
- 0
|
102
|
+
hash: 1041206842017006108
|
91
103
|
requirements: []
|
92
104
|
rubyforge_project:
|
93
|
-
rubygems_version: 1.8.
|
105
|
+
rubygems_version: 1.8.29
|
94
106
|
signing_key:
|
95
107
|
specification_version: 3
|
96
108
|
summary: Low friction deployments should be a breeze. Elastic Beanstalk provides a
|
@@ -101,7 +113,7 @@ test_files:
|
|
101
113
|
- test/cloud_formation_provisioner_test.rb
|
102
114
|
- test/config_loader_test.rb
|
103
115
|
- test/deploy_test.rb
|
104
|
-
- test/
|
116
|
+
- test/eb_environment_test.rb
|
105
117
|
- test/smoke_test_test.rb
|
106
118
|
- test/test_helper.rb
|
107
119
|
has_rdoc:
|
@@ -1,126 +0,0 @@
|
|
1
|
-
module EbDeployer
|
2
|
-
class Beanstalk
|
3
|
-
attr_reader :client
|
4
|
-
|
5
|
-
def initialize(client=AWS::ElasticBeanstalk.new.client)
|
6
|
-
@client = client
|
7
|
-
end
|
8
|
-
|
9
|
-
def create_application(app)
|
10
|
-
@client.create_application(:application_name => app)
|
11
|
-
end
|
12
|
-
|
13
|
-
def delete_application(app)
|
14
|
-
@client.delete_application(:application_name => app)
|
15
|
-
end
|
16
|
-
|
17
|
-
def application_exists?(app)
|
18
|
-
@client.describe_applications(:application_names => [app])[:applications].any?
|
19
|
-
end
|
20
|
-
|
21
|
-
def update_environment(app_name, env_name, version, tier, settings)
|
22
|
-
env_id = convert_env_name_to_id(app_name, [env_name]).first
|
23
|
-
request = {
|
24
|
-
:environment_id => env_id,
|
25
|
-
:version_label => version,
|
26
|
-
:option_settings => settings,
|
27
|
-
:tier => tier
|
28
|
-
}
|
29
|
-
|
30
|
-
@client.update_environment(request)
|
31
|
-
end
|
32
|
-
|
33
|
-
def environment_exists?(app_name, env_name)
|
34
|
-
alive_envs(app_name, [env_name]).any?
|
35
|
-
end
|
36
|
-
|
37
|
-
def environment_names_for_application(app_name)
|
38
|
-
alive_envs(app_name).collect { |env| env[:environment_name] }
|
39
|
-
end
|
40
|
-
|
41
|
-
def create_environment(app_name, env_name, stack_name, cname_prefix, version, tier, settings)
|
42
|
-
request = {
|
43
|
-
:application_name => app_name,
|
44
|
-
:environment_name => env_name,
|
45
|
-
:solution_stack_name => stack_name,
|
46
|
-
:version_label => version,
|
47
|
-
:option_settings => settings,
|
48
|
-
:tier => tier,
|
49
|
-
:cname_prefix => cname_prefix
|
50
|
-
}
|
51
|
-
|
52
|
-
@client.create_environment(request)
|
53
|
-
end
|
54
|
-
|
55
|
-
def delete_environment(app_name, env_name)
|
56
|
-
@client.terminate_environment(:environment_name => env_name)
|
57
|
-
end
|
58
|
-
|
59
|
-
def delete_application_version(app_name, version, delete_source_bundle)
|
60
|
-
request = {
|
61
|
-
:application_name => app_name,
|
62
|
-
:version_label => version,
|
63
|
-
:delete_source_bundle => delete_source_bundle
|
64
|
-
}
|
65
|
-
@client.delete_application_version(request)
|
66
|
-
end
|
67
|
-
|
68
|
-
def create_application_version(app_name, version_label, source_bundle)
|
69
|
-
@client.create_application_version(:application_name => app_name,
|
70
|
-
:source_bundle => source_bundle,
|
71
|
-
:version_label => version_label)
|
72
|
-
end
|
73
|
-
|
74
|
-
def application_version_labels(app_name)
|
75
|
-
application_versions(app_name).map { |apv| apv[:version_label] }
|
76
|
-
end
|
77
|
-
|
78
|
-
def application_versions(app_name)
|
79
|
-
request = { :application_name => app_name }
|
80
|
-
@client.describe_application_versions(request)[:application_versions]
|
81
|
-
end
|
82
|
-
|
83
|
-
def fetch_events(app_name, env_name, params, &block)
|
84
|
-
response = @client.describe_events(params.merge(:application_name => app_name,
|
85
|
-
:environment_name => env_name))
|
86
|
-
return [response[:events], response[:next_token]]
|
87
|
-
end
|
88
|
-
|
89
|
-
def environment_cname_prefix(app_name, env_name)
|
90
|
-
cname = environment_cname(app_name, env_name)
|
91
|
-
if cname =~ /^(.+)\.elasticbeanstalk\.com/
|
92
|
-
$1
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def environment_cname(app_name, env_name)
|
97
|
-
env = alive_envs(app_name, [env_name]).first
|
98
|
-
env && env[:cname]
|
99
|
-
end
|
100
|
-
|
101
|
-
def environment_health_state(app_name, env_name)
|
102
|
-
env = alive_envs(app_name, [env_name]).first
|
103
|
-
env && env[:health]
|
104
|
-
end
|
105
|
-
|
106
|
-
def environment_swap_cname(app_name, env1, env2)
|
107
|
-
env1_id, env2_id = convert_env_name_to_id(app_name, [env1, env2])
|
108
|
-
@client.swap_environment_cnam_es(:source_environment_id => env1_id,
|
109
|
-
:destination_environment_id => env2_id)
|
110
|
-
end
|
111
|
-
|
112
|
-
private
|
113
|
-
|
114
|
-
def convert_env_name_to_id(app_name, env_names)
|
115
|
-
envs = alive_envs(app_name, env_names)
|
116
|
-
envs.map { |env| env[:environment_id] }
|
117
|
-
end
|
118
|
-
|
119
|
-
def alive_envs(app_name, env_names=[])
|
120
|
-
envs = @client.describe_environments(:application_name => app_name, :environment_names => env_names)[:environments]
|
121
|
-
|
122
|
-
envs.select {|e| e[:status] != 'Terminated' }
|
123
|
-
end
|
124
|
-
|
125
|
-
end
|
126
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
module EbDeployer
|
2
|
-
class CloudFormationDriver
|
3
|
-
|
4
|
-
def stack_exists?(name)
|
5
|
-
stack(name).exists?
|
6
|
-
end
|
7
|
-
|
8
|
-
def create_stack(name, template, opts)
|
9
|
-
cloud_formation.stacks.create(name, template, opts)
|
10
|
-
end
|
11
|
-
|
12
|
-
def update_stack(name, template, opts)
|
13
|
-
begin
|
14
|
-
stack(name).update(opts.merge(:template => template))
|
15
|
-
rescue AWS::CloudFormation::Errors::ValidationError => e
|
16
|
-
if e.message =~ /No updates are to be performed/
|
17
|
-
log(e.message)
|
18
|
-
else
|
19
|
-
raise
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def stack_status(name)
|
25
|
-
stack(name).status.downcase.to_sym
|
26
|
-
end
|
27
|
-
|
28
|
-
def query_output(name, key)
|
29
|
-
output = stack(name).outputs.find { |o| o.key == key }
|
30
|
-
output && output.value
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def cloud_formation
|
36
|
-
AWS::CloudFormation.new
|
37
|
-
end
|
38
|
-
|
39
|
-
def stack(name)
|
40
|
-
cloud_formation.stacks[name]
|
41
|
-
end
|
42
|
-
|
43
|
-
def log(msg)
|
44
|
-
puts "[#{Time.now.utc}][cloud_formation_driver] #{msg}"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
module EbDeployer
|
2
|
-
class S3Driver
|
3
|
-
def create_bucket(bucket_name)
|
4
|
-
buckets.create(bucket_name)
|
5
|
-
end
|
6
|
-
|
7
|
-
def bucket_exists?(bucket_name)
|
8
|
-
buckets[bucket_name].exists?
|
9
|
-
end
|
10
|
-
|
11
|
-
def object_length(bucket_name, obj_name)
|
12
|
-
obj(bucket_name, obj_name).content_length rescue nil
|
13
|
-
end
|
14
|
-
|
15
|
-
def upload_file(bucket_name, obj_name, file)
|
16
|
-
o = obj(bucket_name, obj_name)
|
17
|
-
File.open(file) { |f| o.write(f) }
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
def s3
|
22
|
-
AWS::S3.new
|
23
|
-
end
|
24
|
-
|
25
|
-
def obj(bucket_name, obj_name)
|
26
|
-
buckets[bucket_name].objects[obj_name]
|
27
|
-
end
|
28
|
-
|
29
|
-
def buckets
|
30
|
-
s3.buckets
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|