man_eb_deployer 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/release.yml +31 -0
- data/.github/workflows/test.yml +16 -0
- data/.gitignore +12 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +143 -0
- data/Gemfile +10 -0
- data/LICENSE +22 -0
- data/README.md +138 -0
- data/Rakefile +12 -0
- data/TODOS.md +11 -0
- data/bin/eb_deploy +13 -0
- data/eb_deployer.gemspec +22 -0
- data/lib/eb_deployer/application.rb +96 -0
- data/lib/eb_deployer/aws_driver/beanstalk.rb +158 -0
- data/lib/eb_deployer/aws_driver/cloud_formation_driver.rb +53 -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/cf_event_source.rb +26 -0
- data/lib/eb_deployer/cloud_formation_provisioner.rb +120 -0
- data/lib/eb_deployer/component.rb +45 -0
- data/lib/eb_deployer/config_loader.rb +64 -0
- data/lib/eb_deployer/default_component.rb +32 -0
- data/lib/eb_deployer/default_config.rb +20 -0
- data/lib/eb_deployer/default_config.yml +159 -0
- data/lib/eb_deployer/deployment_strategy/blue_green.rb +79 -0
- data/lib/eb_deployer/deployment_strategy/blue_only.rb +45 -0
- data/lib/eb_deployer/deployment_strategy/inplace_update.rb +16 -0
- data/lib/eb_deployer/deployment_strategy.rb +20 -0
- data/lib/eb_deployer/eb_environment.rb +204 -0
- data/lib/eb_deployer/eb_event_source.rb +35 -0
- data/lib/eb_deployer/environment.rb +60 -0
- data/lib/eb_deployer/event_poller.rb +51 -0
- data/lib/eb_deployer/package.rb +39 -0
- data/lib/eb_deployer/resource_stacks.rb +20 -0
- data/lib/eb_deployer/smoke_test.rb +23 -0
- data/lib/eb_deployer/tasks.rb +45 -0
- data/lib/eb_deployer/throttling_handling.rb +17 -0
- data/lib/eb_deployer/utils.rb +33 -0
- data/lib/eb_deployer/version.rb +3 -0
- data/lib/eb_deployer/version_cleaner.rb +30 -0
- data/lib/eb_deployer.rb +339 -0
- data/lib/generators/eb_deployer/install/install_generator.rb +82 -0
- data/lib/generators/eb_deployer/install/templates/eb_deployer.rake +1 -0
- data/lib/generators/eb_deployer/install/templates/eb_deployer.yml.erb +181 -0
- data/lib/generators/eb_deployer/install/templates/ebextensions/01_postgres_packages.config +5 -0
- data/lib/generators/eb_deployer/install/templates/postgres_rds.json +88 -0
- data/test/aws_driver_stubs.rb +350 -0
- data/test/beanstalk_test.rb +23 -0
- data/test/blue_green_deploy_test.rb +114 -0
- data/test/blue_only_deploy_test.rb +78 -0
- data/test/cf_event_poller_test.rb +32 -0
- data/test/cloud_formation_provisioner_test.rb +47 -0
- data/test/config_loader_test.rb +205 -0
- data/test/deploy_test.rb +42 -0
- data/test/eb_environment_test.rb +120 -0
- data/test/eb_event_poller_test.rb +32 -0
- data/test/inplace_update_deploy_test.rb +110 -0
- data/test/multi_components_deploy_test.rb +164 -0
- data/test/rails_generators_test.rb +67 -0
- data/test/resources_deploy_test.rb +191 -0
- data/test/smoke_test_test.rb +23 -0
- data/test/template_deploy_test.rb +13 -0
- data/test/test_helper.rb +68 -0
- data/test/tier_setting_deploy_test.rb +24 -0
- data/test/versions_deploy_test.rb +120 -0
- metadata +176 -0
@@ -0,0 +1,158 @@
|
|
1
|
+
module EbDeployer
|
2
|
+
module AWSDriver
|
3
|
+
class Beanstalk
|
4
|
+
include Utils
|
5
|
+
attr_reader :client
|
6
|
+
|
7
|
+
def initialize(client=Aws::ElasticBeanstalk::Client.new)
|
8
|
+
@client = client
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_application(app)
|
12
|
+
@client.create_application(:application_name => app)
|
13
|
+
end
|
14
|
+
|
15
|
+
def delete_application(app)
|
16
|
+
@client.delete_application(:application_name => app)
|
17
|
+
end
|
18
|
+
|
19
|
+
def application_exists?(app)
|
20
|
+
@client.describe_applications(:application_names => [app])[:applications].any?
|
21
|
+
end
|
22
|
+
|
23
|
+
def update_environment_settings(app, env, settings)
|
24
|
+
env_id = convert_env_name_to_id(app, [env]).first
|
25
|
+
@client.update_environment(:environment_id => env_id, :option_settings => settings)
|
26
|
+
end
|
27
|
+
|
28
|
+
def update_environment(app_name, env_name, version, tier, settings, template_name)
|
29
|
+
env_id = convert_env_name_to_id(app_name, [env_name]).first
|
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)
|
38
|
+
end
|
39
|
+
|
40
|
+
def environment_exists?(app_name, env_name)
|
41
|
+
alive_envs(app_name, [env_name]).any?
|
42
|
+
end
|
43
|
+
|
44
|
+
def environment_names_for_application(app_name)
|
45
|
+
alive_envs(app_name).collect { |env| env[:environment_name] }
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_environment(app_name, env_name, stack_name, cname_prefix, version, tier, tags, settings, template_name)
|
49
|
+
request = reject_nil({
|
50
|
+
:application_name => app_name,
|
51
|
+
:environment_name => env_name,
|
52
|
+
:solution_stack_name => stack_name,
|
53
|
+
:version_label => version,
|
54
|
+
:option_settings => settings,
|
55
|
+
:tier => environment_tier(tier),
|
56
|
+
:cname_prefix => cname_prefix,
|
57
|
+
:tags => tags,
|
58
|
+
:template_name => template_name
|
59
|
+
})
|
60
|
+
@client.create_environment(request)
|
61
|
+
end
|
62
|
+
|
63
|
+
def delete_environment(app_name, env_name)
|
64
|
+
@client.terminate_environment(:environment_name => env_name)
|
65
|
+
end
|
66
|
+
|
67
|
+
def delete_application_version(app_name, version, delete_source_bundle)
|
68
|
+
request = {
|
69
|
+
:application_name => app_name,
|
70
|
+
:version_label => version,
|
71
|
+
:delete_source_bundle => delete_source_bundle
|
72
|
+
}
|
73
|
+
@client.delete_application_version(request)
|
74
|
+
end
|
75
|
+
|
76
|
+
def create_application_version(app_name, version_label, source_bundle)
|
77
|
+
@client.create_application_version(:application_name => app_name,
|
78
|
+
:source_bundle => source_bundle,
|
79
|
+
:version_label => version_label)
|
80
|
+
end
|
81
|
+
|
82
|
+
def application_version_labels(app_name)
|
83
|
+
application_versions(app_name).map { |apv| apv[:version_label] }
|
84
|
+
end
|
85
|
+
|
86
|
+
def application_versions(app_name)
|
87
|
+
request = { :application_name => app_name }
|
88
|
+
@client.describe_application_versions(request)[:application_versions]
|
89
|
+
end
|
90
|
+
|
91
|
+
def fetch_events(app_name, env_name, params, &block)
|
92
|
+
response = @client.describe_events(params.merge(:application_name => app_name,
|
93
|
+
:environment_name => env_name))
|
94
|
+
return [response[:events], response[:next_token]]
|
95
|
+
end
|
96
|
+
|
97
|
+
def environment_cname_prefix(app_name, env_name)
|
98
|
+
cname = environment_cname(app_name, env_name)
|
99
|
+
if cname =~ /^([^\.]+)(?:\.(?:[a-z0-9\-]+))?\.elasticbeanstalk\.com/i
|
100
|
+
$1
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def environment_cname(app_name, env_name)
|
105
|
+
get_environment_attribute(app_name, env_name, :cname)
|
106
|
+
end
|
107
|
+
|
108
|
+
def environment_health_state(app_name, env_name)
|
109
|
+
get_environment_attribute(app_name, env_name, :health)
|
110
|
+
end
|
111
|
+
|
112
|
+
def environment_status(app_name, env_name)
|
113
|
+
get_environment_attribute(app_name, env_name, :status)
|
114
|
+
end
|
115
|
+
|
116
|
+
def environment_verion_label(app_name, env_name)
|
117
|
+
get_environment_attribute(app_name, env_name, :version_label)
|
118
|
+
end
|
119
|
+
|
120
|
+
def environment_swap_cname(app_name, env1, env2)
|
121
|
+
env1_id, env2_id = convert_env_name_to_id(app_name, [env1, env2])
|
122
|
+
@client.swap_environment_cnames(:source_environment_id => env1_id,
|
123
|
+
:destination_environment_id => env2_id)
|
124
|
+
end
|
125
|
+
|
126
|
+
def list_solution_stack_names
|
127
|
+
@client.list_available_solution_stacks[:solution_stacks]
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
TIERS = [
|
133
|
+
{:name=>"Worker", :type=>"SQS/HTTP"},
|
134
|
+
{:name=>"WebServer", :type=>"Standard"}
|
135
|
+
]
|
136
|
+
|
137
|
+
def get_environment_attribute(app_name, env_name, attribute)
|
138
|
+
env = alive_envs(app_name, [env_name]).first
|
139
|
+
env && env[attribute]
|
140
|
+
end
|
141
|
+
|
142
|
+
def environment_tier(name)
|
143
|
+
TIERS.find {|t| t[:name].downcase == name.downcase} || raise("No tier found with name #{name.inspect}")
|
144
|
+
end
|
145
|
+
|
146
|
+
def convert_env_name_to_id(app_name, env_names)
|
147
|
+
envs = alive_envs(app_name, env_names)
|
148
|
+
envs.map { |env| env[:environment_id] }
|
149
|
+
end
|
150
|
+
|
151
|
+
def alive_envs(app_name, env_names=[])
|
152
|
+
envs = @client.describe_environments(:application_name => app_name, :environment_names => env_names)[:environments]
|
153
|
+
|
154
|
+
envs.select {|e| e[:status] != 'Terminated' }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module EbDeployer
|
2
|
+
module AWSDriver
|
3
|
+
class CloudFormationDriver
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@client = Aws::CloudFormation::Client.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def stack_exists?(name)
|
10
|
+
describe_stack(name)
|
11
|
+
true
|
12
|
+
rescue Aws::CloudFormation::Errors::ValidationError
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_stack(name, template, opts)
|
17
|
+
@client.create_stack(opts.merge(:stack_name => name,
|
18
|
+
:template_body => template,
|
19
|
+
:parameters => convert_parameters(opts[:parameters])))
|
20
|
+
end
|
21
|
+
|
22
|
+
def update_stack(name, template, opts)
|
23
|
+
@client.update_stack(opts.merge(:stack_name => name,
|
24
|
+
:template_body => template,
|
25
|
+
:parameters => convert_parameters(opts[:parameters])))
|
26
|
+
end
|
27
|
+
|
28
|
+
def query_output(name, key)
|
29
|
+
output = describe_stack(name)[:outputs].find { |o| o[:output_key] == key }
|
30
|
+
output && output[:output_value]
|
31
|
+
end
|
32
|
+
|
33
|
+
def fetch_events(name, options={})
|
34
|
+
response = @client.describe_stack_events(options.merge(:stack_name => name))
|
35
|
+
return response.stack_events, response.next_token
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def describe_stack(name)
|
41
|
+
@client.describe_stacks(:stack_name => name)[:stacks].first
|
42
|
+
end
|
43
|
+
|
44
|
+
def log(msg)
|
45
|
+
puts "[#{Time.now.utc}][cloud_formation_driver] #{msg}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def convert_parameters(params)
|
49
|
+
params.map { |k, v| {:parameter_key => k, :parameter_value => v}}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module EbDeployer
|
2
|
+
module AWSDriver
|
3
|
+
class S3Driver
|
4
|
+
def create_bucket(bucket_name)
|
5
|
+
s3.create_bucket(:bucket => bucket_name)
|
6
|
+
end
|
7
|
+
|
8
|
+
def bucket_exists?(bucket_name)
|
9
|
+
s3.bucket(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
|
+
o.upload_file(file)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def s3
|
23
|
+
Aws::S3::Resource.new(client: Aws::S3::Client.new)
|
24
|
+
end
|
25
|
+
|
26
|
+
def obj(bucket_name, obj_name)
|
27
|
+
s3.bucket(bucket_name).object(obj_name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def buckets
|
31
|
+
s3.buckets
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module EbDeployer
|
2
|
+
class CfEventSource
|
3
|
+
def initialize(stack_name, cf_driver)
|
4
|
+
@stack_name = stack_name
|
5
|
+
@cf_driver = cf_driver
|
6
|
+
end
|
7
|
+
|
8
|
+
def get_anchor
|
9
|
+
events, _ = @cf_driver.fetch_events(@stack_name)
|
10
|
+
events.first
|
11
|
+
end
|
12
|
+
|
13
|
+
def fetch_events(from_anchor, &block)
|
14
|
+
events, next_token = @cf_driver.fetch_events(@stack_name)
|
15
|
+
should_continue = yield(events)
|
16
|
+
fetch_next(next_token, &block) if next_token && should_continue
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def fetch_next(next_token, &block)
|
21
|
+
events, next_token = @cf_driver.fetch_events(@stack_name, :next_token => next_token)
|
22
|
+
should_continue = yield(events)
|
23
|
+
fetch_next(next_token, &block) if next_token && should_continue
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module EbDeployer
|
2
|
+
class ResourceNotInReadyState < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class CloudFormationProvisioner
|
6
|
+
SUCCESS_STATS = ["CREATE_COMPLETE", "UPDATE_COMPLETE"]
|
7
|
+
FAILED_STATS = ["CREATE_FAILED", "UPDATE_FAILED", "UPDATE_ROLLBACK_COMPLETE"]
|
8
|
+
|
9
|
+
def initialize(stack_name, cf_driver)
|
10
|
+
@stack_name = stack_name
|
11
|
+
@cf_driver = cf_driver
|
12
|
+
@poller = EventPoller.new(CfEventSource.new(@stack_name, @cf_driver))
|
13
|
+
end
|
14
|
+
|
15
|
+
def provision(resources, tags)
|
16
|
+
resources = symbolize_keys(resources)
|
17
|
+
template = File.read(resources[:template])
|
18
|
+
capabilities = resources[:capabilities] || []
|
19
|
+
params = resources[:inputs] || resources[:parameters] || {}
|
20
|
+
policy = File.read(resources[:policy]) if resources[:policy]
|
21
|
+
override_policy = resources[:override_policy] || false
|
22
|
+
anchor = nil
|
23
|
+
begin
|
24
|
+
if stack_exists?
|
25
|
+
anchor = @poller.get_anchor
|
26
|
+
update_stack(template, params, capabilities, policy, override_policy, tags)
|
27
|
+
else
|
28
|
+
create_stack(template, params, capabilities, policy, tags)
|
29
|
+
end
|
30
|
+
rescue Aws::CloudFormation::Errors::ValidationError => e
|
31
|
+
if e.message =~ /No updates are to be performed/
|
32
|
+
log(e.message)
|
33
|
+
return
|
34
|
+
else
|
35
|
+
raise
|
36
|
+
end
|
37
|
+
end
|
38
|
+
wait_for_stack_op_terminate(anchor)
|
39
|
+
log("Resource stack provisioned successfully")
|
40
|
+
end
|
41
|
+
|
42
|
+
def transform_outputs(resources)
|
43
|
+
resources = symbolize_keys(resources)
|
44
|
+
outputs = resources[:outputs] || {}
|
45
|
+
transforms = resources[:transforms] || {}
|
46
|
+
transform_output_to_settings(convert_to_transforms(outputs).merge(transforms))
|
47
|
+
end
|
48
|
+
|
49
|
+
def output(key)
|
50
|
+
@cf_driver.query_output(@stack_name, key)
|
51
|
+
rescue Aws::CloudFormation::Errors::ValidationError
|
52
|
+
raise ResourceNotInReadyState.new("Resource stack not in ready state yet, perhaps you should provision it first?")
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
#todo: remove duplication
|
58
|
+
def symbolize_keys(hash)
|
59
|
+
hash.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def convert_to_transforms(outputs)
|
64
|
+
outputs.inject({}) do |memo, (key, value)|
|
65
|
+
memo[key] = lambda { |output_value| value.merge('value' => output_value) }
|
66
|
+
memo
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def update_stack(template, params, capabilities, policy, override_policy, tags)
|
71
|
+
opts = {:capabilities => capabilities, :parameters => params, :tags => tags}
|
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)
|
79
|
+
end
|
80
|
+
|
81
|
+
def stack_exists?
|
82
|
+
@cf_driver.stack_exists?(@stack_name)
|
83
|
+
end
|
84
|
+
|
85
|
+
def create_stack(template, params, capabilities, policy, tags)
|
86
|
+
opts = {:disable_rollback => true, :capabilities => capabilities, :parameters => params, :tags => tags}
|
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)
|
90
|
+
end
|
91
|
+
|
92
|
+
def transform_output_to_settings(transforms)
|
93
|
+
(transforms || []).inject([]) do |settings, pair|
|
94
|
+
key, transform = pair
|
95
|
+
settings << transform.call(output(key))
|
96
|
+
settings
|
97
|
+
end.flatten
|
98
|
+
end
|
99
|
+
|
100
|
+
def wait_for_stack_op_terminate(anchor)
|
101
|
+
@poller.poll(anchor) do |event|
|
102
|
+
log_event(event)
|
103
|
+
if FAILED_STATS.include?(event.resource_status)
|
104
|
+
raise "Resource stack update failed!"
|
105
|
+
end
|
106
|
+
|
107
|
+
break if event.logical_resource_id == @stack_name && SUCCESS_STATS.include?(event.resource_status)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def log_event(event)
|
112
|
+
puts "[#{event.timestamp}][cloud_formation_provisioner] #{event.resource_type}(#{event.logical_resource_id}) #{event.resource_status} \"#{event.resource_status_reason}\""
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
def log(msg)
|
117
|
+
puts "[#{Time.now.utc}][cloud_formation_provisioner] #{msg}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module EbDeployer
|
2
|
+
class Component
|
3
|
+
attr_reader :name
|
4
|
+
|
5
|
+
def initialize(name, env, options, eb_driver)
|
6
|
+
@name = name
|
7
|
+
@env = env
|
8
|
+
@eb_driver = eb_driver
|
9
|
+
@options = options.dup
|
10
|
+
@component_eb_settings = @options.delete(:option_settings) || []
|
11
|
+
@component_inactive_settings = @options.delete(:inactive_settings) || []
|
12
|
+
strategy_name = @options[:strategy] || @env.strategy_name
|
13
|
+
@strategy = DeploymentStrategy.create(self, strategy_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def cname_prefix
|
17
|
+
@options[:cname_prefix] || default_cname_prefix
|
18
|
+
end
|
19
|
+
|
20
|
+
def deploy(version_label, eb_settings, inactive_settings=[])
|
21
|
+
@strategy.test_compatibility(create_options)
|
22
|
+
@strategy.deploy(version_label,
|
23
|
+
eb_settings + @component_eb_settings,
|
24
|
+
inactive_settings + @component_inactive_settings)
|
25
|
+
end
|
26
|
+
|
27
|
+
def new_eb_env(suffix=nil, cname_prefix_overriding=nil)
|
28
|
+
EbEnvironment.new(@env.app_name,
|
29
|
+
[@env.name, @name, suffix].compact.join('-'),
|
30
|
+
@eb_driver,
|
31
|
+
create_options.merge(:cname_prefix => cname_prefix_overriding || cname_prefix))
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def create_options
|
38
|
+
@env.creation_opts.merge(@options)
|
39
|
+
end
|
40
|
+
|
41
|
+
def default_cname_prefix
|
42
|
+
[@env.app_name, @env.name, @name].join('-')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'digest'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module EbDeployer
|
6
|
+
class ConfigLoader
|
7
|
+
include Utils
|
8
|
+
|
9
|
+
class EvalBinding
|
10
|
+
attr_reader :environment, :package_digest
|
11
|
+
def initialize(package_digest, env)
|
12
|
+
@package_digest = package_digest
|
13
|
+
@environment = env
|
14
|
+
end
|
15
|
+
|
16
|
+
def random_hash
|
17
|
+
SecureRandom.hex[0..9]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def load(options)
|
22
|
+
options = options.dup
|
23
|
+
package_digest = package_digest(options[:package])
|
24
|
+
config_file = options.delete(:config_file)
|
25
|
+
|
26
|
+
env = options[:environment]
|
27
|
+
config_settings = load_config_settings(config_file, package_digest, env)
|
28
|
+
|
29
|
+
app_name = config_settings[:application]
|
30
|
+
|
31
|
+
common_settings = symbolize_keys(config_settings[:common])
|
32
|
+
common_settings[:version_label] ||= package_digest
|
33
|
+
|
34
|
+
envs = config_settings[:environments]
|
35
|
+
raise "Environment #{env} is not defined in #{config_file}" unless envs.has_key?(env)
|
36
|
+
env_settings = symbolize_keys(envs[env] || {})
|
37
|
+
env_option_settings = env_settings.delete(:option_settings) || []
|
38
|
+
|
39
|
+
ret = options.merge(common_settings).merge(env_settings)
|
40
|
+
ret[:application] = app_name
|
41
|
+
ret[:option_settings] ||= []
|
42
|
+
ret[:option_settings] += env_option_settings
|
43
|
+
ret
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def load_config_settings(config_file, package_digest, env)
|
49
|
+
yaml = ERB.new(File.read(config_file)).
|
50
|
+
result(eval_binding(package_digest, env))
|
51
|
+
symbolize_keys(YAML.load(yaml))
|
52
|
+
end
|
53
|
+
|
54
|
+
def eval_binding(package_digest, env)
|
55
|
+
EvalBinding.new(package_digest, env).instance_eval { binding }
|
56
|
+
end
|
57
|
+
|
58
|
+
def package_digest(package)
|
59
|
+
return nil unless package
|
60
|
+
return package unless File.exist?(package)
|
61
|
+
Digest::MD5.file(package).hexdigest
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module EbDeployer
|
2
|
+
class DefaultComponent
|
3
|
+
def initialize(env, creation_opts, strategy_name, eb_driver)
|
4
|
+
@env = env
|
5
|
+
@eb_driver = eb_driver
|
6
|
+
@creation_opts = creation_opts
|
7
|
+
@strategy = DeploymentStrategy.create(self, strategy_name)
|
8
|
+
end
|
9
|
+
|
10
|
+
def cname_prefix
|
11
|
+
@creation_opts[:cname_prefix] || default_cname_prefix
|
12
|
+
end
|
13
|
+
|
14
|
+
def deploy(version_label, eb_settings, inactive_settings=[])
|
15
|
+
@strategy.test_compatibility(@creation_opts)
|
16
|
+
@strategy.deploy(version_label, eb_settings, inactive_settings)
|
17
|
+
end
|
18
|
+
|
19
|
+
def new_eb_env(suffix=nil, cname_prefix_overriding=nil)
|
20
|
+
EbEnvironment.new(@env.app_name,
|
21
|
+
[@env.name, suffix].compact.join('-'),
|
22
|
+
@eb_driver,
|
23
|
+
@creation_opts.merge(:cname_prefix => cname_prefix_overriding || cname_prefix))
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def default_cname_prefix
|
29
|
+
[@env.app_name, @env.name].join('-')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module EbDeployer
|
2
|
+
class DefaultConfig
|
3
|
+
attr_reader :app_name
|
4
|
+
|
5
|
+
def initialize(app_name)
|
6
|
+
@app_name = app_name.gsub('_', '-')
|
7
|
+
end
|
8
|
+
|
9
|
+
def write_to(path)
|
10
|
+
FileUtils.mkdir_p(File.dirname(path))
|
11
|
+
File.open(path, 'w') { |f| f << ERB.new(File.read(config_template)).result(binding) }
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def config_template
|
17
|
+
File.expand_path("../default_config.yml", __FILE__)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|