spiceweasel 2.4.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +39 -2
- data/lib/spiceweasel/berksfile.rb +6 -2
- data/lib/spiceweasel/cli.rb +43 -8
- data/lib/spiceweasel/clusters.rb +31 -25
- data/lib/spiceweasel/data_bags.rb +1 -1
- data/lib/spiceweasel/environments.rb +2 -2
- data/lib/spiceweasel/execute.rb +3 -2
- data/lib/spiceweasel/knife.rb +1 -6
- data/lib/spiceweasel/nodes.rb +263 -77
- data/lib/spiceweasel/roles.rb +2 -2
- data/lib/spiceweasel/version.rb +1 -1
- data/spec/bin/chef_client_spec.rb +72 -0
- data/spec/bin/joyent-vsphere_spec.rb +2 -2
- data/spec/bin/kvm_spec.rb +28 -0
- data/spec/bin/spiceweasel_spec.rb +6 -6
- metadata +44 -46
checksums.yaml
ADDED
@@ -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
|
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
|
-
|
52
|
-
|
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
|
data/lib/spiceweasel/cli.rb
CHANGED
@@ -17,7 +17,7 @@
|
|
17
17
|
#
|
18
18
|
|
19
19
|
require 'mixlib/cli'
|
20
|
-
require '
|
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
|
-
|
186
|
+
case
|
187
|
+
when Spiceweasel::Config[:extractjson]
|
171
188
|
puts JSON.pretty_generate(manifest)
|
172
|
-
|
189
|
+
when Spiceweasel::Config[:extractyaml]
|
173
190
|
puts manifest.to_yaml
|
174
|
-
|
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
|
-
|
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
|
-
|
293
|
-
|
294
|
-
|
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
|
data/lib/spiceweasel/clusters.rb
CHANGED
@@ -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
|
-
|
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 '
|
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::
|
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
|
data/lib/spiceweasel/execute.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/spiceweasel/knife.rb
CHANGED
@@ -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|
|
data/lib/spiceweasel/nodes.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
if
|
58
|
-
count =
|
59
|
-
|
60
|
-
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
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
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
delete_command("knife
|
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
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
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
|
-
|
126
|
-
|
127
|
-
|
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
|
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
|
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
|
data/lib/spiceweasel/roles.rb
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require '
|
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::
|
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
|
data/lib/spiceweasel/version.rb
CHANGED
@@ -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 -
|
42
|
-
knife bootstrap serverB -i ~/.ssh/mray.pem -x user --sudo -
|
43
|
-
knife bootstrap serverC -i ~/.ssh/mray.pem -x user --sudo -
|
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.
|
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-
|
11
|
+
date: 2013-07-24 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
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: '
|
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: '
|
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:
|
207
|
+
rubygems_version: 2.0.3
|
212
208
|
signing_key:
|
213
|
-
specification_version:
|
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
|