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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Thor::Tropo
2
2
 
3
- TODO: Write a gem description
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
- TODO: Write usage instructions here
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 :called_path,
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 => "-d",
28
- :default => Dir.pwd,
29
- :desc => "Directory of your Berksfile",
30
- :banner => "Directory of your Berksfile"
43
+ :aliases => "-b",
44
+ :default => nil,
45
+ :desc => "Berksfile path"
31
46
 
32
- desc "package", "Package cookbooks and upload to S3"
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 => "Force override of version number",
39
- :banner => "Force override of cookbook version"
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 => "Force override of any files on s3 without confirmation",
46
- :banner => "Force overrides of existing files"
61
+ :desc => "overwrite any files on s3 without confirmation"
47
62
 
48
- method_option :noop,
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 :ignore_dirty,
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 => "Ignore any dirty files in directory and package anyways",
59
- :banner => "Ignore dirty repository"
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 :clean_mode,
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
- :desc => "Delete lockfile before running `Berks install`",
66
- :banner => "Delete lockfile before running `Berks install`"
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
- #$config = ThorTropo::Configuration.new(options[:called_path])
107
+ print_help_or_version
108
+
71
109
  $config = ThorTropo::Configuration.new(source_root)
72
110
 
73
111
  unless clean?
74
- unless options[:ignore_dirty]
75
- say "There are files that need to be committed first.", :red
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
- tag_version {
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],:noop => options[:noop]}
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[:noop]
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[:noop]
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 if options[:clean_mode]
118
-
119
- say "[ TROPO ] - Packaging cookbooks from Berksfile", :blue
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
- #berksfile: File.join(options[:called_path],"/Berksfile"),
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
- #output = File.expand_path(File.join(@tmp_dir, "#{options[:called_path].split("/")[-1]}-#{current_version}.tar.gz"))
129
- output = File.expand_path(File.join(@tmp_dir, "#{cookbook_name}-#{current_version}.tar.gz"))
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 cookbook_name
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
- #metadata = Ridley::Chef::Cookbook::Metadata.from_file(File.join(options[:called_path],"metadata.rb"))
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
- sh "git tag -a -m \"Version #{current_version}\" #{current_version}" unless options[:noop]
155
- say "[ TROPO ] - Tagged: #{current_version}", :blue
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[:noop]
264
+ sh "git push --tags" unless options[:"no-op"]
158
265
  rescue => e
159
- say "[ TROPO ] - Untagging: #{current_version} due to error", :red
160
- sh_with_excode "git tag -d #{current_version}"
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
 
@@ -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
- Fog::Storage.new({
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: 1.4.0
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-15 00:00:00.000000000 Z
12
+ date: 2013-07-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: chef