bbc-cosmos-tools 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/bbc-cosmos-tools.gemspec +5 -4
- data/bin/bbc-cosmos-tools +3 -3
- data/lib/bbc/cosmos/tools/api.rb +6 -8
- data/lib/bbc/cosmos/tools/app.rb +4 -4
- data/lib/bbc/cosmos/tools/cloudformation/generator.rb +20 -23
- data/lib/bbc/cosmos/tools/commands/base.rb +8 -10
- data/lib/bbc/cosmos/tools/commands/component.rb +79 -19
- data/lib/bbc/cosmos/tools/commands/config.rb +24 -33
- data/lib/bbc/cosmos/tools/commands/release.rb +100 -112
- data/lib/bbc/cosmos/tools/commands/stack.rb +60 -72
- data/lib/bbc/cosmos/tools/config.rb +19 -22
- data/lib/bbc/cosmos/tools/cosmos_configuration.rb +4 -6
- data/lib/bbc/cosmos/tools/types/base_type.rb +6 -7
- data/lib/bbc/cosmos/tools/types/cfndsl.rb +2 -3
- data/lib/bbc/cosmos/tools/version.rb +1 -1
- metadata +19 -6
@@ -1,8 +1,8 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
require "json"
|
2
|
+
require "pathname"
|
3
|
+
require "bbc/cosmos/tools/commands/base"
|
4
|
+
require "bbc/cosmos/tools/cosmos_configuration"
|
5
|
+
require "bbc/cosmos/tools/api"
|
6
6
|
|
7
7
|
module BBC
|
8
8
|
module Cosmos
|
@@ -15,168 +15,156 @@ module BBC
|
|
15
15
|
|
16
16
|
def initialize(args = [], local_options = {}, thor_config = {})
|
17
17
|
super(args, local_options, thor_config)
|
18
|
-
@api = BBC::Cosmos::Tools::API.new(config.app[
|
18
|
+
@api = BBC::Cosmos::Tools::API.new(config.app["api"], options[:key_path])
|
19
19
|
end
|
20
20
|
|
21
21
|
method_option :tags, :type => :array, :default => nil
|
22
22
|
desc "release list [COMPONENT = nil]", "Lists releases for a component"
|
23
23
|
def list(component = nil)
|
24
|
-
|
24
|
+
say banner
|
25
25
|
|
26
|
-
|
26
|
+
components(options, component).each do |id|
|
27
|
+
response = api.get sprintf(config.app["release"], id)
|
28
|
+
say get_key_value("\nComponent", id)
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
if response.success?
|
34
|
-
data = []
|
35
|
-
JSON.parse(response.body)['releases'].slice!(0, options[:limit]).map do |release|
|
36
|
-
data << [release['version'], release['created_at']]
|
37
|
-
end
|
38
|
-
|
39
|
-
print_table(
|
40
|
-
build_table(['Version', 'Created at'], data)
|
41
|
-
)
|
42
|
-
say "\n"
|
43
|
-
else
|
44
|
-
api_error response
|
30
|
+
if response.success?
|
31
|
+
data = []
|
32
|
+
JSON.parse(response.body)["releases"].slice!(0, options[:limit]).map do |release|
|
33
|
+
data << [release["version"], release["created_at"]]
|
45
34
|
end
|
46
|
-
end
|
47
35
|
|
48
|
-
|
49
|
-
|
36
|
+
print_table(
|
37
|
+
build_table(["Version", "Created at"], data)
|
38
|
+
)
|
39
|
+
say "\n"
|
40
|
+
else
|
41
|
+
api_error response
|
42
|
+
end
|
50
43
|
end
|
44
|
+
|
45
|
+
rescue Exception => e
|
46
|
+
error e.message
|
51
47
|
end
|
52
48
|
|
53
49
|
desc "release deploy [COMPONENT = nil, RELEASE_ID = nil]", "Deploys a release to the specific enironment"
|
54
50
|
method_option :tags, :type => :array, :default => nil, :desc => "The tags of the components you want to deploy (i.e 'renderer')"
|
55
|
-
method_option :from, :type => :string, :default =>
|
51
|
+
method_option :from, :type => :string, :default => "release", :desc => "The location that the deployment shold be taken from (release|int|test)"
|
56
52
|
def deploy(component = nil, release_id = nil)
|
53
|
+
say banner
|
54
|
+
|
55
|
+
components(options, component).each do |id|
|
56
|
+
begin
|
57
|
+
|
58
|
+
component_release = release_id
|
59
|
+
if release_id.nil?
|
60
|
+
|
61
|
+
post_data = {}
|
62
|
+
endpoint = config.app["deploy"]
|
63
|
+
|
64
|
+
case options[:from]
|
65
|
+
when "release"
|
66
|
+
response = api.get sprintf(config.app["release"], id)
|
67
|
+
api_error response unless response.success?
|
68
|
+
component_release = JSON.parse(response.body)["releases"].first["version"]
|
69
|
+
post_data = {
|
70
|
+
"release_version" => component_release
|
71
|
+
}
|
72
|
+
when "int", "test", "live"
|
73
|
+
|
74
|
+
endpoint = config.app["snapshot_deploy"]
|
75
|
+
response = api.get sprintf(config.app["deployments"], id, options[:from])
|
76
|
+
api_error response unless response.success?
|
77
|
+
snapshot_id = JSON.parse(response.body).first["snapshot"]["snapshot_id"]
|
78
|
+
post_data = {
|
79
|
+
"snapshot_id" => snapshot_id
|
80
|
+
}
|
57
81
|
|
58
|
-
|
59
|
-
|
60
|
-
components(options, component).each do |id|
|
61
|
-
begin
|
62
|
-
|
63
|
-
component_release = release_id
|
64
|
-
if release_id.nil?
|
65
|
-
|
66
|
-
post_data = {}
|
67
|
-
endpoint = config.app['deploy']
|
68
|
-
|
69
|
-
case options[:from]
|
70
|
-
when 'release'
|
71
|
-
response = api.get sprintf(config.app['release'], id)
|
72
|
-
api_error response unless response.success?
|
73
|
-
component_release = JSON.parse(response.body)['releases'].first['version']
|
74
|
-
post_data = {
|
75
|
-
'release_version' => component_release
|
76
|
-
}
|
77
|
-
when 'int', 'test', 'live'
|
78
|
-
|
79
|
-
endpoint = config.app['snapshot_deploy']
|
80
|
-
response = api.get sprintf(config.app['deployments'], id, options[:from])
|
81
|
-
api_error response unless response.success?
|
82
|
-
snapshot_id = JSON.parse(response.body).first['snapshot']['snapshot_id']
|
83
|
-
post_data = {
|
84
|
-
'snapshot_id' => snapshot_id
|
85
|
-
}
|
86
|
-
|
87
|
-
else
|
88
|
-
raise("Invalid location: #{options[:from]} to deploy from")
|
89
|
-
end
|
82
|
+
else
|
83
|
+
fail("Invalid location: #{options[:from]} to deploy from")
|
90
84
|
end
|
85
|
+
end
|
91
86
|
|
92
|
-
|
93
|
-
|
94
|
-
if response.success?
|
87
|
+
response = api.post sprintf(endpoint, options[:env], id), JSON.generate(post_data)
|
95
88
|
|
96
|
-
|
97
|
-
say get_key_value("Version", post_data['snapshot_id'] ? post_data['snapshot_id'] : post_data['release_version'])
|
89
|
+
if response.success?
|
98
90
|
|
99
|
-
|
100
|
-
|
91
|
+
say get_key_value("\nComponent", id)
|
92
|
+
say get_key_value("Version", post_data["snapshot_id"] ? post_data["snapshot_id"] : post_data["release_version"])
|
101
93
|
|
102
|
-
|
103
|
-
|
104
|
-
end
|
94
|
+
data = JSON.parse(response.body)
|
95
|
+
say "\nDeployment started successfully: #{config.app['api']}#{data['url']}\n", :green
|
105
96
|
|
106
|
-
|
107
|
-
|
97
|
+
else
|
98
|
+
api_error response
|
108
99
|
end
|
109
|
-
end
|
110
100
|
|
101
|
+
rescue Exception => e
|
102
|
+
error(e.message, false)
|
103
|
+
end
|
104
|
+
end
|
111
105
|
end
|
112
106
|
|
113
107
|
desc "release deployed [COMPONENT = nil]", "Lists releases deloyed for a component in the specified environment"
|
114
108
|
method_option :tags, :type => :array, :default => nil, :desc => "The tags of the components you want to deploy (i.e 'renderer')"
|
115
109
|
def deployed(component = nil)
|
116
|
-
|
117
|
-
|
118
|
-
say banner
|
110
|
+
say banner
|
119
111
|
|
120
|
-
|
112
|
+
components(options, component).each do |id|
|
113
|
+
response = api.get sprintf(config.app["deployments"], id, options[:env])
|
114
|
+
say get_key_value("\nComponent", id)
|
121
115
|
|
122
|
-
|
123
|
-
|
116
|
+
if response.success?
|
117
|
+
data = JSON.parse(response.body)
|
124
118
|
|
125
|
-
if
|
126
|
-
|
127
|
-
|
128
|
-
if data.empty?
|
129
|
-
say "There are currently no deployments for this component", :yellow
|
130
|
-
else
|
119
|
+
if data.empty?
|
120
|
+
say "There are currently no deployments for this component", :yellow
|
121
|
+
else
|
131
122
|
|
132
|
-
|
123
|
+
deployments = []
|
133
124
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
125
|
+
data.slice!(0, options[:limit].to_i).map do |release|
|
126
|
+
deployments << [
|
127
|
+
release["release"]["version"],
|
128
|
+
release["started_at"],
|
129
|
+
release["id"],
|
130
|
+
release["created_by"]["email_address"],
|
131
|
+
deploy_status(release["status"])
|
132
|
+
]
|
133
|
+
end
|
143
134
|
|
144
|
-
|
145
|
-
|
146
|
-
|
135
|
+
print_table(
|
136
|
+
build_table(["Release", "Deployed at", "Deployment id", "Deployed by", "Status"], deployments)
|
137
|
+
)
|
147
138
|
|
148
|
-
|
149
|
-
end
|
150
|
-
else
|
151
|
-
api_error response
|
139
|
+
say "\n"
|
152
140
|
end
|
141
|
+
else
|
142
|
+
api_error response
|
153
143
|
end
|
154
|
-
|
155
|
-
rescue Exception => e
|
156
|
-
error e.message
|
157
144
|
end
|
145
|
+
|
146
|
+
rescue Exception => e
|
147
|
+
error e.message
|
158
148
|
end
|
159
149
|
|
160
150
|
private
|
161
151
|
|
162
152
|
def deploy_status(status)
|
163
153
|
case status
|
164
|
-
when
|
154
|
+
when "pending_bake"
|
165
155
|
set_color(status, :yellow)
|
166
|
-
when
|
156
|
+
when "pending_stack_update_resolution"
|
167
157
|
set_color(status, :yellow)
|
168
|
-
when
|
158
|
+
when "done"
|
169
159
|
set_color(status, :green)
|
170
|
-
when
|
160
|
+
when "failed"
|
171
161
|
set_color(status, :red)
|
172
162
|
else
|
173
163
|
set_color(status, :white)
|
174
164
|
end
|
175
165
|
end
|
176
|
-
|
177
166
|
end
|
178
167
|
end
|
179
168
|
end
|
180
169
|
end
|
181
170
|
end
|
182
|
-
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require "json"
|
2
2
|
require "bbc/cosmos/tools/config"
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "bbc/cosmos/tools/commands/base"
|
4
|
+
require "bbc/cosmos/tools/cloudformation/generator"
|
5
5
|
require "bbc/cosmos/tools/types/factory"
|
6
6
|
|
7
7
|
module BBC
|
@@ -11,46 +11,44 @@ module BBC
|
|
11
11
|
class Stack < Base
|
12
12
|
attr_accessor :api
|
13
13
|
|
14
|
-
class_option :stack, :type => :string, :default =>
|
15
|
-
class_option :type, :type => :string, :default =>
|
14
|
+
class_option :stack, :type => :string, :default => "main", :desc => "The name of the stack to use"
|
15
|
+
class_option :type, :type => :string, :default => "cfndsl", :desc => "The format of your your CloudFormation (default is cfndsl, but can also be json or yaml)", :enum => %w(cfndsl json yaml)
|
16
16
|
|
17
17
|
def initialize(args = [], local_options = {}, thor_config = {})
|
18
18
|
super(args, local_options, thor_config)
|
19
19
|
|
20
20
|
@l = -> data, component, environment do
|
21
|
-
if data[
|
22
|
-
data[
|
21
|
+
if data["Parameters"] && data["Parameters"]["ImageId"]
|
22
|
+
data["Parameters"]["ImageId"]["Default"] = latest_ami_for(component, environment)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
@api = BBC::Cosmos::Tools::API.new(config.app[
|
26
|
+
@api = BBC::Cosmos::Tools::API.new(config.app["api"], options[:key_path])
|
27
27
|
end
|
28
28
|
|
29
29
|
desc "stack list [COMPONENT = nil]", "Lists stacks for a component"
|
30
30
|
method_option :tags, :type => :array, :default => nil, :desc => "The tags of the components you want to deploy (i.e 'renderer')"
|
31
31
|
def list(component = nil)
|
32
|
-
|
33
32
|
say "#{banner}\n"
|
34
33
|
|
35
34
|
components(options, component).each do |id|
|
36
|
-
|
37
|
-
response = api.get sprintf(config.app['stacks'], options[:env], id)
|
35
|
+
response = api.get sprintf(config.app["stacks"], options[:env], id)
|
38
36
|
say get_key_value("\nComponent", id)
|
39
37
|
|
40
38
|
if response.success?
|
41
39
|
|
42
40
|
data = JSON.parse(response.body).map do |stack|
|
43
41
|
[
|
44
|
-
stack[
|
45
|
-
stack[
|
46
|
-
stack[
|
47
|
-
stack[
|
42
|
+
stack["name"].split("-").last,
|
43
|
+
stack["main_stack"],
|
44
|
+
stack["updated_at"],
|
45
|
+
stack["status"]
|
48
46
|
]
|
49
47
|
end
|
50
48
|
|
51
49
|
print_table(
|
52
50
|
build_table(
|
53
|
-
[
|
51
|
+
["Name", "Main stack", "Updated at", "Status"],
|
54
52
|
data
|
55
53
|
)
|
56
54
|
)
|
@@ -61,61 +59,56 @@ module BBC
|
|
61
59
|
end
|
62
60
|
end
|
63
61
|
|
64
|
-
method_option :variant, :type => :string, :default =>
|
62
|
+
method_option :variant, :type => :string, :default => "default", :desc => "The variant to use, i.e default|scheduled"
|
65
63
|
method_option :group, :type => :string, :default => nil, :desc => "The group name to override the component id"
|
66
64
|
desc "stack generate [COMPONENT]", "Generates a cloudformation template based on a type of component, the identifier and the environment"
|
67
65
|
def generate(component)
|
68
|
-
|
69
66
|
say "#{banner(component)}\n"
|
70
67
|
|
71
68
|
type = Tools::Types::Factory.create(component, options, config)
|
72
69
|
data = type.generate_data true
|
73
70
|
say data, :white
|
74
|
-
|
75
71
|
end
|
76
72
|
|
77
|
-
method_option :variant, :type => :string, :default =>
|
73
|
+
method_option :variant, :type => :string, :default => "default", :desc => "The variant to use, i.e default|scheduled"
|
78
74
|
method_option :group, :type => :string, :default => nil, :desc => "The group name to override the component id"
|
79
75
|
method_option :tags, :type => :array, :default => nil, :desc => "The tags of the components you want to deploy (i.e 'renderer')"
|
80
76
|
desc "stack create [COMPONENT, MAIN_STACK = true]", "Generates and create the cloudformation template for the specific component"
|
81
|
-
def create(component = nil, main_stack =
|
82
|
-
|
83
|
-
say "#{banner}\n"
|
84
|
-
|
85
|
-
components(options, component).each do |id|
|
86
|
-
say get_key_value("\nComponent", id)
|
87
|
-
|
88
|
-
type = Tools::Types::Factory.create(id, options, config)
|
89
|
-
data = type.generate_data
|
90
|
-
stack_data = Tools::Cloudformation::Generator.component_stack_details(config.resources, options, id)
|
91
|
-
|
92
|
-
post_data = {
|
93
|
-
'name_suffix' => options[:stack],
|
94
|
-
'service_stack' => main_stack.match(/(true|t|yes|y|1)$/i) != nil,
|
95
|
-
'template' => data,
|
96
|
-
'parameters' => Tools::Cloudformation::Generator.parameters(data, main_stack),
|
97
|
-
}
|
77
|
+
def create(component = nil, main_stack = "true")
|
78
|
+
say "#{banner}\n"
|
98
79
|
|
99
|
-
|
100
|
-
|
80
|
+
components(options, component).each do |id|
|
81
|
+
say get_key_value("\nComponent", id)
|
101
82
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
83
|
+
type = Tools::Types::Factory.create(id, options, config)
|
84
|
+
data = type.generate_data
|
85
|
+
stack_data = Tools::Cloudformation::Generator.component_stack_details(config.resources, options, id)
|
86
|
+
|
87
|
+
post_data = {
|
88
|
+
"name_suffix" => options[:stack],
|
89
|
+
"service_stack" => !main_stack.match(/(true|t|yes|y|1)$/i).nil?,
|
90
|
+
"template" => data,
|
91
|
+
"parameters" => Tools::Cloudformation::Generator.parameters(data, main_stack)
|
92
|
+
}
|
93
|
+
|
94
|
+
post_data["aws_account_id"] = stack_data["account_id"] unless stack_data["account_id"].nil?
|
95
|
+
response = api.post sprintf(config.app["stack_create_endpoint"], options[:env], id), JSON.pretty_generate(post_data)
|
96
|
+
|
97
|
+
if response.success?
|
98
|
+
say "Stack creation for component '#{component}' successfully started", :green
|
99
|
+
else
|
100
|
+
api_error(response, false)
|
107
101
|
end
|
108
|
-
rescue Exception => e
|
109
|
-
error e.message
|
110
102
|
end
|
103
|
+
rescue Exception => e
|
104
|
+
error e.message
|
111
105
|
end
|
112
106
|
|
113
|
-
method_option :variant, :type => :string, :default =>
|
107
|
+
method_option :variant, :type => :string, :default => "default", :desc => "The variant to use, i.e default|scheduled"
|
114
108
|
method_option :group, :type => :string, :default => nil, :desc => "The group name to override the component id"
|
115
109
|
method_option :tags, :type => :array, :default => nil, :desc => "The tags of the components you want to deploy (i.e 'renderer')"
|
116
110
|
desc "stack update [COMPONENT = nil]", "Generates and updates the cloudformation template for the specific component"
|
117
111
|
def update(component = nil)
|
118
|
-
|
119
112
|
say "#{banner}\n"
|
120
113
|
|
121
114
|
components(options, component).each do |id|
|
@@ -125,26 +118,26 @@ module BBC
|
|
125
118
|
|
126
119
|
type = Tools::Types::Factory.create(id, options, config)
|
127
120
|
data = type.generate_data.tap do |d|
|
128
|
-
@l.(d, id, options[:env])
|
121
|
+
@l.call(d, id, options[:env])
|
129
122
|
end
|
130
123
|
|
131
124
|
stack_meta = stack_data(component, stack_name, options[:env])
|
132
125
|
|
133
|
-
if data[
|
134
|
-
data[
|
135
|
-
stack_parameters(stack_meta[
|
136
|
-
data[
|
126
|
+
if data["Parameters"]
|
127
|
+
data["Parameters"] = deep_merge(
|
128
|
+
stack_parameters(stack_meta["parameters"]),
|
129
|
+
data["Parameters"]
|
137
130
|
)
|
138
131
|
|
139
132
|
params = Tools::Cloudformation::Generator.parameters(data, false)
|
140
133
|
end
|
141
134
|
|
142
135
|
post_data = {
|
143
|
-
|
144
|
-
|
136
|
+
"template" => data,
|
137
|
+
"parameters" => params || {}
|
145
138
|
}
|
146
139
|
|
147
|
-
response = api.post sprintf(config.app[
|
140
|
+
response = api.post sprintf(config.app["stack_update_endpoint"], options[:env], id, stack_name), JSON.pretty_generate(post_data)
|
148
141
|
|
149
142
|
if response.success?
|
150
143
|
say "Stack update for component '#{id}' successfully started", :green
|
@@ -152,12 +145,10 @@ module BBC
|
|
152
145
|
api_error(response, false)
|
153
146
|
end
|
154
147
|
end
|
155
|
-
|
156
148
|
end
|
157
149
|
|
158
150
|
desc "stack delete [COMPONENT]", "Deletes a stack"
|
159
151
|
def delete(component)
|
160
|
-
|
161
152
|
say "#{banner(component)}\n"
|
162
153
|
|
163
154
|
reply = yes?("Are you sure you want to delete the above stack?", :yellow)
|
@@ -165,7 +156,7 @@ module BBC
|
|
165
156
|
|
166
157
|
stack_name = "#{options[:env]}-#{component}-#{options[:stack]}"
|
167
158
|
|
168
|
-
response = api.post sprintf(config.app[
|
159
|
+
response = api.post sprintf(config.app["stack_delete"], options[:env], component, stack_name), JSON.pretty_generate({})
|
169
160
|
|
170
161
|
if response.success?
|
171
162
|
say "Stack delete for component '#{component}' successfully started", :green
|
@@ -173,35 +164,33 @@ module BBC
|
|
173
164
|
api_error response
|
174
165
|
end
|
175
166
|
else
|
176
|
-
error
|
167
|
+
error "Action cancelled"
|
177
168
|
end
|
178
|
-
|
179
169
|
end
|
180
170
|
|
181
171
|
desc "stack events [COMPONENT = nil]", "Shows the stack events for a component"
|
182
|
-
method_option :stack, :type => :string, :default =>
|
172
|
+
method_option :stack, :type => :string, :default => "main", :desc => "The name of the stack to use"
|
183
173
|
method_option :limit, :type => :numeric, :default => 5, :desc => "Limit how many records to show"
|
184
174
|
method_option :tags, :type => :array, :default => nil, :desc => "The tags of the components you want to deploy (i.e 'renderer')"
|
185
175
|
def events(component = nil)
|
186
|
-
|
187
176
|
say "#{banner}\n"
|
188
177
|
|
189
178
|
components(options, component).each do |id|
|
190
179
|
say get_key_value("\nComponent", id)
|
191
180
|
|
192
181
|
stack_name = "#{options[:env]}-#{id}-#{options[:stack]}"
|
193
|
-
response = api.get sprintf(config.app[
|
182
|
+
response = api.get sprintf(config.app["stack_events"], options[:env], id, stack_name)
|
194
183
|
|
195
184
|
if response.success?
|
196
185
|
events = JSON.parse(response.body)
|
197
186
|
|
198
|
-
data = events.slice(0,(options[:limit])).map do |event|
|
187
|
+
data = events.slice(0, (options[:limit])).map do |event|
|
199
188
|
event.split(" ")
|
200
189
|
end
|
201
190
|
|
202
191
|
print_table(
|
203
192
|
build_table(
|
204
|
-
[
|
193
|
+
["Event type", "CF type", "Name", "Status"],
|
205
194
|
data
|
206
195
|
)
|
207
196
|
)
|
@@ -223,22 +212,21 @@ module BBC
|
|
223
212
|
end
|
224
213
|
end
|
225
214
|
|
226
|
-
def stack_data(component, stack_name, env =
|
227
|
-
response = api.get sprintf(config.app[
|
215
|
+
def stack_data(component, stack_name, env = "int")
|
216
|
+
response = api.get sprintf(config.app["stack_details"], env, component, stack_name)
|
228
217
|
JSON.parse(response.body)
|
229
218
|
end
|
230
219
|
|
231
|
-
def latest_ami_for(component, env =
|
232
|
-
response = api.get sprintf(config.app[
|
220
|
+
def latest_ami_for(component, env = "int")
|
221
|
+
response = api.get sprintf(config.app["deployments"], component, env)
|
233
222
|
api_error response unless response.success?
|
234
|
-
JSON.parse(response.body).first[
|
223
|
+
JSON.parse(response.body).first["image"]["ami_id"]
|
235
224
|
end
|
236
225
|
|
237
226
|
def deep_merge(merger, mergee)
|
238
|
-
merge_proc =
|
227
|
+
merge_proc = proc { |_key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merge_proc) : v2 }
|
239
228
|
merger.merge(mergee, &merge_proc)
|
240
229
|
end
|
241
|
-
|
242
230
|
end
|
243
231
|
end
|
244
232
|
end
|