Module: PrimaAwsClient

Defined in:
lib/prima_aws_client.rb

Instance Method Summary collapse

Instance Method Details

#alb_clientObject



27
28
29
# File 'lib/prima_aws_client.rb', line 27

def alb_client
  @alb ||= Aws::ElasticLoadBalancingV2::Client.new
end

#artifact_exists?(bucket, path) ⇒ Boolean

Returns:

  • (Boolean)


332
333
334
335
336
337
338
339
# File 'lib/prima_aws_client.rb', line 332

def artifact_exists?(bucket, path)
  resp = s3_client.list_objects(
    bucket: bucket,
    max_keys: 1,
    prefix: path
  )
  !resp.contents.empty?
end

#asg_clientObject



19
20
21
# File 'lib/prima_aws_client.rb', line 19

def asg_client
  @asg ||= Aws::AutoScaling::Client.new
end

#cf_clientObject



15
16
17
# File 'lib/prima_aws_client.rb', line 15

def cf_client
  @cf ||= Aws::CloudFormation::Client.new
end

#cluster_listObject



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/prima_aws_client.rb', line 58

def cluster_list
  stacks = []
  next_token = ''
  loop do
    print '.'.yellow; STDOUT.flush
    options = next_token != '' ? { next_token: next_token } : {}
    begin
      resp = cf_client.describe_stacks(options)
    rescue Aws::CloudFormation::Errors::Throttling => e
      output 'Throttling, retrying in 15 seconds'.red
      sleep 15
      resp = cf_client.describe_stacks(options)
    end
    stacks += resp.stacks
    break unless resp.next_token

    next_token = resp.next_token
  end
  puts '.'.yellow; STDOUT.flush
  stacks.keep_if { |stack| stack.stack_name.include? 'ecs-cluster-qa-' }
  stacks
end

#create_stack(stack_name, stack_body, parameters = [], tags = [], role = nil) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/prima_aws_client.rb', line 103

def create_stack(stack_name, stack_body, parameters = [], tags = [], role = nil)
  cf_args = {
    stack_name: stack_name,
    template_body: stack_body,
    parameters: parameters,
    tags: tags,
    capabilities: ['CAPABILITY_IAM'],
    on_failure: 'ROLLBACK'
  }

  cf_args.merge!(role_arn: role) unless role.nil?

  begin
    cf_client.create_stack(cf_args)
  rescue Aws::CloudFormation::Errors::Throttling, Aws::CloudFormation::Errors::LimitExcedeedException => e
    output 'Throttling, retrying in 15 seconds'.red
    sleep 15
    create_stack(stack_name, stack_body, parameters = [], tags = [])
  else
    output "CloudFormation stack #{stack_name} creation started".green
  end
end

#delete_stack(stack_name) ⇒ Object



212
213
214
215
216
217
218
219
220
# File 'lib/prima_aws_client.rb', line 212

def delete_stack(stack_name)
  cf_client.delete_stack(stack_name: stack_name)
rescue Aws::CloudFormation::Errors::Throttling => e
  output 'Throttling, retrying in 15 seconds'.red
  sleep 15
  delete_stack(stack_name)
else
  output "Stack #{stack_name} shutdown succesfully\n".green
end

#describe_auto_scaling_groups(auto_scaling_group_names, max_records) ⇒ Object



413
414
415
416
417
418
419
420
421
422
# File 'lib/prima_aws_client.rb', line 413

def describe_auto_scaling_groups(auto_scaling_group_names, max_records)
  resp = asg_client.describe_auto_scaling_groups({
                                                   auto_scaling_group_names: auto_scaling_group_names,
                                                   max_records: max_records
                                                 })
rescue Aws::CloudFormation::Errors::Throttling => e
  output 'Throttling, retrying in 15 seconds'.red
  sleep 15
  resp = describe_auto_scaling_groups(auto_scaling_group_names, max_records)
end

#describe_ecs_tasks(cluster, tasks) ⇒ Object



444
445
446
447
448
449
450
451
452
453
# File 'lib/prima_aws_client.rb', line 444

def describe_ecs_tasks(cluster, tasks)
  resp = ecs_client.describe_tasks({
                                     cluster: cluster,
                                     tasks: tasks
                                   })
rescue Aws::CloudFormation::Errors::Throttling => e
  output 'Throttling, retrying in 15 seconds'.red
  sleep 15
  resp = describe_ecs_tasks(cluster, tasks)
end

#describe_instances(instance_ids) ⇒ Object



405
406
407
408
409
410
411
# File 'lib/prima_aws_client.rb', line 405

def describe_instances(instance_ids)
  resp = ec2_client.describe_instances({ instance_ids: instance_ids })
rescue Aws::CloudFormation::Errors::Throttling => e
  output 'Throttling, retrying in 15 seconds'.red
  sleep 15
  resp = describe_instances(instance_ids)
end

#describe_load_balancers(load_balancer_arns) ⇒ Object



424
425
426
427
428
429
430
# File 'lib/prima_aws_client.rb', line 424

def describe_load_balancers(load_balancer_arns)
  resp = alb_client.describe_load_balancers({ load_balancer_arns: load_balancer_arns })
rescue Aws::ElasticLoadBalancingV2::Errors::Throttling => e
  output 'Throttling, retrying in 15 seconds'.red
  sleep 15
  resp = describe_load_balancers(load_balancer_arns)
end

#describe_stack_resource(cluster_stack_name, logical_resource_id) ⇒ Object



397
398
399
400
401
402
403
# File 'lib/prima_aws_client.rb', line 397

def describe_stack_resource(cluster_stack_name, logical_resource_id)
  resp = cf_client.describe_stack_resource({ stack_name: cluster_stack_name, logical_resource_id: logical_resource_id })
rescue Aws::CloudFormation::Errors::Throttling => e
  output 'Throttling, retrying in 15 seconds'.red
  sleep 15
  resp = describe_stack_resource(cluster_stack_name, logical_resource_id)
end

#ec2_clientObject



23
24
25
# File 'lib/prima_aws_client.rb', line 23

def ec2_client
  @ec2 ||= Aws::EC2::Client.new
end

#ecs_clientObject



31
32
33
# File 'lib/prima_aws_client.rb', line 31

def ecs_client
  @ecs ||= Aws::ECS::Client.new
end

#get_autoscaling_capacity(asg_name) ⇒ Object



468
469
470
471
# File 'lib/prima_aws_client.rb', line 468

def get_autoscaling_capacity(asg_name)
  resp = asg_client.describe_auto_scaling_groups(auto_scaling_group_names: [asg_name])
  resp.auto_scaling_groups[0].desired_capacity
end

#get_spotfleet_capacity(fleet_arn) ⇒ Object



473
474
475
476
# File 'lib/prima_aws_client.rb', line 473

def get_spotfleet_capacity(fleet_arn)
  resp = ec2_client.describe_spot_fleet_requests(spot_fleet_request_ids: [fleet_arn])
  resp.spot_fleet_request_configs[0].spot_fleet_request_config.target_capacity
end

#get_stack_outputs(name) ⇒ Object



279
280
281
282
283
284
285
286
287
# File 'lib/prima_aws_client.rb', line 279

def get_stack_outputs(name)
  resp = cf_client.describe_stacks(stack_name: name)
rescue Aws::CloudFormation::Errors::Throttling => e
  output 'Throttling, retrying in 15 seconds'.red
  sleep 15
  get_stack_outputs(name)
else
  resp.stacks[0].outputs
end

#get_stack_parameters(name) ⇒ Object



269
270
271
272
273
274
275
276
277
# File 'lib/prima_aws_client.rb', line 269

def get_stack_parameters(name)
  resp = cf_client.describe_stacks(stack_name: name)
rescue Aws::CloudFormation::Errors::Throttling => e
  output 'Throttling, retrying in 15 seconds'.red
  sleep 15
  get_stack_parameters(name)
else
  resp.stacks[0].parameters
end

#get_stack_tags(name) ⇒ Object



259
260
261
262
263
264
265
266
267
# File 'lib/prima_aws_client.rb', line 259

def get_stack_tags(name)
  resp = cf_client.describe_stacks(stack_name: name)
rescue Aws::CloudFormation::Errors::Throttling => e
  output 'Throttling, retrying in 15 seconds'.red
  sleep 15
  get_stack_tags(name)
else
  resp.stacks[0].tags
end

#get_stack_template(name) ⇒ Object



289
290
291
292
293
294
295
296
297
# File 'lib/prima_aws_client.rb', line 289

def get_stack_template(name)
  resp = cf_client.get_template(stack_name: name)
rescue Aws::CloudFormation::Errors::Throttling => e
  output 'Throttling, retrying in 15 seconds'.red
  sleep 15
  get_stack_template(name)
else
  resp.template_body
end

#list_exportsObject



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/prima_aws_client.rb', line 81

def list_exports
  exports = []
  next_token = ''
  loop do
    print '.'.yellow; STDOUT.flush
    options = next_token != '' ? { next_token: next_token } : {}
    begin
      resp = cf_client.list_exports(options)
    rescue Aws::CloudFormation::Errors::Throttling => e
      output 'Throttling, retrying in 15 seconds'.red
      sleep 15
      resp = cf_client.list_exports(options)
    end
    exports += resp.exports
    break unless resp.next_token

    next_token = resp.next_token
  end
  puts '.'.yellow; STDOUT.flush
  exports
end

#list_import_stacks(export_name) ⇒ Object



376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
# File 'lib/prima_aws_client.rb', line 376

def list_import_stacks(export_name)
  stacks = []
  next_token = ''
  loop do
    print '.'.yellow; STDOUT.flush
    options = next_token != '' ? { export_name: export_name, next_token: next_token } : { export_name: export_name }
    begin
      resp = cf_client.list_imports(options)
    rescue Aws::CloudFormation::Errors::Throttling => e
      output 'Throttling, retrying in 15 seconds'.red
      sleep 15
      resp = cf_client.list_imports(options)
    end
    stacks += resp.imports
    break unless resp.next_token

    next_token = resp.next_token
  end
  stacks
end

#run_ecs_task(cluster, task_definition, overrides, count) ⇒ Object



455
456
457
458
459
460
461
462
463
464
465
466
# File 'lib/prima_aws_client.rb', line 455

def run_ecs_task(cluster, task_definition, overrides, count)
  resp = ecs_client.run_task({
                               cluster: cluster,
                               task_definition: task_definition,
                               overrides: overrides,
                               count: count
                             })
rescue Aws::CloudFormation::Errors::Throttling => e
  output 'Throttling, retrying in 15 seconds'.red
  sleep 15
  resp = run_ecs_task(cluster, task_definition, overrides, count)
end

#s3_clientObject



11
12
13
# File 'lib/prima_aws_client.rb', line 11

def s3_client
  @s3 ||= Aws::S3::Client.new
end

#stack_deleted?(stack_name, failed_statuses = %w[ROLLBACK_IN_PROGRESS ROLLBACK_FAILED DELETE_FAILED UPDATE_ROLLBACK_FAILED UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS]) ⇒ Boolean

Returns:

  • (Boolean)


314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/prima_aws_client.rb', line 314

def stack_deleted?(stack_name, failed_statuses = %w[ROLLBACK_IN_PROGRESS ROLLBACK_FAILED DELETE_FAILED UPDATE_ROLLBACK_FAILED UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS])
  begin
    resp = cf_client.describe_stacks(
      stack_name: stack_name
    )
    stack_status = resp.stacks[0].stack_status
  rescue Aws::CloudFormation::Errors::Throttling => e
    print 'Throttling'.red; STDOUT.flush
    return false
  rescue Aws::CloudFormation::Errors::ValidationError => e
    print 'Stack deleted'
    return true
  end
  raise "The stack #{stack_name} errored out" if failed_statuses.include? stack_status

  ['DELETE_COMPLETE'].include? stack_status
end

#stack_exists?(stack_name) ⇒ Boolean

Returns:

  • (Boolean)


198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/prima_aws_client.rb', line 198

def stack_exists?(stack_name)
  cf_client.describe_stacks(stack_name: stack_name)
rescue Aws::CloudFormation::Errors::Throttling => e
  output 'Throttling, retrying in 15 seconds'.red
  sleep 15
  stack_exists?(stack_name)
rescue Aws::CloudFormation::Errors::ValidationError => e
  return false if e.message.include? 'does not exist'

  raise e
else
  true
end

#stack_listObject



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/prima_aws_client.rb', line 35

def stack_list
  stacks = []
  next_token = ''
  loop do
    print '.'.yellow; STDOUT.flush
    options = next_token != '' ? { next_token: next_token } : {}
    begin
      resp = cf_client.describe_stacks(options)
    rescue Aws::CloudFormation::Errors::Throttling => e
      output 'Throttling, retrying in 15 seconds'.red
      sleep 15
      resp = cf_client.describe_stacks(options)
    end
    stacks += resp.stacks
    break unless resp.next_token

    next_token = resp.next_token
  end
  puts '.'.yellow; STDOUT.flush
  stacks.keep_if { |stack| stack.stack_name.include? '-qa-' }
  stacks
end

#stack_ready?(stack_name, failed_statuses = %w[CREATE_FAILED ROLLBACK_IN_PROGRESS ROLLBACK_FAILED DELETE_IN_PROGRESS DELETE_FAILED DELETE_COMPLETE UPDATE_ROLLBACK_FAILED UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS]) ⇒ Boolean

Returns:

  • (Boolean)


299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/prima_aws_client.rb', line 299

def stack_ready?(stack_name, failed_statuses = %w[CREATE_FAILED ROLLBACK_IN_PROGRESS ROLLBACK_FAILED DELETE_IN_PROGRESS DELETE_FAILED DELETE_COMPLETE UPDATE_ROLLBACK_FAILED UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS])
  begin
    resp = cf_client.describe_stacks(
      stack_name: stack_name
    )
    stack_status = resp.stacks[0].stack_status
  rescue Aws::CloudFormation::Errors::Throttling => e
    print 'Throttling'.red; STDOUT.flush
    return false
  end
  raise "The stack #{stack_name} errored out" if failed_statuses.include? stack_status

  %w[CREATE_COMPLETE UPDATE_COMPLETE UPDATE_ROLLBACK_COMPLETE ROLLBACK_COMPLETE].include? stack_status
end

#update_ecs_service(cluster, service, deployment_configuration) ⇒ Object



432
433
434
435
436
437
438
439
440
441
442
# File 'lib/prima_aws_client.rb', line 432

def update_ecs_service(cluster, service, deployment_configuration)
  resp = ecs_client.update_service(
    cluster: cluster,
    service: service,
    deployment_configuration: deployment_configuration
  )
rescue Aws::CloudFormation::Errors::Throttling => e
  output 'Throttling, retrying in 15 seconds'.red
  sleep 15
  resp = update_ecs_service(cluster, service, deployment_configuration)
end

#update_stack(stack_name, template_body, parameters = [], tags = [], role = nil) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/prima_aws_client.rb', line 126

def update_stack(stack_name, template_body, parameters = [], tags = [], role = nil)
  cf_args = {
    stack_name: stack_name,
    template_body: template_body,
    parameters: parameters,
    tags: tags,
    capabilities: ['CAPABILITY_IAM']
  }

  cf_args.merge!(role_arn: role) unless role.nil?

  begin
    cf_client.update_stack(cf_args)
  rescue Aws::CloudFormation::Errors::Throttling => e
    output 'Throttling, retrying in 15 seconds'.red
    sleep 15
    update_stack(stack_name, template_body, parameters = [], tags = [])
  rescue Aws::CloudFormation::Errors::ValidationError => e
    raise e
  else
    output "CloudFormation stack #{stack_name} update started".green
  end
end

#update_stack_reuse_template(stack_name, parameters = [], tags = [], role = nil) ⇒ Object



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/prima_aws_client.rb', line 174

def update_stack_reuse_template(stack_name, parameters = [], tags = [], role = nil)
  cf_args = {
    stack_name: stack_name,
    use_previous_template: true,
    parameters: parameters,
    tags: tags,
    capabilities: ['CAPABILITY_IAM']
  }

  cf_args.merge!(role_arn: role) unless role.nil?

  begin
    cf_client.update_stack(cf_args)
  rescue Aws::CloudFormation::Errors::Throttling => e
    output 'Throttling, retrying in 15 seconds'.red
    sleep 15
    update_stack(stack_name, template_body, parameters = [], tags = [])
  rescue Aws::CloudFormation::Errors::ValidationError => e
    raise e
  else
    output "CloudFormation stack #{stack_name} update started".green
  end
end

#update_stack_url(stack_name, template_url, parameters = [], tags = [], role = nil) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/prima_aws_client.rb', line 150

def update_stack_url(stack_name, template_url, parameters = [], tags = [], role = nil)
  cf_args = {
    stack_name: stack_name,
    template_url: template_url,
    parameters: parameters,
    tags: tags,
    capabilities: ['CAPABILITY_IAM']
  }

  cf_args.merge!(role_arn: role) unless role.nil?

  begin
    cf_client.update_stack(cf_args)
  rescue Aws::CloudFormation::Errors::Throttling => e
    output 'Throttling, retrying in 15 seconds'.red
    sleep 15
    update_stack_url(stack_name, template_url, parameters = [], tags = [])
  rescue Aws::CloudFormation::Errors::ValidationError => e
    raise e
  else
    output "CloudFormation stack #{stack_name} update started".green
  end
end

#upload_artifact(source_path, destination_path, bucket_name_override = nil) ⇒ Object



341
342
343
344
345
346
347
348
349
350
# File 'lib/prima_aws_client.rb', line 341

def upload_artifact(source_path, destination_path, bucket_name_override = nil)
  output "Uploading artifact (#{(File.size(source_path).to_f / 2**20).round(2)} MiB)\n".yellow
  s3 = Aws::S3::Resource.new
  s3_bucket = !bucket_name_override.nil? ? bucket_name_override : @s3_bucket
  puts s3_bucket
  obj = s3.bucket(s3_bucket).object(destination_path)
  obj.upload_file(source_path)

  output "#{s3_bucket}/#{destination_path} upload success!\n".green
end

#wait_for_artifact(bucket, path) ⇒ Object



352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
# File 'lib/prima_aws_client.rb', line 352

def wait_for_artifact(bucket, path)
  ready = artifact_exists?(bucket, path)
  sleep_seconds = 13
  output "Wating that artifact #{path} becomes ready...\n".yellow
  retries = 0
  until ready
    ready = true if artifact_exists?(bucket, path)
    seconds_elapsed = 0
    loop do
      break if seconds_elapsed >= sleep_seconds

      print '.'.yellow; STDOUT.flush
      sleep 1
      seconds_elapsed += 1
    end
    retries += 1
    if retries > 150
      output "\n Artifact #{path} timed out\n".red
      exit
    end
  end
  output "\nArtifact #{path} created!\n".green
end

#wait_for_stack_ready(stack_name, failed_statuses = %w[CREATE_FAILED ROLLBACK_IN_PROGRESS ROLLBACK_FAILED DELETE_IN_PROGRESS DELETE_FAILED DELETE_COMPLETE UPDATE_ROLLBACK_FAILED UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS]) ⇒ Object



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/prima_aws_client.rb', line 222

def wait_for_stack_ready(stack_name, failed_statuses = %w[CREATE_FAILED ROLLBACK_IN_PROGRESS ROLLBACK_FAILED DELETE_IN_PROGRESS DELETE_FAILED DELETE_COMPLETE UPDATE_ROLLBACK_FAILED UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS])
  ready = false
  sleep_seconds = 13
  output "Waiting for stack #{stack_name}...\n".yellow
  until ready
    ready = true if stack_ready?(stack_name, failed_statuses)
    seconds_elapsed = 0
    loop do
      break if seconds_elapsed >= sleep_seconds

      print '.'.yellow; STDOUT.flush
      sleep 1
      seconds_elapsed += 1
    end
  end
  output "\nStack #{stack_name} ready!\n".green
end

#wait_for_stack_removal(stack_name) ⇒ Object



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/prima_aws_client.rb', line 240

def wait_for_stack_removal(stack_name)
  ready = false
  sleep_seconds = 13
  sleep 10
  output "Waiting for stack #{stack_name}...\n".yellow
  until ready
    ready = true if stack_deleted?(stack_name)
    seconds_elapsed = 0
    loop do
      break if seconds_elapsed >= sleep_seconds

      print '.'.yellow; STDOUT.flush
      sleep 1
      seconds_elapsed += 1
    end
  end
  output "\nStack #{stack_name} eliminato!\n".green
end