spiceweasel 0.7.1 → 0.8

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,6 +2,8 @@ Description
2
2
  ===========
3
3
  Spiceweasel is a command-line tool for batch loading Chef infrastructure. It provides a simple syntax in either JSON or YAML for describing and deploying infrastructure in order with the Chef command-line tool `knife`.
4
4
 
5
+ The `examples` directory provides examples based on the Quick Starts provided at [http://help.opscode.com/kb/otherhelp](http://help.opscode.com/kb/otherhelp).
6
+
5
7
  CHANGELOG.md covers current, previous and future development milestones and contains the features backlog.
6
8
 
7
9
  Requirements
@@ -12,7 +14,7 @@ Written with Chef 0.9.12 and 0.10.0 and supports cookbooks, environments, roles,
12
14
 
13
15
  Testing
14
16
  -------
15
- Tested with Ubuntu 10.04 and 10.10 and Chef 0.9.16 and 0.10.0.rc.1.
17
+ Tested with Ubuntu 10.04 and Chef 0.9.16 and 0.10.2.
16
18
 
17
19
  File Syntax
18
20
  ===========
data/bin/spiceweasel CHANGED
@@ -1,92 +1,17 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'json'
4
- require 'mixlib/cli'
5
- require 'spiceweasel/version'
6
4
  require 'yaml'
7
5
 
8
- #ensure that the run_list contents are present in either the cookbooks or roles
9
- def validate_run_list(run_list, cookbooks, environments, roles)
10
- run_list.each do |item|
11
- if item.start_with?("recipe")
12
- #recipe[foo] or recipe[foo::bar]
13
- recipe = item.slice(7..-2).split("::")[0]
14
- unless cookbooks.member?(recipe)
15
- raise "'#{item}' is an invalid run_list recipe not managed by spiceweasel"
16
- exit(-1)
17
- end
18
- elsif item.start_with?("environment")
19
- #environment[blah]
20
- environment = item.slice(12..-2)
21
- unless environments.member?(environment)
22
- raise "'#{item}' is an invalid run_list environment not managed by spiceweasel"
23
- exit(-1)
24
- end
25
- elsif item.start_with?("role")
26
- #role[blah]
27
- role = item.slice(5..-2)
28
- unless roles.member?(role)
29
- raise "'#{item}' is an invalid run_list role not managed by spiceweasel"
30
- exit(-1)
31
- end
32
- else
33
- raise "'#{item}' is an invalid run_list component"
34
- exit(-1)
35
- end
36
- end
37
- end
38
-
39
- class SpiceweaselCLI
40
- include Mixlib::CLI
41
-
42
- banner("Usage: spiceweasel [option] file")
43
-
44
- option :debug,
45
- :long => "--debug",
46
- :description => "Verbose debugging messages.",
47
- :boolean => true
48
-
49
- option :delete,
50
- :short => "-d",
51
- :long => "--delete",
52
- :description => "Print the knife commands to be delete the infrastructure",
53
- :boolean => true
54
-
55
- option :dryrun,
56
- :long => "--dryrun",
57
- :description => "Print the knife commands to be executed to STDOUT",
58
- :boolean => true
59
-
60
- option :help,
61
- :short => "-h",
62
- :long => "--help",
63
- :description => "Show this message",
64
- :on => :tail,
65
- :boolean => true,
66
- :show_options => true,
67
- :exit => 0
68
-
69
- option :rebuild,
70
- :short => "-r",
71
- :long => "--rebuild",
72
- :description => "Print the knife commands to be delete and recreate the infrastructure",
73
- :boolean => true
74
-
75
- option :version,
76
- :short => "-v",
77
- :long => "--version",
78
- :description => "Version",
79
- :boolean => true,
80
- :proc => lambda {|v| puts "Spiceweasel: #{Spiceweasel::VERSION}" },
81
- :exit => 0
82
- end
6
+ require 'spiceweasel'
83
7
 
84
8
  #process command line options
85
9
  begin
86
- ARGV << "-h" if ARGV.empty?
87
- cli = SpiceweaselCLI.new
10
+ ARGV << "-h" if ARGV.empty?
11
+ cli = Spiceweasel::CLI.new
88
12
  cli.parse_options
89
- rescue OptionParser::InvalidOption => e
13
+ DEBUG = cli.config[:debug]
14
+ rescue OptionParser::InvalidOption => e
90
15
  STDERR.puts e.message
91
16
  puts cli.opt_parser.to_s
92
17
  exit(-1)
@@ -94,7 +19,7 @@ end
94
19
 
95
20
  begin
96
21
  file = ARGV.last
97
- STDOUT.puts "DEBUG: file: #{file}" if cli.config[:debug]
22
+ STDOUT.puts "DEBUG: file: #{file}" if cli.config[:debug]
98
23
  if (file.end_with?(".yml"))
99
24
  input = YAML.load_file ARGV.last
100
25
  elsif (file.end_with?(".json"))
@@ -116,130 +41,35 @@ end
116
41
  create = String.new()
117
42
  delete = String.new()
118
43
 
119
- #cookbooks
120
- cookbooks = input['cookbooks'] || []
121
- cookbook_list = []
122
- cookbooks.each do |cookbook|
123
- cb = cookbook.keys.first
124
- if cookbook[cb] and cookbook[cb].length > 0
125
- version = cookbook[cb][0].to_s || ""
126
- args = cookbook[cb][1] || ""
127
- end
128
- STDOUT.puts "DEBUG: cookbook: #{cb} #{version}" if cli.config[:debug]
129
- delete += "knife cookbook delete #{cb} #{version} -y\n"
130
- if File.directory?("cookbooks")
131
- if version and File.directory?("cookbooks/#{cb}")
132
- #check metadata.rb for requested version
133
- metadata = File.open("cookbooks/#{cb}/metadata.rb").grep(/^version/)[0].split()[1].gsub(/"/,'').to_s
134
- if (metadata != version)
135
- raise "Invalid version #{version} of '#{cb}' requested, #{metadata} is already in the cookbooks directory."
136
- exit(-1)
137
- end
138
- elsif !File.directory?("cookbooks/#{cb}")
139
- create += "knife cookbook site download #{cb} #{version} --file cookbooks/#{cb}.tgz #{args}\n"
140
- create += "tar -C cookbooks/ -xf cookbooks/#{cb}.tgz\n"
141
- end
142
- else
143
- STDERR.puts "cookbooks directory not found, validation and downloading skipped"
144
- end
145
- create += "knife cookbook upload #{cb}\n"
146
- #flatten list of cookbooks for validation later
147
- cookbook_list.push(cb)
148
- end
44
+ cookbook_list = Spiceweasel::CookbookList.new(input['cookbooks'])
45
+ environment_list = Spiceweasel::EnvironmentList.new(input['environments'])
46
+ role_list = Spiceweasel::RoleList.new(input['roles'])
47
+ data_bag_list = Spiceweasel::DataBagList.new(input['data bags'])
149
48
 
150
- #environments
151
- environments = input['environments'] || []
152
- environment_list = []
153
- environments.each do |environment|
154
- STDOUT.puts "DEBUG: environment: #{environment.keys[0]}" if cli.config[:debug]
155
- delete += "knife environment delete #{environment.keys[0]} -y\n"
156
- create += "knife environment from file #{environment.keys[0]}.rb\n"
157
- #flatten list of environments for validation later
158
- environment_list.push(environment.keys[0])
159
- end
49
+ node_list = Spiceweasel::NodeList.new(input['nodes'], cookbook_list, environment_list, role_list)
160
50
 
161
- #roles
162
- roles = input['roles'] || []
163
- role_list = []
164
- roles.each do |role|
165
- STDOUT.puts "DEBUG: role: #{role.keys[0]}" if cli.config[:debug]
166
- delete += "knife role delete #{role.keys[0]} -y\n"
167
- create += "knife role from file #{role.keys[0]}.rb\n"
168
- #flatten list of roles for validation later
169
- role_list.push(role.keys[0])
170
- end
51
+ create += cookbook_list.create
52
+ create += environment_list.create
53
+ create += role_list.create
54
+ create += data_bag_list.create
55
+ create += node_list.create
171
56
 
172
- #data bags
173
- bags = input['data bags'] || []
174
- bags.each do |bag|
175
- STDOUT.puts "DEBUG: data bag: #{bag.keys[0]}" if cli.config[:debug]
176
- delete += "knife data bag delete #{bag.keys[0]} -y\n"
177
- create += "knife data bag create #{bag.keys[0]}\n"
178
- items = bag[bag.keys[0]] || []
179
- secret = nil
180
- while item = items.shift
181
- STDOUT.puts "DEBUG: data bag #{bag.keys[0]} item: #{item}" if cli.config[:debug]
182
- if item.start_with?("secret")
183
- secret = item.split()[1]
184
- next
185
- end
186
- if item =~ /\*/ #wildcard support
187
- files = Dir.glob("data_bags/#{bag.keys[0]}/#{item}.json")
188
- items += files.collect {|x| x[x.rindex('/')+1..-6]}
189
- puts items
190
- next
191
- end
192
- if secret
193
- create += "knife data bag from file #{bag.keys[0]} data_bags/#{bag.keys[0]}/#{item}.json --secret-file #{secret}\n"
194
- else
195
- create += "knife data bag from file #{bag.keys[0]} data_bags/#{bag.keys[0]}/#{item}.json\n"
196
- end
197
- end
198
- end
199
-
200
- nodes = input['nodes'] || []
201
- #currently use bulk_delete for deleting, add provider support real soon
202
- delete += "knife node bulk_delete .* -y\n"
203
- nodes.each do |node|
204
- STDOUT.puts "DEBUG: node: #{node.keys[0]}" if cli.config[:debug]
205
- # delete += "knife node delete #{node[node.keys[0]}\n"
206
- run_list = node[node.keys[0]][0].gsub(/ /,',').split(',')
207
- STDOUT.puts "DEBUG: node run_list: #{run_list}" if cli.config[:debug]
208
- validate_run_list(run_list, cookbook_list, environment_list, role_list)
209
- #provider support
210
- if node.keys[0].start_with?("bluebox","ec2","openstack","rackspace","slicehost","terremark")
211
- provider = node.keys[0].split()
212
- count = 1
213
- if (provider.length == 2)
214
- count = provider[1]
215
- end
216
- #create the instances
217
- count.to_i.times do
218
- create += "knife #{provider[0]} server create #{node[node.keys[0]][1]}"
219
- if run_list.length > 0
220
- create += " -r '#{node[node.keys[0]][0].gsub(/ /,',')}'\n"
221
- end
222
- end
223
- else #multinode support
224
- node.keys[0].split.each do |server|
225
- create += "knife bootstrap #{server} #{node[node.keys[0]][1]}"
226
- if run_list.length > 0
227
- create += " -r '#{node[node.keys[0]][0].gsub(/ /,',')}'\n"
228
- end
229
- end
230
- end
231
- end
57
+ delete += cookbook_list.delete
58
+ delete += environment_list.delete
59
+ delete += role_list.delete
60
+ delete += data_bag_list.delete
61
+ delete += node_list.delete
232
62
 
233
63
  #just print the knife commands, do not execute
234
64
  #if cli.config[:dryrun]
235
- if cli.config[:delete]
65
+ if cli.config[:delete]
236
66
  puts delete unless delete.empty?
237
67
  elsif cli.config[:rebuild]
238
68
  puts delete unless delete.empty?
239
69
  puts create unless create.empty?
240
70
  else
241
71
  puts create unless create.empty?
242
- end
72
+ end
243
73
  #else
244
74
  #eventually we will execute instead of printing knife commands
245
75
  #puts "BAM!"
data/lib/spiceweasel.rb CHANGED
@@ -1,3 +1,9 @@
1
1
  module Spiceweasel
2
- # Your code goes here...
2
+ autoload :CLI, 'spiceweasel/cli'
3
+ autoload :RunList, 'spiceweasel/run_list'
4
+ autoload :CookbookList, 'spiceweasel/cookbook_list'
5
+ autoload :EnvironmentList, 'spiceweasel/environment_list'
6
+ autoload :RoleList, 'spiceweasel/role_list'
7
+ autoload :DataBagList, 'spiceweasel/data_bag_list'
8
+ autoload :NodeList, 'spiceweasel/node_list'
3
9
  end
@@ -0,0 +1,47 @@
1
+ require 'mixlib/cli'
2
+ require 'spiceweasel/version'
3
+
4
+ class Spiceweasel::CLI
5
+ include Mixlib::CLI
6
+
7
+ banner("Usage: spiceweasel [option] file")
8
+
9
+ option :debug,
10
+ :long => "--debug",
11
+ :description => "Verbose debugging messages.",
12
+ :boolean => true
13
+
14
+ option :delete,
15
+ :short => "-d",
16
+ :long => "--delete",
17
+ :description => "Print the knife commands to be delete the infrastructure",
18
+ :boolean => true
19
+
20
+ option :dryrun,
21
+ :long => "--dryrun",
22
+ :description => "Print the knife commands to be executed to STDOUT",
23
+ :boolean => true
24
+
25
+ option :help,
26
+ :short => "-h",
27
+ :long => "--help",
28
+ :description => "Show this message",
29
+ :on => :tail,
30
+ :boolean => true,
31
+ :show_options => true,
32
+ :exit => 0
33
+
34
+ option :rebuild,
35
+ :short => "-r",
36
+ :long => "--rebuild",
37
+ :description => "Print the knife commands to be delete and recreate the infrastructure",
38
+ :boolean => true
39
+
40
+ option :version,
41
+ :short => "-v",
42
+ :long => "--version",
43
+ :description => "Version",
44
+ :boolean => true,
45
+ :proc => lambda {|v| puts "Spiceweasel: #{Spiceweasel::VERSION}" },
46
+ :exit => 0
47
+ end
@@ -0,0 +1,39 @@
1
+ class Spiceweasel::CookbookList
2
+ def initialize(cookbooks = [])
3
+ @create = @delete = ''
4
+ @cookbooks = []
5
+ cookbooks.each do |cookbook|
6
+ cb = cookbook.keys.first
7
+ if cookbook[cb] and cookbook[cb].length > 0
8
+ version = cookbook[cb][0].to_s || ""
9
+ args = cookbook[cb][1] || ""
10
+ end
11
+ STDOUT.puts "DEBUG: cookbook: #{cb} #{version}" if DEBUG
12
+ @delete += "knife cookbook @delete #{cb} #{version} -y\n"
13
+ if File.directory?("cookbooks")
14
+ if version and File.directory?("cookbooks/#{cb}")
15
+ #check metadata.rb for requested version
16
+ metadata = File.open("cookbooks/#{cb}/metadata.rb").grep(/^version/)[0].split()[1].gsub(/"/,'').to_s
17
+ if (metadata != version)
18
+ raise "Invalid version #{version} of '#{cb}' requested, #{metadata} is already in the cookbooks directory."
19
+ exit(-1)
20
+ end
21
+ elsif !File.directory?("cookbooks/#{cb}")
22
+ @create += "knife cookbook site download #{cb} #{version} --file cookbooks/#{cb}.tgz #{args}\n"
23
+ @create += "tar -C cookbooks/ -xf cookbooks/#{cb}.tgz\n"
24
+ end
25
+ else
26
+ STDERR.puts "cookbooks directory not found, validation and downloading skipped"
27
+ end
28
+ @create += "knife cookbook upload #{cb}\n"
29
+
30
+ @cookbooks << cb
31
+ end
32
+ end
33
+
34
+ attr_reader :cookbooks, :create, :delete
35
+
36
+ def member?(cookbook)
37
+ cookbooks.include?(cookbook)
38
+ end
39
+ end
@@ -0,0 +1,32 @@
1
+ class Spiceweasel::DataBagList
2
+ def initialize(data_bags = [])
3
+ @create = @delete = ''
4
+ data_bags.each do |data_bag|
5
+ STDOUT.puts "DEBUG: data bag: #{data_bag.keys[0]}" if DEBUG
6
+ @delete += "knife data bag delete #{data_bag.keys[0]} -y\n"
7
+ @create += "knife data bag create #{data_bag.keys[0]}\n"
8
+ items = data_bag[data_bag.keys[0]] || []
9
+ secret = nil
10
+ while item = items.shift
11
+ STDOUT.puts "DEBUG: data bag #{data_bag.keys[0]} item: #{item}" if DEBUG
12
+ if item.start_with?("secret")
13
+ secret = item.split()[1]
14
+ next
15
+ end
16
+ if item =~ /\*/ #wildcard support
17
+ files = Dir.glob("data_bags/#{data_bag.keys[0]}/#{item}.json")
18
+ items += files.collect {|x| x[x.rindex('/')+1..-6]}
19
+ puts items
20
+ next
21
+ end
22
+ if secret
23
+ @create += "knife data bag from file #{data_bag.keys[0]} data_bags/#{data_bag.keys[0]}/#{item}.json --secret-file #{secret}\n"
24
+ else
25
+ @create += "knife data bag from file #{data_bag.keys[0]} data_bags/#{data_bag.keys[0]}/#{item}.json\n"
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ attr_reader :create, :delete
32
+ end
@@ -0,0 +1,18 @@
1
+ class Spiceweasel::EnvironmentList
2
+ def initialize(environments = [])
3
+ @create = @delete = ''
4
+ @environments = []
5
+ environments.each do |environment|
6
+ STDOUT.puts "DEBUG: environment: #{environment.keys[0]}" if DEBUG
7
+ @delete += "knife environment delete #{environment.keys[0]} -y\n"
8
+ @create += "knife environment from file #{environment.keys[0]}.rb\n"
9
+ @environments << environment.keys[0]
10
+ end
11
+ end
12
+
13
+ attr_reader :environments, :create, :delete
14
+
15
+ def member?(environment)
16
+ environments.include?(environment)
17
+ end
18
+ end
@@ -0,0 +1,38 @@
1
+ class Spiceweasel::NodeList
2
+ def initialize(nodes, cookbook_list, environment_list, role_list)
3
+ nodes ||= []
4
+ @create = @delete = ''
5
+
6
+ @delete += "knife node bulk_delete .* -y\n"
7
+ nodes.each do |node|
8
+ STDOUT.puts "DEBUG: node: #{node.keys[0]}" if DEBUG
9
+ run_list = node[node.keys[0]][0].gsub(/ /,',').split(',')
10
+ STDOUT.puts "DEBUG: node run_list: #{run_list}" if DEBUG
11
+ Spiceweasel::RunList.new(run_list).validate(cookbook_list, environment_list, role_list)
12
+ #provider support
13
+ if node.keys[0].start_with?("bluebox","ec2","openstack","rackspace","slicehost","terremark")
14
+ provider = node.keys[0].split()
15
+ count = 1
16
+ if (provider.length == 2)
17
+ count = provider[1]
18
+ end
19
+ #create the instances
20
+ count.to_i.times do
21
+ @create += "knife #{provider[0]} server create #{node[node.keys[0]][1]}"
22
+ if run_list.length > 0
23
+ @create += " -r '#{node[node.keys[0]][0].gsub(/ /,',')}'\n"
24
+ end
25
+ end
26
+ else #multinode support
27
+ node.keys[0].split.each do |server|
28
+ @create += "knife bootstrap #{server} #{node[node.keys[0]][1]}"
29
+ if run_list.length > 0
30
+ @create += " -r '#{node[node.keys[0]][0].gsub(/ /,',')}'\n"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ attr_reader :create, :delete
38
+ end
@@ -0,0 +1,18 @@
1
+ class Spiceweasel::RoleList
2
+ def initialize(roles = [])
3
+ @create = @delete = ''
4
+ @roles = []
5
+ roles.each do |role|
6
+ STDOUT.puts "DEBUG: role: #{role.keys[0]}" if DEBUG
7
+ @delete += "knife role delete #{role.keys[0]} -y\n"
8
+ @create += "knife role from file #{role.keys[0]}.rb\n"
9
+ @roles << role.keys[0]
10
+ end
11
+ end
12
+
13
+ attr_reader :roles, :create, :delete
14
+
15
+ def member?(role)
16
+ roles.include?(role)
17
+ end
18
+ end
@@ -0,0 +1,36 @@
1
+ class Spiceweasel::RunList
2
+ def initialize(run_list)
3
+ @run_list = run_list
4
+ end
5
+
6
+ def validate(cookbooks, environments, roles)
7
+ @run_list.each do |item|
8
+ if item.start_with?("recipe")
9
+ #recipe[foo] or recipe[foo::bar]
10
+ recipe = item.slice(7..-2).split("::")[0]
11
+ unless cookbooks.member?(recipe)
12
+ raise "'#{item}' is an invalid run_list recipe not managed by spiceweasel"
13
+ exit(-1)
14
+ end
15
+ elsif item.start_with?("environment")
16
+ #environment[blah]
17
+ environment = item.slice(12..-2)
18
+ unless environments.member?(environment)
19
+ raise "'#{item}' is an invalid run_list environment not managed by spiceweasel"
20
+ exit(-1)
21
+ end
22
+ elsif item.start_with?("role")
23
+ #role[blah]
24
+ role = item.slice(5..-2)
25
+ unless roles.member?(role)
26
+ raise "'#{item}' is an invalid run_list role not managed by spiceweasel"
27
+ exit(-1)
28
+ end
29
+ else
30
+ raise "'#{item}' is an invalid run_list component"
31
+ exit(-1)
32
+ end
33
+ end
34
+ end
35
+
36
+ end
@@ -1,3 +1,3 @@
1
1
  module Spiceweasel
2
- VERSION = "0.7.1"
2
+ VERSION = "0.8"
3
3
  end
@@ -0,0 +1,39 @@
1
+ # Cover-all spec to prevent regressions during refactor
2
+ describe 'The Spiceweasel binary' do
3
+ before(:each) do
4
+ @expected_output = <<-OUTPUT
5
+ knife cookbook upload apache2
6
+ knife cookbook upload apt
7
+ knife cookbook upload mysql
8
+ knife environment from file development.rb
9
+ knife environment from file qa.rb
10
+ knife environment from file production.rb
11
+ knife role from file base.rb
12
+ knife role from file monitoring.rb
13
+ knife role from file webserver.rb
14
+ knife data bag create users
15
+ knife data bag from file users data_bags/users/alice.json
16
+ knife data bag from file users data_bags/users/bob.json
17
+ knife data bag from file users data_bags/users/chuck.json
18
+ knife data bag create data
19
+ knife data bag create passwords
20
+ knife data bag from file passwords data_bags/passwords/mysql.json --secret-file secret_key
21
+ knife data bag from file passwords data_bags/passwords/rabbitmq.json --secret-file secret_key
22
+ knife bootstrap serverA -i ~/.ssh/mray.pem -x user --sudo -d ubuntu10.04-gems -r 'role[base]'
23
+ knife bootstrap serverB -i ~/.ssh/mray.pem -x user --sudo -d ubuntu10.04-gems -r 'role[base]'
24
+ knife bootstrap serverC -i ~/.ssh/mray.pem -x user --sudo -d ubuntu10.04-gems -r 'role[base]'
25
+ 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]'
26
+ 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]'
27
+ 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]'
28
+ knife rackspace server create --image 49 --flavor 2 -r 'recipe[mysql],role[monitoring]'
29
+ knife rackspace server create --image 49 --flavor 2 -r 'recipe[mysql],role[monitoring]'
30
+ knife rackspace server create --image 49 --flavor 2 -r 'recipe[mysql],role[monitoring]'
31
+ OUTPUT
32
+
33
+ @spiceweasel_binary = File.join(File.dirname(__FILE__), *%w[.. .. bin spiceweasel])
34
+ end
35
+
36
+ it "maintains consistent output from the example config" do
37
+ `#{@spiceweasel_binary} --dryrun example.yml`.should == @expected_output
38
+ end
39
+ end
metadata CHANGED
@@ -1,27 +1,62 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spiceweasel
3
3
  version: !ruby/object:Gem::Version
4
- hash: 1
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 7
9
- - 1
10
- version: 0.7.1
4
+ version: "0.8"
11
5
  platform: ruby
12
6
  authors:
13
7
  - Matt Ray
8
+ - Elliot Crosby-McCullough
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2011-05-05 00:00:00 -05:00
13
+ date: 2011-07-21 00:00:00 -05:00
19
14
  default_executable:
20
- dependencies: []
21
-
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: chef
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: json
28
+ type: :runtime
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ version:
36
+ - !ruby/object:Gem::Dependency
37
+ name: mixlib-cli
38
+ type: :runtime
39
+ version_requirement:
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ type: :development
49
+ version_requirement:
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
22
56
  description: This provides a CLI for generating knife commands to build Chef-managed infrastructure from a simple YAML file.
23
57
  email:
24
58
  - matt@opscode.com
59
+ - elliot.cm@gmail.com
25
60
  executables:
26
61
  - spiceweasel
27
62
  extensions: []
@@ -29,20 +64,19 @@ extensions: []
29
64
  extra_rdoc_files: []
30
65
 
31
66
  files:
32
- - .gitignore
33
- - CHANGELOG.md
34
- - Gemfile
35
- - README.md
36
- - Rakefile
37
67
  - bin/spiceweasel
38
- - example.json
39
- - example.yml
40
- - lib/spiceweasel.rb
68
+ - lib/spiceweasel/cli.rb
69
+ - lib/spiceweasel/cookbook_list.rb
70
+ - lib/spiceweasel/data_bag_list.rb
71
+ - lib/spiceweasel/environment_list.rb
72
+ - lib/spiceweasel/node_list.rb
73
+ - lib/spiceweasel/role_list.rb
74
+ - lib/spiceweasel/run_list.rb
41
75
  - lib/spiceweasel/version.rb
42
- - spiceweasel.gemspec
43
- - test.sh
76
+ - lib/spiceweasel.rb
77
+ - README.md
44
78
  has_rdoc: true
45
- homepage: ""
79
+ homepage: http://github.com/mattray/spiceweasel
46
80
  licenses: []
47
81
 
48
82
  post_install_message:
@@ -51,29 +85,23 @@ rdoc_options: []
51
85
  require_paths:
52
86
  - lib
53
87
  required_ruby_version: !ruby/object:Gem::Requirement
54
- none: false
55
88
  requirements:
56
89
  - - ">="
57
90
  - !ruby/object:Gem::Version
58
- hash: 3
59
- segments:
60
- - 0
61
91
  version: "0"
92
+ version:
62
93
  required_rubygems_version: !ruby/object:Gem::Requirement
63
- none: false
64
94
  requirements:
65
95
  - - ">="
66
96
  - !ruby/object:Gem::Version
67
- hash: 3
68
- segments:
69
- - 0
70
97
  version: "0"
98
+ version:
71
99
  requirements: []
72
100
 
73
101
  rubyforge_project: spiceweasel
74
- rubygems_version: 1.3.7
102
+ rubygems_version: 1.3.5
75
103
  signing_key:
76
104
  specification_version: 3
77
105
  summary: CLI for generating Chef knife commands from a simple YAML file.
78
- test_files: []
79
-
106
+ test_files:
107
+ - spec/bin/spiceweasel_spec.rb
data/.gitignore DELETED
@@ -1,4 +0,0 @@
1
- *.gem
2
- .bundle
3
- Gemfile.lock
4
- pkg/*
data/CHANGELOG.md DELETED
@@ -1,83 +0,0 @@
1
- This is the current, previous and future development milestones and contains the features backlog.
2
-
3
- 0.1
4
- ===
5
- * initial README.md describing goals
6
- * command-line tool
7
- * basic options all supported
8
- * create repo on GitHub
9
- * publish as a gem on RubyGems
10
-
11
- 0.2
12
- ===
13
- * switch to mixlib-cli
14
- * --dryrun The option `--dryrun` will print the commands to run, but not actually execute them (the default behavior)
15
- * --delete The option `--delete` will delete each cookbook, role, data bag, environment and node described in the yml file. All nodes from the system are deleted with `knife node bulk_delete`.
16
- * --rebuild The option `--rebuild` will remove all currently managed infrastructure for this chef repository and rebuild it from scratch.
17
-
18
- 0.3
19
- ===
20
- * renamed MILESTONES.md to CHANGELOG.md
21
- * fixed version number
22
- * updated YAML schema and examples because Ruby 1.8 does not order hashes.
23
- * validate that the recipes and roles listed in the nodes are loaded
24
-
25
- 0.4
26
- ===
27
- * support versions for cookbooks
28
- * support site vendor for cookbooks
29
-
30
- 0.5
31
- ===
32
- * support JSON and YAML
33
-
34
- 0.6
35
- ===
36
- * add support for cookbook options
37
-
38
- 0.7
39
- =============
40
- * add support for environments
41
- * rescue from parser errors
42
- * update cookbook download syntax
43
- * multiple nodes with same runlists syntax
44
- * add support for encrypted data bags
45
- * wildcard support for data bag items
46
-
47
- 0.7.1 *CURRENT*
48
- ===============
49
- * fixed run list parsing
50
- * updated examples for Chef 0.10
51
- * relaxed validation on existing cookbooks
52
-
53
- BACKLOG
54
- =======
55
- Next
56
- ----
57
- * make spiceweasel a library rather than an executable
58
- * switch to using lib/ directory
59
- * convert to a knife plugin
60
- * knife batch create from file infrastructure.yml
61
- * knife batch delete from file infrastructure.json
62
- * knife batch rebuild from file infrastructure.yml
63
- Future
64
- ------
65
- * --chef-client The option `--chef-client` will make a `knife ssh` call to each box and run `chef-client` on each.
66
- * --chef-client validation that nodes are added
67
- * -e/--execute execute the commands
68
- * catching return codes and retrying (with retry count?)
69
- * make the JSON calls directly with Chef APIs
70
- * execution-phase validation
71
- * check metadata.rb of cookbooks for their dependencies
72
- * validate within role files rather than the names of files (assumption that they are the same)
73
- * validate cookbooks referenced in roles
74
- * validate not trying to use environments with 0.9.x
75
- * validate within environment files rather than the names of files (assumption that they are the same)
76
- * validate cookbooks referenced in environments
77
- * validate recipes from cookbooks in run_lists
78
- * wildcards for environments and roles
79
- * on provider delete take count of vendor-specific, delete if match (ec2 server delete and node delete)
80
- * knife winrm bootstrap FQDN [RUN LIST...] (options)
81
- * use GNU parallel with knife?
82
- * extract existing infrastructure
83
- * knife batch extract
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- # Specify your gem's dependencies in spiceweasel.gemspec
4
- gemspec
data/Rakefile DELETED
@@ -1,2 +0,0 @@
1
- require 'bundler'
2
- Bundler::GemHelper.install_tasks
data/example.json DELETED
@@ -1,73 +0,0 @@
1
- {
2
- "cookbooks":
3
- [
4
- {"apache2":[]},
5
- {"apt":
6
- [
7
- "1.1.1"
8
- ]
9
- },
10
- {"mysql":[]}
11
- ],
12
- "environments":
13
- [
14
- {"development":[]},
15
- {"qa":[]},
16
- {"production":[]}
17
- ],
18
- "roles":
19
- [
20
- {"base":[]},
21
- {"monitoring":[]},
22
- {"webserver":[]}
23
- ],
24
- "data bags":
25
- [
26
- {"users":
27
- [
28
- "alice",
29
- "bob",
30
- "chuck"
31
- ]
32
- },
33
- {"data":
34
- [
35
- "*"
36
- ]
37
- },
38
- {"passwords":
39
- [
40
- "secret secret_key",
41
- "mysql",
42
- "rabbitmq"
43
- ]
44
- }
45
- ],
46
- "nodes":
47
- [
48
- {"serverA":
49
- [
50
- "role[base]",
51
- "-i ~/.ssh/mray.pem -x user --sudo -d ubuntu10.04-gems"
52
- ]
53
- },
54
- {"serverB serverC":
55
- [
56
- "role[base]",
57
- "-i ~/.ssh/mray.pem -x user --sudo -d ubuntu10.04-gems"
58
- ]
59
- },
60
- {"ec2 3":
61
- [
62
- "role[webserver] recipe[mysql::client]",
63
- "-S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7000f019 -f m1.small"
64
- ]
65
- },
66
- {"rackspace 3":
67
- [
68
- "recipe[mysql],role[monitoring]",
69
- "--image 49 --flavor 2"
70
- ]
71
- }
72
- ]
73
- }
data/example.yml DELETED
@@ -1,41 +0,0 @@
1
- cookbooks:
2
- - apache2:
3
- - apt:
4
- - 1.1.1
5
- - mysql:
6
-
7
- environments:
8
- - development:
9
- - qa:
10
- - production:
11
-
12
- roles:
13
- - base:
14
- - monitoring:
15
- - webserver:
16
-
17
- data bags:
18
- - users:
19
- - alice
20
- - bob
21
- - chuck
22
- - data:
23
- - *
24
- - passwords:
25
- - secret secret_key
26
- - mysql
27
- - rabbitmq
28
-
29
- nodes:
30
- - serverA:
31
- - role[base]
32
- - -i ~/.ssh/mray.pem -x user --sudo -d ubuntu10.04-gems
33
- - serverB serverC:
34
- - role[base]
35
- - -i ~/.ssh/mray.pem -x user --sudo -d ubuntu10.04-gems
36
- - ec2 3:
37
- - role[webserver] recipe[mysql::client]
38
- - -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7000f019 -f m1.small
39
- - rackspace 3:
40
- - recipe[mysql],role[monitoring]
41
- - --image 49 --flavor 2
data/spiceweasel.gemspec DELETED
@@ -1,25 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "json"
4
- require "mixlib/cli"
5
- require "spiceweasel/version"
6
- require "yaml"
7
-
8
-
9
- Gem::Specification.new do |s|
10
- s.name = "spiceweasel"
11
- s.version = Spiceweasel::VERSION
12
- s.platform = Gem::Platform::RUBY
13
- s.authors = ["Matt Ray"]
14
- s.email = ["matt@opscode.com"]
15
- s.homepage = ""
16
- s.summary = %q{CLI for generating Chef knife commands from a simple YAML file.}
17
- s.description = %q{This provides a CLI for generating knife commands to build Chef-managed infrastructure from a simple YAML file.}
18
-
19
- s.rubyforge_project = "spiceweasel"
20
-
21
- s.files = `git ls-files`.split("\n")
22
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
- s.require_paths = ["lib"]
25
- end
data/test.sh DELETED
@@ -1,48 +0,0 @@
1
- echo "------------>spiceweasel"
2
- spiceweasel
3
- echo "------------>Return code:$?"
4
- echo "------------>spiceweasel -h"
5
- spiceweasel -h
6
- echo "------------>Return code:$?"
7
- echo "------------>spiceweasel -h example.yml"
8
- spiceweasel -h example.yml
9
- echo "------------>Return code:$?"
10
- echo "------------>spiceweasel -v"
11
- spiceweasel -v
12
- echo "------------>Return code:$?"
13
- echo "------------>spiceweasel -v example.yml"
14
- spiceweasel -v example.yml
15
- echo "------------>Return code:$?"
16
- echo "------------>spiceweasel --version"
17
- spiceweasel --version
18
- echo "------------>Return code:$?"
19
- echo "------------>spiceweasel example.yml"
20
- spiceweasel example.yml
21
- echo "------------>Return code:$?"
22
- echo "------------>spiceweasel --dryrun"
23
- spiceweasel --dryrun
24
- echo "------------>Return code:$?"
25
- echo "------------>spiceweasel --dryrun example.yml"
26
- spiceweasel --dryrun example.yml
27
- echo "------------>Return code:$?"
28
- echo "------------>spiceweasel --help"
29
- spiceweasel --help
30
- echo "------------>Return code:$?"
31
- echo "------------>spiceweasel -d"
32
- spiceweasel -d
33
- echo "------------>Return code:$?"
34
- echo "------------>spiceweasel -d example.yml"
35
- spiceweasel -d example.yml
36
- echo "------------>Return code:$?"
37
- echo "------------>spiceweasel --delete example.yml"
38
- spiceweasel --delete example.yml
39
- echo "------------>Return code:$?"
40
- echo "------------>spiceweasel -r"
41
- spiceweasel -r
42
- echo "------------>Return code:$?"
43
- echo "------------>spiceweasel -r example.yml"
44
- spiceweasel -r example.yml
45
- echo "------------>Return code:$?"
46
- echo "------------>spiceweasel --rebuild example.yml"
47
- spiceweasel --rebuild example.yml
48
- echo "------------>Return code:$?"