thor-tropo 1.4.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +72 -2
- data/changelog.md +10 -0
- data/lib/thor-tropo.rb +161 -50
- data/lib/thor-tropo/configuration.rb +5 -1
- data/lib/thor-tropo/uploader.rb +11 -2
- metadata +2 -2
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Thor::Tropo
|
2
2
|
|
3
|
-
|
3
|
+
Tool used to package released for Chef-Solo installs
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -16,9 +16,79 @@ Or install it yourself as:
|
|
16
16
|
|
17
17
|
$ gem install thor-tropo
|
18
18
|
|
19
|
+
Include in your Thorfile
|
20
|
+
|
21
|
+
include "tropo-tropo"
|
22
|
+
|
23
|
+
### Config
|
24
|
+
|
25
|
+
Thor-Tropo expects a `.deployer` file and will traverse the path from . through ~ until it finds one. The .deployer file format is as follows:
|
26
|
+
|
27
|
+
aws_key: xxxx
|
28
|
+
aws_secret: xxxxx
|
29
|
+
bucket_name: artifacts.bucket.com
|
30
|
+
project_name: tropo/12.2.1/cookbooks/functional_deployment
|
31
|
+
|
32
|
+
|
33
|
+
Inside your project you can add the following at the root of your `top level cookbook`, or as we like to call it, `deployment model`
|
34
|
+
|
35
|
+
`~/my_deployment_model/.deploy`
|
36
|
+
|
37
|
+
project_name: tropo/12.2.1/cookbooks/my_deployment_model
|
38
|
+
cookbooks:
|
39
|
+
- runtime_server
|
40
|
+
- gateway_server
|
41
|
+
|
42
|
+
The important thing to know about .deploy files is that they are implemented as a "first win" type of search pattern. So if you run Thor for your current working directory it will traverse the path all the way to your home directoy looking for .deployer files. If it finds one, and it finds a known attribute, it will use that and ignore any higher values.
|
43
|
+
|
44
|
+
|
45
|
+
#### Example
|
46
|
+
|
47
|
+
~/.deployer
|
48
|
+
|
49
|
+
bucket_name: foo
|
50
|
+
|
51
|
+
~/somewhere/.deployer
|
52
|
+
|
53
|
+
bucket_name: bar
|
54
|
+
|
55
|
+
If you run thor tropo:package from ~/somewhere/.deployer then the bucket_name value will be bar, becaue that is the first one it found and so it "wins". The intent here was that you can store certain common config values globally by simply keeping a .deployer file in your home dir, and then only apply certain project specific settings inside source control with your deployment model. Hacky? Probably.. But it works well for us :)
|
56
|
+
|
19
57
|
## Usage
|
20
58
|
|
21
|
-
|
59
|
+
jdyer@retina:~ » thor help tropo:package
|
60
|
+
Usage:
|
61
|
+
thor tropo:package
|
62
|
+
|
63
|
+
Options:
|
64
|
+
-b, [--berkspath=BERKSPATH] # Berksfile path
|
65
|
+
-V, [--version-override=VERSION-OVERRIDE] # Provide a version for cookbook archive
|
66
|
+
-f, [--force] # overwrite any files on s3 without confirmation
|
67
|
+
-I, [--iam-auth] # Use IAM roles for AWS authorization
|
68
|
+
-i, [--ignore-dirty] # Will ignore any dirty files in git repo and continue to package cookbooks
|
69
|
+
-k, [--keeplock] # Respect Berksfile.lock
|
70
|
+
-c, [--clean-cache] # Delete local Berkshelf cookbook cache
|
71
|
+
-n, [--no-op] # NO-OP mode, Won't actually upload anything. Useful to see what would have happened
|
72
|
+
|
73
|
+
Package cookbooks using Berkshelf and upload file to s3 bucket
|
74
|
+
|
75
|
+
|
76
|
+
## Gotcha's
|
77
|
+
|
78
|
+
#### Search Priorities
|
79
|
+
|
80
|
+
Then you can run thor-tropo from the model project root once and it will package both cookbooks. However there is some logic here...
|
81
|
+
|
82
|
+
* Use path provided by user via --berkspath flag
|
83
|
+
* If there is a Berksfile in the current working directory use that
|
84
|
+
* Use .deployer file config for finding cookbooks to package ( Example below of this .deployer config )
|
85
|
+
|
86
|
+
`~/my_deployment_model/.deploy`
|
87
|
+
|
88
|
+
project_name: tropo/12.2.1/cookbooks/my_deployment_model
|
89
|
+
cookbooks:
|
90
|
+
- runtime_server
|
91
|
+
- gateway_server
|
22
92
|
|
23
93
|
## Contributing
|
24
94
|
|
data/changelog.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
# 2.0.0
|
2
|
+
|
3
|
+
* Support multiple cookbooks via .deployer
|
4
|
+
* Support IAM profiles
|
5
|
+
* Support --version / -v
|
6
|
+
* Support --help / -h
|
7
|
+
* Better logging
|
8
|
+
* Support git tagging via seperate task
|
9
|
+
* Support cleaning berksfile cache
|
10
|
+
|
1
11
|
# 1.4.0
|
2
12
|
|
3
13
|
* Moved cookbook finder into it's own method, SRP :)
|
data/lib/thor-tropo.rb
CHANGED
@@ -18,115 +18,221 @@ module ThorTropo
|
|
18
18
|
class Tasks < Thor
|
19
19
|
include Thor::Actions
|
20
20
|
|
21
|
+
|
21
22
|
@packaged_cookbook = nil
|
22
23
|
|
24
|
+
@working_directory = nil
|
25
|
+
@invoke_directory = Dir.pwd
|
26
|
+
|
23
27
|
namespace "tropo"
|
24
28
|
|
25
|
-
class_option
|
29
|
+
class_option "help",
|
30
|
+
:type => :boolean,
|
31
|
+
:default => false,
|
32
|
+
:aliases => "-h"
|
33
|
+
|
34
|
+
class_option "version",
|
35
|
+
:type => :boolean,
|
36
|
+
:default => false,
|
37
|
+
:aliases => "-v"
|
38
|
+
|
39
|
+
desc "package", "Package cookbooks using Berkshelf and upload file to s3 bucket"
|
40
|
+
|
41
|
+
method_option :berkspath,
|
26
42
|
:type => :string,
|
27
|
-
:aliases => "-
|
28
|
-
:default =>
|
29
|
-
:desc => "
|
30
|
-
:banner => "Directory of your Berksfile"
|
43
|
+
:aliases => "-b",
|
44
|
+
:default => nil,
|
45
|
+
:desc => "Berksfile path"
|
31
46
|
|
32
|
-
|
47
|
+
#:banner => "Path to find your cookbook Berksfile"
|
33
48
|
|
34
49
|
method_option :"version-override",
|
35
50
|
:type => :string,
|
36
51
|
:aliases => "-V",
|
37
52
|
:default => nil,
|
38
|
-
:desc => "
|
39
|
-
|
53
|
+
:desc => "Provide a version for cookbook archive"
|
54
|
+
|
55
|
+
#:banner => "Provider a cookbook version rather then using metadata.rb"
|
40
56
|
|
41
57
|
method_option :force,
|
42
58
|
:type => :boolean,
|
43
59
|
:aliases => "-f",
|
44
60
|
:default => false,
|
45
|
-
:desc => "
|
46
|
-
:banner => "Force overrides of existing files"
|
61
|
+
:desc => "overwrite any files on s3 without confirmation"
|
47
62
|
|
48
|
-
|
49
|
-
:type => :boolean,
|
50
|
-
:aliases => "-n",
|
51
|
-
:default => false,
|
52
|
-
:desc => "NO-OP mode, dont actually upload anything"
|
63
|
+
#:banner => "Ignore existing files and overwrite without confirmation"
|
53
64
|
|
54
|
-
method_option :
|
65
|
+
method_option :"iam-auth",
|
66
|
+
:type => :boolean,
|
67
|
+
:default => false,
|
68
|
+
:aliases => "-I",
|
69
|
+
:desc => "Use IAM roles for AWS authorization"
|
70
|
+
|
71
|
+
#:banner => "Will expect an IAM role is present for S3 Auth. Useful for CI"
|
72
|
+
|
73
|
+
method_option :"ignore-dirty",
|
55
74
|
:type => :boolean,
|
56
75
|
:aliases => "-i",
|
57
76
|
:default => false,
|
58
|
-
:desc => "
|
59
|
-
|
77
|
+
:desc => "Will ignore any dirty files in git repo and continue to package cookbooks"
|
78
|
+
|
79
|
+
#:banner => "Ignore dirty git repository"
|
60
80
|
|
61
|
-
method_option :
|
81
|
+
method_option :keeplock,
|
82
|
+
:type => :boolean,
|
83
|
+
:aliases => "-k",
|
84
|
+
:default => false,
|
85
|
+
:desc => "Respect Berksfile.lock"
|
86
|
+
|
87
|
+
#:banner => "Don't delete lockfile before running `Berks install`"
|
88
|
+
|
89
|
+
method_option :"clean-cache",
|
62
90
|
:type => :boolean,
|
63
91
|
:aliases => "-c",
|
64
92
|
:default => false,
|
65
|
-
|
66
|
-
|
93
|
+
|
94
|
+
#:banner => "Delete Berkshelf cookbook cache",
|
95
|
+
:desc => "Delete local Berkshelf cookbook cache"
|
96
|
+
|
97
|
+
method_option :"no-op",
|
98
|
+
:type => :boolean,
|
99
|
+
:aliases => "-n",
|
100
|
+
:default => false,
|
101
|
+
:desc => "NO-OP mode, Won't actually upload anything. Useful to see what would have happened"
|
102
|
+
#:banner => "NO-OP mode",
|
103
|
+
|
67
104
|
|
68
105
|
def package
|
69
106
|
|
70
|
-
|
107
|
+
print_help_or_version
|
108
|
+
|
71
109
|
$config = ThorTropo::Configuration.new(source_root)
|
72
110
|
|
73
111
|
unless clean?
|
74
|
-
|
75
|
-
|
76
|
-
exit 1
|
77
|
-
end
|
112
|
+
say "[ TROPO ] - There are files that need to be committed first.", :red
|
113
|
+
exit 1 unless options[:"ignore-dirty"]
|
78
114
|
end
|
79
115
|
|
80
|
-
|
116
|
+
clean_berks_cache if options[:"clean-cache"]
|
117
|
+
|
118
|
+
if path_priorities
|
81
119
|
bundle_cookbook
|
82
|
-
upload_cookbook @packaged_cookbook, $config.project_name, {:force => options[:force],:
|
83
|
-
|
120
|
+
upload_cookbook @packaged_cookbook, $config.project_name, {:force => options[:force],:"no-op" => options[:"no-op"]}
|
121
|
+
else
|
122
|
+
if $config.cookbooks.is_a? Array
|
123
|
+
say "[ TROPO ] - Found multiple cookbooks, packaging individual projects", :cyan
|
124
|
+
home = Dir.pwd
|
125
|
+
|
126
|
+
$config.cookbooks.each do |cookbook|
|
127
|
+
break if options[:path]
|
128
|
+
@working_directory = File.expand_path(File.join(home,cookbook))
|
129
|
+
say "[ TROPO ] - Switcing to #{@working_directory}", :blue
|
130
|
+
Dir.chdir(@working_directory)
|
131
|
+
bundle_cookbook
|
132
|
+
upload_cookbook @packaged_cookbook, $config.project_name, {:force => options[:force],:noop => options[:"no-op"]}
|
133
|
+
#@working_directory = nil
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
84
140
|
|
141
|
+
desc "tag", "Tag release"
|
142
|
+
|
143
|
+
method_option :version,
|
144
|
+
:type => :string,
|
145
|
+
:aliases => "-v",
|
146
|
+
:default => nil,
|
147
|
+
:required => true,
|
148
|
+
:desc => "Set a tag for the release and push to remote",
|
149
|
+
:desc => "Set a tag for the release and push to remote"
|
150
|
+
def tag
|
151
|
+
print_help_or_version
|
152
|
+
|
153
|
+
if File.exists?(".git")
|
154
|
+
tag_version options[:version]
|
155
|
+
else
|
156
|
+
say "[ TROPO ] - Directory is not managed by Git, quiting..", :red
|
157
|
+
exit 1
|
158
|
+
end
|
85
159
|
end
|
86
160
|
|
87
161
|
no_tasks do
|
88
162
|
|
163
|
+
|
164
|
+
def print_help_or_version
|
165
|
+
if options[:help]
|
166
|
+
help "package"
|
167
|
+
exit 0
|
168
|
+
elsif options[:version]
|
169
|
+
say "[ TROPO ] Version - #{ThorTropo::VERSION}", :blue
|
170
|
+
exit 0
|
171
|
+
end
|
172
|
+
end
|
173
|
+
def path_priorities
|
174
|
+
if options[:berkspath]
|
175
|
+
say "[ TROPO ] - Detected Berkspath was provided, so we will use this", :blue
|
176
|
+
### User specified berkspath, this is highest priority
|
177
|
+
@working_directory = File.expand_path(options[:berkspath])
|
178
|
+
elsif Dir.glob("*").include?("Berksfile")
|
179
|
+
say "[ TROPO ] - Detected Berksfile in current directory and no --berkspath was provided. We'll use local Berksfile.", :blue
|
180
|
+
### Found berksfile in working directory
|
181
|
+
@working_directory = File.expand_path(".")
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|
89
186
|
def upload_cookbook(local_file,path,opts={})
|
90
187
|
uploader = ThorTropo::Uploader.new({
|
91
188
|
:access_key => $config.aws_key,
|
92
189
|
:secret_key => $config.aws_secret,
|
93
|
-
:bucket => $config.bucket_name
|
190
|
+
:bucket => $config.bucket_name,
|
191
|
+
:use_iam => options[:"iam-auth"]
|
94
192
|
})
|
95
193
|
|
96
|
-
uploader.upload :local_file => local_file, :path => path, :force => options[:force], :noop=>options[:
|
194
|
+
uploader.upload :local_file => local_file, :path => path, :force => options[:force], :noop => options[:"no-op"]
|
195
|
+
end
|
196
|
+
|
197
|
+
def clean_berks_cache
|
198
|
+
say "[ TROPO ] - Clearing local Berkshelf cookbook cache", :green
|
199
|
+
|
200
|
+
unless options[:"no-op"]
|
201
|
+
remove_dir (File.expand_path(File.join(Dir.home,".berkshelf","cookbooks")))
|
202
|
+
end
|
97
203
|
end
|
98
204
|
|
99
205
|
def clean?
|
100
|
-
#sh_with_excode("cd #{options[:called_path]}; git diff --exit-code")[1] == 0
|
101
206
|
sh_with_excode("cd #{source_root}; git diff --exit-code")[1] == 0
|
102
207
|
end
|
103
208
|
|
104
209
|
def clean_lockfile
|
105
|
-
#berksfile = "#{options[:called_path]}/Berksfile.lock"
|
106
210
|
berksfile = "#{source_root}/Berksfile.lock"
|
107
211
|
|
108
212
|
if File.exists? berksfile
|
109
213
|
say "[ TROPO ] - Removing Berksfile.lock before running Berkshelf", :blue
|
110
|
-
remove_file(berksfile) unless options[:
|
214
|
+
remove_file(berksfile) unless options[:"no-op"]
|
111
215
|
else
|
112
216
|
say "[ TROPO ] - Unable to find berksfile to delete - [ #{berksfile} ]", :yellow
|
113
217
|
end
|
114
218
|
end
|
115
219
|
|
116
220
|
def bundle_cookbook
|
117
|
-
clean_lockfile
|
118
|
-
|
119
|
-
say "[ TROPO ] - Packaging cookbooks
|
221
|
+
clean_lockfile unless options[:keeplock]
|
222
|
+
berksfile = File.join(source_root,"/Berksfile")
|
223
|
+
say "[ TROPO ] - Packaging cookbooks using #{berksfile}", :blue
|
120
224
|
@tmp_dir = Dir.mktmpdir
|
121
225
|
opts = {
|
122
|
-
|
123
|
-
berksfile: File.join(source_root,"/Berksfile"),
|
226
|
+
berksfile: berksfile,
|
124
227
|
path: "#{@tmp_dir}/cookbooks"
|
125
228
|
}
|
126
229
|
|
230
|
+
Dir.chdir File.dirname(berksfile)
|
127
231
|
invoke("berkshelf:install", [], opts)
|
128
|
-
|
129
|
-
|
232
|
+
|
233
|
+
@_invocations.except!(Berkshelf::Cli) ### Clear Berkshelf from invocations array, because apperently you can't invoke the same task twice...
|
234
|
+
|
235
|
+
output = File.expand_path(File.join(@tmp_dir, "#{get_cookbook_name}-#{current_version}.tar.gz"))
|
130
236
|
|
131
237
|
Dir.chdir(@tmp_dir) do |dir|
|
132
238
|
tgz = Zlib::GzipWriter.new(File.open(output, 'wb'))
|
@@ -136,7 +242,7 @@ module ThorTropo
|
|
136
242
|
|
137
243
|
end
|
138
244
|
|
139
|
-
def
|
245
|
+
def get_cookbook_name
|
140
246
|
source_root.split("/")[-1]
|
141
247
|
end
|
142
248
|
|
@@ -144,28 +250,33 @@ module ThorTropo
|
|
144
250
|
if options[:"version-override"]
|
145
251
|
options[:"version-override"]
|
146
252
|
else
|
147
|
-
|
253
|
+
|
148
254
|
metadata = Ridley::Chef::Cookbook::Metadata.from_file(File.join(source_root,"metadata.rb"))
|
149
255
|
metadata.version
|
150
256
|
end
|
151
257
|
end
|
152
258
|
|
153
|
-
def tag_version
|
154
|
-
|
155
|
-
|
259
|
+
def tag_version(version=nil)
|
260
|
+
git_tag = version || current_version
|
261
|
+
sh "git tag -a -m \"Version #{git_tag}\" #{git_tag}" unless options[:"no-op"]
|
262
|
+
say "[ TROPO ] - Tagged: #{git_tag}", :blue
|
156
263
|
yield if block_given?
|
157
|
-
sh "git push --tags" unless options[:
|
264
|
+
sh "git push --tags" unless options[:"no-op"]
|
158
265
|
rescue => e
|
159
|
-
say "[ TROPO ] - Untagging: #{
|
160
|
-
sh_with_excode "git tag -d #{
|
266
|
+
say "[ TROPO ] - Untagging: #{git_tag} due to error", :red
|
267
|
+
sh_with_excode "git tag -d #{git_tag}"
|
161
268
|
say "[ TROPO ] - #{e}", :red
|
162
269
|
exit 1
|
163
270
|
end
|
164
271
|
|
165
272
|
## Get the directory to Berksfile
|
166
273
|
def source_root
|
274
|
+
berks_path = unless options[:berkspath]
|
275
|
+
Dir.pwd
|
276
|
+
else
|
277
|
+
@working_directory || File.expand_path(options[:berkspath])
|
278
|
+
end
|
167
279
|
|
168
|
-
berks_path = File.expand_path(options[:called_path])
|
169
280
|
if File.exists? berks_path
|
170
281
|
berks_path
|
171
282
|
else
|
@@ -6,7 +6,7 @@ module ThorTropo
|
|
6
6
|
require 'pathname'
|
7
7
|
require 'yaml'
|
8
8
|
|
9
|
-
attr_reader :bucket_name, :aws_secret, :aws_key, :project_name
|
9
|
+
attr_reader :bucket_name, :aws_secret, :aws_key, :project_name, :cookbooks
|
10
10
|
|
11
11
|
def initialize(path)
|
12
12
|
file_name=".deployer"
|
@@ -40,6 +40,10 @@ module ThorTropo
|
|
40
40
|
@project_name = config['project_name'] unless @project_name
|
41
41
|
end
|
42
42
|
|
43
|
+
if config['cookbooks']
|
44
|
+
@cookbooks = config['cookbooks'] unless @cookbooks
|
45
|
+
end
|
46
|
+
|
43
47
|
end
|
44
48
|
}
|
45
49
|
|
data/lib/thor-tropo/uploader.rb
CHANGED
@@ -13,6 +13,7 @@ module ThorTropo
|
|
13
13
|
@debug_mode = opts[:debug_mode]
|
14
14
|
@connection = setup_connection(opts[:access_key],opts[:secret_key])
|
15
15
|
@bucket_name = get_bucket( opts[:bucket] || 'artifacts.voxeolabs.net' )
|
16
|
+
@use_iam = opts[:use_iam]
|
16
17
|
end
|
17
18
|
|
18
19
|
def upload(opts={})
|
@@ -56,11 +57,19 @@ module ThorTropo
|
|
56
57
|
private
|
57
58
|
|
58
59
|
def setup_connection(u,p)
|
59
|
-
|
60
|
+
if @use_iam
|
61
|
+
opts = {
|
62
|
+
:provider => 'AWS',
|
63
|
+
:use_iam_profile => true
|
64
|
+
}
|
65
|
+
else
|
66
|
+
opts = {
|
60
67
|
:provider => 'AWS',
|
61
68
|
:aws_access_key_id => u,
|
62
69
|
:aws_secret_access_key => p
|
63
|
-
|
70
|
+
}
|
71
|
+
end
|
72
|
+
Fog::Storage.new(opts)
|
64
73
|
end
|
65
74
|
|
66
75
|
def get_bucket(bucket_name)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thor-tropo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: chef
|