spiceweasel 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -12,7 +12,7 @@ Requirements
12
12
  ============
13
13
  Spiceweasel currently depends on `knife` to run commands for it, but does not explicitly depend on the `chef` gem yet. Infrastructure files must either end in .json or .yml to be processed.
14
14
 
15
- Written and tested initially with Chef 0.9.12 (should still work) and continuing development with the 0.10 series. It is tested with Ruby 1.8.7 and 1.9.2.
15
+ Written and tested initially with Chef 0.9.12 (should still work) and continuing development with the 10. series. It is tested with Ruby 1.8.7 and 1.9.2.
16
16
 
17
17
  File Syntax
18
18
  ===========
@@ -43,7 +43,7 @@ data bags:
43
43
  - bob
44
44
  - chuck
45
45
  - data:
46
- - *
46
+ - "*"
47
47
  - passwords:
48
48
  - secret secret_key
49
49
  - mysql
@@ -60,7 +60,7 @@ nodes:
60
60
  - -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7000f019 -f m1.small
61
61
  - rackspace 3:
62
62
  - recipe[mysql],role[monitoring]
63
- - --image 49 --flavor 2
63
+ - --image 49 --flavor 2 --node-name rs{{n}}.example.com
64
64
  - windows_winrm winboxA:
65
65
  - role[base],role[iisserver]
66
66
  - -x Administrator -P 'super_secret_password'
@@ -143,7 +143,7 @@ From the `example.json`:
143
143
  {"rackspace 3":
144
144
  [
145
145
  "recipe[mysql],role[monitoring]",
146
- "--image 49 --flavor 2"
146
+ "--image 49 --flavor 2 --node-name rs{{n}}.example.com"
147
147
  ]
148
148
  },
149
149
  {"windows_winrm winboxA":
@@ -225,7 +225,7 @@ knife role from file webserver.rb
225
225
 
226
226
  Data Bags
227
227
  ---------
228
- The `data bags` section of the manifest currently creates the data bags listed with `knife data bag create FOO` where `FOO` is the name of the data bag. Individual items may be added to the data bag as part of a JSON or YAML sequence, the assumption is made that they `.json` files and in the proper `data_bags/FOO` directory. You may also pass a wildcard as an entry to load all matching data bags (ie. `*`). Encrypted data bags are supported by listing `secret filename` as the first item (where `filename` is the secret key to be used). Validation is done to ensure the JSON is properly formatted, the id matches and any secret keys are in the correct locations. Assuming the presence of `dataA.json` and `dataB.json` in the `data_bags/data` directory, the YAML snippet
228
+ The `data bags` section of the manifest currently creates the data bags listed with `knife data bag create FOO` where `FOO` is the name of the data bag. Individual items may be added to the data bag as part of a JSON or YAML sequence, the assumption is made that they `.json` files and in the proper `data_bags/FOO` directory. You may also pass a wildcard as an entry to load all matching data bags (ie. `"*"`). Encrypted data bags are supported by listing `secret filename` as the first item (where `filename` is the secret key to be used). Validation is done to ensure the JSON is properly formatted, the id matches and any secret keys are in the correct locations. Assuming the presence of `dataA.json` and `dataB.json` in the `data_bags/data` directory, the YAML snippet
229
229
 
230
230
  ``` yaml
231
231
  data bags:
@@ -234,7 +234,7 @@ data bags:
234
234
  - bob
235
235
  - chuck
236
236
  - data:
237
- - *
237
+ - "*"
238
238
  - passwords:
239
239
  - secret secret_key
240
240
  - mysql
@@ -258,7 +258,7 @@ knife data bag from file passwords rabbitmq.json --secret-file secret_key
258
258
 
259
259
  Nodes
260
260
  -----
261
- The `nodes` section of the manifest bootstraps a node for each entry where the entry is a hostname or provider and count. A shortcut syntax for bulk-creating nodes with various providers where the line starts with the provider and ends with the number of nodes to be provisioned. Windows nodes need to specify either `windows_winrm` or `windows_ssh` depending on the protocol used, followed by the name of the node(s). Each node requires 2 items after it in a sequence. You may also use the `--parallel` flag from the command line, allowing provider commands to run simultaneously for faster deployment.
261
+ The `nodes` section of the manifest bootstraps a node for each entry where the entry is a hostname or provider and count. A shortcut syntax for bulk-creating nodes with various providers where the line starts with the provider and ends with the number of nodes to be provisioned. Windows nodes need to specify either `windows_winrm` or `windows_ssh` depending on the protocol used, followed by the name of the node(s). Each node requires 2 items after it in a sequence. You may also use the `--parallel` flag from the command line, allowing provider commands to run simultaneously for faster deployment. If you want to give your nodes names, simply pass `-N NAME{{n}}` or `--node-name NAME{{n}}` and the `{{n}}` will be substituted by a number (works with or without --parallel).
262
262
 
263
263
  The first item after the node is the run_list and the second are the CLI options used. The run_list may be space or comma-delimited. Validation is performed on the run_list components to ensure that only cookbooks and roles listed in the manifest are used. Validation on the options ensures that any Environments referenced are also listed. You may specify multiple nodes to have the same configuration by listing them separated by a space. The example YAML snippet
264
264
 
@@ -275,7 +275,7 @@ nodes:
275
275
  - -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7000f019 -f m1.small
276
276
  - rackspace 3:
277
277
  - recipe[mysql],role[monitoring]
278
- - --image 49 --flavor 2
278
+ - --image 49 --flavor 2 --node-name rs{{n}}.example.com
279
279
  - windows_winrm winboxA:
280
280
  - role[base],role[iisserver]
281
281
  - -x Administrator -P 'super_secret_password'
@@ -294,14 +294,31 @@ knife ec2 server create -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7
294
294
  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]'
295
295
  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]'
296
296
  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]'
297
- knife rackspace server create --image 49 --flavor 2 -r 'recipe[mysql],role[monitoring]'
298
- knife rackspace server create --image 49 --flavor 2 -r 'recipe[mysql],role[monitoring]'
299
- knife rackspace server create --image 49 --flavor 2 -r 'recipe[mysql],role[monitoring]'
297
+ knife rackspace server create --image 49 --flavor 2 --node-name rs1.example.com -r 'recipe[mysql],role[monitoring]'
298
+ knife rackspace server create --image 49 --flavor 2 --node-name rs2.example.com -r 'recipe[mysql],role[monitoring]'
299
+ knife rackspace server create --image 49 --flavor 2 --node-name rs3.example.com -r 'recipe[mysql],role[monitoring]'
300
300
  knife bootstrap windows winrm winboxA -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
301
301
  knife bootstrap windows ssh winboxB -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
302
302
  knife bootstrap windows ssh winboxC -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
303
303
  ```
304
304
 
305
+ Using `--parallel` with the following block and the `-N webserver{{n}}`
306
+
307
+ ``` yaml
308
+ nodes:
309
+ - ec2 3:
310
+ - role[webserver]
311
+ - -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7000f019 -f m1.small -N webserver{{n}}
312
+ ```
313
+
314
+ produces the following:
315
+
316
+ ```
317
+ seq 3 | parallel -j 0 -v "knife ec2 server create -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7000f019 -f m1.small -N webserver{} -r 'role[base],role[tc],role[users]'"
318
+ ```
319
+
320
+ which generates nodes named "webserver1", "webserver2" and "webserver3".
321
+
305
322
  Extract
306
323
  =======
307
324
  Spiceweasel may also be used to generate knife commands or Spiceweasel manifests in JSON or YAML.
@@ -30,13 +30,13 @@ begin
30
30
  ARGV << "-h" if ARGV.empty?
31
31
  cli = Spiceweasel::CLI.new
32
32
  cli.parse_options
33
- DEBUG = cli.config[:debug]
34
- PARALLEL = cli.config[:parallel]
35
- SITEINSTALL = cli.config[:siteinstall]
36
- NOVALIDATION = cli.config[:novalidation]
37
- EXTRACTLOCAL = cli.config[:extractlocal]
38
- EXTRACTYAML = cli.config[:extractyaml]
39
- EXTRACTJSON = cli.config[:extractjson]
33
+ Spiceweasel::DEBUG = cli.config[:debug]
34
+ Spiceweasel::PARALLEL = cli.config[:parallel]
35
+ Spiceweasel::SITEINSTALL = cli.config[:siteinstall]
36
+ Spiceweasel::NOVALIDATION = cli.config[:novalidation]
37
+ Spiceweasel::EXTRACTLOCAL = cli.config[:extractlocal]
38
+ Spiceweasel::EXTRACTYAML = cli.config[:extractyaml]
39
+ Spiceweasel::EXTRACTJSON = cli.config[:extractjson]
40
40
  rescue OptionParser::InvalidOption => e
41
41
  STDERR.puts e.message
42
42
  puts cli.opt_parser.to_s
@@ -51,13 +51,13 @@ if cli.config[:serverurl]
51
51
  options['knife_options'] += " --server-url " + cli.config[:serverurl]
52
52
  end
53
53
 
54
- if EXTRACTLOCAL || EXTRACTJSON || EXTRACTYAML
54
+ if Spiceweasel::EXTRACTLOCAL || Spiceweasel::EXTRACTJSON || Spiceweasel::EXTRACTYAML
55
55
  input = Spiceweasel::DirectoryExtractor.parse_objects
56
- STDOUT.puts "DEBUG: extract input: #{input}" if DEBUG
56
+ STDOUT.puts "DEBUG: extract input: #{input}" if Spiceweasel::DEBUG
57
57
  else
58
58
  begin
59
59
  file = ARGV.last
60
- STDOUT.puts "DEBUG: file: #{file}" if DEBUG
60
+ STDOUT.puts "DEBUG: file: #{file}" if Spiceweasel::DEBUG
61
61
  if (file.end_with?(".yml"))
62
62
  input = YAML.load_file ARGV.last
63
63
  elsif (file.end_with?(".json"))
@@ -66,16 +66,20 @@ else
66
66
  STDERR.puts "ERROR: Unknown file type, please use a file ending with either '.json' or '.yml'."
67
67
  exit(-1)
68
68
  end
69
+ rescue Psych::SyntaxError => e
70
+ STDERR.puts e.message
71
+ STDERR.puts "ERROR: Parsing error in #{file}."
72
+ exit(-1)
69
73
  rescue JSON::ParserError => e
70
74
  STDERR.puts e.message
71
- STDERR.puts "ERROR: Parsing error in the infrastructure file provided."
75
+ STDERR.puts "ERROR: Parsing error in #{file}."
72
76
  exit(-1)
73
77
  rescue Exception
74
78
  STDERR.puts "ERROR: No infrastructure .json or .yml file provided."
75
79
  puts cli.opt_parser.to_s
76
80
  exit(-1)
77
81
  end
78
- STDOUT.puts "DEBUG: file input: #{input}" if DEBUG
82
+ STDOUT.puts "DEBUG: file input: #{input}" if Spiceweasel::DEBUG
79
83
  end
80
84
 
81
85
  create = String.new()
@@ -107,9 +111,9 @@ elsif cli.config[:rebuild]
107
111
  puts delete unless delete.empty?
108
112
  puts create unless create.empty?
109
113
  else
110
- if EXTRACTJSON
114
+ if Spiceweasel::EXTRACTJSON
111
115
  puts JSON.pretty_generate(input)
112
- elsif EXTRACTYAML
116
+ elsif Spiceweasel::EXTRACTYAML
113
117
  puts input.to_yaml
114
118
  else
115
119
  puts create unless create.empty?
@@ -1,7 +1,7 @@
1
1
  #
2
2
  # Author:: Matt Ray (<matt@opscode.com>)
3
3
  #
4
- # Copyright:: 2011, Opscode, Inc <legal@opscode.com>
4
+ # Copyright:: 2011-2012, 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.
@@ -29,12 +29,12 @@ class Spiceweasel::CookbookList
29
29
  version = cookbook[cb][0].to_s || ""
30
30
  args = cookbook[cb][1] || ""
31
31
  end
32
- STDOUT.puts "DEBUG: cookbook: #{cb} #{version}" if DEBUG
32
+ STDOUT.puts "DEBUG: cookbook: #{cb} #{version}" if Spiceweasel::DEBUG
33
33
  if File.directory?("cookbooks")
34
34
  if File.directory?("cookbooks/#{cb}")
35
- validateMetadata(cb,version) unless NOVALIDATION
35
+ validateMetadata(cb,version) unless Spiceweasel::NOVALIDATION
36
36
  else
37
- if SITEINSTALL #use knife cookbook site install
37
+ if Spiceweasel::SITEINSTALL #use knife cookbook site install
38
38
  @create += "knife cookbook#{options['knife_options']} site install #{cb} #{version} #{args}\n"
39
39
  else #use knife cookbook site download, untar and then remove the tarball
40
40
  @create += "knife cookbook#{options['knife_options']} site download #{cb} #{version} --file cookbooks/#{cb}.tgz #{args}\n"
@@ -43,14 +43,14 @@ class Spiceweasel::CookbookList
43
43
  end
44
44
  end
45
45
  else
46
- STDERR.puts "'cookbooks' directory not found, unable to validate, download and load cookbooks" unless NOVALIDATION
46
+ STDERR.puts "'cookbooks' directory not found, unable to validate, download and load cookbooks" unless Spiceweasel::NOVALIDATION
47
47
  end
48
48
  @create += "knife cookbook#{options['knife_options']} upload #{cb}\n"
49
- @delete += "knife cookbook#{options['knife_options']} delete #{cb} #{version} -y\n"
49
+ @delete += "knife cookbook#{options['knife_options']} delete #{cb} #{version} -a -y\n"
50
50
 
51
51
  @cookbook_list[cb] = version
52
52
  end
53
- validateDependencies() unless NOVALIDATION
53
+ validateDependencies() unless Spiceweasel::NOVALIDATION
54
54
  end
55
55
  end
56
56
 
@@ -58,29 +58,28 @@ class Spiceweasel::CookbookList
58
58
  def validateMetadata(cookbook,version)
59
59
  #check metadata.rb for requested version
60
60
  metadata = File.open("cookbooks/#{cookbook}/metadata.rb").grep(/^version/)[0].split()[1].gsub(/"/,'').to_s
61
- STDOUT.puts "DEBUG: cookbook metadata version: #{metadata}" if DEBUG
61
+ STDOUT.puts "DEBUG: cookbook metadata version: #{metadata}" if Spiceweasel::DEBUG
62
62
  if version and (metadata != version)
63
63
  STDERR.puts "ERROR: Invalid version '#{version}' of '#{cookbook}' requested, '#{metadata}' is already in the cookbooks directory."
64
64
  exit(-1)
65
65
  end
66
66
  deps = File.open("cookbooks/#{cookbook}/metadata.rb").grep(/^depends/)
67
67
  deps.each do |dependency|
68
- STDOUT.puts "DEBUG: cookbook #{cookbook} metadata dependency: #{dependency}" if DEBUG
68
+ STDOUT.puts "DEBUG: cookbook #{cookbook} metadata dependency: #{dependency}" if Spiceweasel::DEBUG
69
69
  line = dependency.split()
70
- cbdep = ''
71
- if line[1] =~ /^"/ #ignore variables and versions
72
- cbdep = line[1].gsub(/"/,'')
70
+ if line[1] =~ /^["']/ #ignore variables and versions
71
+ cbdep = line[1].gsub(/["']/,'')
73
72
  cbdep.gsub!(/\,/,'') if cbdep.end_with?(',')
73
+ STDOUT.puts "DEBUG: cookbook #{cookbook} metadata depends: #{cbdep}" if Spiceweasel::DEBUG
74
+ @dependencies << cbdep
74
75
  end
75
- STDOUT.puts "DEBUG: cookbook #{cookbook} metadata depends: #{cbdep}" if DEBUG
76
- @dependencies << cbdep
77
76
  end
78
77
  return @cookbook
79
78
  end
80
79
 
81
80
  #compare the list of cookbook deps with those specified
82
81
  def validateDependencies()
83
- STDOUT.puts "DEBUG: cookbook validateDependencies: '#{@dependencies}'" if DEBUG
82
+ STDOUT.puts "DEBUG: cookbook validateDependencies: '#{@dependencies}'" if Spiceweasel::DEBUG
84
83
  @dependencies.each do |dep|
85
84
  if !member?(dep)
86
85
  STDERR.puts "ERROR: Cookbook dependency '#{dep}' is missing from the list of cookbooks in the manifest."
@@ -23,23 +23,23 @@ class Spiceweasel::DataBagList
23
23
  @create = @delete = ''
24
24
  if data_bags
25
25
  if !File.directory?("data_bags")
26
- STDERR.puts "ERROR: 'data_bags' directory not found, unable to validate or load data bag items" unless NOVALIDATION
26
+ STDERR.puts "ERROR: 'data_bags' directory not found, unable to validate or load data bag items" unless Spiceweasel::NOVALIDATION
27
27
  end
28
28
  data_bags.each do |data_bag|
29
29
  db = data_bag.keys[0]
30
- STDOUT.puts "DEBUG: data bag: #{db}" if DEBUG
30
+ STDOUT.puts "DEBUG: data bag: #{db}" if Spiceweasel::DEBUG
31
31
  if !File.directory?("data_bags/#{db}")
32
- STDERR.puts "ERROR: 'data_bags/#{db}' directory not found, unable to validate or load data bag items" unless NOVALIDATION
32
+ STDERR.puts "ERROR: 'data_bags/#{db}' directory not found, unable to validate or load data bag items" unless Spiceweasel::NOVALIDATION
33
33
  end
34
34
  @create += "knife data bag#{options['knife_options']} create #{db}\n"
35
35
  @delete += "knife data bag#{options['knife_options']} delete #{db} -y\n"
36
36
  items = data_bag[db] || []
37
37
  secret = nil
38
38
  while item = items.shift
39
- STDOUT.puts "DEBUG: data bag #{db} item: #{item}" if DEBUG
39
+ STDOUT.puts "DEBUG: data bag #{db} item: #{item}" if Spiceweasel::DEBUG
40
40
  if item.start_with?("secret")
41
41
  secret = item.split()[1]
42
- if !File.exists?(secret) and !NOVALIDATION
42
+ if !File.exists?(secret) and !Spiceweasel::NOVALIDATION
43
43
  STDERR.puts "ERROR: secret key #{secret} not found, unable to load encrypted data bags for data bag #{db}."
44
44
  exit(-1)
45
45
  end
@@ -48,10 +48,10 @@ class Spiceweasel::DataBagList
48
48
  if item =~ /\*/ #wildcard support, will fail if directory not present
49
49
  files = Dir.glob("data_bags/#{db}/#{item}.json")
50
50
  items += files.collect {|x| x[x.rindex('/')+1..-6]}
51
- STDOUT.puts "DEBUG: found items '#{items}' for data bag: #{db}" if DEBUG
51
+ STDOUT.puts "DEBUG: found items '#{items}' for data bag: #{db}" if Spiceweasel::DEBUG
52
52
  next
53
53
  end
54
- validateItem(db, item) unless NOVALIDATION
54
+ validateItem(db, item) unless Spiceweasel::NOVALIDATION
55
55
  if secret
56
56
  @create += "knife data bag#{options['knife_options']} from file #{db} #{item}.json --secret-file #{secret}\n"
57
57
  else
@@ -25,13 +25,13 @@ class Spiceweasel::DirectoryExtractor
25
25
  cookbooks = []
26
26
  Dir.glob("cookbooks/*").each do |cookbook_full_path|
27
27
  cookbook = cookbook_full_path.split('/').last
28
- STDOUT.puts "DEBUG: dir_ext: cookbook: '#{cookbook}'" if DEBUG
28
+ STDOUT.puts "DEBUG: dir_ext: cookbook: '#{cookbook}'" if Spiceweasel::DEBUG
29
29
  cookbook_data = Spiceweasel::CookbookData.new(cookbook)
30
30
  if cookbook_data.is_readable?
31
31
  cookbooks << cookbook_data.read
32
32
  end
33
33
  end
34
- STDOUT.puts "DEBUG: dir_ext: cookbooks: '#{cookbooks}'" if DEBUG
34
+ STDOUT.puts "DEBUG: dir_ext: cookbooks: '#{cookbooks}'" if Spiceweasel::DEBUG
35
35
  cookbooks = self.order_cookbooks_by_dependency(cookbooks)
36
36
  objects["cookbooks"] = cookbooks unless cookbooks.empty?
37
37
 
@@ -39,7 +39,7 @@ class Spiceweasel::DirectoryExtractor
39
39
  roles = []
40
40
  Dir.glob("roles/*.{rb,json}").each do |role_full_path|
41
41
  role = self.grab_name_from_path(role_full_path)
42
- STDOUT.puts "DEBUG: dir_ext: role: '#{role}'" if DEBUG
42
+ STDOUT.puts "DEBUG: dir_ext: role: '#{role}'" if Spiceweasel::DEBUG
43
43
  roles << {role => nil}
44
44
  end
45
45
  objects["roles"] = roles unless roles.nil?
@@ -47,7 +47,7 @@ class Spiceweasel::DirectoryExtractor
47
47
  environments = []
48
48
  Dir.glob("environments/*.{rb,json}").each do |environment_full_path|
49
49
  environment = self.grab_name_from_path(environment_full_path)
50
- STDOUT.puts "DEBUG: dir_ext: environment: '#{environment}'" if DEBUG
50
+ STDOUT.puts "DEBUG: dir_ext: environment: '#{environment}'" if Spiceweasel::DEBUG
51
51
  environments << {environment => nil}
52
52
  end
53
53
  objects["environments"] = environments unless environments.empty?
@@ -55,10 +55,10 @@ class Spiceweasel::DirectoryExtractor
55
55
  data_bags = []
56
56
  Dir.glob("data_bags/*").each do |data_bag_full_path|
57
57
  data_bag = data_bag_full_path.split('/').last
58
- STDOUT.puts "DEBUG: dir_ext: data_bag: '#{data_bag}'" if DEBUG
58
+ STDOUT.puts "DEBUG: dir_ext: data_bag: '#{data_bag}'" if Spiceweasel::DEBUG
59
59
  data_bag_items = []
60
60
  Dir.glob("#{data_bag_full_path}/*.{rb,json}").each do |data_bag_item_full_path|
61
- STDOUT.puts "DEBUG: dir_ext: data_bag: '#{data_bag}':'#{data_bag_item_full_path}'" if DEBUG
61
+ STDOUT.puts "DEBUG: dir_ext: data_bag: '#{data_bag}':'#{data_bag_item_full_path}'" if Spiceweasel::DEBUG
62
62
  data_bag_items << self.grab_name_from_path(data_bag_item_full_path)
63
63
  end if File.directory?(data_bag_full_path)
64
64
  data_bags << {data_bag => data_bag_items} unless data_bag_items.empty?
@@ -102,12 +102,12 @@ class Spiceweasel::DirectoryExtractor
102
102
  unsorted_cookbooks.push(cookbook)
103
103
  scount = scount + 1
104
104
  end
105
- STDOUT.puts "DEBUG: dir_ext: sorted_cookbooks: '#{sorted_cookbooks}' #{scount}" if DEBUG
105
+ STDOUT.puts "DEBUG: dir_ext: sorted_cookbooks: '#{sorted_cookbooks}' #{scount}" if Spiceweasel::DEBUG
106
106
  end
107
107
  if scount > 0
108
108
  remainders = unsorted_cookbooks.collect {|x| x['name']}
109
- STDOUT.puts "DEBUG: dir_ext: remainders: '#{remainders}'" if DEBUG
110
- if NOVALIDATION #stuff is missing, oh well
109
+ STDOUT.puts "DEBUG: dir_ext: remainders: '#{remainders}'" if Spiceweasel::DEBUG
110
+ if Spiceweasel::NOVALIDATION #stuff is missing, oh well
111
111
  sorted_cookbooks.push(remainders).flatten!
112
112
  else
113
113
  deps = unsorted_cookbooks.collect {|x| x['dependencies'].collect {|x| x['cookbook']} - sorted_cookbooks}
@@ -25,11 +25,11 @@ class Spiceweasel::EnvironmentList
25
25
  if environments
26
26
  environments.each do |env|
27
27
  environment = env.keys[0]
28
- STDOUT.puts "DEBUG: environment: #{environment}" if DEBUG
28
+ STDOUT.puts "DEBUG: environment: #{environment}" if Spiceweasel::DEBUG
29
29
  if File.directory?("environments")
30
- validate(environment, cookbooks) unless NOVALIDATION
30
+ validate(environment, cookbooks) unless Spiceweasel::NOVALIDATION
31
31
  else
32
- STDERR.puts "'environments' directory not found, unable to validate or load environments" unless NOVALIDATION
32
+ STDERR.puts "'environments' directory not found, unable to validate or load environments" unless Spiceweasel::NOVALIDATION
33
33
  end
34
34
  if File.exists?("environments/#{environment}.json")
35
35
  @create += "knife environment#{options['knife_options']} from file #{environment}.json\n"
@@ -56,7 +56,7 @@ class Spiceweasel::EnvironmentList
56
56
  envcookbooks = File.open("environments/#{environment}.rb").grep(/^cookbook /)
57
57
  envcookbooks.each do |cb|
58
58
  dep = cb.split()[1].gsub(/"/,'').gsub(/,/,'')
59
- STDOUT.puts "DEBUG: environment: '#{environment}' cookbook: '#{dep}'" if DEBUG
59
+ STDOUT.puts "DEBUG: environment: '#{environment}' cookbook: '#{dep}'" if Spiceweasel::DEBUG
60
60
  if !cookbooks.member?(dep)
61
61
  STDERR.puts "ERROR: Cookbook dependency '#{dep}' from environment '#{environment}' is missing from the list of cookbooks in the manifest."
62
62
  exit(-1)
@@ -67,16 +67,16 @@ class Spiceweasel::EnvironmentList
67
67
  f = File.read("environments/#{environment}.json")
68
68
  JSON.create_id = nil
69
69
  envfile = JSON.parse(f, {:symbolize_names => false})
70
- STDOUT.puts "DEBUG: environment: '#{environment}' file: '#{envfile}'" if DEBUG
70
+ STDOUT.puts "DEBUG: environment: '#{environment}' file: '#{envfile}'" if Spiceweasel::DEBUG
71
71
  #validate that the name inside the file matches
72
- STDOUT.puts "DEBUG: environment: '#{environment}' name: '#{envfile['name']}'" if DEBUG
72
+ STDOUT.puts "DEBUG: environment: '#{environment}' name: '#{envfile['name']}'" if Spiceweasel::DEBUG
73
73
  if !environment.eql?(envfile['name'])
74
74
  STDERR.puts "ERROR: Environment '#{environment}' listed in the manifest does not match the name '#{envfile['name']}' within the 'environments/#{environment}.json' file."
75
75
  exit(-1)
76
76
  end
77
77
  #validate the cookbooks exist if they're mentioned
78
78
  envfile['cookbook_versions'].keys.each do |cb|
79
- STDOUT.puts "DEBUG: environment: '#{environment}' cookbook: '#{cb}'" if DEBUG
79
+ STDOUT.puts "DEBUG: environment: '#{environment}' cookbook: '#{cb}'" if Spiceweasel::DEBUG
80
80
  if !cookbooks.member?(cb.to_s)
81
81
  STDERR.puts "ERROR: Cookbook dependency '#{cb}' from environment '#{environment}' is missing from the list of cookbooks in the manifest."
82
82
  exit(-1)
@@ -4,14 +4,14 @@ class Spiceweasel::NodeList
4
4
  if nodes
5
5
  nodes.each do |node|
6
6
  nname = node.keys[0]
7
- STDOUT.puts "DEBUG: node: '#{nname}'" if DEBUG
7
+ STDOUT.puts "DEBUG: node: '#{nname}'" if Spiceweasel::DEBUG
8
8
  #convert spaces to commas, drop multiple commas
9
9
  run_list = node[nname][0].gsub(/ /,',').gsub(/,+/,',')
10
- STDOUT.puts "DEBUG: node: 'node[nname]' run_list: '#{run_list}'" if DEBUG
11
- validateRunList(nname, run_list, cookbooks, roles) unless NOVALIDATION
10
+ STDOUT.puts "DEBUG: node: 'node[nname]' run_list: '#{run_list}'" if Spiceweasel::DEBUG
11
+ validateRunList(nname, run_list, cookbooks, roles) unless Spiceweasel::NOVALIDATION
12
12
  noptions = node[nname][1]
13
- STDOUT.puts "DEBUG: node: 'node[nname]' options: '#{noptions}'" if DEBUG
14
- validateOptions(nname, noptions, environments) unless NOVALIDATION
13
+ STDOUT.puts "DEBUG: node: 'node[nname]' options: '#{noptions}'" if Spiceweasel::DEBUG
14
+ validateOptions(nname, noptions, environments) unless Spiceweasel::NOVALIDATION
15
15
  #provider support
16
16
  if nname.start_with?("bluebox ","clodo ","cs ","ec2 ","gandi ","hp ","openstack ","rackspace ","slicehost ","terremark ","voxel ")
17
17
  provider = nname.split()
@@ -19,15 +19,15 @@ class Spiceweasel::NodeList
19
19
  if (provider.length == 2)
20
20
  count = provider[1]
21
21
  end
22
- if PARALLEL
22
+ if Spiceweasel::PARALLEL
23
23
  @create += "seq #{count} | parallel -j 0 -v \""
24
- @create += "knife #{provider[0]}#{options['knife_options']} server create #{noptions}"
24
+ @create += "knife #{provider[0]}#{options['knife_options']} server create #{noptions}".gsub(/\{\{n\}\}/, '{}')
25
25
  if run_list.length > 0
26
26
  @create += " -r '#{run_list}'\"\n"
27
27
  end
28
28
  else
29
- count.to_i.times do
30
- @create += "knife #{provider[0]}#{options['knife_options']} server create #{noptions}"
29
+ count.to_i.times do |i|
30
+ @create += "knife #{provider[0]}#{options['knife_options']} server create #{noptions}".gsub(/\{\{n\}\}/, (i + 1).to_s)
31
31
  if run_list.length > 0
32
32
  @create += " -r '#{run_list}'\n"
33
33
  end
@@ -46,8 +46,8 @@ class Spiceweasel::NodeList
46
46
  end
47
47
  @delete += "knife node#{options['knife_options']} list | xargs knife #{provider[0]} server delete -y\n"
48
48
  else #node bootstrap support
49
- nname.split.each do |server|
50
- @create += "knife bootstrap#{options['knife_options']} #{server} #{noptions}"
49
+ nname.split.each_with_index do |server, i|
50
+ @create += "knife bootstrap#{options['knife_options']} #{server} #{noptions}".gsub(/\{\{n\}\}/, (i + 1).to_s)
51
51
  if run_list.length > 0
52
52
  @create += " -r '#{run_list}'\n"
53
53
  end
@@ -25,11 +25,11 @@ class Spiceweasel::RoleList
25
25
  if roles
26
26
  flatroles = roles.collect {|x| x.keys}.flatten
27
27
  flatroles.each do |role|
28
- STDOUT.puts "DEBUG: role: #{role}" if DEBUG
28
+ STDOUT.puts "DEBUG: role: #{role}" if Spiceweasel::DEBUG
29
29
  if File.directory?("roles")
30
- validate(role, environments, cookbooks, flatroles) unless NOVALIDATION
30
+ validate(role, environments, cookbooks, flatroles) unless Spiceweasel::NOVALIDATION
31
31
  else
32
- STDERR.puts "ERROR: 'roles' directory not found, unable to validate or load roles" unless NOVALIDATION
32
+ STDERR.puts "ERROR: 'roles' directory not found, unable to validate or load roles" unless Spiceweasel::NOVALIDATION
33
33
  end
34
34
  if File.exists?("roles/#{role}.json")
35
35
  @create += "knife role#{options['knife_options']} from file #{role}.json\n"
@@ -48,7 +48,7 @@ class Spiceweasel::RoleList
48
48
  if File.exists?("roles/#{role}.rb")
49
49
  #validate that the name inside the file matches
50
50
  name = File.open("roles/#{role}.rb").grep(/^name/)[0].split()[1].gsub(/"/,'').to_s
51
- STDOUT.puts "DEBUG: role: '#{role}' name: '#{name}'" if DEBUG
51
+ STDOUT.puts "DEBUG: role: '#{role}' name: '#{name}'" if Spiceweasel::DEBUG
52
52
  if !role.eql?(name)
53
53
  STDERR.puts "ERROR: Role '#{role}' listed in the manifest does not match the name '#{name}' within the roles/#{role}.rb file."
54
54
  exit(-1)
@@ -56,12 +56,12 @@ class Spiceweasel::RoleList
56
56
  #grab any lines with 'recipe[' or 'role['
57
57
  rolerl = File.open("roles/#{role}.rb").grep(/recipe\[|role\[/)
58
58
  rolerl.each do |line|
59
- STDOUT.puts "DEBUG: role: '#{role}' line: '#{line}'" if DEBUG
59
+ STDOUT.puts "DEBUG: role: '#{role}' line: '#{line}'" if Spiceweasel::DEBUG
60
60
  line.strip.split(',').each do |rl|
61
61
  if rl =~ /recipe\[/ #it's a cookbook
62
62
  #split on the brackets and any colons
63
63
  dep = rl.split(/\[|\]/)[1].split(':')[0]
64
- STDOUT.puts "DEBUG: role: '#{role}' cookbook: '#{rl}': dep: '#{dep}'" if DEBUG
64
+ STDOUT.puts "DEBUG: role: '#{role}' cookbook: '#{rl}': dep: '#{dep}'" if Spiceweasel::DEBUG
65
65
  if !cookbooks.member?(dep)
66
66
  STDERR.puts "ERROR: Cookbook dependency '#{dep}' from role '#{role}' is missing from the list of cookbooks in the manifest."
67
67
  exit(-1)
@@ -69,7 +69,7 @@ class Spiceweasel::RoleList
69
69
  elsif rl =~ /role\[/ #it's a role
70
70
  #split on the brackets
71
71
  dep = rl.split(/\[|\]/)[1]
72
- STDOUT.puts "DEBUG: role: '#{role}' role: '#{rl}': dep: '#{dep}'" if DEBUG
72
+ STDOUT.puts "DEBUG: role: '#{role}' role: '#{rl}': dep: '#{dep}'" if Spiceweasel::DEBUG
73
73
  if !roles.member?(dep)
74
74
  STDERR.puts "ERROR: Role dependency '#{dep}' from role '#{role}' is missing from the list of roles in the manifest."
75
75
  exit(-1)
@@ -84,7 +84,7 @@ class Spiceweasel::RoleList
84
84
  JSON.create_id = nil
85
85
  rolefile = JSON.parse(f, {:symbolize_names => false})
86
86
  #validate that the name inside the file matches
87
- STDOUT.puts "DEBUG: role: '#{role}' name: '#{rolefile['name']}'" if DEBUG
87
+ STDOUT.puts "DEBUG: role: '#{role}' name: '#{rolefile['name']}'" if Spiceweasel::DEBUG
88
88
  if !role.eql?(rolefile['name'])
89
89
  STDERR.puts "ERROR: Role '#{role}' listed in the manifest does not match the name '#{rolefile['name']}' within the 'roles/#{role}.json' file."
90
90
  exit(-1)
@@ -94,7 +94,7 @@ class Spiceweasel::RoleList
94
94
  if rl =~ /recipe\[/ #it's a cookbook
95
95
  #split on the brackets and any colons
96
96
  dep = rl.split(/\[|\]/)[1].split(':')[0]
97
- STDOUT.puts "DEBUG: role: '#{role}' cookbook: '#{rl}': dep: '#{dep}'" if DEBUG
97
+ STDOUT.puts "DEBUG: role: '#{role}' cookbook: '#{rl}': dep: '#{dep}'" if Spiceweasel::DEBUG
98
98
  if !cookbooks.member?(dep)
99
99
  STDERR.puts "ERROR: Cookbook dependency '#{dep}' from role '#{role}' is missing from the list of cookbooks in the manifest."
100
100
  exit(-1)
@@ -102,7 +102,7 @@ class Spiceweasel::RoleList
102
102
  elsif rl =~ /role\[/ #it's a role
103
103
  #split on the brackets
104
104
  dep = rl.split(/\[|\]/)[1]
105
- STDOUT.puts "DEBUG: role: '#{role}' role: '#{rl}': dep: '#{dep}'" if DEBUG
105
+ STDOUT.puts "DEBUG: role: '#{role}' role: '#{rl}': dep: '#{dep}'" if Spiceweasel::DEBUG
106
106
  if !roles.member?(dep)
107
107
  STDERR.puts "ERROR: Role dependency '#{dep}' from role '#{role}' is missing from the list of roles in the manifest."
108
108
  exit(-1)
@@ -17,5 +17,5 @@
17
17
  #
18
18
 
19
19
  module Spiceweasel
20
- VERSION = "1.1.2"
20
+ VERSION = "1.2.0"
21
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spiceweasel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-05-23 00:00:00.000000000Z
13
+ date: 2012-09-06 00:00:00.000000000Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
17
- requirement: &70201875475900 !ruby/object:Gem::Requirement
17
+ requirement: &70331172604580 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70201875475900
25
+ version_requirements: *70331172604580
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: mixlib-cli
28
- requirement: &70201875475480 !ruby/object:Gem::Requirement
28
+ requirement: &70331172604160 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *70201875475480
36
+ version_requirements: *70331172604160
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: rspec
39
- requirement: &70201875475060 !ruby/object:Gem::Requirement
39
+ requirement: &70331172603740 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,7 +44,7 @@ dependencies:
44
44
  version: '0'
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *70201875475060
47
+ version_requirements: *70331172603740
48
48
  description: Provides a CLI tool for generating knife commands to build Chef-managed
49
49
  infrastructure from a simple YAML or JSON file.
50
50
  email: