gantree 0.2.7 → 0.3.0
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.
- 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
|