bbc-cosmos-tools 0.5.2 → 0.6.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.
@@ -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