Skip to content

Commit 33b25e6

Browse files
authored
Merge pull request #117 from toshke/travis_build_test
Travis build test
2 parents dbd9bd3 + 9c03ce8 commit 33b25e6

11 files changed

Lines changed: 197 additions & 46 deletions

File tree

.github/CONTRIBUTING

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,14 @@ for that task within CLI wrapper.
1212
### Adding new services
1313

1414
- Add template in `templates/services/service_name.rb`
15+
16+
17+
### Setting up travis builds and tests
18+
19+
Due travis limitation of secrets not being available in PR builds, cloudformation templates are not validated in PR
20+
builds. However, you should still have them executed on your own forks in travis. To setup builds, add following secrets
21+
in
22+
23+
- `AWS_REGION=us-east-1` - (or any other region you deem appropriate)
24+
- `AWS_ACCESS_KEY_ID` - your limited access key having only `cloudformation:ValidateTemplate` permissions
25+
- `AWS_SECRET_ACCESS_KEY` - your limited access key having only `cloudformation:ValidateTemplate` permissions

.travis.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
sudo: required
2+
dist: trusty
3+
rvm:
4+
- 2.3
5+
python:
6+
- 3.6
7+
#before_install:
8+
# - |
9+
# sudo apt-get update && \
10+
# sudo apt-get install software-properties-common -y && \
11+
# sudo add-apt-repository ppa:deadsnakes/ppa -y && \
12+
# sudo apt-add-repository ppa:brightbox/ruby-ng -y && \
13+
# sudo apt-get update && sudo apt-get install python3.6 python3-pip -y && \
14+
# sudo apt-get install ruby2.3 -y
15+
script:
16+
- gem build ciinabox-ecs.gemspec
17+
- gem install ciinabox-ecs-*.gem
18+
- which ciinabox-ecs && ciinabox-ecs help
19+
- cfndsl -u
20+
- |
21+
git clone https://github.com/base2services/ciinabox-ecs-examples
22+
cd ciinabox-ecs-examples
23+
which pip
24+
git checkout master
25+
set -x
26+
for ciinabox in demo_* ; do
27+
printf "\n\nTesting ${ciinabox}\n\n"
28+
# avoid validation in PRs as aws creds are not available
29+
set +e
30+
if [[ "$TRAVIS_EVENT_TYPE" =~ ^push|api$ ]]; then
31+
ciinabox-ecs generate validate ${ciinabox}
32+
else
33+
ciinabox-ecs generate ${ciinabox}
34+
fi
35+
if [ $? -ne 0 ]; then
36+
printf "\n\nCIINABOX test configuration ${ciinabox} failed\n\n"
37+
exit 2
38+
fi
39+
done
40+
deploy:
41+
provider: rubygems
42+
api_key: "${RUBYGEMS_API_KEY}"
43+
on:
44+
all_branches: true
45+
condition: $TRAVIS_BRANCH =~ ^develop|master && $TRAVIS_EVENT_TYPE =~ ^push|api$ && $TRAVIS_REPO_SLUG == "base2Services/ciinabox-ecs"

Gemfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
source 'https://rubygems.org'
22

33
gem 'rake'
4-
gem 'cfndsl','0.15.2'
4+
gem 'cfndsl', '~>0.16'
55
gem 'cfn_manage'
66
gem 'deep_merge'
77
gem 'rubyzip'
8+
gem 'aws-sdk-s3', '~>1'
9+
gem 'aws-sdk-cloudformation', '~>1'

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
[![Build Status](https://travis-ci.com/base2services/ciinabox-ecs.svg?branch=develop)](https://travis-ci.com/base2services/ciinabox-ecs.svg?branch=develop)
2+
13
# ciinabox ECS
24

35
ciinabox pronounced ciin a box is a set of automation for building

Rakefile

Lines changed: 90 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ require 'tempfile'
1111
require 'json'
1212
require_relative './ext/common_helper'
1313
require_relative './ext/zip_helper'
14+
require 'aws-sdk-s3'
15+
require 'aws-sdk-cloudformation'
1416
require 'ciinabox-ecs' if Gem::Specification::find_all_by_name('ciinabox-ecs').any?
1517

1618
namespace :ciinabox do
@@ -38,7 +40,7 @@ namespace :ciinabox do
3840
config = default_params
3941
end
4042

41-
Dir["#{ciinaboxes_dir}/#{ciinabox_name}/config/*.yml"].each { |config_file|
43+
Dir["#{ciinaboxes_dir}/#{ciinabox_name}/config/*.yml"].each {|config_file|
4244
if not config_file.include?('params.yml')
4345
config = config.merge(YAML.load(File.read(config_file)))
4446
end
@@ -48,12 +50,12 @@ namespace :ciinabox do
4850

4951
# ciinabox binary version
5052
if Gem.loaded_specs['ciinabox-ecs'].nil?
51-
config['ciinabox_binary_version'] = `git rev-parse --short HEAD`.gsub("\n",'')
53+
config['ciinabox_binary_version'] = `git rev-parse --short HEAD`.gsub("\n", '')
5254
else
5355
config['ciinabox_binary_version'] = Gem.loaded_specs['ciinabox-ecs'].version.to_s
5456
end
5557

56-
File.write('debug-ciinabox.config.yaml',config.to_yaml) if ENV['DEBUG']
58+
File.write('debug-ciinabox.config.yaml', config.to_yaml) if ENV['DEBUG']
5759

5860
stack_name = config["stack_name"] || "ciinabox"
5961

@@ -64,8 +66,8 @@ namespace :ciinabox do
6466
templates2 = Dir["#{ciinaboxes_dir}/#{ciinabox_name}/templates/**/*.rb"]
6567

6668
## we want to exclude overridden templates
67-
templatesLocalFileNames = templates2.collect { |templateFile| File.basename(templateFile) }
68-
templates = templates.select { |templateFile| not templatesLocalFileNames.include? File.basename(templateFile) }
69+
templatesLocalFileNames = templates2.collect {|templateFile| File.basename(templateFile)}
70+
templates = templates.select {|templateFile| not templatesLocalFileNames.include? File.basename(templateFile)}
6971
templates = templates + templates2
7072
end
7173

@@ -87,13 +89,13 @@ namespace :ciinabox do
8789
tmp_file = write_config_tmp_file(config)
8890

8991
CfnDsl::RakeTask.new do |t|
90-
extras = [[:yaml,"#{current_dir}/config/default_params.yml"]]
92+
extras = [[:yaml, "#{current_dir}/config/default_params.yml"]]
9193
extras << [:yaml, "#{current_dir}/config/default_lambdas.yml"]
9294
if File.exist? "#{ciinaboxes_dir}/ciinabox_config.yml"
9395
extras << [:yaml, "#{ciinaboxes_dir}/ciinabox_config.yml"]
9496
end
95-
(Dir["#{ciinaboxes_dir}/#{ciinabox_name}/config/*.yml"].map { |f| [:yaml,f]}).each {|c| extras<<c}
96-
extras << [:ruby,"#{current_dir}/ext/helper.rb"]
97+
(Dir["#{ciinaboxes_dir}/#{ciinabox_name}/config/*.yml"].map {|f| [:yaml, f]}).each {|c| extras << c}
98+
extras << [:ruby, "#{current_dir}/ext/helper.rb"]
9799
extras << [:yaml, tmp_file.path]
98100
t.cfndsl_opts = {
99101
verbose: true,
@@ -165,16 +167,16 @@ namespace :ciinabox do
165167
if File.exist?("#{ciinaboxes_dir}/#{ciinabox_name}/config/params.yml")
166168
config_output = user_params.merge(input_hash) #Merges input hash into user-provided template
167169
config_yaml = config_output.to_yaml #Convert output to YAML for writing
168-
File.open("#{ciinaboxes_dir}/#{ciinabox_name}/config/params.yml", 'w') { |f| f.write(config_yaml) }
170+
File.open("#{ciinaboxes_dir}/#{ciinabox_name}/config/params.yml", 'w') {|f| f.write(config_yaml)}
169171
else
170-
File.open("#{ciinaboxes_dir}/#{ciinabox_name}/config/params.yml", 'w') { |f| f.write(input_result) }
172+
File.open("#{ciinaboxes_dir}/#{ciinabox_name}/config/params.yml", 'w') {|f| f.write(input_result)}
171173
end
172174

173175
default_services = YAML.load(File.read("#{current_dir}/config/default_services.yml"))
174176

175177
class ::Hash
176178
def deep_merge(second)
177-
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 }
179+
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}
178180
self.merge(second.to_h, &merger)
179181
end
180182
end
@@ -184,10 +186,10 @@ namespace :ciinabox do
184186
user_services = YAML.load(File.read("#{ciinaboxes_dir}/#{ciinabox_name}/config/services.yml"))
185187
combined_services = default_services.deep_merge(user_services)
186188
yml_combined_services = combined_services.to_yaml
187-
File.open("#{ciinaboxes_dir}/#{ciinabox_name}/config/services.yml", 'w') { |f| f.write(yml_combined_services) }
189+
File.open("#{ciinaboxes_dir}/#{ciinabox_name}/config/services.yml", 'w') {|f| f.write(yml_combined_services)}
188190
else
189191
yml_default_services = default_services.to_yaml
190-
File.open("#{ciinaboxes_dir}/#{ciinabox_name}/config/services.yml", 'w') { |f| f.write(yml_default_services) }
192+
File.open("#{ciinaboxes_dir}/#{ciinabox_name}/config/services.yml", 'w') {|f| f.write(yml_default_services)}
191193
end
192194

193195
display_active_ciinabox ciinaboxes_dir, ciinabox_name
@@ -251,7 +253,7 @@ namespace :ciinabox do
251253
check_active_ciinabox(config)
252254
ciinabox_name = config['ciinabox_name']
253255
cert_dir = "#{ciinaboxes_dir}/#{ciinabox_name}"
254-
status, result = aws_execute( config, [
256+
status, result = aws_execute(config, [
255257
'iam', 'upload-server-certificate',
256258
'--server-certificate-name ciinabox',
257259
"--certificate-body file://#{cert_dir}/ssl/ciinabox.crt",
@@ -387,6 +389,13 @@ namespace :ciinabox do
387389
desc('Package Lambda Functions as ZipFiles')
388390
task :package_lambdas do
389391
check_active_ciinabox(config)
392+
393+
# custom lambda modification
394+
lambda_stack_required = config['acm_auto_issue_validate']
395+
# in future any new conditions for lambda stack would be added here
396+
# lambda_stack_required ||= some_new_condition
397+
config['lambdas'] = nil unless lambda_stack_required
398+
390399
if !config['lambdas'].nil? && !config['lambdas']['functions'].nil?
391400
log_header 'Package lambda functions'
392401

@@ -513,7 +522,7 @@ namespace :ciinabox do
513522
'--out json'
514523
])
515524
resp = JSON.parse(result)
516-
cert_output = resp['Stacks'][0]['Outputs'].find { |k| k['OutputKey'] == 'DefaultSSLCertificate' }
525+
cert_output = resp['Stacks'][0]['Outputs'].find {|k| k['OutputKey'] == 'DefaultSSLCertificate'}
517526
if cert_output.nil?
518527
STDERR.puts("ACM certificate is not present in stack outputs")
519528
exit -1
@@ -525,6 +534,64 @@ namespace :ciinabox do
525534
puts "Set #{cert_arn} as default_cert_arn"
526535
end
527536

537+
538+
desc('validate cloudformation templates')
539+
task :validate do
540+
cfn = Aws::CloudFormation::Client.new(region: config['source_region'])
541+
s3 = Aws::S3::Client.new(region: config['source_region'])
542+
Dir.glob("output/**/*.json") do |file|
543+
template_content = IO.read(file)
544+
# Skip if empty template generated
545+
next if (template_content == "null\n")
546+
template = File.open(file, 'rb')
547+
filename = File.basename file
548+
template_bytesize = template_content.bytesize
549+
file_size = File.size file
550+
local_validation = (template_content.bytesize < 51200)
551+
puts "INFO - #{file}: Filesize: #{file_size}, Bytesize: #{template_bytesize}, local validation: #{local_validation}"
552+
begin
553+
if not local_validation
554+
puts "INFO - Copy #{file} -> s3://#{config['source_bucket']}/cloudformation/#{project_name}/validate/#{filename}"
555+
s3.put_object({
556+
body: template,
557+
bucket: "#{config['source_bucket']}",
558+
key: "cloudformation/#{project_name}/validate/#{filename}",
559+
})
560+
template_url = "https://#{config['source_bucket']}.s3.amazonaws.com/cloudformation/#{project_name}/validate/#{filename}"
561+
puts "INFO - Copied #{file} to s3://#{config['source_bucket']}/cloudformation/#{project_name}/validate/#{filename}"
562+
puts "INFO - Validating #{template_url}"
563+
else
564+
puts "INFO - Validating #{file}"
565+
end
566+
begin
567+
resp = cfn.validate_template({ template_url: template_url }) unless local_validation
568+
resp = cfn.validate_template({ template_body: template_content }) if local_validation
569+
puts "INFO - Template #{filename} validated successfully"
570+
rescue => e
571+
puts "ERROR - Template #{filename} failed to validate: #{e}"
572+
exit 1
573+
end
574+
575+
rescue => e
576+
puts "ERROR - #{e.class}, #{e}"
577+
exit 1
578+
end
579+
end
580+
puts "INFO - #{Dir["output/**/*.json"].count} templates validated successfully"
581+
end
582+
583+
desc('vendor templates from ciinabox gem into ciinabox folder')
584+
task :vendor do
585+
Dir["#{current_dir}/templates/**/*.rb"].each do |template_path|
586+
relative_path = template_path.gsub("#{current_dir}/", '')
587+
target_path = "#{@ciinaboxes_dir}/#{@ciinabox_name}/#{relative_path}"
588+
target_dir = File.dirname(target_path)
589+
FileUtils.mkdir_p target_dir
590+
puts "#{relative_path} -> #{target_path}"
591+
FileUtils.copy template_path, target_path
592+
end
593+
end
594+
528595
def add_ciinabox_config_setting(element, value)
529596
file_name = "#{@ciinaboxes_dir}/#{@ciinabox_name}/config/params.yml"
530597
File.write(file_name,
@@ -534,7 +601,7 @@ namespace :ciinabox do
534601
)
535602
end
536603

537-
def remove_update_ciinabox_config_setting(element, new_value='')
604+
def remove_update_ciinabox_config_setting(element, new_value = '')
538605
f = File.new("#{@ciinaboxes_dir}/#{@ciinabox_name}/config/params.yml", 'r+')
539606
found = false
540607
f.each do |line|
@@ -550,7 +617,7 @@ namespace :ciinabox do
550617
end
551618
end
552619
f.close
553-
add_ciinabox_config_setting(element, new_value) if((not found) and (not new_value.empty?))
620+
add_ciinabox_config_setting(element, new_value) if ((not found) and (not new_value.empty?))
554621
end
555622

556623
def check_active_ciinabox(config)
@@ -608,12 +675,12 @@ namespace :ciinabox do
608675
question = ("#{question} (y/n)? [#{default ? 'y' : 'n'}]")
609676
while true
610677
case get_input(question)
611-
when ''
612-
return default
613-
when 'Y', 'y', 'yes'
614-
return true
615-
when /\A[nN]o?\Z/ #n or no
616-
return false
678+
when ''
679+
return default
680+
when 'Y', 'y', 'yes'
681+
return true
682+
when /\A[nN]o?\Z/ #n or no
683+
return false
617684
end
618685
end
619686
end
Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ require 'rake'
22

33
Gem::Specification.new do |s|
44
s.name = 'ciinabox-ecs'
5-
s.version = '0.2.8'
6-
s.date = '2018-05-07'
5+
s.version = '0.2.10'
6+
s.version = "#{s.version}.alpha.#{Time.now.getutc.to_i}" if ENV['TRAVIS'] and ENV['TRAVIS_BRANCH'] != 'master'
7+
s.date = Date.today.to_s
78
s.summary = 'Manage ciinabox on Aws Ecs'
89
s.description = ''
910
s.authors = ['Base2Services']
@@ -14,8 +15,10 @@ Gem::Specification.new do |s|
1415
s.executables << 'ciinabox-ecs'
1516
s.require_paths = ['lib']
1617
s.add_runtime_dependency 'rake', '~>12'
17-
s.add_runtime_dependency 'cfndsl', '~>0.15.2'
18-
s.add_runtime_dependency 'cfn_manage', '~>0.3.0'
18+
s.add_runtime_dependency 'aws-sdk-s3', '~>1'
19+
s.add_runtime_dependency 'aws-sdk-cloudformation', '~>1'
20+
s.add_runtime_dependency 'cfndsl', '~>0.16'
21+
s.add_runtime_dependency 'cfn_manage', '~>0'
1922
s.add_runtime_dependency 'deep_merge', '~>1.2'
2023
s.add_runtime_dependency 'rubyzip', '~> 1.2'
2124
end

config/default_params.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,3 +315,7 @@ acm_auto_issue_validate: true
315315
include_vpn_stack: false
316316
# open the vpn upd connection port 1194 to all ips
317317
vpn_udp_public: false
318+
319+
# Default public access is considered whole internet
320+
publicAccess:
321+
- 0.0.0.0/0

lambdas/acm_issuer_validator/install.sh

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash
2+
3+
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
4+
cd $DIR/..
5+
rm -rf lib
6+
7+
function pipinstall () {
8+
if [ $(which pip) == '' ]; then
9+
echo "ERROR! No pip installed. Try installing either python3 pip or docker"
10+
exit -1
11+
fi
12+
13+
pip install aws-acm-cert-validator==0.1.11 -t lib
14+
}
15+
16+
if [ $(which docker) == '' ]; then
17+
pipinstall
18+
else
19+
docker run --rm -v $DIR/..:/dst -w /dst -u $UID python:3-alpine pip install aws-acm-cert-validator==0.1.11 -t lib
20+
fi

0 commit comments

Comments
 (0)