spiceweasel 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,18 +1,18 @@
1
1
  Description
2
2
  ===========
3
- Spiceweasel is a command-line tool for batch loading Chef infrastructure from a file.. It provides a simple syntax in either JSON or YAML for describing and deploying infrastructure in order with the Chef command-line tool `knife`. This manifest may be bundled with a Chef repository to deploy the infrastructure contained within the repository and validate that the components listed are all present.
3
+ Spiceweasel is a command-line tool for batch loading Chef infrastructure from a file. It provides a simple syntax in either JSON or YAML for describing and deploying infrastructure in order with the Chef command-line tool `knife`. This manifest may be bundled with a Chef repository to deploy the infrastructure contained within the repository and validate that the components listed are all present.
4
4
 
5
5
  The `examples` directory provides example manifests based on the Quick Starts provided at [http://help.opscode.com/kb/otherhelp](http://help.opscode.com/kb/otherhelp).
6
6
 
7
- The [https://github.com/mattray/ravel-repo](https://github.com/mattray/ravel-repo) provides a working example for bootstrapping a Chef repository with Spiceweasel.
7
+ The [https://github.com/mattray/vbacd-repo](https://github.com/mattray/vbacd-repo) provides a working example for bootstrapping a Chef repository with Spiceweasel.
8
8
 
9
9
  The [CHANGELOG.md](https://github.com/mattray/spiceweasel/blob/master/CHANGELOG.md) covers current, previous and future development milestones and contains the features backlog.
10
10
 
11
11
  Requirements
12
12
  ============
13
- Spiceweasel currently depends on `knife` to run commands for it, but does not explicitly depend on the `chef` gem. Infrastructure files must either end in .json or .yml to be processed.
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.
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.
16
16
 
17
17
  File Syntax
18
18
  ===========
@@ -26,20 +26,17 @@ From the `example.yml`:
26
26
  cookbooks:
27
27
  - apache2:
28
28
  - apt:
29
- - 1.1.1
29
+ - 1.2.0
30
30
  - mysql:
31
-
32
31
  environments:
33
32
  - development:
34
33
  - qa:
35
34
  - production:
36
-
37
35
  roles:
38
36
  - base:
39
37
  - iisserver:
40
38
  - monitoring:
41
39
  - webserver:
42
-
43
40
  data bags:
44
41
  - users:
45
42
  - alice
@@ -51,7 +48,6 @@ data bags:
51
48
  - secret secret_key
52
49
  - mysql
53
50
  - rabbitmq
54
-
55
51
  nodes:
56
52
  - serverA:
57
53
  - role[base]
@@ -84,7 +80,7 @@ From the `example.json`:
84
80
  {"apache2":[]},
85
81
  {"apt":
86
82
  [
87
- "1.1.1"
83
+ "1.2.0"
88
84
  ]
89
85
  },
90
86
  {"mysql":[]}
@@ -174,7 +170,7 @@ The `cookbooks` section of the manifest currently supports `knife cookbook uploa
174
170
  cookbooks:
175
171
  - apache2:
176
172
  - apt:
177
- - 1.1.0
173
+ - 1.2.0
178
174
  - mysql:
179
175
  ```
180
176
 
@@ -182,7 +178,7 @@ produces the knife commands
182
178
 
183
179
  ```
184
180
  knife cookbook upload apache2
185
- knife cookbook site download apt 1.1.0 --file cookbooks/apt.tgz
181
+ knife cookbook site download apt 1.2.0 --file cookbooks/apt.tgz
186
182
  tar -C cookbooks/ -xf cookbooks/apt.tgz
187
183
  rm -f cookbooks/apt.tgz
188
184
  knife cookbook upload apt
@@ -253,8 +249,8 @@ knife data bag from file users alice.json
253
249
  knife data bag from file users bob.json
254
250
  knife data bag from file users chuck.json
255
251
  knife data bag create data
256
- knife data bag from file users dataA.json
257
- knife data bag from file users dataB.json
252
+ knife data bag from file data dataA.json
253
+ knife data bag from file data dataB.json
258
254
  knife data bag create passwords
259
255
  knife data bag from file passwords mysql.json --secret-file secret_key
260
256
  knife data bag from file passwords rabbitmq.json --secret-file secret_key
@@ -306,6 +302,25 @@ knife bootstrap windows ssh winboxB -x Administrator -P 'super_secret_password'
306
302
  knife bootstrap windows ssh winboxC -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
307
303
  ```
308
304
 
305
+ Extract
306
+ =======
307
+ Spiceweasel may also be used to generate knife commands or Spiceweasel manifests in JSON or YAML.
308
+
309
+ ```
310
+ spiceweasel --extractlocal
311
+ ```
312
+ When run in your Chef repository generates the `knife` commands required to upload all the existing infrastructure that is found in the cookbooks, roles, environments and data bags directories with validation.
313
+
314
+ ```
315
+ spiceweasel --extractjson
316
+ ```
317
+ When run in your Chef repository generates JSON-formatted output that may be captured and used as your Spiceweasel manifest file.
318
+
319
+ ```
320
+ spiceweasel --extractyaml
321
+ ```
322
+ When run in your Chef repository generates YAML-formatted output that may be captured and used as your Spiceweasel manifest file.
323
+
309
324
  Usage
310
325
  =====
311
326
  To parse a spiceweasel manifest, run the following from your Chef repository directory:
@@ -322,6 +337,9 @@ spiceweasel path/to/infrastructure.yml
322
337
 
323
338
  This will generate the knife commands to build the described infrastructure. Infrastructure manifest files must end in either `.json` or `.yml`.
324
339
 
340
+ OPTIONS
341
+ =======
342
+
325
343
  -c/--knifeconfig
326
344
  ----------------
327
345
  Specify a knife.rb configuration file to use with the knife commands.
@@ -338,6 +356,18 @@ The delete command will generate the knife commands to delete the infrastructure
338
356
  --------
339
357
  This is the default action, printing the knife commands to be run without executing them.
340
358
 
359
+ --extractlocal
360
+ --------------
361
+ When run in a chef repository, this will print the knife commands to be run.
362
+
363
+ --extractjson
364
+ --------------
365
+ When run in a chef repository, this will print a new JSON manifest that may be used as input to Spiceweasel.
366
+
367
+ --extractyaml
368
+ --------------
369
+ When run in a chef repository, this will print a new YAML manifest that may be used as input to Spiceweasel.
370
+
341
371
  -h/--help
342
372
  ---------
343
373
  Print the currently-supported usage options for spiceweasel.
@@ -366,7 +396,7 @@ License and Author
366
396
  ==================
367
397
  Author: Matt Ray <matt@opscode.com>
368
398
 
369
- Copyright: 2011 Opscode, Inc
399
+ Copyright: 2011-2012 Opscode, Inc
370
400
 
371
401
  Licensed under the Apache License, Version 2.0 (the "License");
372
402
  you may not use this file except in compliance with the License.
@@ -34,6 +34,9 @@ begin
34
34
  PARALLEL = cli.config[:parallel]
35
35
  SITEINSTALL = cli.config[:siteinstall]
36
36
  NOVALIDATION = cli.config[:novalidation]
37
+ EXTRACTLOCAL = cli.config[:extractlocal]
38
+ EXTRACTYAML = cli.config[:extractyaml]
39
+ EXTRACTJSON = cli.config[:extractjson]
37
40
  rescue OptionParser::InvalidOption => e
38
41
  STDERR.puts e.message
39
42
  puts cli.opt_parser.to_s
@@ -41,28 +44,37 @@ rescue OptionParser::InvalidOption => e
41
44
  end
42
45
 
43
46
  if cli.config[:knifeconfig]
44
- options['knife_options']=" -c "+cli.config[:knifeconfig]
47
+ options['knife_options'] += " -c " + cli.config[:knifeconfig]
45
48
  end
46
49
 
47
- begin
48
- file = ARGV.last
49
- STDOUT.puts "DEBUG: file: #{file}" if cli.config[:debug]
50
- if (file.end_with?(".yml"))
51
- input = YAML.load_file ARGV.last
52
- elsif (file.end_with?(".json"))
53
- input = JSON.parse(File.read(ARGV.last))
54
- else
55
- STDERR.puts "ERROR: Unknown file type, please use a file ending with either '.json' or '.yml'."
50
+ if cli.config[:serverurl]
51
+ options['knife_options'] += " --server-url " + cli.config[:serverurl]
52
+ end
53
+
54
+ if EXTRACTLOCAL || EXTRACTJSON || EXTRACTYAML
55
+ input = Spiceweasel::DirectoryExtractor.parse_objects
56
+ STDOUT.puts "DEBUG: extract input: #{input}" if DEBUG
57
+ else
58
+ begin
59
+ file = ARGV.last
60
+ STDOUT.puts "DEBUG: file: #{file}" if DEBUG
61
+ if (file.end_with?(".yml"))
62
+ input = YAML.load_file ARGV.last
63
+ elsif (file.end_with?(".json"))
64
+ input = JSON.parse(File.read(ARGV.last))
65
+ else
66
+ STDERR.puts "ERROR: Unknown file type, please use a file ending with either '.json' or '.yml'."
67
+ exit(-1)
68
+ end
69
+ rescue JSON::ParserError => e
70
+ STDERR.puts e.message
71
+ STDERR.puts "ERROR: Parsing error in the infrastructure file provided."
72
+ exit(-1)
73
+ rescue Exception
74
+ STDERR.puts "ERROR: No infrastructure .json or .yml file provided."
75
+ puts cli.opt_parser.to_s
56
76
  exit(-1)
57
77
  end
58
- rescue JSON::ParserError => e
59
- STDERR.puts e.message
60
- STDERR.puts "ERROR: Parsing error in the infrastructure file provided."
61
- exit(-1)
62
- rescue Exception
63
- STDERR.puts "ERROR: No infrastructure .json or .yml file provided."
64
- puts cli.opt_parser.to_s
65
- exit(-1)
66
78
  end
67
79
 
68
80
  create = String.new()
@@ -94,7 +106,13 @@ elsif cli.config[:rebuild]
94
106
  puts delete unless delete.empty?
95
107
  puts create unless create.empty?
96
108
  else
97
- puts create unless create.empty?
109
+ if EXTRACTJSON
110
+ puts JSON.pretty_generate(input)
111
+ elsif EXTRACTYAML
112
+ puts input.to_yaml
113
+ else
114
+ puts create unless create.empty?
115
+ end
98
116
  end
99
117
  #else
100
118
  #eventually we will execute instead of printing knife commands
@@ -23,4 +23,6 @@ module Spiceweasel
23
23
  autoload :RoleList, 'spiceweasel/role_list'
24
24
  autoload :DataBagList, 'spiceweasel/data_bag_list'
25
25
  autoload :NodeList, 'spiceweasel/node_list'
26
+ autoload :DirectoryExtractor, 'spiceweasel/directory_extractor'
27
+ autoload :CookbookData, 'spiceweasel/cookbook_data'
26
28
  end
@@ -4,7 +4,19 @@ require 'spiceweasel/version'
4
4
  class Spiceweasel::CLI
5
5
  include Mixlib::CLI
6
6
 
7
- banner("Usage: spiceweasel [option] file")
7
+ banner("Usage: spiceweasel [option] file\n spiceweasel [option] --extractlocal")
8
+
9
+ option :extractlocal,
10
+ :long => "--extractlocal",
11
+ :description => "Use contents of local chef repository directories to generate knife commands to build infrastructure"
12
+
13
+ option :extractjson,
14
+ :long => "--extractjson",
15
+ :description => "Use contents of local chef repository directories to generate JSON spiceweasel manifest"
16
+
17
+ option :extractyaml,
18
+ :long => "--extractyaml",
19
+ :description => "Use contents of local chef repository directories to generate YAML spiceweasel manifest"
8
20
 
9
21
  option :debug,
10
22
  :long => "--debug",
@@ -14,7 +26,7 @@ class Spiceweasel::CLI
14
26
  option :delete,
15
27
  :short => "-d",
16
28
  :long => "--delete",
17
- :description => "Print the knife commands to be delete the infrastructure",
29
+ :description => "Print the knife commands to delete the infrastructure",
18
30
  :boolean => true
19
31
 
20
32
  option :dryrun,
@@ -31,10 +43,15 @@ class Spiceweasel::CLI
31
43
  :show_options => true,
32
44
  :exit => 0
33
45
 
46
+ option :serverurl,
47
+ :short => "-s URL",
48
+ :long => "--server-url URL",
49
+ :description => "Specify the Chef Server URL"
50
+
34
51
  option :knifeconfig,
35
52
  :short => "-c CONFIG",
36
53
  :long => "--knifeconfig CONFIG",
37
- :description => "Specify the knife.rb configuration file to use"
54
+ :description => "Specify the knife.rb configuration file"
38
55
 
39
56
  option :novalidation,
40
57
  :long => "--novalidation",
@@ -60,7 +77,7 @@ class Spiceweasel::CLI
60
77
  option :version,
61
78
  :short => "-v",
62
79
  :long => "--version",
63
- :description => "Version",
80
+ :description => "Show spiceweasel version",
64
81
  :boolean => true,
65
82
  :proc => lambda {|v| puts "Spiceweasel: #{Spiceweasel::VERSION}" },
66
83
  :exit => 0
@@ -0,0 +1,66 @@
1
+ #
2
+ # Author:: Geoff Meakin
3
+ # Author:: Matt Ray (<matt@opscode.com>)
4
+ #
5
+ # Copyright:: 2012, Opscode, Inc <legal@opscode.com>
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ class Spiceweasel::CookbookData
21
+
22
+ attr_accessor :_name, :_dependencies, :_version
23
+
24
+ def initialize(file_name)
25
+ @_name = file_name.split('/').last
26
+ @_dependencies = []
27
+ @_version = ""
28
+ @file_name = file_name
29
+ end
30
+
31
+ def is_readable?
32
+ return false unless File.directory?("cookbooks/#{@_name}")
33
+ return false unless File.exists?("cookbooks/#{@_name}/metadata.rb")
34
+ true
35
+ end
36
+
37
+ def read
38
+ if File.exists?("cookbooks/#{@_name}/metadata.rb") && File.readable?("cookbooks/#{@_name}/metadata.rb")
39
+ self.instance_eval(IO.read("cookbooks/#{@_name}/metadata.rb"), "cookbooks/#{@_name}/metadata.rb", 1)
40
+ else
41
+ raise IOError, "Cannot open or read cookbooks/#{@_name}/metadata.rb!"
42
+ end
43
+ {:name => @_name, :version => @_version, :dependencies => @_dependencies }
44
+ end
45
+
46
+ def name(*args) # Override metadata.rb DSL
47
+ @_name = args.shift
48
+ end
49
+
50
+ def version(*args) # Override metadata.rb DSL
51
+ @_version = args.shift
52
+ end
53
+
54
+ def depends(*args) # Override metadata.rb DSL
55
+ cookbook = args.shift
56
+ if args.length > 0
57
+ cookbook_version = args.shift
58
+ end
59
+ @_dependencies << {:cookbook => cookbook, :version => cookbook_version}
60
+ end
61
+
62
+ def method_missing(m, *args, &block)
63
+ true
64
+ end
65
+
66
+ end
@@ -65,13 +65,14 @@ class Spiceweasel::CookbookList
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
69
  line = dependency.split()
69
70
  cbdep = ''
70
- if line[1][0].eql?('"') #ignore variables and versions
71
+ if line[1] =~ /^"/ #ignore variables and versions
71
72
  cbdep = line[1].gsub(/"/,'')
72
73
  cbdep.gsub!(/\,/,'') if cbdep.end_with?(',')
73
74
  end
74
- STDOUT.puts "DEBUG: #{cookbook} metadata depends: #{cbdep}" if DEBUG
75
+ STDOUT.puts "DEBUG: cookbook #{cookbook} metadata depends: #{cbdep}" if DEBUG
75
76
  @dependencies << cbdep
76
77
  end
77
78
  return @cookbook
@@ -79,6 +80,7 @@ class Spiceweasel::CookbookList
79
80
 
80
81
  #compare the list of cookbook deps with those specified
81
82
  def validateDependencies()
83
+ STDOUT.puts "DEBUG: cookbook validateDependencies: '#{@dependencies}'" if DEBUG
82
84
  @dependencies.each do |dep|
83
85
  if !member?(dep)
84
86
  STDERR.puts "ERROR: Cookbook dependency '#{dep}' is missing from the list of cookbooks in the manifest."
@@ -0,0 +1,140 @@
1
+ #
2
+ # Author:: Geoff Meakin
3
+ # Author:: Matt Ray (<matt@opscode.com>)
4
+ #
5
+ # Copyright:: 2012, Opscode, Inc <legal@opscode.com>
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ class Spiceweasel::DirectoryExtractor
21
+
22
+ def self.parse_objects
23
+ objects = {"cookbooks" => nil, "roles" => nil, "environments" => nil, "data bags" => nil, "nodes" => nil}
24
+ # COOKBOOKS
25
+ cookbooks = []
26
+ Dir.glob("cookbooks/*").each do |cookbook_full_path|
27
+ cookbook = self.grab_filename_from_path cookbook_full_path
28
+ STDOUT.puts "DEBUG: dir_ext: cookbook: '#{cookbook}'" if DEBUG
29
+ cookbook_data = Spiceweasel::CookbookData.new(cookbook)
30
+ if cookbook_data.is_readable?
31
+ cookbooks << cookbook_data.read
32
+ end
33
+ end
34
+ cookbook_names = self.order_cookbooks_by_dependency cookbooks
35
+ objects["cookbooks"] = cookbook_names unless cookbook_names.empty?
36
+
37
+ # ROLES
38
+ roles = []
39
+ Dir.glob("roles/*.{rb,json}").each do |role_full_path|
40
+ role = self.grab_name_from_path role_full_path
41
+ STDOUT.puts "DEBUG: dir_ext: role: '#{role}'" if DEBUG
42
+ roles << {role => nil}
43
+ end
44
+ objects["roles"] = roles unless roles.nil?
45
+ # ENVIRONMENTS
46
+ environments = []
47
+ Dir.glob("environments/*.{rb,json}").each do |environment_full_path|
48
+ environment = self.grab_name_from_path environment_full_path
49
+ STDOUT.puts "DEBUG: dir_ext: environment: '#{environment}'" if DEBUG
50
+ environments << {environment => nil}
51
+ end
52
+ objects["environments"] = environments unless environments.empty?
53
+ # DATA BAGS
54
+ data_bags = []
55
+ Dir.glob("data_bags/*").each do |data_bag_full_path|
56
+ data_bag = data_bag_full_path.split('/').last
57
+ STDOUT.puts "DEBUG: dir_ext: data_bag: '#{data_bag}'" if DEBUG
58
+ data_bag_items = []
59
+ Dir.glob("#{data_bag_full_path}/*.{rb,json}").each do |data_bag_item_full_path|
60
+ STDOUT.puts "DEBUG: dir_ext: data_bag: '#{data_bag}':'#{data_bag_item_full_path}'" if DEBUG
61
+ data_bag_items << self.grab_name_from_path(data_bag_item_full_path)
62
+ end if File.directory?(data_bag_full_path)
63
+ data_bags << {data_bag => data_bag_items} unless data_bag_items.empty?
64
+ end
65
+ objects["data bags"] = data_bags unless data_bags.empty?
66
+ # NODES
67
+ # TODO: Cant use this yet as node_list.rb doesnt support node from file syntax but expects the node info to be part of the objects passed in
68
+ # nodes = []
69
+ # Dir.glob("nodes/*.{rb,json}").each do |node_full_path|
70
+ # node = self.grab_name_from_path node_full_path
71
+ # nodes << {node => nil}
72
+ # end
73
+ # objects["nodes"] = nodes unless nodes.empty?
74
+
75
+ objects
76
+ end
77
+
78
+ def self.grab_filename_from_path path
79
+ path.split('/').last
80
+ end
81
+
82
+ def self.grab_name_from_path path
83
+ name = self.grab_filename_from_path(path).split('.')
84
+ if name.length>1
85
+ name.pop
86
+ end
87
+ name.join('.')
88
+ end
89
+ def self.order_cookbooks_by_dependency cookbooks
90
+
91
+ # Weak algorithm, not particularly elegant, ignores version info as unlikely to have two versions of a cookbook anyway
92
+ ordered_cookbooks = []
93
+
94
+ left_to_sort = cookbooks
95
+ num_sorted_cookbooks_this_iteration = -1
96
+
97
+ while left_to_sort.size > 0 && num_sorted_cookbooks_this_iteration != 0
98
+
99
+ unsorted_cookbooks = left_to_sort
100
+ left_to_sort = []
101
+ num_sorted_cookbooks_this_iteration
102
+ unsorted_cookbooks.each do |cookbook|
103
+ name = cookbook[:name]
104
+ dependencies = cookbook[:dependencies]
105
+
106
+ next if ordered_cookbooks.include? name
107
+
108
+ if dependencies.nil?
109
+ ordered_cookbooks << name
110
+ num_sorted_cookbooks_this_iteration += 1
111
+ next
112
+ end
113
+
114
+ dependencies_satisfied_yet = true
115
+ dependencies.each {|dependency| dependencies_satisfied_yet = false unless ordered_cookbooks.include? dependency[:cookbook]}
116
+ if dependencies_satisfied_yet
117
+ ordered_cookbooks << name
118
+ num_sorted_cookbooks_this_iteration += 1
119
+ next
120
+ end
121
+
122
+ left_to_sort << cookbook
123
+
124
+ end
125
+
126
+ end
127
+
128
+ if left_to_sort.size > 0
129
+ STDERR.puts "ERROR: Dependencies not satisfied or circular dependencies between cookbooks: #{left_to_sort}"
130
+ exit(-1)
131
+ end
132
+ output_cookbooks = []
133
+ ordered_cookbooks.each do |cookbook|
134
+ output_cookbooks << {cookbook => nil}
135
+ end
136
+ output_cookbooks
137
+
138
+ end
139
+
140
+ end
@@ -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.
@@ -65,15 +65,17 @@ class Spiceweasel::EnvironmentList
65
65
  elsif File.exists?("environments/#{environment}.json")
66
66
  #load the json, don't symbolize since we don't need json_class
67
67
  f = File.read("environments/#{environment}.json")
68
- envfile = JSON.parse(f, {symbolize_names: 'false'})
68
+ JSON.create_id = nil
69
+ envfile = JSON.parse(f, {:symbolize_names => false})
70
+ STDOUT.puts "DEBUG: environment: '#{environment}' file: '#{envfile}'" if DEBUG
69
71
  #validate that the name inside the file matches
70
- STDOUT.puts "DEBUG: environment: '#{environment}' name: '#{envfile[:name]}'" if DEBUG
71
- if !environment.eql?(envfile[:name])
72
- STDERR.puts "ERROR: Environment '#{environment}' listed in the manifest does not match the name '#{envfile[:name]}' within the 'environments/#{environment}.json' file."
72
+ STDOUT.puts "DEBUG: environment: '#{environment}' name: '#{envfile['name']}'" if DEBUG
73
+ if !environment.eql?(envfile['name'])
74
+ STDERR.puts "ERROR: Environment '#{environment}' listed in the manifest does not match the name '#{envfile['name']}' within the 'environments/#{environment}.json' file."
73
75
  exit(-1)
74
76
  end
75
77
  #validate the cookbooks exist if they're mentioned
76
- envfile[:cookbook_versions].keys.each do |cb|
78
+ envfile['cookbook_versions'].keys.each do |cb|
77
79
  STDOUT.puts "DEBUG: environment: '#{environment}' cookbook: '#{cb}'" if DEBUG
78
80
  if !cookbooks.member?(cb.to_s)
79
81
  STDERR.puts "ERROR: Cookbook dependency '#{cb}' from environment '#{environment}' is missing from the list of cookbooks in the manifest."
@@ -13,7 +13,7 @@ class Spiceweasel::NodeList
13
13
  STDOUT.puts "DEBUG: node: 'node[nname]' options: '#{noptions}'" if DEBUG
14
14
  validateOptions(nname, noptions, environments) unless NOVALIDATION
15
15
  #provider support
16
- if nname.start_with?("bluebox ","clodo ","cs ","ec2 ","gandi ","openstack ","rackspace ","slicehost ","terremark ","voxel ")
16
+ if nname.start_with?("bluebox ","clodo ","cs ","ec2 ","gandi ","hp ","openstack ","rackspace ","slicehost ","terremark ","voxel ")
17
17
  provider = nname.split()
18
18
  count = 1
19
19
  if (provider.length == 2)
@@ -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.
@@ -81,15 +81,16 @@ class Spiceweasel::RoleList
81
81
  elsif File.exists?("roles/#{role}.json")
82
82
  #load the json, don't symbolize since we don't need json_class
83
83
  f = File.read("roles/#{role}.json")
84
- rolefile = JSON.parse(f, {symbolize_names: 'false'})
84
+ JSON.create_id = nil
85
+ rolefile = JSON.parse(f, {:symbolize_names => false})
85
86
  #validate that the name inside the file matches
86
- STDOUT.puts "DEBUG: role: '#{role}' name: '#{rolefile[:name]}'" if DEBUG
87
- if !role.eql?(rolefile[:name])
88
- STDERR.puts "ERROR: Role '#{role}' listed in the manifest does not match the name '#{rolefile[:name]}' within the 'roles/#{role}.json' file."
87
+ STDOUT.puts "DEBUG: role: '#{role}' name: '#{rolefile['name']}'" if DEBUG
88
+ if !role.eql?(rolefile['name'])
89
+ STDERR.puts "ERROR: Role '#{role}' listed in the manifest does not match the name '#{rolefile['name']}' within the 'roles/#{role}.json' file."
89
90
  exit(-1)
90
91
  end
91
92
  #validate the cookbooks and roles exist if they're mentioned in run_lists
92
- rolefile[:run_list].each do |rl|
93
+ rolefile['run_list'].each do |rl|
93
94
  if rl =~ /recipe\[/ #it's a cookbook
94
95
  #split on the brackets and any colons
95
96
  dep = rl.split(/\[|\]/)[1].split(':')[0]
@@ -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.
@@ -17,5 +17,5 @@
17
17
  #
18
18
 
19
19
  module Spiceweasel
20
- VERSION = "1.0.0"
20
+ VERSION = "1.1.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.0.0
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,12 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-12-23 00:00:00.000000000 -06:00
14
- default_executable:
13
+ date: 2012-05-22 00:00:00.000000000Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: json
18
- requirement: &2151771000 !ruby/object:Gem::Requirement
17
+ requirement: &70140549239420 !ruby/object:Gem::Requirement
19
18
  none: false
20
19
  requirements:
21
20
  - - ! '>='
@@ -23,10 +22,10 @@ dependencies:
23
22
  version: '0'
24
23
  type: :runtime
25
24
  prerelease: false
26
- version_requirements: *2151771000
25
+ version_requirements: *70140549239420
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: mixlib-cli
29
- requirement: &2151768280 !ruby/object:Gem::Requirement
28
+ requirement: &70140549239000 !ruby/object:Gem::Requirement
30
29
  none: false
31
30
  requirements:
32
31
  - - ! '>='
@@ -34,10 +33,10 @@ dependencies:
34
33
  version: '0'
35
34
  type: :runtime
36
35
  prerelease: false
37
- version_requirements: *2151768280
36
+ version_requirements: *70140549239000
38
37
  - !ruby/object:Gem::Dependency
39
38
  name: rspec
40
- requirement: &2151764400 !ruby/object:Gem::Requirement
39
+ requirement: &70140549238580 !ruby/object:Gem::Requirement
41
40
  none: false
42
41
  requirements:
43
42
  - - ! '>='
@@ -45,7 +44,7 @@ dependencies:
45
44
  version: '0'
46
45
  type: :development
47
46
  prerelease: false
48
- version_requirements: *2151764400
47
+ version_requirements: *70140549238580
49
48
  description: Provides a CLI tool for generating knife commands to build Chef-managed
50
49
  infrastructure from a simple YAML or JSON file.
51
50
  email:
@@ -58,8 +57,10 @@ extra_rdoc_files: []
58
57
  files:
59
58
  - bin/spiceweasel
60
59
  - lib/spiceweasel/cli.rb
60
+ - lib/spiceweasel/cookbook_data.rb
61
61
  - lib/spiceweasel/cookbook_list.rb
62
62
  - lib/spiceweasel/data_bag_list.rb
63
+ - lib/spiceweasel/directory_extractor.rb
63
64
  - lib/spiceweasel/environment_list.rb
64
65
  - lib/spiceweasel/node_list.rb
65
66
  - lib/spiceweasel/role_list.rb
@@ -67,7 +68,6 @@ files:
67
68
  - lib/spiceweasel.rb
68
69
  - README.md
69
70
  - spec/bin/spiceweasel_spec.rb
70
- has_rdoc: true
71
71
  homepage: http://github.com/mattray/spiceweasel
72
72
  licenses: []
73
73
  post_install_message:
@@ -88,9 +88,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
88
  version: '0'
89
89
  requirements: []
90
90
  rubyforge_project: spiceweasel
91
- rubygems_version: 1.6.2
91
+ rubygems_version: 1.8.15
92
92
  signing_key:
93
93
  specification_version: 3
94
94
  summary: CLI for generating Chef knife commands from a simple YAML file.
95
95
  test_files:
96
96
  - spec/bin/spiceweasel_spec.rb
97
+ has_rdoc: