spiceweasel 1.2.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +201 -0
- data/README.md +141 -241
- data/bin/spiceweasel +2 -104
- data/lib/spiceweasel.rb +5 -11
- data/lib/spiceweasel/cli.rb +249 -83
- data/lib/spiceweasel/clusters.rb +53 -0
- data/lib/spiceweasel/config.rb +46 -0
- data/lib/spiceweasel/cookbooks.rb +105 -0
- data/lib/spiceweasel/data_bags.rb +89 -0
- data/lib/spiceweasel/environments.rb +103 -0
- data/lib/spiceweasel/execute.rb +42 -0
- data/lib/spiceweasel/extract_local.rb +130 -0
- data/lib/spiceweasel/log.rb +30 -0
- data/lib/spiceweasel/nodes.rb +126 -0
- data/lib/spiceweasel/roles.rb +131 -0
- data/lib/spiceweasel/version.rb +1 -1
- data/spec/bin/spiceweasel_spec.rb +44 -12
- metadata +106 -25
- data/lib/spiceweasel/cookbook_data.rb +0 -66
- data/lib/spiceweasel/cookbook_list.rb +0 -96
- data/lib/spiceweasel/data_bag_list.rb +0 -81
- data/lib/spiceweasel/directory_extractor.rb +0 -121
- data/lib/spiceweasel/environment_list.rb +0 -96
- data/lib/spiceweasel/node_list.rb +0 -98
- data/lib/spiceweasel/role_list.rb +0 -124
@@ -0,0 +1,30 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Matt Ray (<matt@opscode.com>)
|
3
|
+
#
|
4
|
+
# Copyright:: 2012, Opscode, Inc <legal@opscode.com>
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'mixlib/log'
|
20
|
+
|
21
|
+
module Spiceweasel
|
22
|
+
class Log
|
23
|
+
extend Mixlib::Log
|
24
|
+
|
25
|
+
#not quite ready for timestamps
|
26
|
+
Mixlib::Log::Formatter.show_time = false
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,126 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Matt Ray (<matt@opscode.com>)
|
3
|
+
#
|
4
|
+
# Copyright:: 2011-2012, Opscode, Inc <legal@opscode.com>
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module Spiceweasel
|
20
|
+
class Nodes
|
21
|
+
|
22
|
+
PROVIDERS = %w{bluebox clodo cs ec2 gandi hp lxc openstack rackspace slicehost terremark voxel}
|
23
|
+
|
24
|
+
attr_reader :create, :delete
|
25
|
+
|
26
|
+
def initialize(nodes, cookbooks, environments, roles)
|
27
|
+
@create = Array.new
|
28
|
+
@delete = Array.new
|
29
|
+
if nodes
|
30
|
+
Spiceweasel::Log.debug("nodes: #{nodes}")
|
31
|
+
nodes.each do |node|
|
32
|
+
name = node.keys.first
|
33
|
+
Spiceweasel::Log.debug("node: '#{name}' '#{node[name]}'")
|
34
|
+
if node[name]
|
35
|
+
#convert spaces to commas, drop multiple commas
|
36
|
+
run_list = node[name]['run_list'] || ''
|
37
|
+
run_list = run_list.gsub(/ /,',').gsub(/,+/,',')
|
38
|
+
Spiceweasel::Log.debug("node: '#{name}' run_list: '#{run_list}'")
|
39
|
+
validateRunList(name, run_list, cookbooks, roles) unless Spiceweasel::Config[:novalidation]
|
40
|
+
options = node[name]['options'] || ''
|
41
|
+
Spiceweasel::Log.debug("node: '#{name}' options: '#{options}'")
|
42
|
+
validateOptions(name, options, environments) unless Spiceweasel::Config[:novalidation]
|
43
|
+
end
|
44
|
+
#provider support
|
45
|
+
provider = name.split()
|
46
|
+
if PROVIDERS.member?(provider[0])
|
47
|
+
count = 1
|
48
|
+
if provider.length == 2
|
49
|
+
count = provider[1]
|
50
|
+
end
|
51
|
+
if Spiceweasel::Config[:parallel]
|
52
|
+
parallel = "seq #{count} | parallel -j 0 -v \""
|
53
|
+
parallel += "knife #{provider[0]}#{Spiceweasel::Config[:knife_options]} server create #{options}".gsub(/\{\{n\}\}/, '{}')
|
54
|
+
parallel += " -r '#{run_list}'" unless run_list.empty?
|
55
|
+
parallel += "\""
|
56
|
+
@create.push(parallel)
|
57
|
+
else
|
58
|
+
count.to_i.times do |i|
|
59
|
+
server = "knife #{provider[0]}#{Spiceweasel::Config[:knife_options]} server create #{options}".gsub(/\{\{n\}\}/, (i + 1).to_s)
|
60
|
+
server += " -r '#{run_list}'" unless run_list.empty?
|
61
|
+
@create.push(server)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
@delete.push("knife node#{Spiceweasel::Config[:knife_options]} list | xargs knife #{provider[0]} server delete -y")
|
65
|
+
elsif name.start_with?("windows") #windows node bootstrap support
|
66
|
+
nodeline = name.split()
|
67
|
+
provider = nodeline.shift.split('_') #split on 'windows_ssh' etc
|
68
|
+
nodeline.each do |server|
|
69
|
+
server = "knife bootstrap #{provider[0]} #{provider[1]}#{Spiceweasel::Config[:knife_options]} #{server} #{options}"
|
70
|
+
server += " -r '#{run_list}'" unless run_list.empty?
|
71
|
+
@create.push(server)
|
72
|
+
@delete.push("knife node#{Spiceweasel::Config[:knife_options]} delete #{server} -y")
|
73
|
+
@delete.push("knife client#{Spiceweasel::Config[:knife_options]} delete #{server} -y")
|
74
|
+
end
|
75
|
+
@delete.push("knife node#{Spiceweasel::Config[:knife_options]} list | xargs knife #{provider[0]} server delete -y")
|
76
|
+
else #node bootstrap support
|
77
|
+
name.split.each_with_index do |server, i|
|
78
|
+
server = "knife bootstrap#{Spiceweasel::Config[:knife_options]} #{server} #{options}".gsub(/\{\{n\}\}/, (i + 1).to_s)
|
79
|
+
server += " -r '#{run_list}'" unless run_list.empty?
|
80
|
+
@create.push(server)
|
81
|
+
@delete.push("knife node#{Spiceweasel::Config[:knife_options]} delete #{server} -y")
|
82
|
+
@delete.push("knife client#{Spiceweasel::Config[:knife_options]} delete #{server} -y")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
@delete.push("knife node#{Spiceweasel::Config[:knife_options]} bulk delete .* -y")
|
88
|
+
end
|
89
|
+
|
90
|
+
#ensure run_list contents are listed previously.
|
91
|
+
def validateRunList(node, run_list, cookbooks, roles)
|
92
|
+
run_list.split(',').each do |item|
|
93
|
+
if item.start_with?("recipe[")
|
94
|
+
#recipe[foo] or recipe[foo::bar]
|
95
|
+
cb = item.split(/\[|\]/)[1].split(':')[0]
|
96
|
+
unless cookbooks.member?(cb)
|
97
|
+
STDERR.puts "ERROR: '#{node}' run list cookbook '#{cb}' is missing from the list of cookbooks in the manifest."
|
98
|
+
exit(-1)
|
99
|
+
end
|
100
|
+
elsif item.start_with?("role[")
|
101
|
+
#role[blah]
|
102
|
+
role = item.split(/\[|\]/)[1]
|
103
|
+
unless roles.member?(role)
|
104
|
+
STDERR.puts "ERROR: '#{node}' run list role '#{role}' is missing from the list of roles in the manifest."
|
105
|
+
exit(-1)
|
106
|
+
end
|
107
|
+
else
|
108
|
+
STDERR.puts "ERROR: '#{node}' run list '#{item}' is an invalid run list entry in the manifest."
|
109
|
+
exit(-1)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
#for now, just check that -E is legit
|
115
|
+
def validateOptions(node, options, environments)
|
116
|
+
if options =~ /-E/ #check for environments
|
117
|
+
env = options.split('-E')[1].split()[0]
|
118
|
+
unless environments.member?(env)
|
119
|
+
STDERR.puts "ERROR: '#{node}' environment '#{env}' is missing from the list of environments in the manifest."
|
120
|
+
exit(-1)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Matt Ray (<matt@opscode.com>)
|
3
|
+
#
|
4
|
+
# Copyright:: 2011-2012, Opscode, Inc <legal@opscode.com>
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'json'
|
20
|
+
|
21
|
+
module Spiceweasel
|
22
|
+
class Roles
|
23
|
+
|
24
|
+
attr_reader :role_list, :create, :delete
|
25
|
+
|
26
|
+
def initialize(roles = {}, environments = [], cookbooks = {})
|
27
|
+
@create = Array.new
|
28
|
+
@delete = Array.new
|
29
|
+
@role_list = Array.new
|
30
|
+
if roles
|
31
|
+
Spiceweasel::Log.debug("roles: #{roles}")
|
32
|
+
flatroles = roles.collect {|x| x.keys}.flatten
|
33
|
+
flatroles.each do |role|
|
34
|
+
Spiceweasel::Log.debug("role: #{role}")
|
35
|
+
if File.directory?("roles")
|
36
|
+
validate(role, environments, cookbooks, flatroles) unless Spiceweasel::Config[:novalidation]
|
37
|
+
elsif !Spiceweasel::Config[:novalidation]
|
38
|
+
STDERR.puts "ERROR: 'roles' directory not found, unable to validate or load roles"
|
39
|
+
exit(-1)
|
40
|
+
end
|
41
|
+
if File.exists?("roles/#{role}.json")
|
42
|
+
@create.push("knife role#{Spiceweasel::Config[:knife_options]} from file #{role}.json")
|
43
|
+
else #assume no .json means they want .rb and catchall for misssing dir
|
44
|
+
@create.push("knife role#{Spiceweasel::Config[:knife_options]} from file #{role}.rb")
|
45
|
+
end
|
46
|
+
@delete.push("knife role#{Spiceweasel::Config[:knife_options]} delete #{role} -y")
|
47
|
+
@role_list.push(role)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
#validate the content of the role file
|
53
|
+
def validate(role, environments, cookbooks, roles)
|
54
|
+
#validate the role passed in match the name of either the .rb or .json
|
55
|
+
if File.exists?("roles/#{role}.rb")
|
56
|
+
#validate that the name inside the file matches
|
57
|
+
name = File.open("roles/#{role}.rb").grep(/^name/)[0].split()[1].gsub(/"/,'').to_s
|
58
|
+
Spiceweasel::Log.debug("role: '#{role}' name: '#{name}'")
|
59
|
+
if !role.eql?(name)
|
60
|
+
STDERR.puts "ERROR: Role '#{role}' listed in the manifest does not match the name '#{name}' within the roles/#{role}.rb file."
|
61
|
+
exit(-1)
|
62
|
+
end
|
63
|
+
#grab any lines with 'recipe[' or 'role['
|
64
|
+
rolerl = File.open("roles/#{role}.rb").grep(/recipe\[|role\[/)
|
65
|
+
rolerl.each do |line|
|
66
|
+
Spiceweasel::Log.debug("role: '#{role}' line: '#{line}'")
|
67
|
+
line.strip.split(',').each do |rl|
|
68
|
+
if rl =~ /recipe\[/ #it's a cookbook
|
69
|
+
#split on the brackets and any colons
|
70
|
+
dep = rl.split(/\[|\]/)[1].split(':')[0]
|
71
|
+
Spiceweasel::Log.debug("role: '#{role}' cookbook: '#{rl}': dep: '#{dep}'")
|
72
|
+
if !cookbooks.member?(dep)
|
73
|
+
STDERR.puts "ERROR: Cookbook dependency '#{dep}' from role '#{role}' is missing from the list of cookbooks in the manifest."
|
74
|
+
exit(-1)
|
75
|
+
end
|
76
|
+
elsif rl =~ /role\[/ #it's a role
|
77
|
+
#split on the brackets
|
78
|
+
dep = rl.split(/\[|\]/)[1]
|
79
|
+
Spiceweasel::Log.debug("role: '#{role}' role: '#{rl}': dep: '#{dep}'")
|
80
|
+
if !roles.member?(dep)
|
81
|
+
STDERR.puts "ERROR: Role dependency '#{dep}' from role '#{role}' is missing from the list of roles in the manifest."
|
82
|
+
exit(-1)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
#TODO validate any environment-specific runlists
|
88
|
+
elsif File.exists?("roles/#{role}.json")
|
89
|
+
#load the json, don't symbolize since we don't need json_class
|
90
|
+
f = File.read("roles/#{role}.json")
|
91
|
+
JSON.create_id = nil
|
92
|
+
rolefile = JSON.parse(f, {:symbolize_names => false})
|
93
|
+
#validate that the name inside the file matches
|
94
|
+
Spiceweasel::Log.debug("role: '#{role}' name: '#{rolefile['name']}'")
|
95
|
+
if !role.eql?(rolefile['name'])
|
96
|
+
STDERR.puts "ERROR: Role '#{role}' listed in the manifest does not match the name '#{rolefile['name']}' within the 'roles/#{role}.json' file."
|
97
|
+
exit(-1)
|
98
|
+
end
|
99
|
+
#validate the cookbooks and roles exist if they're mentioned in run_lists
|
100
|
+
rolefile['run_list'].each do |rl|
|
101
|
+
if rl =~ /recipe\[/ #it's a cookbook
|
102
|
+
#split on the brackets and any colons
|
103
|
+
dep = rl.split(/\[|\]/)[1].split(':')[0]
|
104
|
+
Spiceweasel::Log.debug("role: '#{role}' cookbook: '#{rl}': dep: '#{dep}'")
|
105
|
+
if !cookbooks.member?(dep)
|
106
|
+
STDERR.puts "ERROR: Cookbook dependency '#{dep}' from role '#{role}' is missing from the list of cookbooks in the manifest."
|
107
|
+
exit(-1)
|
108
|
+
end
|
109
|
+
elsif rl =~ /role\[/ #it's a role
|
110
|
+
#split on the brackets
|
111
|
+
dep = rl.split(/\[|\]/)[1]
|
112
|
+
Spiceweasel::Log.debug("role: '#{role}' role: '#{rl}': dep: '#{dep}'")
|
113
|
+
if !roles.member?(dep)
|
114
|
+
STDERR.puts "ERROR: Role dependency '#{dep}' from role '#{role}' is missing from the list of roles in the manifest."
|
115
|
+
exit(-1)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
#TODO validate any environment-specific runlists
|
120
|
+
else #role is not here
|
121
|
+
STDERR.puts "ERROR: Invalid Role '#{role}' listed in the manifest but not found in the roles directory."
|
122
|
+
exit(-1)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def member?(role)
|
127
|
+
role_list.include?(role)
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
data/lib/spiceweasel/version.rb
CHANGED
@@ -2,8 +2,40 @@
|
|
2
2
|
describe 'The Spiceweasel binary' do
|
3
3
|
before(:each) do
|
4
4
|
@expected_output = <<-OUTPUT
|
5
|
+
knife cookbook delete apache2 -a -y
|
6
|
+
knife cookbook delete apt 1.2.0 -a -y
|
7
|
+
knife cookbook delete mysql -a -y
|
8
|
+
knife environment delete development -y
|
9
|
+
knife environment delete qa -y
|
10
|
+
knife environment delete production -y
|
11
|
+
knife role delete base -y
|
12
|
+
knife role delete iisserver -y
|
13
|
+
knife role delete monitoring -y
|
14
|
+
knife role delete webserver -y
|
15
|
+
knife data bag delete users -y
|
16
|
+
knife data bag delete data -y
|
17
|
+
knife data bag delete passwords -y
|
18
|
+
knife node delete knife bootstrap serverA -i ~/.ssh/mray.pem -x user --sudo -r 'role[base]' -y
|
19
|
+
knife client delete knife bootstrap serverA -i ~/.ssh/mray.pem -x user --sudo -r 'role[base]' -y
|
20
|
+
knife node delete knife bootstrap serverB -i ~/.ssh/mray.pem -x user --sudo -E production -r 'role[base]' -y
|
21
|
+
knife client delete knife bootstrap serverB -i ~/.ssh/mray.pem -x user --sudo -E production -r 'role[base]' -y
|
22
|
+
knife node delete knife bootstrap serverC -i ~/.ssh/mray.pem -x user --sudo -E production -r 'role[base]' -y
|
23
|
+
knife client delete knife bootstrap serverC -i ~/.ssh/mray.pem -x user --sudo -E production -r 'role[base]' -y
|
24
|
+
knife node list | xargs knife rackspace server delete -y
|
25
|
+
knife node delete knife bootstrap windows winrm winboxA -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]' -y
|
26
|
+
knife client delete knife bootstrap windows winrm winboxA -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]' -y
|
27
|
+
knife node list | xargs knife windows server delete -y
|
28
|
+
knife node delete knife bootstrap windows ssh winboxB -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]' -y
|
29
|
+
knife client delete knife bootstrap windows ssh winboxB -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]' -y
|
30
|
+
knife node delete knife bootstrap windows ssh winboxC -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]' -y
|
31
|
+
knife client delete knife bootstrap windows ssh winboxC -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]' -y
|
32
|
+
knife node list | xargs knife windows server delete -y
|
33
|
+
knife node bulk delete .* -y
|
34
|
+
knife node list | xargs knife ec2 server delete -y
|
35
|
+
knife node list | xargs knife ec2 server delete -y
|
36
|
+
knife node bulk delete .* -y
|
5
37
|
knife cookbook upload apache2
|
6
|
-
knife cookbook upload apt
|
38
|
+
knife cookbook upload apt --freeze
|
7
39
|
knife cookbook upload mysql
|
8
40
|
knife environment from file development.rb
|
9
41
|
knife environment from file qa.rb
|
@@ -20,25 +52,25 @@ knife data bag create data
|
|
20
52
|
knife data bag create passwords
|
21
53
|
knife data bag from file passwords mysql.json --secret-file secret_key
|
22
54
|
knife data bag from file passwords rabbitmq.json --secret-file secret_key
|
23
|
-
knife bootstrap serverA -i ~/.ssh/mray.pem -x user --sudo -
|
24
|
-
knife bootstrap serverB -i ~/.ssh/mray.pem -x user --sudo -
|
25
|
-
knife bootstrap serverC -i ~/.ssh/mray.pem -x user --sudo -
|
26
|
-
knife
|
27
|
-
knife
|
28
|
-
knife
|
29
|
-
knife ec2 server create -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7000f019 -f m1.small -r 'role[webserver],recipe[mysql::client]'
|
30
|
-
knife rackspace server create --image 49 --flavor 2 -r 'recipe[mysql],role[monitoring]'
|
31
|
-
knife rackspace server create --image 49 --flavor 2 -r 'recipe[mysql],role[monitoring]'
|
32
|
-
knife rackspace server create --image 49 --flavor 2 -r 'recipe[mysql],role[monitoring]'
|
55
|
+
knife bootstrap serverA -i ~/.ssh/mray.pem -x user --sudo -r 'role[base]'
|
56
|
+
knife bootstrap serverB -i ~/.ssh/mray.pem -x user --sudo -E production -r 'role[base]'
|
57
|
+
knife bootstrap serverC -i ~/.ssh/mray.pem -x user --sudo -E production -r 'role[base]'
|
58
|
+
knife rackspace server create --image 49 --flavor 2 -N db1 -r 'recipe[mysql],role[monitoring]'
|
59
|
+
knife rackspace server create --image 49 --flavor 2 -N db2 -r 'recipe[mysql],role[monitoring]'
|
60
|
+
knife rackspace server create --image 49 --flavor 2 -N db3 -r 'recipe[mysql],role[monitoring]'
|
33
61
|
knife bootstrap windows winrm winboxA -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
|
34
62
|
knife bootstrap windows ssh winboxB -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
|
35
63
|
knife bootstrap windows ssh winboxC -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
|
64
|
+
knife ec2 server create -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-8af0f326 -f m1.medium -j '{"tags":["amazon+rolemysql"]}' -r 'role[mysql]'
|
65
|
+
knife ec2 server create -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7000f019 -f m1.small -j '{"tags":["amazon+rolewebserverrecipemysqlclient"]}' -r 'role[webserver],recipe[mysql::client]'
|
66
|
+
knife ec2 server create -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7000f019 -f m1.small -j '{"tags":["amazon+rolewebserverrecipemysqlclient"]}' -r 'role[webserver],recipe[mysql::client]'
|
67
|
+
knife ec2 server create -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7000f019 -f m1.small -j '{"tags":["amazon+rolewebserverrecipemysqlclient"]}' -r 'role[webserver],recipe[mysql::client]'
|
36
68
|
OUTPUT
|
37
69
|
|
38
70
|
@spiceweasel_binary = File.join(File.dirname(__FILE__), *%w[.. .. bin spiceweasel])
|
39
71
|
end
|
40
72
|
|
41
73
|
it "maintains consistent output from the example config" do
|
42
|
-
`#{@spiceweasel_binary} --novalidation
|
74
|
+
`#{@spiceweasel_binary} -r --novalidation examples/example.yml`.should == @expected_output
|
43
75
|
end
|
44
76
|
end
|
metadata
CHANGED
@@ -1,20 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spiceweasel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Matt Ray
|
9
|
-
- Elliot Crosby-McCullough
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date:
|
12
|
+
date: 2013-01-08 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: json
|
17
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
18
|
requirements:
|
20
19
|
- - ! '>='
|
@@ -22,10 +21,15 @@ dependencies:
|
|
22
21
|
version: '0'
|
23
22
|
type: :runtime
|
24
23
|
prerelease: false
|
25
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
26
30
|
- !ruby/object:Gem::Dependency
|
27
31
|
name: mixlib-cli
|
28
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
29
33
|
none: false
|
30
34
|
requirements:
|
31
35
|
- - ! '>='
|
@@ -33,10 +37,79 @@ dependencies:
|
|
33
37
|
version: '0'
|
34
38
|
type: :runtime
|
35
39
|
prerelease: false
|
36
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: mixlib-config
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: mixlib-log
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: mixlib-shellout
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: chef
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
37
110
|
- !ruby/object:Gem::Dependency
|
38
111
|
name: rspec
|
39
|
-
requirement:
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
40
113
|
none: false
|
41
114
|
requirements:
|
42
115
|
- - ! '>='
|
@@ -44,32 +117,41 @@ dependencies:
|
|
44
117
|
version: '0'
|
45
118
|
type: :development
|
46
119
|
prerelease: false
|
47
|
-
version_requirements:
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
48
126
|
description: Provides a CLI tool for generating knife commands to build Chef-managed
|
49
|
-
infrastructure from a simple
|
127
|
+
infrastructure from a simple JSON or YAML file.
|
50
128
|
email:
|
51
129
|
- matt@opscode.com
|
52
|
-
- elliot.cm@gmail.com
|
53
130
|
executables:
|
54
131
|
- spiceweasel
|
55
132
|
extensions: []
|
56
133
|
extra_rdoc_files: []
|
57
134
|
files:
|
135
|
+
- LICENSE
|
136
|
+
- README.md
|
58
137
|
- bin/spiceweasel
|
59
138
|
- lib/spiceweasel/cli.rb
|
60
|
-
- lib/spiceweasel/
|
61
|
-
- lib/spiceweasel/
|
62
|
-
- lib/spiceweasel/
|
63
|
-
- lib/spiceweasel/
|
64
|
-
- lib/spiceweasel/
|
65
|
-
- lib/spiceweasel/
|
66
|
-
- lib/spiceweasel/
|
139
|
+
- lib/spiceweasel/clusters.rb
|
140
|
+
- lib/spiceweasel/config.rb
|
141
|
+
- lib/spiceweasel/cookbooks.rb
|
142
|
+
- lib/spiceweasel/data_bags.rb
|
143
|
+
- lib/spiceweasel/environments.rb
|
144
|
+
- lib/spiceweasel/execute.rb
|
145
|
+
- lib/spiceweasel/extract_local.rb
|
146
|
+
- lib/spiceweasel/log.rb
|
147
|
+
- lib/spiceweasel/nodes.rb
|
148
|
+
- lib/spiceweasel/roles.rb
|
67
149
|
- lib/spiceweasel/version.rb
|
68
150
|
- lib/spiceweasel.rb
|
69
|
-
- README.md
|
70
151
|
- spec/bin/spiceweasel_spec.rb
|
71
|
-
homepage:
|
72
|
-
licenses:
|
152
|
+
homepage: https://github.com/mattray/spiceweasel
|
153
|
+
licenses:
|
154
|
+
- Apache
|
73
155
|
post_install_message:
|
74
156
|
rdoc_options: []
|
75
157
|
require_paths:
|
@@ -87,11 +169,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
87
169
|
- !ruby/object:Gem::Version
|
88
170
|
version: '0'
|
89
171
|
requirements: []
|
90
|
-
rubyforge_project:
|
91
|
-
rubygems_version: 1.8.
|
172
|
+
rubyforge_project:
|
173
|
+
rubygems_version: 1.8.24
|
92
174
|
signing_key:
|
93
175
|
specification_version: 3
|
94
|
-
summary: CLI for generating Chef knife commands from a simple YAML file.
|
176
|
+
summary: CLI for generating Chef knife commands from a simple JSON or YAML file.
|
95
177
|
test_files:
|
96
178
|
- spec/bin/spiceweasel_spec.rb
|
97
|
-
has_rdoc:
|