spiceweasel 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 627c6a6eb70983a3e5983fffbd71531819c8b860
4
+ data.tar.gz: 6bf43f3a1d8782bd0dbc52cc337cda04063b7001
5
+ SHA512:
6
+ metadata.gz: fa76e167b464d2864b0c8e43c1d2e52b0f7cfda1070053a3d69f18dc46a08261c0809e2ed013a101eda7db47b2dee0d3a6ae11b09d48c83bd647b0365d111a08
7
+ data.tar.gz: f8507cfee9414238ff01c57893eb0ee07a937c4a6a8ac3b892d88887e9afed4ded2d5b7605e82ddfc242c8105e303c83b7422ac929bce9a364d3f59baafa2b4a
data/README.md CHANGED
@@ -13,7 +13,7 @@ The [CHANGELOG.md](https://github.com/mattray/spiceweasel/blob/master/CHANGELOG.
13
13
 
14
14
  Spiceweasel currently depends on `knife` to run commands for it, and requires the `chef` gem for validating cookbook metadata. [Berkshelf](https://berkshelf.com) is a dependency for the Cookbook `Berksfile` support. Infrastructure files must end in `.rb`, `.json` or `.yml` to be processed.
15
15
 
16
- Written and tested with the Chef 11.x series (previous versions of Chef may still work). It is tested with Ruby 1.9.3. Version 2.0 was the last version known to work with Ruby 1.8.7 due to the introduction of the Berkshelf dependency in 2.1.
16
+ Written and tested with the Chef 11.x series (previous versions of Chef may still work). It is tested with Ruby 1.9.3. Version 2.0 was the last version known to work with Ruby 1.8.7 due to the introduction of the Berkshelf dependency in 2.1. If you want to use Ruby 2.0, you will need to use the Chef 11.6 (or later) gem.
17
17
 
18
18
  # File Syntax #
19
19
 
@@ -202,7 +202,7 @@ which generates nodes named "webserver1", "webserver2" and "webserver3".
202
202
 
203
203
  ## Clusters ##
204
204
 
205
- Clusters are not a type supported by Chef, this is a logical construct added by Spiceweasel to enable managing sets of infrastructure together. The `clusters` section is a special case of `nodes`, where each member of the named cluster in the manifest will be put in the same environment to ensure that the entire cluster may be created in sync (refresh and delete coming soon). The node syntax is the same as that under `nodes`, the only addition is the cluster name.
205
+ Clusters are not a type supported by Chef, this is a logical construct added by Spiceweasel to enable managing sets of infrastructure together. The `clusters` section is a special case of `nodes`, where each member of the named cluster in the manifest will be put in the same Environment to ensure that the entire cluster may be created in sync (refresh and delete coming soon). The node syntax is the same as that under `nodes`, the only addition is the cluster name.
206
206
 
207
207
  ```
208
208
  clusters:
@@ -226,6 +226,33 @@ knife ec2 server create -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7
226
226
 
227
227
  Another use of `clusters` is with the `--cluster-file` option, which will allow the use of a different file to define the members of the cluster. If there are any `nodes` or `clusters` defined in the primary manifest file, they will be removed and the content of the `--cluster-file` will be used instead. This allows you to switch the target destination of infrastructure by picking different `--cluster-file` endpoints.
228
228
 
229
+ ## knife ##
230
+
231
+ The `knife` section allows you to run arbitrary knife commands after you have deployed the infrastructure specified in the rest of the manifest. Validation is done to ensure that the knife commands called are installed on the system. The example YAML snippet
232
+
233
+ ``` yaml
234
+ knife:
235
+ - ssh:
236
+ - "'role:monitoring' 'sudo chef-client' -x user"
237
+ - rackspace server delete:
238
+ - -y --node-name db3 --purge
239
+ - vsphere:
240
+ - vm clone --bootstrap --template 'abc' my-new-webserver1
241
+ - vm clone --bootstrap --template 'def' my-new-webserver2
242
+ - vsphere vm clone:
243
+ - --bootstrap --template 'ghi' my-new-webserver3
244
+ ```
245
+
246
+ assumes the `knife-rackspace` and `knife-vsphere` plugins are installed and produces the knife commands
247
+
248
+ ```
249
+ knife ssh 'role:monitoring' 'sudo chef-client' -x user
250
+ knife rackspace server delete -y --node-name db3 --purge
251
+ knife vsphere vm clone --bootstrap --template 'abc' my-new-webserver1
252
+ knife vsphere vm clone --bootstrap --template 'def' my-new-webserver2
253
+ knife vsphere vm clone --bootstrap --template 'ghi' my-new-webserver3
254
+ ```
255
+
229
256
  # Extract #
230
257
 
231
258
  Spiceweasel may be used to generate knife commands or Spiceweasel manifests in JSON or YAML from an existing Chef repository.
@@ -271,6 +298,16 @@ When using the delete or rebuild commands, whether or not to attempt to delete a
271
298
 
272
299
  Specify a knife.rb configuration file to use with the knife commands.
273
300
 
301
+ ## --chef-client ##
302
+
303
+ This will generate the knife commands to run the chef-client on each of the nodes in the manifest. The nodes refreshed will be matched by node name, environment for clusters and by cloud provider run list otherwise.
304
+
305
+ knife ssh 'name:*' 'sudo chef-client'
306
+ knife ssh 'role:base and recipe:apt\:\:cacher-ng' 'uptime'
307
+ knife ssh "role:web"
308
+
309
+ You may also use `-a` or `--attribute` to specify an attribute to use with `knife ssh`.
310
+
274
311
  ## --cluster-file ##
275
312
 
276
313
  Specify the file to use to override the `nodes` and `clusters` from the primary manifest file. This allows you to switch the target destination of infrastructure by picking different `--cluster-file` endpoints.
@@ -48,8 +48,12 @@ module Spiceweasel
48
48
  create_command("berks upload #{berks_options}")
49
49
  Berkshelf.ui.mute do
50
50
  Spiceweasel::Log.debug("berkshelf resolving dependencies: #{resolve_opts}")
51
- # berks.resolve(resolve_opts) blows up with Berkshelf 2.0
52
- berks.resolve(resolve_opts).each do |cb|
51
+ if(Gem::Version.new(Berkshelf::VERSION) >= Gem::Version.new('2.0.0'))
52
+ ckbks = berks.install(resolve_opts)
53
+ else
54
+ ckbks = berks.resolve(resolve_opts)
55
+ end
56
+ ckbks.each do |cb|
53
57
  @cookbook_list[cb.cookbook_name] = cb.version
54
58
  delete_command("knife cookbook#{Spiceweasel::Config[:knife_options]} delete #{cb.cookbook_name} #{cb.version} -a -y")
55
59
  end
@@ -17,7 +17,7 @@
17
17
  #
18
18
 
19
19
  require 'mixlib/cli'
20
- require 'json'
20
+ require 'yajl/json_gem'
21
21
  require 'yaml'
22
22
 
23
23
  require 'spiceweasel'
@@ -54,6 +54,16 @@ module Spiceweasel
54
54
  :description => 'Delete all nodes for the provider(s) in the infrastructure',
55
55
  :boolean => false
56
56
 
57
+ option :attribute,
58
+ :short => '-a',
59
+ :long => '--attribute ATTR',
60
+ :description => "The attribute to use for opening the connection - default depends on the context. Used in conjunction with '--chef-client'"
61
+
62
+ option :chefclient,
63
+ :long => '--chef-client',
64
+ :description => 'Print the knife commands to run chef-client on the nodes of the infrastructure',
65
+ :boolean => true
66
+
57
67
  option :delete,
58
68
  :short => '-d',
59
69
  :long => '--delete',
@@ -130,6 +140,12 @@ module Spiceweasel
130
140
  :description => "Use the 'install' command with 'knife cookbook site' instead of the default 'download'",
131
141
  :boolean => true
132
142
 
143
+ option :timeout,
144
+ :short => '-T seconds',
145
+ :long => '--timeout',
146
+ :description => "Specify the maximum number of seconds a command is allowed to run without producing output. Default is 60 seconds",
147
+ :default => 60
148
+
133
149
  option :version,
134
150
  :short => '-v',
135
151
  :long => '--version',
@@ -167,17 +183,18 @@ module Spiceweasel
167
183
 
168
184
  create, delete = process_manifest(manifest)
169
185
 
170
- if Spiceweasel::Config[:extractjson]
186
+ case
187
+ when Spiceweasel::Config[:extractjson]
171
188
  puts JSON.pretty_generate(manifest)
172
- elsif Spiceweasel::Config[:extractyaml]
189
+ when Spiceweasel::Config[:extractyaml]
173
190
  puts manifest.to_yaml
174
- elsif Spiceweasel::Config[:delete]
191
+ when Spiceweasel::Config[:delete]
175
192
  if Spiceweasel::Config[:execute]
176
193
  Execute.new(delete)
177
194
  else
178
195
  puts delete unless delete.empty?
179
196
  end
180
- elsif Spiceweasel::Config[:rebuild]
197
+ when Spiceweasel::Config[:rebuild]
181
198
  if Spiceweasel::Config[:execute]
182
199
  Execute.new(delete)
183
200
  Execute.new(create)
@@ -192,6 +209,7 @@ module Spiceweasel
192
209
  puts create unless create.empty?
193
210
  end
194
211
  end
212
+
195
213
  exit 0
196
214
  end
197
215
 
@@ -219,6 +237,9 @@ module Spiceweasel
219
237
  else
220
238
  knife.configure_chef
221
239
  end
240
+ if @config[:timeout]
241
+ Spiceweasel::Config[:cmd_timeout] = @config[:timeout].to_i
242
+ end
222
243
  if @config[:serverurl]
223
244
  Spiceweasel::Config[:knife_options] += "--server-url #{@config[:serverurl]} "
224
245
  end
@@ -289,14 +310,28 @@ module Spiceweasel
289
310
  environments = Environments.new(manifest['environments'], cookbooks)
290
311
  roles = Roles.new(manifest['roles'], environments, cookbooks)
291
312
  data_bags = DataBags.new(manifest['data bags'])
292
- nodes = Nodes.new(manifest['nodes'], cookbooks, environments, roles)
293
- clusters = Clusters.new(manifest['clusters'], cookbooks, environments, roles)
294
- knife = Knife.new(manifest['knife'])
313
+ knifecommands = get_knife_commands() unless Spiceweasel::Config[:novalidation]
314
+ nodes = Nodes.new(manifest['nodes'], cookbooks, environments, roles, knifecommands)
315
+ clusters = Clusters.new(manifest['clusters'], cookbooks, environments, roles, knifecommands)
316
+ knife = Knife.new(manifest['knife'], knifecommands)
295
317
 
296
318
  create += environments.create + roles.create + data_bags.create + nodes.create + clusters.create + knife.create
297
319
  delete += environments.delete + roles.delete + data_bags.delete + nodes.delete + clusters.delete
320
+
321
+ # --chef-client only runs on nodes
322
+ if Spiceweasel::Config[:chefclient]
323
+ create = nodes.create + clusters.create
324
+ delete = []
325
+ end
298
326
  return create, delete
299
327
  end
300
328
 
329
+ def get_knife_commands()
330
+ require 'mixlib/shellout'
331
+ allknifes = Mixlib::ShellOut.new('knife -h').run_command.stdout.split(/\n/)
332
+ allknifes.keep_if {|x| x.start_with?('knife')}
333
+ Spiceweasel::Log.debug(allknifes)
334
+ return allknifes
335
+ end
301
336
  end
302
337
  end
@@ -1,7 +1,7 @@
1
1
  #
2
2
  # Author:: Matt Ray (<matt@opscode.com>)
3
3
  #
4
- # Copyright:: 2012, Opscode, Inc <legal@opscode.com>
4
+ # Copyright:: 2012-2013, Opscode, Inc <legal@opscode.com>
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -21,39 +21,45 @@ module Spiceweasel
21
21
 
22
22
  attr_reader :create, :delete
23
23
 
24
- def initialize(clusters, cookbooks, environments, roles)
24
+ def initialize(clusters, cookbooks, environments, roles, knifecommands)
25
25
  @create = Array.new
26
26
  @delete = Array.new
27
27
  if clusters
28
28
  Spiceweasel::Log.debug("clusters: #{clusters}")
29
29
  clusters.each do |cluster|
30
30
  cluster_name = cluster.keys.first
31
- Spiceweasel::Log.debug("cluster: '#{cluster_name}' '#{cluster[cluster_name]}'")
32
- # add a tag to the Nodes
33
- cluster[cluster_name].each do |node|
34
- node_name = node.keys.first
35
- run_list = node[node_name]['run_list'] || ''
36
- options = node[node_name]['options'] || ''
37
- # cluster tag is the cluster name + runlist once tags are working for every plugin
38
- # until then, we're going to override the Environment
39
- if options =~ /-E/ #delete any Environment
40
- env = options.split('-E')[1].split[0]
41
- edel = "-E#{env}"
42
- options[edel] = "" if options.include?(edel)
43
- edel = "-E #{env}"
44
- options[edel] = "" if options.include?(edel)
45
- Spiceweasel::Log.warn("deleting specified Environment '#{env}' from cluster: '#{cluster_name}'")
46
- end
47
- #push the Environment back on the options
48
- node[node_name]['options'] = options + " -E #{cluster_name}"
49
- end
50
- # let's reuse the Nodes logic
51
- nodes = Spiceweasel::Nodes.new(cluster[cluster_name], cookbooks, environments, roles)
52
- @create.concat(nodes.create)
53
- @delete.concat(nodes.delete)
31
+ cluster_process_nodes(cluster, cluster_name, cookbooks, environments, roles, knifecommands)
54
32
  end
55
33
  end
56
34
  end
57
35
 
36
+ # configure the individual nodes within the cluster
37
+ def cluster_process_nodes(cluster, environment, cookbooks, environments, roles, knifecommands)
38
+ Spiceweasel::Log.debug("cluster::cluster_process_nodes '#{environment}' '#{cluster[environment]}'")
39
+ cluster[environment].each do |node|
40
+ node_name = node.keys.first
41
+ options = node[node_name]['options'] || ''
42
+ validate_environment(options, environment, environments) unless Spiceweasel::Config[:novalidation]
43
+ #push the Environment back on the options
44
+ node[node_name]['options'] = options + " -E #{environment}"
45
+ end
46
+ # let's reuse the Nodes logic
47
+ nodes = Spiceweasel::Nodes.new(cluster[environment], cookbooks, environments, roles, knifecommands)
48
+ @create.concat(nodes.create)
49
+ @delete.concat(nodes.delete)
50
+ end
51
+
52
+ def validate_environment(options, cluster, environments)
53
+ unless environments.member?(cluster)
54
+ STDERR.puts "ERROR: Environment '#{cluster}' is listed in the cluster, but not specified as an 'environment' in the manifest."
55
+ exit(-1)
56
+ end
57
+ if options =~ /-E/ #Environment must match the cluster
58
+ env = options.split('-E')[1].split[0]
59
+ STDERR.puts "ERROR: Environment '#{env}' is specified for a node in cluster '#{cluster}'. The Environment is the cluster name."
60
+ exit(-1)
61
+ end
62
+ end
63
+
58
64
  end
59
65
  end
@@ -16,7 +16,7 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
- require 'json'
19
+ require 'yajl/json_gem'
20
20
 
21
21
  module Spiceweasel
22
22
  class DataBags
@@ -16,7 +16,7 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
- require 'json'
19
+ require 'yajl/json_gem'
20
20
 
21
21
  module Spiceweasel
22
22
  class Environments
@@ -73,7 +73,7 @@ module Spiceweasel
73
73
  when /\.json$/
74
74
  env = Chef::JSONCompat.from_json(IO.read(file))
75
75
  when /\.rb$/
76
- if (Chef::Version.new(Chef::VERSION) < Chef::Version.new('11.0.0'))
76
+ if (Chef::VERSION.split('.')[0].to_i < 11)
77
77
  env = Chef::Environment.new(false)
78
78
  else
79
79
  env = Chef::Environment.new
@@ -1,7 +1,7 @@
1
1
  #
2
2
  # Author:: Matt Ray (<matt@opscode.com>)
3
3
  #
4
- # Copyright:: 2012, Opscode, Inc <legal@opscode.com>
4
+ # Copyright:: 2012-2013, Opscode, Inc <legal@opscode.com>
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -25,7 +25,8 @@ module Spiceweasel
25
25
  def initialize(commands)
26
26
  # for now we're shelling out
27
27
  commands.each do | cmd |
28
- knife = Mixlib::ShellOut.new(cmd.command, cmd.shellout_opts.merge(:live_stream => STDOUT))
28
+ Spiceweasel::Log.debug("Command will timeout after #{Spiceweasel::Config[:cmd_timeout]} seconds.")
29
+ knife = Mixlib::ShellOut.new(cmd.command, cmd.shellout_opts.merge(:live_stream => STDOUT, :timeout => Spiceweasel::Config[:timeout]))
29
30
  # check for parallel? and eventually use threads
30
31
  knife.run_command
31
32
  puts knife.stderr
@@ -16,8 +16,6 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
- require 'mixlib/shellout'
20
-
21
19
  module Spiceweasel
22
20
  class Knife
23
21
 
@@ -25,12 +23,9 @@ module Spiceweasel
25
23
 
26
24
  attr_reader :knife_list, :create
27
25
 
28
- def initialize(knives = {})
26
+ def initialize(knives = {}, allknifes = [])
29
27
  @create = Array.new
30
28
  if knives
31
- allknifes = Mixlib::ShellOut.new('knife -h').run_command.stdout.split(/\n/)
32
- allknifes.keep_if {|x| x.start_with?('knife')}
33
- Spiceweasel::Log.debug(allknifes)
34
29
  knives.each do |knife|
35
30
  Spiceweasel::Log.debug("knife: #{knife}")
36
31
  knife.keys.each do |knf|
@@ -21,28 +21,29 @@ module Spiceweasel
21
21
 
22
22
  include CommandHelper
23
23
 
24
- PROVIDERS = %w{bluebox clodo cs ec2 gandi hp joyent lxc openstack rackspace slicehost terremark vagrant voxel vsphere}
24
+ PROVIDERS = %w{bluebox clodo cs ec2 gandi hp joyent kvm lxc openstack rackspace slicehost terremark vagrant voxel vsphere}
25
25
 
26
26
  attr_reader :create, :delete
27
27
 
28
- def initialize(nodes, cookbooks, environments, roles)
28
+ def initialize(nodes, cookbooks, environments, roles, knifecommands)
29
29
  @create = Array.new
30
30
  @delete = Array.new
31
+ chefclient = Array.new
32
+ create_command_options = {}
31
33
  if nodes
32
34
  Spiceweasel::Log.debug("nodes: #{nodes}")
33
35
  nodes.each do |node|
34
36
  name = node.keys.first
37
+ names = name.split
35
38
  Spiceweasel::Log.debug("node: '#{name}' '#{node[name]}'")
39
+ # get the node's run_list and options
36
40
  if node[name]
37
- #convert spaces to commas, drop multiple commas
38
- run_list = node[name]['run_list'] || ''
39
- run_list = run_list.gsub(/ /,',').gsub(/,+/,',')
41
+ run_list = process_run_list(node[name]['run_list'])
40
42
  Spiceweasel::Log.debug("node: '#{name}' run_list: '#{run_list}'")
41
- validateRunList(name, run_list, cookbooks, roles) unless Spiceweasel::Config[:novalidation]
43
+ validate_run_list(name, run_list, cookbooks, roles) unless Spiceweasel::Config[:novalidation]
42
44
  options = node[name]['options'] || ''
43
45
  Spiceweasel::Log.debug("node: '#{name}' options: '#{options}'")
44
- validateOptions(name, options, environments) unless Spiceweasel::Config[:novalidation]
45
- create_command_options = {}
46
+ validate_options(name, options, environments) unless Spiceweasel::Config[:novalidation]
46
47
  %w(allow_create_failure timeout).each do |key|
47
48
  if(node[name].has_key?(key))
48
49
  create_command_options[key] = node[name][key]
@@ -50,86 +51,53 @@ module Spiceweasel
50
51
  end
51
52
  additional_commands = node[name]['additional_commands'] || []
52
53
  end
53
- #provider support
54
- provider = name.split()
55
- if PROVIDERS.member?(provider[0])
56
- count = 1
57
- if provider.length == 2
58
- count = provider[1]
59
- end
60
- provided_names = []
61
- if Spiceweasel::Config[:parallel]
62
- parallel = "seq #{count} | parallel -j 0 -v \""
63
- if provider[0].eql?('vsphere')
64
- parallel += "knife #{provider[0]}#{Spiceweasel::Config[:knife_options]} vm clone #{options}".gsub(/\{\{n\}\}/, '{}')
65
- else
66
- parallel += "knife #{provider[0]}#{Spiceweasel::Config[:knife_options]} server create #{options}".gsub(/\{\{n\}\}/, '{}')
67
- end
68
- parallel += " -r '#{run_list}'" unless run_list.empty?
69
- parallel += "\""
70
- create_command(parallel, create_command_options)
71
- else
72
- count.to_i.times do |i|
73
- if provider[0].eql?('vsphere')
74
- server = "knife #{provider[0]}#{Spiceweasel::Config[:knife_options]} vm clone #{options}".gsub(/\{\{n\}\}/, (i + 1).to_s)
75
- else
76
- server = "knife #{provider[0]}#{Spiceweasel::Config[:knife_options]} server create #{options}".gsub(/\{\{n\}\}/, (i + 1).to_s)
77
- end
78
- server += " -r '#{run_list}'" unless run_list.empty?
79
- provided_names << node[name]['name'].gsub('{{n}}', (i + 1).to_s) if node[name]['name']
80
- create_command(server, create_command_options)
54
+ if Spiceweasel::Config[:chefclient]
55
+ chefclient.push(process_chef_client(names, options, run_list))
56
+ else #create/delete
57
+ #provider support
58
+ if PROVIDERS.member?(names[0])
59
+ count = 1
60
+ if names.length == 2
61
+ count = names[1]
81
62
  end
82
- end
83
- if Spiceweasel::Config[:bulkdelete] && provided_names.empty? && provider[0] != 'windows'
84
- if provider[0].eql?('vsphere')
85
- delete_command("knife node#{Spiceweasel::Config[:knife_options]} list | xargs knife #{provider[0]} vm delete -y")
86
- else
87
- delete_command("knife node#{Spiceweasel::Config[:knife_options]} list | xargs knife #{provider[0]} server delete -y")
63
+ process_providers(names[0], count, node[name]['name'], options, run_list, create_command_options, knifecommands)
64
+ elsif names[0].start_with?("windows_")
65
+ #windows node bootstrap support
66
+ protocol = names.shift.split('_') #split on 'windows_ssh' etc
67
+ names.each do |server|
68
+ servercommand = "knife bootstrap #{protocol[0]} #{protocol[1]}#{Spiceweasel::Config[:knife_options]} #{server} #{options}"
69
+ servercommand += " -r '#{run_list}'" unless run_list.empty?
70
+ create_command(servercommand, create_command_options)
71
+ delete_command("knife node#{Spiceweasel::Config[:knife_options]} delete #{server} -y")
72
+ delete_command("knife client#{Spiceweasel::Config[:knife_options]} delete #{server} -y")
88
73
  end
89
74
  else
90
- provided_names.each do |p_name|
91
- if provider[0].eql?('vsphere')
92
- delete_command("knife #{provider[0]} vm delete -y #{p_name}")
93
- else
94
- delete_command("knife #{provider[0]} server delete -y #{p_name}")
95
- end
96
- delete_command("knife node#{Spiceweasel::Config[:knife_options]} delete #{p_name} -y")
97
- delete_command("knife client#{Spiceweasel::Config[:knife_options]} delete #{p_name} -y")
75
+ #node bootstrap support
76
+ name.split.each_with_index do |server, i|
77
+ servercommand = "knife bootstrap#{Spiceweasel::Config[:knife_options]} #{server} #{options}".gsub(/\{\{n\}\}/, (i + 1).to_s)
78
+ servercommand += " -r '#{run_list}'" unless run_list.empty?
79
+ create_command(servercommand, create_command_options)
80
+ delete_command("knife node#{Spiceweasel::Config[:knife_options]} delete #{server} -y")
81
+ delete_command("knife client#{Spiceweasel::Config[:knife_options]} delete #{server} -y")
98
82
  end
99
83
  end
100
- elsif name.start_with?("windows") #windows node bootstrap support
101
- nodeline = name.split()
102
- provider = nodeline.shift.split('_') #split on 'windows_ssh' etc
103
- nodeline.each do |server|
104
- servercommand = "knife bootstrap #{provider[0]} #{provider[1]}#{Spiceweasel::Config[:knife_options]} #{server} #{options}"
105
- servercommand += " -r '#{run_list}'" unless run_list.empty?
106
- create_command(servercommand, create_command_options)
107
- delete_command("knife node#{Spiceweasel::Config[:knife_options]} delete #{server} -y")
108
- delete_command("knife client#{Spiceweasel::Config[:knife_options]} delete #{server} -y")
109
- end
110
- else #node bootstrap support
111
- name.split.each_with_index do |server, i|
112
- servercommand = "knife bootstrap#{Spiceweasel::Config[:knife_options]} #{server} #{options}".gsub(/\{\{n\}\}/, (i + 1).to_s)
113
- servercommand += " -r '#{run_list}'" unless run_list.empty?
114
- create_command(servercommand, create_command_options)
115
- delete_command("knife node#{Spiceweasel::Config[:knife_options]} delete #{server} -y")
116
- delete_command("knife client#{Spiceweasel::Config[:knife_options]} delete #{server} -y")
117
- end
118
- end
119
- unless additional_commands.empty?
120
- additional_commands.each do |cmd|
121
- create_command(cmd, create_command_options)
84
+ unless additional_commands.empty?
85
+ additional_commands.each do |cmd|
86
+ create_command(cmd, create_command_options)
87
+ end
122
88
  end
123
89
  end
124
90
  end
125
- end
126
- if Spiceweasel::Config[:bulkdelete]
127
- delete_command("knife node#{Spiceweasel::Config[:knife_options]} bulk delete .* -y")
91
+ if Spiceweasel::Config[:bulkdelete]
92
+ delete_command("knife node#{Spiceweasel::Config[:knife_options]} bulk delete .* -y")
93
+ end
94
+ #remove repeats in chefclient and push into create_command
95
+ chefclient.flatten.each_with_index {|x,i| create_command(x, create_command_options) unless x.eql?(chefclient[i-1])}
128
96
  end
129
97
  end
130
98
 
131
99
  #ensure run_list contents are listed previously.
132
- def validateRunList(node, run_list, cookbooks, roles)
100
+ def validate_run_list(node, run_list, cookbooks, roles)
133
101
  run_list.split(',').each do |item|
134
102
  if item.start_with?("recipe[")
135
103
  #recipe[foo] or recipe[foo::bar]
@@ -153,7 +121,7 @@ module Spiceweasel
153
121
  end
154
122
 
155
123
  #for now, just check that -E is legit
156
- def validateOptions(node, options, environments)
124
+ def validate_options(node, options, environments)
157
125
  if options =~ /-E/ #check for environments
158
126
  env = options.split('-E')[1].split()[0]
159
127
  unless environments.member?(env)
@@ -163,5 +131,223 @@ module Spiceweasel
163
131
  end
164
132
  end
165
133
 
134
+ #manage all the provider logic
135
+ def process_providers(provider, count, name, options, run_list, create_command_options, knifecommands)
136
+ validate_provider(provider, knifecommands) unless Spiceweasel::Config[:novalidation]
137
+ provided_names = []
138
+ if Spiceweasel::Config[:parallel]
139
+ parallel = "seq #{count} | parallel -u -j 0 -v \""
140
+ if ['vsphere'].member?(provider)
141
+ parallel += "knife #{provider}#{Spiceweasel::Config[:knife_options]} vm clone #{options}".gsub(/\{\{n\}\}/, '{}')
142
+ elsif ['kvm'].member?(provider)
143
+ parallel += "knife #{provider}#{Spiceweasel::Config[:knife_options]} vm create #{options}".gsub(/\{\{n\}\}/, '{}')
144
+ else
145
+ parallel += "knife #{provider}#{Spiceweasel::Config[:knife_options]} server create #{options}".gsub(/\{\{n\}\}/, '{}')
146
+ end
147
+ parallel += " -r '#{run_list}'" unless run_list.empty?
148
+ parallel += "\""
149
+ create_command(parallel, create_command_options)
150
+ else
151
+ count.to_i.times do |i|
152
+ if ['vsphere'].member?(provider)
153
+ server = "knife #{provider}#{Spiceweasel::Config[:knife_options]} vm clone #{options}".gsub(/\{\{n\}\}/, (i + 1).to_s)
154
+ elsif ['kvm'].member?(provider)
155
+ server = "knife #{provider}#{Spiceweasel::Config[:knife_options]} vm create #{options}".gsub(/\{\{n\}\}/, (i + 1).to_s)
156
+ else
157
+ server = "knife #{provider}#{Spiceweasel::Config[:knife_options]} server create #{options}".gsub(/\{\{n\}\}/, (i + 1).to_s)
158
+ end
159
+ server += " -r '#{run_list}'" unless run_list.empty?
160
+ provided_names << name.gsub('{{n}}', (i + 1).to_s) if name
161
+ create_command(server, create_command_options)
162
+ end
163
+ end
164
+ if Spiceweasel::Config[:bulkdelete] && provided_names.empty? && provider != 'windows'
165
+ if ['kvm','vsphere'].member?(provider)
166
+ delete_command("knife node#{Spiceweasel::Config[:knife_options]} list | xargs knife #{provider} vm delete -y")
167
+ else
168
+ delete_command("knife node#{Spiceweasel::Config[:knife_options]} list | xargs knife #{provider} server delete -y")
169
+ end
170
+ else
171
+ provided_names.each do |p_name|
172
+ if ['kvm','vsphere'].member?(provider)
173
+ delete_command("knife #{provider} vm delete -y #{p_name}")
174
+ else
175
+ delete_command("knife #{provider} server delete -y #{p_name}")
176
+ end
177
+ delete_command("knife node#{Spiceweasel::Config[:knife_options]} delete #{p_name} -y")
178
+ delete_command("knife client#{Spiceweasel::Config[:knife_options]} delete #{p_name} -y")
179
+ end
180
+ end
181
+ end
182
+
183
+ #check that the knife plugin is installed
184
+ def validate_provider(provider, knifecommands)
185
+ unless knifecommands.index {|x| x.start_with?("knife #{provider}")}
186
+ STDERR.puts "ERROR: 'knife #{provider}' is not a currently installed plugin for knife."
187
+ exit(-1)
188
+ end
189
+ end
190
+
191
+ def process_chef_client(names, options, run_list)
192
+ commands = []
193
+ environment = nil
194
+ protocol = 'ssh'
195
+ protooptions = ''
196
+ #protocol options
197
+ sudo = nil
198
+ value = nil #store last option for space-separated values
199
+ options.split().each do |opt|
200
+ sudo = 'sudo ' if opt =~ /^--sudo$/
201
+ protooptions += '--no-host-key-verify ' if opt =~ /^--no-host-key-verify$/
202
+ # SSH identity file used for authentication
203
+ if value =~ /^-i$|^--identity-file$/
204
+ protooptions += "-i #{opt} "
205
+ value = nil
206
+ end
207
+ if opt =~ /^-i|^--identity-file/
208
+ if opt =~ /^-i$|^--identity-file$/
209
+ value = '-i'
210
+ else
211
+ opt.sub!(/-i/,'') if opt =~ /^-i/
212
+ opt.sub!(/--identity-file/,'') if opt =~ /^--identity-file/
213
+ protooptions += "-i #{opt} "
214
+ value = nil
215
+ end
216
+ end
217
+ # ssh gateway
218
+ if value =~ /^-G$|^--ssh-gateway$/
219
+ protooptions += "-G #{opt} "
220
+ value = nil
221
+ end
222
+ if opt =~ /^-G|^--ssh-gateway/
223
+ if opt =~ /^-G$|^--ssh-gateway$/
224
+ value = '-G'
225
+ else
226
+ opt.sub!(/-G/,'') if opt =~ /^-G/
227
+ opt.sub!(/--ssh-gateway/,'') if opt =~ /^--ssh-gateway/
228
+ protooptions += "-G #{opt} "
229
+ value = nil
230
+ end
231
+ end
232
+ # ssh password
233
+ if value =~ /^-P$|^--ssh-password$/
234
+ protooptions += "-P #{opt} "
235
+ value = nil
236
+ end
237
+ if opt =~ /^-P|^--ssh-password/
238
+ if opt =~ /^-P$|^--ssh-password$/
239
+ value = '-P'
240
+ else
241
+ opt.sub!(/-P/,'') if opt =~ /^-P/
242
+ opt.sub!(/--ssh-password/,'') if opt =~ /^--ssh-password/
243
+ protooptions += "-P #{opt} "
244
+ value = nil
245
+ end
246
+ end
247
+ # ssh port
248
+ if value =~ /^-p$|^--ssh-port$/
249
+ protooptions += "-p #{opt} "
250
+ value = nil
251
+ end
252
+ if opt =~ /^-p|^--ssh-port/
253
+ if opt =~ /^-p$|^--ssh-port$/
254
+ value = '-p'
255
+ else
256
+ opt.sub!(/-p/,'') if opt =~ /^-p/
257
+ opt.sub!(/--ssh-port/,'') if opt =~ /^--ssh-port/
258
+ protooptions += "-p #{opt} "
259
+ value = nil
260
+ end
261
+ end
262
+ # ssh username
263
+ if value =~ /^-x$|^--ssh-user$/
264
+ protooptions += "-x #{opt} "
265
+ sudo = 'sudo ' unless opt.eql?('root')
266
+ value = nil
267
+ end
268
+ if opt =~ /^-x|^--ssh-user/
269
+ if opt =~ /^-x$|^--ssh-user$/
270
+ value = '-x'
271
+ else
272
+ opt.sub!(/-x/,'') if opt =~ /^-x/
273
+ opt.sub!(/--ssh-user/,'') if opt =~ /^--ssh-user/
274
+ protooptions += "-x #{opt} "
275
+ sudo = 'sudo ' unless opt.eql?('root')
276
+ value = nil
277
+ end
278
+ end
279
+ # environment
280
+ if value =~ /^-E$|^--environment$/
281
+ environment = opt
282
+ value = nil
283
+ end
284
+ if opt =~ /^-E|^--environment/
285
+ if opt =~ /^-E$|^--environment$/
286
+ value = '-E'
287
+ else
288
+ opt.sub!(/-E/,'') if opt =~ /^-E/
289
+ opt.sub!(/--environment/,'') if opt =~ /^--environment/
290
+ environment = opt
291
+ value = nil
292
+ end
293
+ end
294
+ # nodename
295
+ if value =~ /^-N$|^--node-name$/
296
+ names = [opt.gsub(/{{n}}/, '*')]
297
+ value = nil
298
+ end
299
+ if opt =~ /^-N|^--node-name/
300
+ if opt =~ /^-N$|^--node-name$/
301
+ value = '-N'
302
+ else
303
+ opt.sub!(/-N/,'') if opt =~ /^-N/
304
+ opt.sub!(/--node-name/,'') if opt =~ /^--node-name/
305
+ names = [opt.gsub(/{{n}}/, '*')]
306
+ value = nil
307
+ end
308
+ end
309
+ end
310
+ if names[0].start_with?("windows_")
311
+ #windows node bootstrap support
312
+ protocol = names.shift.split('_')[1] #split on 'windows_ssh' etc
313
+ sudo = nil #no sudo for Windows even if ssh is used
314
+ end
315
+ names = [] if PROVIDERS.member?(names[0])
316
+ # check options for -N, override name
317
+ protooptions += "-a #{Spiceweasel::Config[:attribute]}" if Spiceweasel::Config[:attribute]
318
+ if names.empty?
319
+ search = chef_client_search(nil, run_list, environment)
320
+ commands.push("knife #{protocol} '#{search}' '#{sudo}chef-client' #{protooptions} #{Spiceweasel::Config[:knife_options]}")
321
+ else
322
+ names.each do |name|
323
+ search = chef_client_search(name, run_list, environment)
324
+ commands.push("knife #{protocol} '#{search}' '#{sudo}chef-client' #{protooptions} #{Spiceweasel::Config[:knife_options]}")
325
+ end
326
+ end
327
+ return commands
328
+ end
329
+
330
+ #create the knife ssh chef-client search pattern
331
+ def chef_client_search(name, run_list, environment)
332
+ search = []
333
+ search.push("name:#{name}") if name
334
+ search.push("chef_environment:#{environment}") if environment
335
+ run_list.split(',').each do |item|
336
+ item.sub!(/\[/, ':')
337
+ item.chop!
338
+ item.sub!(/::/, '\:\:')
339
+ search.push(item)
340
+ end
341
+ return "#{search.join(" and ")}"
342
+ end
343
+
344
+ #standardize the node run_list formatting
345
+ def process_run_list(run_list)
346
+ return '' if run_list.nil?
347
+ run_list.gsub!(/ /,',')
348
+ run_list.gsub!(/,+/,',')
349
+ return run_list
350
+ end
351
+
166
352
  end
167
353
  end
@@ -16,7 +16,7 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
- require 'json'
19
+ require 'yajl/json_gem'
20
20
  require 'chef'
21
21
 
22
22
  module Spiceweasel
@@ -75,7 +75,7 @@ module Spiceweasel
75
75
  when /\.json$/
76
76
  c_role = Chef::JSONCompat.from_json(IO.read(file))
77
77
  when /\.rb$/
78
- if(Chef::Version.new(Chef::VERSION) < Chef::Version.new('11.0.0'))
78
+ if (Chef::VERSION.split('.')[0].to_i < 11)
79
79
  c_role = Chef::Role.new(true)
80
80
  else
81
81
  c_role = Chef::Role.new
@@ -17,5 +17,5 @@
17
17
  #
18
18
 
19
19
  module Spiceweasel
20
- VERSION = '2.4.0'
20
+ VERSION = '2.5.0'
21
21
  end
@@ -0,0 +1,72 @@
1
+ describe 'testing 2.5 --chef-client' do
2
+ before(:each) do
3
+ @expected_output = <<-OUTPUT
4
+ knife ssh 'name:serverA and role:base' 'sudo chef-client' -i ~/.ssh/mray.pem -x user --no-host-key-verify -p 22
5
+ knife ssh 'name:serverB and chef_environment:development and role:base' 'sudo chef-client' -i ~/.ssh/mray.pem -x user
6
+ knife ssh 'name:serverC and chef_environment:development and role:base' 'sudo chef-client' -i ~/.ssh/mray.pem -x user
7
+ knife ssh 'name:db* and chef_environment:qa and recipe:mysql and role:monitoring' 'chef-client'
8
+ knife winrm 'name:winboxA and role:base and role:iisserver' 'chef-client' -x Administrator -P 'super_secret_password'
9
+ knife ssh 'name:winboxB and role:base and role:iisserver' 'chef-client' -x Administrator -P 'super_secret_password'
10
+ knife ssh 'name:winboxC and role:base and role:iisserver' 'chef-client' -x Administrator -P 'super_secret_password'
11
+ knife ssh 'chef_environment:amazon and role:mysql' 'sudo chef-client' -i ~/.ssh/mray.pem -x ubuntu -G default
12
+ knife ssh 'chef_environment:amazon and role:webserver and recipe:mysql\\:\\:client' 'sudo chef-client' -i ~/.ssh/mray.pem -x ubuntu -G default
13
+ OUTPUT
14
+
15
+ @spiceweasel_binary = File.join(File.dirname(__FILE__), *%w[.. .. bin spiceweasel])
16
+ end
17
+
18
+ it "test chef-client in 2.5, yml" do
19
+ `#{@spiceweasel_binary} --novalidation --chef-client examples/example.yml`.should == @expected_output
20
+ end
21
+
22
+ it "test chef-client in 2.5, json" do
23
+ `#{@spiceweasel_binary} --novalidation --chef-client examples/example.json`.should == @expected_output
24
+ end
25
+
26
+ it "test chef-client in 2.5, rb" do
27
+ `#{@spiceweasel_binary} --novalidation --chef-client examples/example.rb`.should == @expected_output
28
+ end
29
+ end
30
+
31
+ describe 'testing 2.5 --chef-client with --cluster-file' do
32
+ before(:each) do
33
+ @expected_output = <<-OUTPUT
34
+ knife ssh 'name:serverB and chef_environment:qa and role:base and role:webserver' 'sudo chef-client' -i ~/.ssh/mray.pem -x user
35
+ knife ssh 'name:serverC and chef_environment:qa and role:base and role:webserver' 'sudo chef-client' -i ~/.ssh/mray.pem -x user
36
+ knife winrm 'name:winboxA and chef_environment:qa and role:base and role:iisserver' 'chef-client' -x Administrator -P 'super_secret_password'
37
+ knife ssh 'name:winboxB and chef_environment:qa and role:base and role:iisserver' 'chef-client' -x Administrator -P 'super_secret_password'
38
+ knife ssh 'name:winboxC and chef_environment:qa and role:base and role:iisserver' 'chef-client' -x Administrator -P 'super_secret_password'
39
+ knife ssh 'chef_environment:qa and role:webserver and recipe:mysql\\:\\:client' 'sudo chef-client' -x ubuntu -P ubuntu
40
+ OUTPUT
41
+
42
+ @spiceweasel_binary = File.join(File.dirname(__FILE__), *%w[.. .. bin spiceweasel])
43
+ end
44
+
45
+ it "test chef-client with --cluster-file in 2.5, yml" do
46
+ `#{@spiceweasel_binary} --novalidation --chef-client --cluster-file examples/cluster-file-example.yml examples/example.yml`.should == @expected_output
47
+ end
48
+
49
+ it "test chef-client with --cluster-file in 2.5, json" do
50
+ `#{@spiceweasel_binary} --novalidation --chef-client --cluster-file examples/cluster-file-example.yml examples/example.json`.should == @expected_output
51
+ end
52
+
53
+ it "test chef-client with --cluster-file in 2.5, rb" do
54
+ `#{@spiceweasel_binary} --novalidation --chef-client --cluster-file examples/cluster-file-example.yml examples/example.rb`.should == @expected_output
55
+ end
56
+ end
57
+
58
+ describe 'testing 2.5 --chef-client with -a' do
59
+ before(:each) do
60
+ @expected_output = <<-OUTPUT
61
+ knife ssh 'chef_environment:mycluster and role:mysql' 'sudo chef-client' -i ~/.ssh/mray.pem -x ubuntu -a ec2.public_hostname
62
+ knife ssh 'chef_environment:mycluster and role:webserver and recipe:mysql\\:\\:client' 'sudo chef-client' -i ~/.ssh/mray.pem -x ubuntu -a ec2.public_hostname
63
+ OUTPUT
64
+
65
+ @spiceweasel_binary = File.join(File.dirname(__FILE__), *%w[.. .. bin spiceweasel])
66
+ end
67
+
68
+ it "test chef-client with -a ec2.public_hostname in 2.5" do
69
+ `#{@spiceweasel_binary} --novalidation --chef-client -a ec2.public_hostname examples/example-cluster.yml`.should == @expected_output
70
+ end
71
+
72
+ end
@@ -11,8 +11,8 @@ knife node bulk delete .* -y
11
11
  knife cookbook upload apache2
12
12
  knife environment from file qa.rb
13
13
  knife role from file base.rb
14
- seq 2 | parallel -j 0 -v "knife joyent server create -i ~/.ssh/joyent.pem -E qa -r 'role[base]'"
15
- seq 2 | parallel -j 0 -v "knife vsphere vm clone -P secret_password -x Administrator --template some_template -r 'role[base]'"
14
+ seq 2 | parallel -u -j 0 -v "knife joyent server create -i ~/.ssh/joyent.pem -E qa -r 'role[base]'"
15
+ seq 2 | parallel -u -j 0 -v "knife vsphere vm clone -P secret_password -x Administrator --template some_template -r 'role[base]'"
16
16
  OUTPUT
17
17
 
18
18
  @spiceweasel_binary = File.join(File.dirname(__FILE__), *%w[.. .. bin spiceweasel])
@@ -0,0 +1,28 @@
1
+ describe 'testing 2.5 kvm' do
2
+ before(:each) do
3
+ @expected_output = <<-OUTPUT
4
+ knife cookbook delete apache2 -a -y
5
+ knife environment delete qa -y
6
+ knife role delete base -y
7
+ knife node delete winboxA -y
8
+ knife client delete winboxA -y
9
+ knife node delete winboxB -y
10
+ knife client delete winboxB -y
11
+ knife cookbook upload apache2
12
+ knife environment from file qa.rb
13
+ knife role from file base.rb
14
+ seq 2 | parallel -u -j 0 -v "knife kvm vm create -E qa --template-file ~/.chef/bootstrap/ubuntu11.10-gems.erb --vm-disk /path-to/ubuntu1110-x64.qcow2 --vm-name knife-kvm-test-ubuntu --ssh-user ubuntu --ssh-password ubuntu --pool default --kvm-host my-test-host --kvm-user root --kvm-password secret -r 'role[base]'"
15
+ knife bootstrap windows winrm winboxA -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
16
+ knife bootstrap windows winrm winboxB -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
17
+ seq 1 | parallel -u -j 0 -v "knife kvm vm create -E production --template-file ~/.chef/bootstrap/ubuntu11.10-gems.erb --vm-disk /path-to/ubuntu1110-x64.qcow2 --vm-name knife-kvm-test-ubuntu --ssh-user ubuntu --ssh-password ubuntu --pool default --kvm-host my-test-host --kvm-user root --kvm-password secret -E qa -r 'role[mysql]'"
18
+ seq 3 | parallel -u -j 0 -v "knife kvm vm create --template-file ~/.chef/bootstrap/ubuntu11.10-gems.erb --vm-disk /path-to/ubuntu1110-x64.qcow2 --vm-name knife-kvm-test-ubuntu --ssh-user ubuntu --ssh-password ubuntu --pool default --kvm-host my-test-host --kvm-user root --kvm-password secret -E qa -r 'role[webserver],recipe[mysql::client]'"
19
+ OUTPUT
20
+
21
+ @spiceweasel_binary = File.join(File.dirname(__FILE__), *%w[.. .. bin spiceweasel])
22
+ end
23
+
24
+ it "test kvm, cluster functionality from 2.5" do
25
+ `#{@spiceweasel_binary} --parallel -r --novalidation examples/kvm-example.yml`.should == @expected_output
26
+ end
27
+
28
+ end
@@ -38,12 +38,12 @@ knife data bag from file users alice.json bob.json chuck.json
38
38
  knife data bag create data
39
39
  knife data bag create passwords
40
40
  knife data bag from file passwords mysql.json rabbitmq.json --secret-file secret_key
41
- knife bootstrap serverA -i ~/.ssh/mray.pem -x user --sudo -r 'role[base]'
42
- knife bootstrap serverB -i ~/.ssh/mray.pem -x user --sudo -E production -r 'role[base]'
43
- knife bootstrap serverC -i ~/.ssh/mray.pem -x user --sudo -E production -r 'role[base]'
44
- knife rackspace server create --image 49 --flavor 2 -N db1 -r 'recipe[mysql],role[monitoring]'
45
- knife rackspace server create --image 49 --flavor 2 -N db2 -r 'recipe[mysql],role[monitoring]'
46
- knife rackspace server create --image 49 --flavor 2 -N db3 -r 'recipe[mysql],role[monitoring]'
41
+ knife bootstrap serverA --identity-file ~/.ssh/mray.pem --ssh-user user --sudo --no-host-key-verify --ssh-port 22 -r 'role[base]'
42
+ knife bootstrap serverB -E development -i ~/.ssh/mray.pem -x user --sudo -r 'role[base]'
43
+ knife bootstrap serverC -E development -i ~/.ssh/mray.pem -x user --sudo -r 'role[base]'
44
+ knife rackspace server create --image 49 -E qa --flavor 2 -N db1 -r 'recipe[mysql],role[monitoring]'
45
+ knife rackspace server create --image 49 -E qa --flavor 2 -N db2 -r 'recipe[mysql],role[monitoring]'
46
+ knife rackspace server create --image 49 -E qa --flavor 2 -N db3 -r 'recipe[mysql],role[monitoring]'
47
47
  knife bootstrap windows winrm winboxA -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
48
48
  knife bootstrap windows ssh winboxB -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
49
49
  knife bootstrap windows ssh winboxC -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
metadata CHANGED
@@ -1,158 +1,153 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spiceweasel
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
5
- prerelease:
4
+ version: 2.5.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Matt Ray
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-06-15 00:00:00.000000000 Z
11
+ date: 2013-07-24 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
- name: json
14
+ name: yajl-ruby
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: mixlib-cli
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: mixlib-config
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: mixlib-log
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - '>='
68
60
  - !ruby/object:Gem::Version
69
61
  version: '0'
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - '>='
76
67
  - !ruby/object:Gem::Version
77
68
  version: '0'
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: mixlib-shellout
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - '>='
84
74
  - !ruby/object:Gem::Version
85
75
  version: '0'
86
76
  type: :runtime
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - '>='
92
81
  - !ruby/object:Gem::Version
93
82
  version: '0'
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: chef
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
- - - ! '>='
87
+ - - '>='
100
88
  - !ruby/object:Gem::Version
101
89
  version: '0.10'
102
90
  type: :runtime
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
- - - ! '>='
94
+ - - '>='
108
95
  - !ruby/object:Gem::Version
109
96
  version: '0.10'
110
97
  - !ruby/object:Gem::Dependency
111
98
  name: berkshelf
112
99
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
100
  requirements:
115
101
  - - <
116
102
  - !ruby/object:Gem::Version
117
- version: '2'
103
+ version: '3'
118
104
  type: :runtime
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
107
  requirements:
123
108
  - - <
124
109
  - !ruby/object:Gem::Version
125
- version: '2'
110
+ version: '3'
126
111
  - !ruby/object:Gem::Dependency
127
112
  name: solve
128
113
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
114
  requirements:
131
- - - ! '>='
115
+ - - '>='
132
116
  - !ruby/object:Gem::Version
133
117
  version: '0'
134
118
  type: :runtime
135
119
  prerelease: false
136
120
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
121
  requirements:
139
- - - ! '>='
122
+ - - '>='
140
123
  - !ruby/object:Gem::Version
141
124
  version: '0'
142
125
  - !ruby/object:Gem::Dependency
143
126
  name: rspec
144
127
  requirement: !ruby/object:Gem::Requirement
145
- none: false
146
128
  requirements:
147
- - - ! '>='
129
+ - - '>='
148
130
  - !ruby/object:Gem::Version
149
131
  version: '0'
150
132
  type: :development
151
133
  prerelease: false
152
134
  version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
135
  requirements:
155
- - - ! '>='
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rake
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
156
151
  - !ruby/object:Gem::Version
157
152
  version: '0'
158
153
  description: Provides a CLI tool for generating knife commands to build Chef-managed
@@ -184,35 +179,38 @@ files:
184
179
  - lib/spiceweasel/roles.rb
185
180
  - lib/spiceweasel/version.rb
186
181
  - lib/spiceweasel.rb
182
+ - spec/bin/chef_client_spec.rb
187
183
  - spec/bin/joyent-vsphere_spec.rb
188
184
  - spec/bin/knife_spec.rb
185
+ - spec/bin/kvm_spec.rb
189
186
  - spec/bin/spiceweasel_spec.rb
190
187
  homepage: https://github.com/mattray/spiceweasel
191
188
  licenses:
192
189
  - Apache
190
+ metadata: {}
193
191
  post_install_message:
194
192
  rdoc_options: []
195
193
  require_paths:
196
194
  - lib
197
195
  required_ruby_version: !ruby/object:Gem::Requirement
198
- none: false
199
196
  requirements:
200
- - - ! '>='
197
+ - - '>='
201
198
  - !ruby/object:Gem::Version
202
199
  version: '1.9'
203
200
  required_rubygems_version: !ruby/object:Gem::Requirement
204
- none: false
205
201
  requirements:
206
- - - ! '>='
202
+ - - '>='
207
203
  - !ruby/object:Gem::Version
208
204
  version: '0'
209
205
  requirements: []
210
206
  rubyforge_project:
211
- rubygems_version: 1.8.25
207
+ rubygems_version: 2.0.3
212
208
  signing_key:
213
- specification_version: 3
209
+ specification_version: 4
214
210
  summary: CLI for generating Chef knife commands from a simple JSON or YAML file.
215
211
  test_files:
212
+ - spec/bin/chef_client_spec.rb
216
213
  - spec/bin/joyent-vsphere_spec.rb
217
214
  - spec/bin/knife_spec.rb
215
+ - spec/bin/kvm_spec.rb
218
216
  - spec/bin/spiceweasel_spec.rb