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.
@@ -1,8 +1,8 @@
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'
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['api'], options[:key_path])
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
- begin
24
+ say banner
25
25
 
26
- say banner
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
- components(options, component).each do |id|
29
-
30
- response = api.get sprintf(config.app['release'], id)
31
- say get_key_value("\nComponent", id)
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
- rescue Exception => e
49
- error e.message
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 => 'release', :desc => "The location that the deployment shold be taken from (release|int|test)"
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
- say banner
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
- response = api.post sprintf(endpoint, options[:env], id), JSON.generate(post_data)
93
-
94
- if response.success?
87
+ response = api.post sprintf(endpoint, options[:env], id), JSON.generate(post_data)
95
88
 
96
- say get_key_value("\nComponent", id)
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
- data = JSON.parse(response.body)
100
- say "\nDeployment started successfully: #{config.app['api']}#{data['url']}\n", :green
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
- else
103
- api_error response
104
- end
94
+ data = JSON.parse(response.body)
95
+ say "\nDeployment started successfully: #{config.app['api']}#{data['url']}\n", :green
105
96
 
106
- rescue Exception => e
107
- error(e.message, false)
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
- begin
117
-
118
- say banner
110
+ say banner
119
111
 
120
- components(options, component).each do |id|
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
- response = api.get sprintf(config.app['deployments'], id, options[:env])
123
- say get_key_value("\nComponent", id)
116
+ if response.success?
117
+ data = JSON.parse(response.body)
124
118
 
125
- if response.success?
126
- data = JSON.parse(response.body)
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
- deployments = []
123
+ deployments = []
133
124
 
134
- data.slice!(0, options[:limit].to_i).map do |release|
135
- deployments << [
136
- release['release']['version'],
137
- release['started_at'],
138
- release['id'],
139
- release['created_by']['email_address'],
140
- deploy_status(release['status'])
141
- ]
142
- end
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
- print_table(
145
- build_table(['Release', 'Deployed at', 'Deployment id', 'Deployed by', 'Status'], deployments)
146
- )
135
+ print_table(
136
+ build_table(["Release", "Deployed at", "Deployment id", "Deployed by", "Status"], deployments)
137
+ )
147
138
 
148
- say "\n"
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 'pending_bake'
154
+ when "pending_bake"
165
155
  set_color(status, :yellow)
166
- when 'pending_stack_update_resolution'
156
+ when "pending_stack_update_resolution"
167
157
  set_color(status, :yellow)
168
- when 'done'
158
+ when "done"
169
159
  set_color(status, :green)
170
- when 'failed'
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 'bbc/cosmos/tools/commands/base'
4
- require 'bbc/cosmos/tools/cloudformation/generator'
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 => '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 => ["cfndsl", "json", "yaml"]
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['Parameters'] && data['Parameters']['ImageId']
22
- data['Parameters']['ImageId']['Default'] = latest_ami_for(component, environment)
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['api'], options[:key_path])
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['name'].split('-').last,
45
- stack['main_stack'],
46
- stack['updated_at'],
47
- stack['status']
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
- ['Name', 'Main stack', 'Updated at', 'Status'],
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 => 'default', :desc => "The variant to use, i.e default|scheduled"
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 => 'default', :desc => "The variant to use, i.e default|scheduled"
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 = 'true')
82
- begin
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
- post_data['aws_account_id'] = stack_data['account_id'] unless stack_data['account_id'].nil?
100
- response = api.post sprintf(config.app['stack_create_endpoint'], options[:env], id), JSON.pretty_generate(post_data)
80
+ components(options, component).each do |id|
81
+ say get_key_value("\nComponent", id)
101
82
 
102
- if response.success?
103
- say "Stack creation for component '#{component}' successfully started", :green
104
- else
105
- api_error(response, false)
106
- end
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 => 'default', :desc => "The variant to use, i.e default|scheduled"
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['Parameters']
134
- data['Parameters'] = deep_merge(
135
- stack_parameters(stack_meta['parameters']),
136
- data['Parameters']
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
- 'template' => data,
144
- 'parameters' => params || {}
136
+ "template" => data,
137
+ "parameters" => params || {}
145
138
  }
146
139
 
147
- response = api.post sprintf(config.app['stack_update_endpoint'], options[:env], id, stack_name), JSON.pretty_generate(post_data)
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['stack_delete'], options[:env], component, stack_name), JSON.pretty_generate({})
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 'Action cancelled'
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 => 'main', :desc => "The name of the stack to use"
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['stack_events'], options[:env], id, stack_name)
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
- ['Event type', 'CF type', 'Name', 'Status'],
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 = 'int')
227
- response = api.get sprintf(config.app['stack_details'], env, component, stack_name)
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 = 'int')
232
- response = api.get sprintf(config.app['deployments'], component, env)
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['image']['ami_id']
223
+ JSON.parse(response.body).first["image"]["ami_id"]
235
224
  end
236
225
 
237
226
  def deep_merge(merger, mergee)
238
- merge_proc = Proc.new { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merge_proc) : v2 }
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