gantree 0.2.7 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +5 -0
- data/README.md +9 -5
- data/gantree.gemspec +3 -0
- data/lib/gantree.rb +2 -1
- data/lib/gantree/base.rb +24 -0
- data/lib/gantree/cli.rb +4 -2
- data/lib/gantree/deploy.rb +27 -23
- data/lib/gantree/init.rb +31 -23
- data/lib/gantree/notification.rb +1 -1
- data/lib/gantree/{cfn.rb → stack.rb} +26 -27
- data/lib/gantree/version.rb +1 -1
- data/spec/lib/{cli_spec.rb → gantree/cli_spec.rb} +3 -0
- data/spec/lib/gantree/deploy_spec.rb +73 -0
- data/spec/lib/gantree/init_spec.rb +95 -0
- data/spec/lib/gantree/stack_spec.rb +23 -0
- data/spec/spec_helper.rb +23 -6
- metadata +39 -7
- data/spec/lib/deploy_spec.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a0d7adf5bc5062c5e4a37f37f097f04f96c73d4
|
4
|
+
data.tar.gz: 46a5a976386359a4acba7ded4c19cf7e7640fea4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91399ef827763928ac3f922876ae86b90137a76ca7d3172419671e37cb7693d63b3af8668baaf4631792e737b0f9eb411c87ac6179f306506ceaa1f3c5876b2b
|
7
|
+
data.tar.gz: f62e5b8a8fe21c2abc213ce10c75913c76750cb516ec3c750a6a44d059833567f0a905a2fa74b199ed4e5ac913f43bb99855726948ba1ec82431db666cd21421
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -19,6 +19,7 @@ GEM
|
|
19
19
|
detabulator (0.1.0)
|
20
20
|
diff-lcs (1.2.5)
|
21
21
|
docile (1.1.5)
|
22
|
+
fakeweb (1.3.0)
|
22
23
|
ffi (1.9.3)
|
23
24
|
formatador (0.2.5)
|
24
25
|
guard (2.6.1)
|
@@ -78,6 +79,7 @@ GEM
|
|
78
79
|
slop (3.6.0)
|
79
80
|
thor (0.19.1)
|
80
81
|
timers (1.1.0)
|
82
|
+
vcr (2.9.3)
|
81
83
|
webmock (1.18.0)
|
82
84
|
addressable (>= 2.3.6)
|
83
85
|
crack (>= 0.3.2)
|
@@ -90,12 +92,15 @@ DEPENDENCIES
|
|
90
92
|
aws-sdk-v1
|
91
93
|
cloudformation-ruby-dsl
|
92
94
|
codeclimate-test-reporter
|
95
|
+
fakeweb
|
93
96
|
guard
|
94
97
|
guard-bundler
|
95
98
|
guard-rspec
|
96
99
|
highline
|
97
100
|
json
|
101
|
+
pry
|
98
102
|
rake
|
99
103
|
rspec
|
100
104
|
slackr
|
105
|
+
vcr
|
101
106
|
webmock
|
data/README.md
CHANGED
@@ -34,16 +34,20 @@ gem install gantree
|
|
34
34
|
```
|
35
35
|
|
36
36
|
### Initialize
|
37
|
-
|
38
37
|
What this does is create a new Dockerrun.aws.json inside your repository and uploads your docker login credentials to s3 (for private repo access) so you can do deploys. We need the -u to specify a username to rename your .dockercfg and reference it in the Dockerrun.aws.json
|
39
38
|
|
40
|
-
For a public repo
|
41
39
|
```
|
42
|
-
|
40
|
+
# the username here is your docker.hub login
|
41
|
+
gantree init -u frodriguez -p 3000 bleacher/cauldron:master
|
42
|
+
# this will upload your docker config files to a bucket called "frodrigeuz-docker-cgfs"
|
43
43
|
```
|
44
|
-
|
44
|
+
If you don't have a docker.hub account, you can still use gantree without the `-u` flag, but you will have to explicitly specify the bucket for S3 storage since the default S3 bucket name is generated from the docker.hub login.
|
45
|
+
|
46
|
+
##### Specify the bucket for to S3 store docker configuration
|
45
47
|
```
|
46
|
-
|
48
|
+
# Since S3 bucket names are globally namespaced, the default bucket may be taken and unavailable
|
49
|
+
# Gantree gives you the option to specify an S3 bucket name of your choice
|
50
|
+
gantree init -u frodgriguez -p 3000 -b hopefully_this_bucket_name_is_available bleacher/cauldron:master
|
47
51
|
```
|
48
52
|
|
49
53
|
### Deploy
|
data/gantree.gemspec
CHANGED
@@ -34,4 +34,7 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_development_dependency "guard"
|
35
35
|
spec.add_development_dependency "guard-bundler"
|
36
36
|
spec.add_development_dependency "guard-rspec"
|
37
|
+
spec.add_development_dependency "pry"
|
38
|
+
spec.add_development_dependency "vcr"
|
37
39
|
end
|
40
|
+
|
data/lib/gantree.rb
CHANGED
data/lib/gantree/base.rb
CHANGED
@@ -1,10 +1,34 @@
|
|
1
1
|
module Gantree
|
2
2
|
class Base
|
3
|
+
def check_credentials
|
4
|
+
raise "Please set your AWS Environment Variables" unless ENV['AWS_SECRET_ACCESS_KEY']
|
5
|
+
raise "Please set your AWS Environment Variables" unless ENV['AWS_ACCESS_KEY_ID']
|
6
|
+
end
|
7
|
+
|
3
8
|
def print_options
|
4
9
|
@options.each do |param, value|
|
5
10
|
puts "#{param}: #{value}"
|
6
11
|
end
|
7
12
|
end
|
13
|
+
|
14
|
+
def set_aws_keys
|
15
|
+
AWS.config(
|
16
|
+
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
|
17
|
+
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
def s3
|
22
|
+
@s3 ||= AWS::S3.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def default_name(app)
|
26
|
+
[
|
27
|
+
app.match(/^[a-zA-Z]*\-([a-zA-Z]*)\-[a-zA-Z]*\-([a-zA-Z]*\d*)/)[1],
|
28
|
+
app.match(/^([a-zA-Z]*)\-([a-zA-Z]*)\-[a-zA-Z]*\-([a-zA-Z]*\d*)/)[1],
|
29
|
+
app.match(/^([a-zA-Z]*)\-([a-zA-Z]*)\-[a-zA-Z]*\-([a-zA-Z]*\d*)/)[3]
|
30
|
+
].join("-")
|
31
|
+
end
|
8
32
|
end
|
9
33
|
end
|
10
34
|
|
data/lib/gantree/cli.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "pry"
|
1
2
|
require 'thor'
|
2
3
|
require 'aws-sdk-v1'
|
3
4
|
require 'gantree/cli/help'
|
@@ -18,9 +19,9 @@ module Gantree
|
|
18
19
|
end
|
19
20
|
|
20
21
|
desc "init IMAGE", "create a dockerrun for your IMAGE"
|
21
|
-
method_option :user , :aliases => "-u", :desc => "user credentials for private repo"
|
22
|
+
method_option :user , :aliases => "-u", :desc => "user credentials for private dockerhub repo"
|
22
23
|
method_option :port , :aliases => "-p", :desc => "port of running application"
|
23
|
-
method_option :bucket , :aliases => "-b", :desc => "set bucket name, default is 'docker-cfgs'"
|
24
|
+
method_option :bucket , :aliases => "-b", :desc => "set bucket name, default is '<user>-docker-cfgs'"
|
24
25
|
option :dry_run, :aliases => "-d", :desc => "do not actually upload to s3 bucket"
|
25
26
|
def init image
|
26
27
|
Gantree::Init.new(image, options).run
|
@@ -63,3 +64,4 @@ module Gantree
|
|
63
64
|
end
|
64
65
|
end
|
65
66
|
end
|
67
|
+
|
data/lib/gantree/deploy.rb
CHANGED
@@ -4,17 +4,16 @@ require_relative 'notification'
|
|
4
4
|
|
5
5
|
module Gantree
|
6
6
|
class Deploy < Base
|
7
|
+
attr_reader :app, :env
|
8
|
+
|
9
|
+
def initialize app, options
|
10
|
+
check_credentials
|
11
|
+
set_aws_keys
|
7
12
|
|
8
|
-
def initialize app,options
|
9
13
|
@options = options
|
10
14
|
@ext = @options[:ext]
|
11
|
-
|
12
|
-
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
|
13
|
-
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'])
|
14
|
-
@app = @options[:env] || app.match(/^[a-zA-Z]*\-([a-zA-Z]*)\-[a-zA-Z]*\-([a-zA-Z]*\d*)/)[1] + "-" + app.match(/^([a-zA-Z]*)\-([a-zA-Z]*)\-[a-zA-Z]*\-([a-zA-Z]*\d*)/)[1] + '-' + app.match(/^([a-zA-Z]*)\-([a-zA-Z]*)\-[a-zA-Z]*\-([a-zA-Z]*\d*)/)[3]
|
15
|
+
@app = @options[:env] || default_name(app)
|
15
16
|
@env = app
|
16
|
-
@eb = AWS::ElasticBeanstalk::Client.new
|
17
|
-
@s3 = AWS::S3.new
|
18
17
|
@dockerrun_file = "Dockerrun.aws.json"
|
19
18
|
end
|
20
19
|
|
@@ -22,33 +21,37 @@ module Gantree
|
|
22
21
|
puts "Deploying #{@env} on #{@app}"
|
23
22
|
print_options
|
24
23
|
return if @options[:dry_run]
|
25
|
-
@
|
24
|
+
@packaged_version = create_version_files
|
26
25
|
upload_to_s3 if @options[:dry_run].nil?
|
27
26
|
clean_up
|
28
27
|
create_eb_version if @options[:dry_run].nil?
|
29
28
|
update_application if @options[:dry_run].nil?
|
30
29
|
if @options[:slack]
|
31
|
-
msg = "#{ENV['USER']} is deploying #{@
|
30
|
+
msg = "#{ENV['USER']} is deploying #{@packaged_version} to #{@app}"
|
32
31
|
Notification.new(@options[:slack]).say(msg) unless @options[:silent]
|
33
32
|
end
|
34
33
|
end
|
35
34
|
|
36
35
|
private
|
36
|
+
def eb
|
37
|
+
@eb ||= AWS::ElasticBeanstalk::Client.new
|
38
|
+
end
|
39
|
+
|
37
40
|
def upload_to_s3
|
38
|
-
key = File.basename(@
|
41
|
+
key = File.basename(@packaged_version)
|
39
42
|
check_version_bucket
|
40
|
-
puts "uploading #{@
|
41
|
-
|
43
|
+
puts "uploading #{@packaged_version} to #{@app}-versions"
|
44
|
+
s3.buckets["#{@app}-versions"].objects[key].write(:file => @packaged_version)
|
42
45
|
end
|
43
46
|
|
44
47
|
def create_eb_version
|
45
48
|
begin
|
46
|
-
|
49
|
+
eb.create_application_version({
|
47
50
|
:application_name => @app,
|
48
|
-
:version_label => @
|
51
|
+
:version_label => @packaged_version,
|
49
52
|
:source_bundle => {
|
50
53
|
:s3_bucket => "#{@app}-versions",
|
51
|
-
:s3_key => @
|
54
|
+
:s3_key => @packaged_version
|
52
55
|
}
|
53
56
|
})
|
54
57
|
rescue AWS::ElasticBeanstalk::Errors::InvalidParameterValue => e
|
@@ -58,9 +61,9 @@ module Gantree
|
|
58
61
|
|
59
62
|
def update_application
|
60
63
|
begin
|
61
|
-
|
64
|
+
eb.update_environment({
|
62
65
|
:environment_name => @env,
|
63
|
-
:version_label => @
|
66
|
+
:version_label => @packaged_version,
|
64
67
|
:option_settings => autodetect_app_role
|
65
68
|
})
|
66
69
|
rescue AWS::ElasticBeanstalk::Errors::InvalidParameterValue
|
@@ -69,12 +72,12 @@ module Gantree
|
|
69
72
|
end
|
70
73
|
|
71
74
|
def create_version_files
|
72
|
-
|
75
|
+
time_stamp = Time.now.to_i
|
73
76
|
branch = `git rev-parse --abbrev-ref HEAD`
|
74
77
|
puts "branch: #{branch}"
|
75
78
|
hash = `git rev-parse --verify --short #{branch}`.strip
|
76
79
|
puts "hash #{hash}"
|
77
|
-
version = "#{@env}-#{hash}-#{
|
80
|
+
version = "#{@env}-#{hash}-#{time_stamp}"
|
78
81
|
puts "version: #{version}"
|
79
82
|
#auto_detect_app_role if @options[:autodetect_app_role] == true
|
80
83
|
set_tag_to_deploy if @options[:tag]
|
@@ -94,7 +97,7 @@ module Gantree
|
|
94
97
|
docker = JSON.parse(IO.read(@dockerrun_file))
|
95
98
|
image = docker["Image"]["Name"]
|
96
99
|
image.gsub!(/:(.*)$/, ":#{@options[:tag]}")
|
97
|
-
IO.write(@dockerrun_file,JSON.pretty_generate(docker))
|
100
|
+
IO.write(@dockerrun_file, JSON.pretty_generate(docker))
|
98
101
|
end
|
99
102
|
|
100
103
|
def autodetect_app_role
|
@@ -165,14 +168,15 @@ module Gantree
|
|
165
168
|
|
166
169
|
def check_version_bucket
|
167
170
|
name = "#{@app}-versions"
|
168
|
-
bucket =
|
169
|
-
|
171
|
+
bucket = s3.buckets[name] # makes no request
|
172
|
+
s3.buckets.create(name) unless bucket.exists?
|
170
173
|
end
|
171
174
|
|
172
175
|
def clean_up
|
173
|
-
FileUtils.rm_rf(@
|
176
|
+
FileUtils.rm_rf(@packaged_version)
|
174
177
|
`git checkout Dockerrun.aws.json` # reverts back to original Dockerrun.aws.json
|
175
178
|
`rm -rf .ebextensions/` if ext?
|
176
179
|
end
|
177
180
|
end
|
178
181
|
end
|
182
|
+
|
data/lib/gantree/init.rb
CHANGED
@@ -2,17 +2,16 @@ require 'thor'
|
|
2
2
|
require 'aws-sdk-v1'
|
3
3
|
|
4
4
|
module Gantree
|
5
|
-
|
6
5
|
class Init < Base
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
attr_reader :image, :options, :bucket_name
|
7
|
+
|
8
|
+
def initialize image, options
|
9
|
+
check_credentials
|
10
|
+
set_aws_keys
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
@s3 = AWS::S3.new
|
12
|
+
@image = image
|
13
|
+
@options = options
|
14
|
+
@bucket_name = @options.bucket || default_bucket_name
|
16
15
|
end
|
17
16
|
|
18
17
|
def run
|
@@ -20,48 +19,57 @@ module Gantree
|
|
20
19
|
print_options
|
21
20
|
|
22
21
|
FileUtils.rm("Dockerrun.aws.json") if File.exist?("Dockerrun.aws.json")
|
23
|
-
|
22
|
+
create_docker_config_s3_bucket unless options[:dry_run]
|
24
23
|
create_dockerrun
|
25
|
-
upload_docker_config if
|
24
|
+
upload_docker_config if options.user && !options[:dry_run]
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def default_bucket_name
|
29
|
+
[@options.user, "docker", "cfgs"].compact.join("-")
|
26
30
|
end
|
27
31
|
|
28
|
-
def
|
29
|
-
bucket =
|
32
|
+
def create_docker_config_s3_bucket
|
33
|
+
bucket = s3.buckets.create(bucket_name) unless s3.buckets[bucket_name].exists?
|
30
34
|
end
|
31
35
|
|
32
36
|
def dockerrun_object
|
33
37
|
docker = {
|
34
38
|
AWSEBDockerrunVersion: "1",
|
35
39
|
Image: {
|
36
|
-
Name:
|
40
|
+
Name: image,
|
37
41
|
Update: true
|
38
42
|
},
|
39
43
|
Logging: "/var/log/nginx",
|
40
44
|
Ports: [
|
41
45
|
{
|
42
|
-
ContainerPort:
|
46
|
+
ContainerPort: options.port
|
43
47
|
}
|
44
48
|
]
|
45
49
|
}
|
46
|
-
if
|
50
|
+
if options.user
|
47
51
|
docker["Authentication"] = {
|
48
|
-
Bucket:
|
49
|
-
Key: "#{
|
52
|
+
Bucket: bucket_name,
|
53
|
+
Key: "#{options.user}.dockercfg"
|
50
54
|
}
|
51
55
|
end
|
52
56
|
docker
|
53
57
|
end
|
54
58
|
|
55
59
|
def create_dockerrun
|
56
|
-
IO.write("Dockerrun.aws.json",JSON.pretty_generate(dockerrun_object))
|
60
|
+
IO.write("Dockerrun.aws.json", JSON.pretty_generate(dockerrun_object))
|
57
61
|
end
|
58
62
|
|
59
63
|
def upload_docker_config
|
60
|
-
raise "You need to run 'docker login' to generate a .dockercfg file"
|
61
|
-
filename = "#{ENV['HOME']}/#{
|
62
|
-
FileUtils.cp("#{ENV['HOME']}/.dockercfg", "#{ENV['HOME']}/#{
|
64
|
+
raise "You need to run 'docker login' to generate a .dockercfg file" unless dockercfg_file_exist?
|
65
|
+
filename = "#{ENV['HOME']}/#{options.user}.dockercfg"
|
66
|
+
FileUtils.cp("#{ENV['HOME']}/.dockercfg", "#{ENV['HOME']}/#{options.user}.dockercfg")
|
63
67
|
key = File.basename(filename)
|
64
|
-
|
68
|
+
s3.buckets[bucket_name].objects[key].write(:file => filename)
|
69
|
+
end
|
70
|
+
|
71
|
+
def dockercfg_file_exist?
|
72
|
+
File.exist?("#{ENV['HOME']}/.dockercfg")
|
65
73
|
end
|
66
74
|
end
|
67
75
|
end
|
data/lib/gantree/notification.rb
CHANGED
@@ -6,12 +6,12 @@ require_relative 'cfn/resources'
|
|
6
6
|
|
7
7
|
module Gantree
|
8
8
|
class Stack < Base
|
9
|
+
attr_reader :env
|
10
|
+
|
9
11
|
def initialize stack_name,options
|
10
12
|
check_credentials
|
11
|
-
|
12
|
-
|
13
|
-
:secret_access_key => ENV['AWS_SECRET_ACCES_KEY'])
|
14
|
-
@s3 = AWS::S3.new
|
13
|
+
set_aws_keys
|
14
|
+
|
15
15
|
@cfm = AWS::CloudFormation.new
|
16
16
|
@size = options[:instance_size]
|
17
17
|
@size ||= "t1.micro"
|
@@ -19,7 +19,7 @@ module Gantree
|
|
19
19
|
require 'cloudformation-ruby-dsl/cfntemplate'
|
20
20
|
require 'cloudformation-ruby-dsl/spotprice'
|
21
21
|
require 'cloudformation-ruby-dsl/table'"
|
22
|
-
@env = options[:env] ||
|
22
|
+
@env = options[:env] || default_name(stack_name)
|
23
23
|
additional_options = {
|
24
24
|
instance_size: @size,
|
25
25
|
stack_name: stack_name,
|
@@ -33,11 +33,6 @@ module Gantree
|
|
33
33
|
@options = options.merge(additional_options)
|
34
34
|
end
|
35
35
|
|
36
|
-
def check_credentials
|
37
|
-
raise "Please set your AWS Environment Variables" if ENV['AWS_SECRET_ACCESS_KEY'] == nil
|
38
|
-
raise "Please set your AWS Environment Variables" if ENV['AWS_ACCESS_KEY_ID'] == nil
|
39
|
-
end
|
40
|
-
|
41
36
|
def create
|
42
37
|
@options[:rds_enabled] = rds_enabled? if @options[:rds]
|
43
38
|
print_options
|
@@ -51,8 +46,7 @@ module Gantree
|
|
51
46
|
puts "Updating stack from local cfn repo"
|
52
47
|
unless @options[:dry_run] then
|
53
48
|
upload_templates
|
54
|
-
|
55
|
-
@cfm.stacks[@options[:stack_name]].update(:template => template)
|
49
|
+
@cfm.stacks[@options[:stack_name]].update(:template => stack_template)
|
56
50
|
end
|
57
51
|
end
|
58
52
|
|
@@ -70,6 +64,11 @@ module Gantree
|
|
70
64
|
end
|
71
65
|
end
|
72
66
|
|
67
|
+
private
|
68
|
+
def stack_template
|
69
|
+
s3.buckets["#{@options[:cfn_bucket]}/#{env}"].objects["#{env}-master.cfn.json"]
|
70
|
+
end
|
71
|
+
|
73
72
|
def create_cfn_if_needed
|
74
73
|
Dir.mkdir 'cfn' unless File.directory?("cfn")
|
75
74
|
end
|
@@ -81,11 +80,11 @@ module Gantree
|
|
81
80
|
origin_env = @options[:dupe].match(/^[a-zA-Z]*\-([a-zA-Z]*)\-[a-zA-Z]*\-([a-zA-Z]*\d*)/)[1] + "-" + env_from_dupe = @options[:dupe].match(/^([a-zA-Z]*)\-([a-zA-Z]*)\-[a-zA-Z]*\-([a-zA-Z]*\d*)/)[1] + '-' + env_from_dupe = @options[:dupe].match(/^([a-zA-Z]*)\-([a-zA-Z]*)\-[a-zA-Z]*\-([a-zA-Z]*\d*)/)[3]
|
82
81
|
templates = ['master','resources','beanstalk']
|
83
82
|
templates.each do |template|
|
84
|
-
FileUtils.cp("cfn/#{origin_env}-#{template}.cfn.json", "cfn/#{
|
85
|
-
file = IO.read("cfn/#{
|
83
|
+
FileUtils.cp("cfn/#{origin_env}-#{template}.cfn.json", "cfn/#{env}-#{template}.cfn.json")
|
84
|
+
file = IO.read("cfn/#{env}-#{template}.cfn.json")
|
86
85
|
file.gsub!(/#{escape_characters_in_string(orgin_stack_name)}/, @options[:stack_name])
|
87
86
|
file.gsub!(/#{escape_characters_in_string(origin_env)}/, @options[:env])
|
88
|
-
IO.write("cfn/#{
|
87
|
+
IO.write("cfn/#{env}-#{template}.cfn.json",file)
|
89
88
|
end
|
90
89
|
else
|
91
90
|
puts "Generating templates from gantree"
|
@@ -104,7 +103,7 @@ module Gantree
|
|
104
103
|
IO.write("cfn/#{template_name}.rb", template)
|
105
104
|
json = `ruby cfn/#{template_name}.rb expand`
|
106
105
|
Dir.mkdir 'cfn' rescue Errno::ENOENT
|
107
|
-
template_file_name = "#{
|
106
|
+
template_file_name = "#{env}-#{template_name}.cfn.json"
|
108
107
|
IO.write("cfn/#{template_file_name}", json)
|
109
108
|
puts "Created #{template_file_name} in the cfn directory"
|
110
109
|
FileUtils.rm("cfn/#{template_name}.rb")
|
@@ -114,27 +113,26 @@ module Gantree
|
|
114
113
|
check_template_bucket
|
115
114
|
templates = ['master','resources','beanstalk']
|
116
115
|
templates.each do |template|
|
117
|
-
filename = "cfn/#{
|
116
|
+
filename = "cfn/#{env}-#{template}.cfn.json"
|
118
117
|
key = File.basename(filename)
|
119
|
-
|
118
|
+
s3.buckets["#{@options[:cfn_bucket]}/#{env}"].objects[key].write(:file => filename)
|
120
119
|
end
|
121
120
|
puts "templates uploaded"
|
122
121
|
end
|
123
122
|
|
124
123
|
def check_template_bucket
|
125
|
-
bucket_name = "#{@options[:cfn_bucket]}/#{
|
126
|
-
if
|
127
|
-
puts "uploading cfn templates to #{@options[:cfn_bucket]}/#{
|
124
|
+
bucket_name = "#{@options[:cfn_bucket]}/#{env}"
|
125
|
+
if s3.buckets[bucket_name].exists?
|
126
|
+
puts "uploading cfn templates to #{@options[:cfn_bucket]}/#{env}"
|
128
127
|
else
|
129
|
-
puts "creating bucket #{@options[:cfn_bucket]}/#{
|
130
|
-
|
128
|
+
puts "creating bucket #{@options[:cfn_bucket]}/#{env} to upload templates"
|
129
|
+
s3.buckets.create(bucket_name)
|
131
130
|
end
|
132
131
|
end
|
133
132
|
|
134
133
|
def create_aws_cfn_stack
|
135
134
|
puts "Creating stack on aws..."
|
136
|
-
|
137
|
-
stack = @cfm.stacks.create(@options[:stack_name], template,{ :disable_rollback => true })
|
135
|
+
stack = @cfm.stacks.create(@options[:stack_name], stack_template, :disable_rollback => true)
|
138
136
|
end
|
139
137
|
|
140
138
|
def rds_enabled?
|
@@ -150,9 +148,9 @@ module Gantree
|
|
150
148
|
end
|
151
149
|
|
152
150
|
def env_type
|
153
|
-
if
|
151
|
+
if env.include?("prod")
|
154
152
|
"prod"
|
155
|
-
elsif
|
153
|
+
elsif env.include?("stag")
|
156
154
|
"stag"
|
157
155
|
else
|
158
156
|
""
|
@@ -160,3 +158,4 @@ module Gantree
|
|
160
158
|
end
|
161
159
|
end
|
162
160
|
end
|
161
|
+
|
data/lib/gantree/version.rb
CHANGED
@@ -7,6 +7,9 @@ require 'spec_helper'
|
|
7
7
|
# $ rake clean:vcr ; time rake
|
8
8
|
describe Gantree::CLI do
|
9
9
|
before(:all) do
|
10
|
+
ENV['AWS_ACCESS_KEY_ID'] = 'FAKE_AWS_ACCESS_KEY'
|
11
|
+
ENV['AWS_SECRET_ACCESS_KEY'] = 'FAKE_AWS_SECRET_ACCESS_KEY'
|
12
|
+
|
10
13
|
@env = "stag-knarr-app-s1"
|
11
14
|
@app = "knarr-stag-s1"
|
12
15
|
@owner = "bleacher"
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "pry"
|
3
|
+
|
4
|
+
describe Gantree::Deploy do
|
5
|
+
before(:all) do
|
6
|
+
ENV['AWS_ACCESS_KEY_ID'] = 'FAKE_AWS_ACCESS_KEY'
|
7
|
+
ENV['AWS_SECRET_ACCESS_KEY'] = 'FAKE_AWS_SECRET_ACCESS_KEY'
|
8
|
+
|
9
|
+
@env = "stag-knarr-app-s1"
|
10
|
+
@owner = "bleacher"
|
11
|
+
@repo = "cauldron"
|
12
|
+
@tag = "master"
|
13
|
+
@user = "feelobot"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "returns branch name of repo url" do
|
17
|
+
options = { ext: "git@github.com:br/.ebextensions:basic" }
|
18
|
+
deploy = Gantree::Deploy.new(@env, options)
|
19
|
+
expect(deploy.send(:get_ext_branch)).to eq "basic"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns just the repo url" do
|
23
|
+
options = { ext: "git@github.com:br/.ebextensions:basic" }
|
24
|
+
deploy = Gantree::Deploy.new(@env,options)
|
25
|
+
expect(deploy.send(:get_ext_repo)).to eq "git@github.com:br/.ebextensions"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "sets app roles if enabled" do
|
29
|
+
options = { autodetect_app_role: true}
|
30
|
+
deploy = Gantree::Deploy.new("stag-knarr-listener-s1", options)
|
31
|
+
expect(deploy.send(:autodetect_app_role)).to eq([{:option_name=>"ROLE", :value=>"listener", :namespace=>"aws:elasticbeanstalk:application:environment"}])
|
32
|
+
end
|
33
|
+
|
34
|
+
it "AWS gets the correct keys" do
|
35
|
+
gd = Gantree::Deploy.new(
|
36
|
+
"image_name",
|
37
|
+
:env => "cauldron-stag-s1"
|
38
|
+
)
|
39
|
+
expect(AWS).to receive(:config).with(
|
40
|
+
:access_key_id => 'FAKE_AWS_ACCESS_KEY',
|
41
|
+
:secret_access_key => 'FAKE_AWS_SECRET_ACCESS_KEY'
|
42
|
+
)
|
43
|
+
gd.set_aws_keys
|
44
|
+
end
|
45
|
+
|
46
|
+
it "parses env option" do
|
47
|
+
gd = Gantree::Deploy.new(
|
48
|
+
"stag-cauldron-app-s1",
|
49
|
+
:env => "cauldron-stag-s1"
|
50
|
+
)
|
51
|
+
expect(gd.app).to eq("cauldron-stag-s1")
|
52
|
+
expect(gd.env).to eq("stag-cauldron-app-s1")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "parses default env" do
|
56
|
+
gd = Gantree::Deploy.new(
|
57
|
+
"stag-cauldron-app-s1",
|
58
|
+
{}
|
59
|
+
)
|
60
|
+
expect(gd.app).to eq("cauldron-stag-s1")
|
61
|
+
expect(gd.env).to eq("stag-cauldron-app-s1")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "raises an error when no aws keys in ENV" do
|
65
|
+
ENV['AWS_ACCESS_KEY_ID'] = nil
|
66
|
+
ENV['AWS_SECRET_ACCESS_KEY'] = nil
|
67
|
+
expect{gd = Gantree::Deploy.new(
|
68
|
+
"image_name",
|
69
|
+
:env => "cauldron-stag-s1"
|
70
|
+
)}.to raise_error(RuntimeError)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "pry"
|
3
|
+
|
4
|
+
describe Gantree::Init do
|
5
|
+
before(:all) do
|
6
|
+
ENV['AWS_ACCESS_KEY_ID'] = 'FAKE_AWS_ACCESS_KEY'
|
7
|
+
ENV['AWS_SECRET_ACCESS_KEY'] = 'FAKE_AWS_SECRET_ACCESS_KEY'
|
8
|
+
|
9
|
+
ENV["HOME"] = "/Users/gantree_user"
|
10
|
+
|
11
|
+
@options = Thor::CoreExt::HashWithIndifferentAccess.new(
|
12
|
+
"port" => "3000",
|
13
|
+
"user" => "gantree_user",
|
14
|
+
"bucket" => "bucket314159"
|
15
|
+
)
|
16
|
+
|
17
|
+
@s3_bucket = AWS::S3::Bucket.new("bucket314159")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "initializes the variables properly" do
|
21
|
+
gi = Gantree::Init.new("bleacher/cauldron:master", @options)
|
22
|
+
|
23
|
+
expect(gi.image).to eq("bleacher/cauldron:master")
|
24
|
+
expect(gi.options.port).to eq("3000")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "AWS gets the correct keys" do
|
28
|
+
gi = Gantree::Init.new("image_name", @options)
|
29
|
+
expect(AWS).to receive(:config).with(
|
30
|
+
:access_key_id => 'FAKE_AWS_ACCESS_KEY',
|
31
|
+
:secret_access_key => 'FAKE_AWS_SECRET_ACCESS_KEY'
|
32
|
+
)
|
33
|
+
gi.set_aws_keys
|
34
|
+
end
|
35
|
+
|
36
|
+
it "uses default bucket_name" do
|
37
|
+
options_no_bucket_name = Thor::CoreExt::HashWithIndifferentAccess.new(
|
38
|
+
"port" => "3000",
|
39
|
+
"user" => "gantree_user"
|
40
|
+
)
|
41
|
+
gi = Gantree::Init.new("image_name", options_no_bucket_name)
|
42
|
+
expect(gi.bucket_name).to eq("gantree_user-docker-cfgs")
|
43
|
+
|
44
|
+
options_no_bucket_name_or_user = Thor::CoreExt::HashWithIndifferentAccess.new(
|
45
|
+
"port" => "3000"
|
46
|
+
)
|
47
|
+
gi2 = Gantree::Init.new("image_name", options_no_bucket_name_or_user)
|
48
|
+
expect(gi2.bucket_name).to eq("docker-cfgs")
|
49
|
+
end
|
50
|
+
|
51
|
+
it "generates a dockerrun object" do
|
52
|
+
gi = Gantree::Init.new("bleacher/cauldron:master", @options)
|
53
|
+
|
54
|
+
dro = gi.send(:dockerrun_object)
|
55
|
+
expect(dro).to eq(
|
56
|
+
:AWSEBDockerrunVersion=>"1",
|
57
|
+
:Image=>{:Name=>"bleacher/cauldron:master", :Update=>true},
|
58
|
+
:Logging=>"/var/log/nginx",
|
59
|
+
:Ports=>[{:ContainerPort=>"3000"}],
|
60
|
+
"Authentication"=>{:Bucket=>"bucket314159", :Key=>"gantree_user.dockercfg"}
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "creates docker config folder when s3 bucket already exists" do
|
65
|
+
gi = Gantree::Init.new("bleacher/cauldron:master", @options)
|
66
|
+
AWS::S3::BucketCollection.any_instance.stub(:[]).with(anything()) {Existence}
|
67
|
+
AWS::S3::BucketCollection.stub(:create) {"OK"}
|
68
|
+
|
69
|
+
expect(gi.send(:create_docker_config_s3_bucket)).to eq(nil)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "creates docker config folder when s3 bucket doesnt not exist" do
|
73
|
+
gi = Gantree::Init.new("bleacher/cauldron:master", @options)
|
74
|
+
AWS::S3::BucketCollection.any_instance.stub(:[]).with(anything()) {NonExistence}
|
75
|
+
AWS::S3::BucketCollection.any_instance.stub(:create).with(@options.bucket) {@s3_bucket}
|
76
|
+
|
77
|
+
expect(gi.send(:create_docker_config_s3_bucket)).to eq(@s3_bucket)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "uploads docker config to s3" do
|
81
|
+
gi = Gantree::Init.new("bleacher/cauldron:master", @options)
|
82
|
+
|
83
|
+
Gantree::Init.any_instance.stub(:dockercfg_file_exist?) { true }
|
84
|
+
FileUtils.stub(:cp).with(
|
85
|
+
"/Users/gantree_user/.dockercfg",
|
86
|
+
"/Users/gantree_user/gantree_user.dockercfg"
|
87
|
+
) {"OK"}
|
88
|
+
AWS::S3::S3Object.any_instance.stub(:write).with(
|
89
|
+
:file => "/Users/gantree_user/gantree_user.dockercfg"
|
90
|
+
) {"OK"}
|
91
|
+
|
92
|
+
expect(gi.send(:upload_docker_config)).to eq("OK")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "pry"
|
3
|
+
|
4
|
+
describe Gantree::Stack do
|
5
|
+
it "parses the env from env options" do
|
6
|
+
gs = Gantree::Stack.new(
|
7
|
+
"stag-linguist-app-s1",
|
8
|
+
:env => "linguist-stag-s1"
|
9
|
+
)
|
10
|
+
|
11
|
+
expect(gs.env).to eq("linguist-stag-s1")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "parses the env from stack_name" do
|
15
|
+
gs = Gantree::Stack.new(
|
16
|
+
"stag-linguist-app-s1",
|
17
|
+
{}
|
18
|
+
)
|
19
|
+
|
20
|
+
expect(gs.env).to eq("linguist-stag-s1")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
data/spec/spec_helper.rb
CHANGED
@@ -6,14 +6,12 @@
|
|
6
6
|
ENV['VCR'] ? ENV['VCR'] : ENV['VCR'] = '1'
|
7
7
|
ENV['TEST'] = '1'
|
8
8
|
ENV['CODECLIMATE_REPO_TOKEN'] = ENV['CODECLIMATE_GANTREE_TOKEN']
|
9
|
-
ENV['AWS_SECRET_ACCESS_KEY'] = 'asdfasdf2394230434'
|
10
|
-
ENV['AWS_ACCESS_KEY_ID'] = 'adsfasdf984443df'
|
11
|
-
|
12
9
|
|
13
10
|
require "codeclimate-test-reporter"
|
14
11
|
CodeClimate::TestReporter.start
|
15
12
|
|
16
13
|
require "pp"
|
14
|
+
require "vcr"
|
17
15
|
|
18
16
|
root = File.expand_path('../../', __FILE__)
|
19
17
|
require "#{root}/lib/gantree"
|
@@ -48,7 +46,26 @@ RSpec.configure do |c|
|
|
48
46
|
FileUtils.rm_rf("*.zip")
|
49
47
|
end
|
50
48
|
end
|
51
|
-
|
49
|
+
#
|
52
50
|
#VCR.configure do |config|
|
53
|
-
# config.
|
54
|
-
#
|
51
|
+
# config.cassette_library_dir = "spec/fixtures/vcr"
|
52
|
+
# config.hook_into :fakeweb
|
53
|
+
# config.default_cassette_options = {:record => :once}
|
54
|
+
# config.ignore_hosts "codeclimate.com"
|
55
|
+
#end
|
56
|
+
#
|
57
|
+
#
|
58
|
+
|
59
|
+
class Existence
|
60
|
+
def self.exists?
|
61
|
+
true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class NonExistence
|
66
|
+
def self.exists?
|
67
|
+
false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gantree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Felix
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -220,6 +220,34 @@ dependencies:
|
|
220
220
|
- - ">="
|
221
221
|
- !ruby/object:Gem::Version
|
222
222
|
version: '0'
|
223
|
+
- !ruby/object:Gem::Dependency
|
224
|
+
name: pry
|
225
|
+
requirement: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - ">="
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
requirements:
|
234
|
+
- - ">="
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: '0'
|
237
|
+
- !ruby/object:Gem::Dependency
|
238
|
+
name: vcr
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
240
|
+
requirements:
|
241
|
+
- - ">="
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: '0'
|
244
|
+
type: :development
|
245
|
+
prerelease: false
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - ">="
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '0'
|
223
251
|
description: cli tool for automating docker deploys to elastic beanstalk
|
224
252
|
email:
|
225
253
|
- felix.a.rod@gmail.com
|
@@ -241,7 +269,6 @@ files:
|
|
241
269
|
- gantree.gemspec
|
242
270
|
- lib/gantree.rb
|
243
271
|
- lib/gantree/base.rb
|
244
|
-
- lib/gantree/cfn.rb
|
245
272
|
- lib/gantree/cfn/beanstalk.rb
|
246
273
|
- lib/gantree/cfn/master.rb
|
247
274
|
- lib/gantree/cfn/resources.rb
|
@@ -250,9 +277,12 @@ files:
|
|
250
277
|
- lib/gantree/deploy.rb
|
251
278
|
- lib/gantree/init.rb
|
252
279
|
- lib/gantree/notification.rb
|
280
|
+
- lib/gantree/stack.rb
|
253
281
|
- lib/gantree/version.rb
|
254
|
-
- spec/lib/cli_spec.rb
|
255
|
-
- spec/lib/deploy_spec.rb
|
282
|
+
- spec/lib/gantree/cli_spec.rb
|
283
|
+
- spec/lib/gantree/deploy_spec.rb
|
284
|
+
- spec/lib/gantree/init_spec.rb
|
285
|
+
- spec/lib/gantree/stack_spec.rb
|
256
286
|
- spec/spec_helper.rb
|
257
287
|
homepage: https://github.com/feelobot/gantree
|
258
288
|
licenses:
|
@@ -282,6 +312,8 @@ summary: This tool is intended to help you setup a Dockerrun.aws.json which allo
|
|
282
312
|
allows you to do versioned deploys to your Elastic Beanstalk application and create
|
283
313
|
an archive of every versioned Dockerrun.aws.json in amazons s3 bucket service.
|
284
314
|
test_files:
|
285
|
-
- spec/lib/cli_spec.rb
|
286
|
-
- spec/lib/deploy_spec.rb
|
315
|
+
- spec/lib/gantree/cli_spec.rb
|
316
|
+
- spec/lib/gantree/deploy_spec.rb
|
317
|
+
- spec/lib/gantree/init_spec.rb
|
318
|
+
- spec/lib/gantree/stack_spec.rb
|
287
319
|
- spec/spec_helper.rb
|
data/spec/lib/deploy_spec.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require_relative '../../lib/gantree/deploy'
|
3
|
-
|
4
|
-
describe "#Deploy" do
|
5
|
-
before(:all) do
|
6
|
-
@env = "stag-knarr-app-s1"
|
7
|
-
@owner = "bleacher"
|
8
|
-
@repo = "cauldron"
|
9
|
-
@tag = "master"
|
10
|
-
@user = "feelobot"
|
11
|
-
end
|
12
|
-
|
13
|
-
describe ".get_ext_branch" do
|
14
|
-
it "returns branch name of repo url" do
|
15
|
-
options = { ext: "git@github.com:br/.ebextensions:basic" }
|
16
|
-
deploy = Gantree::Deploy.new(@env,options)
|
17
|
-
expect(deploy.instance_eval { get_ext_branch }).to eq "basic"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe ".get_ext_repo" do
|
22
|
-
it "returns just the repo url" do
|
23
|
-
options = { ext: "git@github.com:br/.ebextensions:basic" }
|
24
|
-
deploy = Gantree::Deploy.new(@env,options)
|
25
|
-
expect(deploy.instance_eval { get_ext_repo }).to eq "git@github.com:br/.ebextensions"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe ".auto_detect_app_role" do
|
30
|
-
it "sets app roles if enabled" do
|
31
|
-
options = { autodetect_app_role: true}
|
32
|
-
deploy = Gantree::Deploy.new("stag-knarr-listener-s1",options)
|
33
|
-
puts deploy.instance_eval { autodetect_app_role }
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|