ciinabox-ecs 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
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