ciinabox-ecs 0.1.6

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.
data/Rakefile ADDED
@@ -0,0 +1,649 @@
1
+ require 'cfndsl/rake_task'
2
+ require 'rake'
3
+ require 'yaml'
4
+ require 'erb'
5
+ require 'fileutils'
6
+ require 'pathname'
7
+ require 'net/http'
8
+ require 'securerandom'
9
+ require 'base64'
10
+ require 'tempfile'
11
+ require 'json'
12
+ require_relative './ext/common_helper'
13
+ require_relative './ext/zip_helper'
14
+ namespace :ciinabox do
15
+
16
+ #load config
17
+ current_dir = File.expand_path File.dirname(__FILE__)
18
+
19
+ templates = Dir["#{current_dir}/templates/**/*.rb"]
20
+ ciinaboxes_dir = ENV['CIINABOXES_DIR'] || 'ciinaboxes'
21
+ ciinabox_name = ENV['CIINABOX'] || ''
22
+
23
+ @ciinaboxes_dir = ciinaboxes_dir
24
+ @ciinabox_name = ciinabox_name
25
+
26
+ #Load and merge standard ciinabox-provided parameters
27
+ default_params = YAML.load(File.read("#{current_dir}/config/default_params.yml")) if File.exist?("#{current_dir}/config/default_params.yml")
28
+ lambda_params = YAML.load(File.read("#{current_dir}/config/default_lambdas.yml"))
29
+ default_params.merge!(lambda_params)
30
+
31
+ if File.exist?("#{ciinaboxes_dir}/#{ciinabox_name}/config/params.yml")
32
+ user_params = YAML.load(File.read("#{ciinaboxes_dir}/#{ciinabox_name}/config/params.yml"))
33
+ config = default_params.merge(user_params)
34
+ else
35
+ user_params = {}
36
+ config = default_params
37
+ end
38
+
39
+ Dir["#{ciinaboxes_dir}/#{ciinabox_name}/config/*.yml"].each { |config_file|
40
+ if not config_file.include?('params.yml')
41
+ config = config.merge(YAML.load(File.read(config_file)))
42
+ end
43
+ }
44
+ config['lambdas'] = {} unless config.key? 'lambdas'
45
+ config['lambdas'].extend(config['default_lambdas'])
46
+
47
+ File.write('debug-ciinabox.config.yaml',config.to_yaml) if ENV['DEBUG']
48
+
49
+ stack_name = config["stack_name"] || "ciinabox"
50
+
51
+ #if {ciinaboxes_dir}/#{ciinabox_name}/templates
52
+ #render and add to templates
53
+
54
+ if File.exist?("#{ciinaboxes_dir}/#{ciinabox_name}/templates")
55
+ templates2 = Dir["#{ciinaboxes_dir}/#{ciinabox_name}/templates/**/*.rb"]
56
+
57
+ ## we want to exclude overridden templates
58
+ templatesLocalFileNames = templates2.collect { |templateFile| File.basename(templateFile) }
59
+ templates = templates.select { |templateFile| not templatesLocalFileNames.include? File.basename(templateFile) }
60
+ templates = templates + templates2
61
+ end
62
+
63
+ files = []
64
+ templates.each do |template|
65
+ filename = "#{template}"
66
+ output = template.sub! /.*templates\//, ''
67
+ output = output.sub! '.rb', '.json'
68
+ files << { filename: filename, output: "output/#{output}" }
69
+ end
70
+
71
+ # Generate cloudformation templates, includes packaging of lambda functions
72
+ desc("Generate CloudFormation templates")
73
+ task :generate => ['ciinabox:package_lambdas'] do
74
+ check_active_ciinabox(config)
75
+ FileUtils.mkdir_p 'output/services'
76
+
77
+ # Write config generated by lambda package to tmp file, and pass to templates
78
+ tmp_file = write_config_tmp_file(config)
79
+
80
+ CfnDsl::RakeTask.new do |t|
81
+ extras = [[:yaml, "#{current_dir}/config/default_params.yml"]]
82
+ extras << [:yaml, "#{current_dir}/config/default_lambdas.yml"]
83
+ if File.exist? "#{ciinaboxes_dir}/ciinabox_config.yml"
84
+ extras << [:yaml, "#{ciinaboxes_dir}/ciinabox_config.yml"]
85
+ end
86
+ (Dir["#{ciinaboxes_dir}/#{ciinabox_name}/config/*.yml"].map { |f| [:yaml, f] }).each { |c| extras<<c }
87
+ extras << [:ruby, "#{current_dir}/ext/helper.rb"]
88
+ extras << [:yaml, tmp_file.path]
89
+ t.cfndsl_opts = {
90
+ verbose: true,
91
+ files: files,
92
+ extras: extras
93
+ }
94
+ end
95
+
96
+ Rake::Task['generate'].invoke
97
+ end
98
+
99
+ # Header output
100
+ def log_header(header)
101
+ puts "\n\n ========== #{header} ========== \n [#{Time.now}]\n\n\n"
102
+ end
103
+
104
+ desc('Initialise a new ciinabox environment')
105
+ task :init do |t, args|
106
+
107
+ autogenerated_bucket_name = "ciinabox-deployment-#{SecureRandom.uuid}"
108
+
109
+ ciinabox_name = get_input("Enter the name of your ciinabox:")
110
+ @ciinabox_name = ciinabox_name
111
+ ENV['CIINABOX'] = ciinabox_name
112
+
113
+ ciinabox_region = get_input("Enter the AWS region to create your ciinabox [us-east-1]:")
114
+ puts 'Using us-east-1 as AWS region' if ciinabox_region.strip == ''
115
+ ciinabox_region = 'us-east-1' if ciinabox_region.strip == ''
116
+
117
+ ciinabox_source_bucket = get_input("Enter the name of the S3 bucket to deploy ciinabox to [#{autogenerated_bucket_name}]:")
118
+ ciinabox_source_bucket = autogenerated_bucket_name if ciinabox_source_bucket.strip == ''
119
+
120
+ ciinabox_tools_domain = get_input("Enter top level domain (e.g tools.example.com), must exist in Route53 in the same AWS account:")
121
+ ciinabox_aws_profile = get_input("Enter AWS profile you wish to use for provisioning (empty for default):")
122
+
123
+ profile_switch = ciinabox_aws_profile != '' ? "--profile #{ciinabox_aws_profile}" : ''
124
+ ciinabox_aws_account = `aws sts get-caller-identity --region #{ciinabox_region} #{profile_switch} --output text --query Account`.sub('\n', '').strip
125
+
126
+ puts "Using AWS Account #{ciinabox_aws_account}"
127
+
128
+ stack_name = get_input("Enter the name of created Cloud Formation stack [ciinabox]:")
129
+ stack_name = 'ciinabox' if (stack_name.strip == '')
130
+
131
+ include_dood_slave = yesno("Include docker-outside-of-docker slave", false)
132
+ include_dind_slave = yesno("Include docker-in-docker slave", true)
133
+ self_signed = yesno("Use selfsigned rather than ACM issued and validated certificate", false)
134
+ acm_auto_issue_validate = !self_signed
135
+ use_iam_role = yesno("Use existing role for CIINABOX cluster", true)
136
+ if use_iam_role then
137
+ ciinabox_iam_role_name = get_input('Enter name of iam role to use with CIINABOX cluster [ciinabox]:')
138
+ ciinabox_iam_role_name = 'ciinabox' if ciinabox_iam_role_name.strip == ''
139
+ end
140
+
141
+ ciinabox_docker_repo = get_input('Enter name of private docker repository for images [empty for public images]:')
142
+
143
+ if ciinabox_name == ''
144
+ puts 'You must enter a name for your ciinabox'
145
+ exit 1
146
+ end
147
+
148
+ my_public_ip = get_my_public_ip_address + "/32"
149
+ create_dirs ciinaboxes_dir, ciinabox_name
150
+
151
+ #Settings preference - 1) User-input 2) User-provided params.yml 3) Default template
152
+
153
+ ciinabox_params = File.read("#{current_dir}/config/ciinabox_params.yml.erb")
154
+ input_result = ERB.new(ciinabox_params).result(binding)
155
+ input_hash = YAML.load(input_result) #Converts user input to hash
156
+ if File.exist?("#{ciinaboxes_dir}/#{ciinabox_name}/config/params.yml")
157
+ config_output = user_params.merge(input_hash) #Merges input hash into user-provided template
158
+ config_yaml = config_output.to_yaml #Convert output to YAML for writing
159
+ File.open("#{ciinaboxes_dir}/#{ciinabox_name}/config/params.yml", 'w') { |f| f.write(config_yaml) }
160
+ else
161
+ File.open("#{ciinaboxes_dir}/#{ciinabox_name}/config/params.yml", 'w') { |f| f.write(input_result) }
162
+ end
163
+
164
+ default_services = YAML.load(File.read("#{current_dir}/config/default_services.yml"))
165
+
166
+ class ::Hash
167
+ def deep_merge(second)
168
+ merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : Array === v1 && Array === v2 ? v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
169
+ self.merge(second.to_h, &merger)
170
+ end
171
+ end
172
+
173
+ if File.exist?("#{ciinaboxes_dir}/#{ciinabox_name}/config/services.yml")
174
+ puts "Using user-provided services.yml File"
175
+ user_services = YAML.load(File.read("#{ciinaboxes_dir}/#{ciinabox_name}/config/services.yml"))
176
+ combined_services = default_services.deep_merge(user_services)
177
+ yml_combined_services = combined_services.to_yaml
178
+ File.open("#{ciinaboxes_dir}/#{ciinabox_name}/config/services.yml", 'w') { |f| f.write(yml_combined_services) }
179
+ else
180
+ yml_default_services = default_services.to_yaml
181
+ File.open("#{ciinaboxes_dir}/#{ciinabox_name}/config/services.yml", 'w') { |f| f.write(yml_default_services) }
182
+ end
183
+
184
+ display_active_ciinabox ciinaboxes_dir, ciinabox_name
185
+ end
186
+
187
+
188
+ desc('Current status of the active ciinabox')
189
+ task :status do
190
+ check_active_ciinabox(config)
191
+ status, result = aws_execute(config, ['cloudformation', 'describe-stacks', "--stack-name #{stack_name}", '--query "Stacks[0].StackStatus"', '--out text'])
192
+ if status > 0
193
+ puts "fail to get status for #{config['ciinabox_name']}...has it been created?"
194
+ exit 1
195
+ end
196
+ output = result.chop!
197
+ if output == 'CREATE_COMPLETE' || output == 'UPDATE_COMPLETE'
198
+ puts "#{config['ciinabox_name']} ciinabox is alive!!!!"
199
+ display_ecs_ip_address config
200
+ else
201
+ puts "#{config['ciinabox_name']} ciinabox is in state: #{output}"
202
+ end
203
+ end
204
+
205
+ desc('Creates the source bucket for deploying ciinabox')
206
+ task :create_source_bucket do
207
+ check_active_ciinabox(config)
208
+ status, result = aws_execute(config, ['s3', 'ls', "s3://#{config['source_bucket']}/ciinabox/#{config['ciinabox_version']}/"])
209
+ if status > 0
210
+ status, result = aws_execute(config, ['s3', 'mb', "s3://#{config['source_bucket']}"])
211
+ puts result
212
+ if status > 0
213
+ puts "fail to create source bucket see error logs for details"
214
+ exit status
215
+ else
216
+ puts "Successfully created S3 source deployment bucket #{config['source_bucket']}"
217
+ end
218
+ else
219
+ puts "Source deployment bucket #{config['source_bucket']} already exists"
220
+ end
221
+ end
222
+
223
+ desc('Create self-signed SSL certs for use with ciinabox')
224
+ task :create_server_cert do
225
+ check_active_ciinabox(config)
226
+ ciinabox_name = config['ciinabox_name']
227
+ dns_domain = config['dns_domain']
228
+ script = "
229
+ openssl req -nodes -new -x509 -newkey rsa:4096 -days 3650 \
230
+ -keyout #{ciinaboxes_dir}/#{ciinabox_name}/ssl/ciinabox.key \
231
+ -out #{ciinaboxes_dir}/#{ciinabox_name}/ssl/ciinabox.crt \
232
+ -subj '/C=AU/ST=Melbourne/L=Melbourne/O=#{ciinabox_name}/OU=ciinabox/CN=*.#{dns_domain}'
233
+ "
234
+ result = `#{script}`
235
+ puts result
236
+ end
237
+
238
+ desc('Uploads SSL server certs for ciinabox')
239
+ task :upload_server_cert do
240
+ check_active_ciinabox(config)
241
+
242
+ check_active_ciinabox(config)
243
+ ciinabox_name = config['ciinabox_name']
244
+ cert_dir = "#{ciinaboxes_dir}/#{ciinabox_name}"
245
+ status, result = aws_execute( config, [
246
+ 'iam', 'upload-server-certificate',
247
+ '--server-certificate-name ciinabox',
248
+ "--certificate-body file://#{cert_dir}/ssl/ciinabox.crt",
249
+ "--private-key file://#{cert_dir}/ssl/ciinabox.key",
250
+ "--certificate-chain file://#{cert_dir}/ssl/ciinabox.crt"
251
+ ])
252
+ if status > 0
253
+ puts "fail to create or update IAM server-certificates. See error logs for details"
254
+ puts result
255
+ exit status
256
+ end
257
+
258
+ certificate_arn = JSON.parse(result)['CertificateArn']
259
+ puts "Successfully uploaded ACM certificate #{certificate_arn}."
260
+ # remove_update_ciinabox_config_setting('default_ssl_cert_id', certificate_arn)
261
+ # puts "Ciinabox #{ciinabox_name} config file updated with new cert"
262
+ end
263
+
264
+ desc('Generate ciinabox AWS keypair')
265
+ task :generate_keypair do
266
+ check_active_ciinabox(config)
267
+ ciinabox_name = config['ciinabox_name']
268
+ keypair_dir = "#{ciinaboxes_dir}/#{ciinabox_name}/ssl"
269
+ if File.exists?("#{keypair_dir}/ciinabox.pem")
270
+ puts "keypair for ciinabox #{ciinabox_name} already exists...please delete if you wish to re-create it"
271
+ exit 1
272
+ end
273
+ status, result = aws_execute(config, ['ec2', 'create-key-pair',
274
+ "--key-name ciinabox",
275
+ "--query 'KeyMaterial'",
276
+ "--out text"
277
+ ], "#{keypair_dir}/ciinabox.pem")
278
+ puts result
279
+ if status > 0
280
+ puts "fail to create keypair see error logs for details"
281
+ exit status
282
+ else
283
+ result = `chmod 0600 #{keypair_dir}/ciinabox.pem`
284
+ puts "Successfully created ciinabox ssh keypair"
285
+ end
286
+ end
287
+
288
+ desc('Deploy Cloudformation templates to S3')
289
+ task :deploy do
290
+ check_active_ciinabox(config)
291
+ status, result = aws_execute(config, ['s3', 'sync', 'output/', "s3://#{config['source_bucket']}/ciinabox/#{config['ciinabox_version']}/"])
292
+ puts result
293
+ if status > 0
294
+ puts "fail to upload rendered templates to S3 bucket #{config['source_bucket']}"
295
+ exit status
296
+ else
297
+ puts "Successfully uploaded rendered templates to S3 bucket #{config['source_bucket']}"
298
+ end
299
+ end
300
+
301
+ desc('Creates the ciinabox environment')
302
+ task :create do
303
+ check_active_ciinabox(config)
304
+ status, result = aws_execute(config, ['cloudformation', 'create-stack',
305
+ "--stack-name #{stack_name}",
306
+ "--template-url https://#{config['source_bucket']}.s3.amazonaws.com/ciinabox/#{config['ciinabox_version']}/ciinabox.json",
307
+ '--capabilities CAPABILITY_IAM'
308
+ ])
309
+ puts result
310
+ if status > 0
311
+ puts "Failed to create ciinabox environment"
312
+ exit status
313
+ else
314
+ puts "Starting creation of ciinabox environment"
315
+ end
316
+ end
317
+
318
+ desc('Updates the ciinabox environment')
319
+ task :update do
320
+ check_active_ciinabox(config)
321
+ status, result = aws_execute(config, ['cloudformation', 'update-stack',
322
+ "--stack-name #{stack_name}",
323
+ "--template-url https://#{config['source_bucket']}.s3.amazonaws.com/ciinabox/#{config['ciinabox_version']}/ciinabox.json",
324
+ '--capabilities CAPABILITY_IAM'
325
+ ])
326
+ puts result
327
+ if status > 0
328
+ puts "Failed to update ciinabox environment"
329
+ exit status
330
+ else
331
+ puts "Starting updating of ciinabox environment"
332
+ end
333
+ end
334
+
335
+ desc('Turn off your ciinabox environment')
336
+ task :down do
337
+ # Use cfn_manage gem for this
338
+ command = 'stop'
339
+ start_stop_env(command, config)
340
+ end
341
+
342
+ desc('Turn on your ciinabox environment')
343
+ task :up do
344
+ # Use cfn_manage gem for this
345
+ command = 'start'
346
+ start_stop_env(command, config)
347
+ end
348
+
349
+ desc('Deletes/tears down the ciinabox environment')
350
+ task :tear_down do
351
+ check_active_ciinabox(config)
352
+ STDOUT.puts "Are you sure you want to tear down the #{config['ciinabox_name']} ciinabox? (y/n)"
353
+ input = STDIN.gets.strip
354
+ if input == 'y'
355
+ status, result = aws_execute(config, ['cloudformation', 'delete-stack', "--stack-name #{stack_name}"])
356
+ puts result
357
+ if status > 0
358
+ puts "fail to tear down ciinabox environment"
359
+ exit status
360
+ else
361
+ puts "Starting tear down of ciinabox environment"
362
+ end
363
+ else
364
+ puts "good choice...keep enjoying your ciinabox"
365
+ end
366
+ end
367
+
368
+ desc('SSH into your ciinabox environment')
369
+ task :ssh do
370
+ keypair = "#{ciinaboxes_dir}/#{ciinabox_name}/ssl/ciinabox.pem"
371
+ `ssh-add #{ciinaboxes_dir}/#{ciinabox_name}/ssl/ciinabox.pem`
372
+ puts "# execute the following:"
373
+ puts "ssh -A ec2-user@nata.#{config['dns_domain']} -i #{keypair}"
374
+ puts "# and then"
375
+ puts "ssh #{get_ecs_ip_address(config)}"
376
+ end
377
+
378
+ desc('Package Lambda Functions as ZipFiles')
379
+ task :package_lambdas do
380
+ check_active_ciinabox(config)
381
+ if !config['lambdas'].nil? && !config['lambdas']['functions'].nil?
382
+ log_header 'Package lambda functions'
383
+
384
+ # Clear previous packages
385
+
386
+ FileUtils.rmtree 'output/lambdas'
387
+
388
+ # Cached downloads map
389
+ cached_downloads = {}
390
+ config['lambdas']['functions'].each do |name, lambda_config|
391
+ timestamp = Time.now.getutc.to_i
392
+ # create folder
393
+
394
+ config_file_folder = "output/lambdas/#{name}/#{timestamp}"
395
+ FileUtils.mkdir_p config_file_folder
396
+
397
+ # download file if code remote archive
398
+ puts "Processing function #{name}...\n"
399
+
400
+ if lambda_config['local']
401
+ lambda_source_path = "#{current_dir}/#{lambda_config['code']}" if lambda_config['local']
402
+ lambda_source_file = File.basename(lambda_source_path)
403
+ tmpdir = "output/package_lambdas/#{name}"
404
+ FileUtils.mkdir_p tmpdir
405
+ FileUtils.cp_r(lambda_source_path, tmpdir)
406
+ lambda_source_path = "#{tmpdir}/#{lambda_source_file}"
407
+ else
408
+ lambda_source_path = "#{ciinaboxes_dir}/#{ciinabox_name}/#{lambda_config['code']}"
409
+ end
410
+
411
+ lambda_source_dir = File.dirname(lambda_source_path)
412
+
413
+ lambda_source_file = File.basename(lambda_source_path)
414
+ lambda_source_file = '.' if Pathname.new(lambda_source_path).directory?
415
+
416
+ lambda_source_dir = lambda_source_path if Pathname.new(lambda_source_path).directory?
417
+ puts "Lambda source path: #{lambda_source_path}"
418
+ puts "Lambda source dir: #{lambda_source_dir}"
419
+
420
+ unless lambda_config['package_cmd'].nil?
421
+ package_cmd = "cd #{lambda_source_dir} && #{lambda_config['package_cmd']}"
422
+ puts 'Processing package command...'
423
+ package_result = system(package_cmd)
424
+ unless package_result
425
+ puts "Error packaging lambda function, following command failed\n\n#{package_cmd}\n\n"
426
+ exit -4
427
+ end
428
+ end
429
+
430
+ if lambda_config['code'].include? 'http'
431
+ if cached_downloads.key? lambda_config['code']
432
+ puts "Using already downloaded archive #{lambda_config['code']}"
433
+ FileUtils.copy(cached_downloads[lambda_config['code']], "#{config_file_folder}/src.zip")
434
+ else
435
+ puts "Downloading file #{lambda_config['code']} ..."
436
+ File.write("#{config_file_folder}/src.zip", Net::HTTP.get(URI.parse(lambda_config['code'])))
437
+ puts 'Download complete'
438
+ cached_downloads[lambda_config['code']] = "#{config_file_folder}/src.zip"
439
+ end
440
+ else
441
+
442
+ zip_generator = Ciinabox::Util::ZipFileGenerator.new(lambda_source_dir,
443
+ "#{config_file_folder}/src.zip")
444
+
445
+ zip_generator.write
446
+
447
+ end
448
+
449
+ sha256 = Digest::SHA256.file "#{config_file_folder}/src.zip"
450
+ sha256 = sha256.base64digest
451
+ puts "Created zip package #{config_file_folder}/src.zip for lambda #{name} with digest #{sha256}"
452
+ lambda_config['code_sha256'] = sha256
453
+ lambda_config['timestamp'] = timestamp
454
+ end
455
+
456
+ FileUtils.rmtree 'output/package_lambdas'
457
+ end
458
+ end
459
+
460
+ desc('Initialize configuration, create required assets in AWS account, create Cloud Formation stack')
461
+ task :full_install do
462
+
463
+ Rake::Task['ciinabox:init'].invoke
464
+
465
+ # Reload config
466
+ user_params = YAML.load(File.read("#{ciinaboxes_dir}/#{ciinabox_name}/config/params.yml"))
467
+ config = default_params.merge(user_params)
468
+
469
+ if (yesno('Create source bucket', true))
470
+ Rake::Task['ciinabox:create_source_bucket'].invoke
471
+ end
472
+
473
+ if (yesno("Create and upload server certificate?\n(chose yes if using local hosts file for DNS to tools)", false))
474
+ Rake::Task['ciinabox:create_server_cert'].invoke
475
+ Rake::Task['ciinabox:upload_server_cert'].invoke
476
+ user_params = YAML.load(File.read("#{ciinaboxes_dir}/#{ciinabox_name}/config/params.yml"))
477
+ end
478
+
479
+ # Create ciinabox keypair
480
+ if (yesno('Create and upload ciinabox key', true))
481
+ Rake::Task['ciinabox:generate_keypair'].invoke
482
+ end
483
+
484
+ # Generate CF
485
+ Rake::Task['ciinabox:generate'].invoke
486
+
487
+ # Deploy CF
488
+ Rake::Task['ciinabox:deploy'].invoke
489
+
490
+ # Create stack
491
+ Rake::Task['ciinabox:create'].invoke
492
+
493
+ puts "Waiting for Cloud Formation stack creation completion ..."
494
+ aws_execute(config, ["cloudformation wait stack-create-complete --stack-name #{stack_name}"])
495
+
496
+ end
497
+
498
+ desc('Replace previously auto-generated IAM certificate with auto-validated ACM certificate (if one exists)')
499
+ task :update_cert_to_acm do
500
+ status, result = aws_execute(config, [
501
+ 'cloudformation',
502
+ 'describe-stacks',
503
+ "--stack-name #{stack_name}",
504
+ '--out json'
505
+ ])
506
+ resp = JSON.parse(result)
507
+ cert_output = resp['Stacks'][0]['Outputs'].find { |k| k['OutputKey'] == 'DefaultSSLCertificate' }
508
+ if cert_output.nil?
509
+ STDERR.puts("ACM certificate is not present in stack outputs")
510
+ exit -1
511
+ end
512
+ cert_arn = cert_output['OutputValue']
513
+
514
+ # as we don't want to remove any comments
515
+ remove_update_ciinabox_config_setting('default_ssl_cert_id', cert_arn)
516
+ puts "Set #{cert_arn} as default_cert_arn"
517
+ end
518
+
519
+ def add_ciinabox_config_setting(element, value)
520
+ file_name = "#{@ciinaboxes_dir}/#{@ciinabox_name}/config/params.yml"
521
+ File.write(file_name,
522
+ "\n" + "#{element}: #{value}",
523
+ File.size(file_name),
524
+ mode: 'a'
525
+ )
526
+ end
527
+
528
+ def remove_update_ciinabox_config_setting(element, new_value='')
529
+ f = File.new("#{@ciinaboxes_dir}/#{@ciinabox_name}/config/params.yml", 'r+')
530
+ found = false
531
+ f.each do |line|
532
+ if line.include?(element)
533
+ # seek back to the beginning of the line.
534
+ f.seek(-line.length, IO::SEEK_CUR)
535
+
536
+ # overwrite line with spaces and add a newline char
537
+ f.write('') if new_value.empty?
538
+ f.write("#{element}: #{new_value}") unless new_value.empty?
539
+ f.write("\n")
540
+ found = true
541
+ end
542
+ end
543
+ f.close
544
+ add_ciinabox_config_setting(element, new_value) if((not found) and (not new_value.empty?))
545
+ end
546
+
547
+ def check_active_ciinabox(config)
548
+ if (config.nil? || config['ciinabox_name'].nil?)
549
+ puts "no active ciinabox - either export CIINABOX variable or set ciinabox name as last command line argument"
550
+ exit 1
551
+ end
552
+ end
553
+
554
+ def aws_execute(config, cmd, output = nil)
555
+ config['aws_profile'].nil? ? '' : cmd << "--profile #{config['aws_profile']}"
556
+ config['aws_region'].nil? ? '' : cmd << "--region #{config['aws_region']}"
557
+ args = cmd.join(" ")
558
+ if config['log_level'] == :debug
559
+ puts "executing: aws #{args}"
560
+ end
561
+ if output.nil?
562
+ result = `aws #{args} 2>&1`
563
+ else
564
+ result = `aws #{args} > #{output}`
565
+ end
566
+ return $?.to_i, result
567
+ end
568
+
569
+ def display_active_ciinabox(ciinaboxes_dir, ciinabox)
570
+ puts "# Enable active ciinabox by executing or override ciinaboxes base directory:"
571
+ puts "export CIINABOXES_DIR=\"#{ciinaboxes_dir}\""
572
+ puts "export CIINABOX=\"#{ciinabox}\""
573
+ end
574
+
575
+ def display_ecs_ip_address(config)
576
+ ip_address = get_ecs_ip_address(config)
577
+ if ip_address.nil?
578
+ puts "Unable to get ECS cluster private ip"
579
+ else
580
+ puts "ECS cluster private ip:#{ip_address}"
581
+ end
582
+ end
583
+
584
+ def get_ecs_ip_address(config)
585
+ status, result = aws_execute(config, [
586
+ 'ec2',
587
+ 'describe-instances',
588
+ '--query Reservations[*].Instances[?Tags[?Value==\`ciinabox-ecs\`]].PrivateIpAddress',
589
+ '--out text'
590
+ ])
591
+ if status > 0
592
+ return nil
593
+ else
594
+ return result
595
+ end
596
+ end
597
+
598
+ def yesno(question, default)
599
+ question = ("#{question} (y/n)? [#{default ? 'y' : 'n'}]")
600
+ while true
601
+ case get_input(question)
602
+ when ''
603
+ return default
604
+ when 'Y', 'y', 'yes'
605
+ return true
606
+ when /\A[nN]o?\Z/ #n or no
607
+ return false
608
+ end
609
+ end
610
+ end
611
+
612
+ def get_input(prompt)
613
+ puts prompt
614
+ $stdin.gets.chomp
615
+ end
616
+
617
+ def create_dirs(dir, name)
618
+ config_dirname = File.dirname("#{dir}/#{name}/config/ignore.txt")
619
+ unless File.directory?(config_dirname)
620
+ FileUtils.mkdir_p(config_dirname)
621
+ end
622
+ ssl_dirname = File.dirname("#{dir}/#{name}/ssl/ignore.txt")
623
+ unless File.directory?(ssl_dirname)
624
+ FileUtils.mkdir_p(ssl_dirname)
625
+ end
626
+ config_dirname
627
+ end
628
+
629
+ def get_my_public_ip_address
630
+ Net::HTTP.get(URI("http://api.ipify.org"))
631
+ end
632
+
633
+ def write_config_tmp_file(config)
634
+ #write config to tmp file
635
+ tmp_file = Tempfile.new(%w(config_obj .yml))
636
+ tmp_file << { config: config }.to_yaml
637
+ tmp_file.rewind
638
+ return tmp_file
639
+ end
640
+
641
+ def start_stop_env(command, config)
642
+ cmd = "cfn_manage #{command}-environment --stack-name #{config['stack_name']} "
643
+ cmd += " --source-bucket #{config['source_bucket']}"
644
+ cmd += " --region #{config['source_region']}"
645
+ cmd += " --profile #{config['aws_profile']}" if not config['aws_profile'].nil?
646
+ result = system(cmd)
647
+ exit -1 if not result
648
+ end
649
+ end