jamie 0.1.0.alpha13 → 0.1.0.alpha14

Sign up to get free protection for your applications and to get access to all the features.
data/lib/jamie/cli.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
+ require 'erb'
4
+ require 'ostruct'
3
5
  require 'thor'
4
6
 
5
7
  require 'jamie'
@@ -47,31 +49,18 @@ module Jamie
47
49
  exit 1
48
50
  end
49
51
 
50
- desc "init", "does the world"
52
+ desc "init", "Adds some configuration to your cookbook so Jamie can rock"
51
53
  def init
52
- create_file ".jamie.yml", default_yaml
53
- append_to_file("Rakefile", <<-RAKE.gsub(/ {8}/, '')) if init_rakefile?
54
-
55
- begin
56
- require 'jamie/rake_tasks'
57
- Jamie::RakeTasks.new
58
- rescue LoadError
59
- puts ">>>>> Jamie gem not loaded, omitting tasks" unless ENV['CI']
60
- end
61
- RAKE
62
- append_to_file("Thorfile", <<-THOR.gsub(/ {8}/, '')) if init_thorfile?
54
+ InitGenerator.new.init
55
+ end
63
56
 
64
- begin
65
- require 'jamie/thor_tasks'
66
- Jamie::ThorTasks.new
67
- rescue LoadError
68
- puts ">>>>> Jamie gem not loaded, omitting tasks" unless ENV['CI']
69
- end
70
- THOR
71
- empty_directory "test/integration/standard" if init_test_dir?
72
- append_to_gitignore(".jamie/")
73
- append_to_gitignore(".jamie.local.yml")
74
- add_plugins
57
+ desc "new_plugin [NAME]", "Generate a new Jamie Driver plugin gem project"
58
+ method_option :license, :aliases => "-l", :default => "apachev2",
59
+ :desc => "Type of license for gem (apachev2, mit, gplv3, gplv2, reserved)"
60
+ def new_plugin(name)
61
+ g = NewPluginGenerator.new
62
+ g.options = options
63
+ g.new_plugin(name)
75
64
  end
76
65
 
77
66
  private
@@ -143,6 +132,42 @@ module Jamie
143
132
  }
144
133
  ]
145
134
  end
135
+ end
136
+
137
+ # A project initialization generator, to help prepare a cookbook project for
138
+ # testing with Jamie.
139
+ class InitGenerator < Thor
140
+
141
+ include Thor::Actions
142
+
143
+ desc "init", "Adds some configuration to your cookbook so Jamie can rock"
144
+ def init
145
+ create_file ".jamie.yml", default_yaml
146
+ append_to_file("Rakefile", <<-RAKE.gsub(/ {8}/, '')) if init_rakefile?
147
+
148
+ begin
149
+ require 'jamie/rake_tasks'
150
+ Jamie::RakeTasks.new
151
+ rescue LoadError
152
+ puts ">>>>> Jamie gem not loaded, omitting tasks" unless ENV['CI']
153
+ end
154
+ RAKE
155
+ append_to_file("Thorfile", <<-THOR.gsub(/ {8}/, '')) if init_thorfile?
156
+
157
+ begin
158
+ require 'jamie/thor_tasks'
159
+ Jamie::ThorTasks.new
160
+ rescue LoadError
161
+ puts ">>>>> Jamie gem not loaded, omitting tasks" unless ENV['CI']
162
+ end
163
+ THOR
164
+ empty_directory "test/integration/standard" if init_test_dir?
165
+ append_to_gitignore(".jamie/")
166
+ append_to_gitignore(".jamie.local.yml")
167
+ add_plugins
168
+ end
169
+
170
+ private
146
171
 
147
172
  def default_yaml
148
173
  url_base = "https://opscode-vm.s3.amazonaws.com/vagrant/boxes"
@@ -259,4 +284,162 @@ module Jamie
259
284
  end
260
285
  end
261
286
  end
287
+
288
+ # A generator to create a new Jamie driver plugin.
289
+ class NewPluginGenerator < Thor
290
+
291
+ include Thor::Actions
292
+
293
+ desc "new_plugin [NAME]", "Generate a new Jamie Driver plugin gem project"
294
+ method_option :license, :aliases => "-l", :default => "apachev2",
295
+ :desc => "Type of license for gem (apachev2, mit, gplv3, gplv2, reserved)"
296
+ def new_plugin(plugin_name)
297
+ if ! run("command -v bundle", :verbose => false)
298
+ die "Bundler must be installed and on your PATH: `gem install bundler'"
299
+ end
300
+
301
+ @plugin_name = plugin_name
302
+ @gem_name = "jamie-#{plugin_name}"
303
+ @gemspec = "#{gem_name}.gemspec"
304
+ @klass_name = Util.to_camel_case(plugin_name)
305
+ @constant = Util.to_snake_case(plugin_name).upcase
306
+ @license = options[:license]
307
+ @author = %x{git config user.name}.chomp
308
+ @email = %x{git config user.email}.chomp
309
+ @year = Time.now.year
310
+
311
+ create_plugin
312
+ end
313
+
314
+ private
315
+
316
+ attr_reader :plugin_name, :gem_name, :gemspec, :klass_name,
317
+ :constant, :license, :author, :email, :year
318
+
319
+ def create_plugin
320
+ run("bundle gem #{gem_name}") unless File.directory?(gem_name)
321
+
322
+ inside(gem_name) do
323
+ update_gemspec
324
+ update_gemfile
325
+ update_rakefile
326
+ create_src_files
327
+ cleanup
328
+ create_license
329
+ add_git_files
330
+ end
331
+ end
332
+
333
+ def update_gemspec
334
+ gsub_file(gemspec, %r{require '#{gem_name}/version'},
335
+ %{require 'jamie/driver/#{plugin_name}_version.rb'})
336
+ gsub_file(gemspec, %r{Jamie::#{klass_name}::VERSION},
337
+ %{Jamie::Driver::#{constant}_VERSION})
338
+ gsub_file(gemspec, %r{(gem\.executables\s*) =.*$},
339
+ '\1 = []')
340
+ gsub_file(gemspec, %r{(gem\.description\s*) =.*$},
341
+ '\1 = "' + "Jamie::Driver::#{klass_name} - " +
342
+ "A Jamie Driver for #{klass_name}\"")
343
+ gsub_file(gemspec, %r{(gem\.summary\s*) =.*$},
344
+ '\1 = gem.description')
345
+ gsub_file(gemspec, %r{(gem\.homepage\s*) =.*$},
346
+ '\1 = "https://github.com/jamie-ci/' +
347
+ "#{gem_name}/\"")
348
+ insert_into_file(gemspec,
349
+ "\n gem.add_dependency 'jamie'\n", :before => "end\n")
350
+ insert_into_file(gemspec,
351
+ "\n gem.add_development_dependency 'cane'\n", :before => "end\n")
352
+ insert_into_file(gemspec,
353
+ " gem.add_development_dependency 'tailor'\n", :before => "end\n")
354
+ end
355
+
356
+ def update_gemfile
357
+ append_to_file("Gemfile", "\ngroup :test do\n gem 'rake'\nend\n")
358
+ end
359
+
360
+ def update_rakefile
361
+ append_to_file("Rakefile", <<-RAKEFILE.gsub(/^ {8}/, ''))
362
+ require 'cane/rake_task'
363
+ require 'tailor/rake_task'
364
+
365
+ desc "Run cane to check quality metrics"
366
+ Cane::RakeTask.new
367
+
368
+ Tailor::RakeTask.new
369
+
370
+ task :default => [ :cane, :tailor ]
371
+ RAKEFILE
372
+ end
373
+
374
+ def create_src_files
375
+ license_comments = rendered_license.gsub(/^/, '# ').gsub(/\s+$/, '')
376
+
377
+ empty_directory("lib/jamie/driver")
378
+ create_template("plugin/version.rb",
379
+ "lib/jamie/driver/#{plugin_name}_version.rb",
380
+ :klass_name => klass_name, :constant => constant,
381
+ :license => license_comments)
382
+ create_template("plugin/driver.rb",
383
+ "lib/jamie/driver/#{plugin_name}.rb",
384
+ :klass_name => klass_name, :license => license_comments)
385
+ end
386
+
387
+ def rendered_license
388
+ TemplateRenderer.render("plugin/license_#{license}",
389
+ :author => author, :email => email, :year => year)
390
+ end
391
+
392
+ def create_license
393
+ dest_file = case license
394
+ when "mit" then "LICENSE.txt"
395
+ when "apachev2", "reserved" then "LICENSE"
396
+ when "gplv2", "gplv3" then "COPYING"
397
+ else
398
+ raise ArgumentError, "No such license #{license}"
399
+ end
400
+
401
+ create_file(dest_file, rendered_license)
402
+ end
403
+
404
+ def cleanup
405
+ %W(LICENSE.txt lib/#{gem_name}/version.rb lib/#{gem_name}.rb).each do |f|
406
+ run("git rm -f #{f}") if File.exists?(f)
407
+ end
408
+ remove_dir("lib/#{gem_name}")
409
+ end
410
+
411
+ def add_git_files
412
+ run("git add .")
413
+ end
414
+
415
+ def create_template(template, destination, data = {})
416
+ create_file(destination, TemplateRenderer.render(template, data))
417
+ end
418
+
419
+ # Renders an ERB template with a hash of template variables.
420
+ class TemplateRenderer < OpenStruct
421
+
422
+ def self.render(template, data = {})
423
+ renderer = new(template, data)
424
+ yield renderer if block_given?
425
+ renderer.render
426
+ end
427
+
428
+ def initialize(template, data = {})
429
+ super()
430
+ data[:template] = template
431
+ data.each { |key, value| send("#{key}=", value) }
432
+ end
433
+
434
+ def render
435
+ ERB.new(IO.read(template_file)).result(binding)
436
+ end
437
+
438
+ private
439
+
440
+ def template_file
441
+ Jamie.source_root.join("templates", "#{template}.erb").to_s
442
+ end
443
+ end
444
+ end
262
445
  end
@@ -1,7 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
- require 'mixlib/shellout'
4
-
5
3
  require 'jamie'
6
4
 
7
5
  module Jamie
data/lib/jamie/vagrant.rb CHANGED
@@ -47,6 +47,7 @@ module Jamie
47
47
  chef.run_list = instance.run_list
48
48
  chef.json = instance.attributes
49
49
  chef.data_bags_path = instance.suite.data_bags_path
50
+ chef.roles_path = instance.suite.roles_path
50
51
  end
51
52
  end
52
53
  end
data/lib/jamie/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Jamie
4
4
 
5
- VERSION = "0.1.0.alpha13"
5
+ VERSION = "0.1.0.alpha14"
6
6
  end
data/lib/jamie.rb CHANGED
@@ -18,6 +18,13 @@ require 'jamie/version'
18
18
 
19
19
  module Jamie
20
20
 
21
+ # Returns the root path of the Jamie gem source code.
22
+ #
23
+ # @return [Pathname] root path of gem
24
+ def self.source_root
25
+ @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
26
+ end
27
+
21
28
  # Base configuration class for Jamie. This class exposes configuration such
22
29
  # as the location of the Jamie YAML file, instances, log_levels, etc.
23
30
  class Config
@@ -122,7 +129,12 @@ module Jamie
122
129
 
123
130
  def new_suite(hash)
124
131
  data_bags_path = calculate_data_bags_path(hash['name'])
125
- Suite.new(hash.rmerge({ 'data_bags_path' => data_bags_path }))
132
+ roles_path = calculate_roles_path(hash['name'])
133
+ path_hash = {
134
+ 'data_bags_path' => data_bags_path,
135
+ 'roles_path' => roles_path
136
+ }
137
+ Suite.new(hash.rmerge(path_hash))
126
138
  end
127
139
 
128
140
  def new_platform(hash)
@@ -159,14 +171,33 @@ module Jamie
159
171
  default_driver_config.rmerge(common_driver_config.rmerge(platform_config))
160
172
  end
161
173
 
174
+ def calculate_roles_path(suite_name)
175
+ suite_roles_path = File.join(test_base_path, suite_name, "roles")
176
+ common_roles_path = File.join(test_base_path, "roles")
177
+ top_level_roles_path = File.join(Dir.pwd, "roles")
178
+
179
+ if File.directory?(suite_roles_path)
180
+ suite_roles_path
181
+ elsif File.directory?(common_roles_path)
182
+ common_roles_path
183
+ elsif File.directory?(top_level_roles_path)
184
+ top_level_roles_path
185
+ else
186
+ nil
187
+ end
188
+ end
189
+
162
190
  def calculate_data_bags_path(suite_name)
163
191
  suite_data_bags_path = File.join(test_base_path, suite_name, "data_bags")
164
192
  common_data_bags_path = File.join(test_base_path, "data_bags")
193
+ top_level_data_bags_path = File.join(Dir.pwd, "data_bags")
165
194
 
166
195
  if File.directory?(suite_data_bags_path)
167
196
  suite_data_bags_path
168
197
  elsif File.directory?(common_data_bags_path)
169
198
  common_data_bags_path
199
+ elsif File.directory?(top_level_data_bags_path)
200
+ top_level_data_bags_path
170
201
  else
171
202
  nil
172
203
  end
@@ -198,6 +229,10 @@ module Jamie
198
229
  # not exist
199
230
  attr_reader :data_bags_path
200
231
 
232
+ # @return [String] local path to the suite's roles, or nil if one does
233
+ # not exist
234
+ attr_reader :roles_path
235
+
201
236
  # Constructs a new suite.
202
237
  #
203
238
  # @param [Hash] options configuration for a new suite
@@ -213,6 +248,7 @@ module Jamie
213
248
  @run_list = options['run_list']
214
249
  @attributes = options['attributes'] || Hash.new
215
250
  @data_bags_path = options['data_bags_path']
251
+ @roles_path = options['roles_path']
216
252
  end
217
253
 
218
254
  private
@@ -887,6 +923,7 @@ module Jamie
887
923
  upload_solo_rb scp
888
924
  upload_cookbooks scp
889
925
  upload_data_bags scp if instance.suite.data_bags_path
926
+ upload_roles scp if instance.suite.roles_path
890
927
  end
891
928
  end
892
929
 
@@ -926,6 +963,16 @@ module Jamie
926
963
  end
927
964
  end
928
965
 
966
+ def upload_roles(scp)
967
+ roles_dir = instance.suite.roles_path
968
+ scp.upload!(roles_dir, "#{chef_home}/roles",
969
+ :recursive => true
970
+ ) do |ch, name, sent, total|
971
+ file = name.sub(%r{^#{roles_dir}/}, '')
972
+ puts " #{file}: #{sent}/#{total}"
973
+ end
974
+ end
975
+
929
976
  def solo_rb_contents
930
977
  solo = []
931
978
  solo << %{node_name "#{instance.name}"}
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ <%= license %>
4
+
5
+ require 'jamie'
6
+
7
+ module Jamie
8
+
9
+ module Driver
10
+
11
+ # <%= klass_name %> driver for Jamie.
12
+ class <%= klass_name %> < Jamie::Driver::SSHBase
13
+
14
+ def perform_create(instance, state)
15
+ end
16
+
17
+ def perform_destroy(instance, state)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ Author:: <%= author %> (<<%= email %>>)
2
+
3
+ Copyright (C) <%= year %>, <%= author %>
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
@@ -0,0 +1,18 @@
1
+ Author:: <%= author %> (<<%= email %>>)
2
+
3
+ Copyright (C) <%= year %> <%= author %>
4
+
5
+ This program is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU General Public License
7
+ as published by the Free Software Foundation; either version 2
8
+ of the License, or (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
+ Boston, MA 02110-1301, USA.
@@ -0,0 +1,16 @@
1
+ Author:: <%= author %> (<<%= email %>>)
2
+
3
+ Copyright (C) <%= year %> <%= author %>
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
@@ -0,0 +1,22 @@
1
+ Author:: <%= author %> (<<%= email %>>)
2
+
3
+ Copyright (c) <%= year %>, <%= author %>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,5 @@
1
+ Author:: <%= author %> (<<%= email %>>)
2
+
3
+ Copyright (C) <%= year %>, <%= author %>
4
+
5
+ All rights reserved - Do Not Redistribute
@@ -0,0 +1,12 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ <%= license %>
4
+
5
+ module Jamie
6
+
7
+ module Driver
8
+
9
+ # Version string for <%= klass_name %> Jamie driver
10
+ <%= constant %>_VERSION = "0.1.0"
11
+ end
12
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jamie
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.alpha13
4
+ version: 0.1.0.alpha14
5
5
  prerelease: 6
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: 2012-12-20 00:00:00.000000000 Z
12
+ date: 2012-12-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -180,6 +180,13 @@ files:
180
180
  - lib/jamie/vagrant.rb
181
181
  - lib/jamie/version.rb
182
182
  - lib/vendor/hash_recursive_merge.rb
183
+ - templates/plugin/driver.rb.erb
184
+ - templates/plugin/license_apachev2.erb
185
+ - templates/plugin/license_gplv2.erb
186
+ - templates/plugin/license_gplv3.erb
187
+ - templates/plugin/license_mit.erb
188
+ - templates/plugin/license_reserved.erb
189
+ - templates/plugin/version.rb.erb
183
190
  homepage: ''
184
191
  licenses: []
185
192
  post_install_message:
@@ -194,7 +201,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
194
201
  version: '0'
195
202
  segments:
196
203
  - 0
197
- hash: -1363591312854279086
204
+ hash: 168460114090032110
198
205
  required_rubygems_version: !ruby/object:Gem::Requirement
199
206
  none: false
200
207
  requirements: