spiceweasel 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/bin/spiceweasel CHANGED
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # Author:: Matt Ray (<matt@opscode.com>)
5
5
  #
6
- # Copyright:: 2011, Opscode, Inc <legal@opscode.com>
6
+ # Copyright:: 2011-2012, Opscode, Inc <legal@opscode.com>
7
7
  #
8
8
  # Licensed under the Apache License, Version 2.0 (the "License");
9
9
  # you may not use this file except in compliance with the License.
@@ -18,108 +18,6 @@
18
18
  # limitations under the License.
19
19
  #
20
20
 
21
- require 'json'
22
- require 'yaml'
23
-
24
21
  require 'spiceweasel'
25
22
 
26
- options={'knife_options' => ''}
27
-
28
- #process command line options
29
- begin
30
- ARGV << "-h" if ARGV.empty?
31
- cli = Spiceweasel::CLI.new
32
- cli.parse_options
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
- rescue OptionParser::InvalidOption => e
41
- STDERR.puts e.message
42
- puts cli.opt_parser.to_s
43
- exit(-1)
44
- end
45
-
46
- if cli.config[:knifeconfig]
47
- options['knife_options'] += " -c " + cli.config[:knifeconfig]
48
- end
49
-
50
- if cli.config[:serverurl]
51
- options['knife_options'] += " --server-url " + cli.config[:serverurl]
52
- end
53
-
54
- if Spiceweasel::EXTRACTLOCAL || Spiceweasel::EXTRACTJSON || Spiceweasel::EXTRACTYAML
55
- input = Spiceweasel::DirectoryExtractor.parse_objects
56
- STDOUT.puts "DEBUG: extract input: #{input}" if Spiceweasel::DEBUG
57
- else
58
- begin
59
- file = ARGV.last
60
- STDOUT.puts "DEBUG: file: #{file}" if Spiceweasel::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 Psych::SyntaxError => e
70
- STDERR.puts e.message
71
- STDERR.puts "ERROR: Parsing error in #{file}."
72
- exit(-1)
73
- rescue JSON::ParserError => e
74
- STDERR.puts e.message
75
- STDERR.puts "ERROR: Parsing error in #{file}."
76
- exit(-1)
77
- rescue Exception
78
- STDERR.puts "ERROR: No infrastructure .json or .yml file provided."
79
- puts cli.opt_parser.to_s
80
- exit(-1)
81
- end
82
- STDOUT.puts "DEBUG: file input: #{input}" if Spiceweasel::DEBUG
83
- end
84
-
85
- create = String.new()
86
- delete = String.new()
87
-
88
- cookbook_list = Spiceweasel::CookbookList.new(input['cookbooks'], options)
89
- environment_list = Spiceweasel::EnvironmentList.new(input['environments'], cookbook_list, options)
90
- role_list = Spiceweasel::RoleList.new(input['roles'], environment_list, cookbook_list, options)
91
- data_bag_list = Spiceweasel::DataBagList.new(input['data bags'], options)
92
- node_list = Spiceweasel::NodeList.new(input['nodes'], cookbook_list, environment_list, role_list, options)
93
-
94
- create += cookbook_list.create
95
- create += environment_list.create
96
- create += role_list.create
97
- create += data_bag_list.create
98
- create += node_list.create
99
-
100
- delete += cookbook_list.delete
101
- delete += environment_list.delete
102
- delete += role_list.delete
103
- delete += data_bag_list.delete
104
- delete += node_list.delete
105
-
106
- #just print the knife commands, do not execute
107
- #if cli.config[:dryrun]
108
- if cli.config[:delete]
109
- puts delete unless delete.empty?
110
- elsif cli.config[:rebuild]
111
- puts delete unless delete.empty?
112
- puts create unless create.empty?
113
- else
114
- if Spiceweasel::EXTRACTJSON
115
- puts JSON.pretty_generate(input)
116
- elsif Spiceweasel::EXTRACTYAML
117
- puts input.to_yaml
118
- else
119
- puts create unless create.empty?
120
- end
121
- end
122
- #else
123
- #eventually we will execute instead of printing knife commands
124
- #puts "BAM!"
125
- #end
23
+ Spiceweasel::CLI.new.run
data/lib/spiceweasel.rb CHANGED
@@ -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.
@@ -16,13 +16,7 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
- module Spiceweasel
20
- autoload :CLI, 'spiceweasel/cli'
21
- autoload :CookbookList, 'spiceweasel/cookbook_list'
22
- autoload :EnvironmentList, 'spiceweasel/environment_list'
23
- autoload :RoleList, 'spiceweasel/role_list'
24
- autoload :DataBagList, 'spiceweasel/data_bag_list'
25
- autoload :NodeList, 'spiceweasel/node_list'
26
- autoload :DirectoryExtractor, 'spiceweasel/directory_extractor'
27
- autoload :CookbookData, 'spiceweasel/cookbook_data'
28
- end
19
+ require 'spiceweasel/version'
20
+ require 'spiceweasel/cli'
21
+ require 'spiceweasel/config'
22
+ require 'spiceweasel/log'
@@ -1,85 +1,251 @@
1
- require 'mixlib/cli'
2
- require 'spiceweasel/version'
3
-
4
- class Spiceweasel::CLI
5
- include Mixlib::CLI
6
-
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"
20
-
21
- option :debug,
22
- :long => "--debug",
23
- :description => "Verbose debugging messages",
24
- :boolean => true
25
-
26
- option :delete,
27
- :short => "-d",
28
- :long => "--delete",
29
- :description => "Print the knife commands to delete the infrastructure",
30
- :boolean => true
31
-
32
- option :dryrun,
33
- :long => "--dryrun",
34
- :description => "Print the knife commands to be executed to STDOUT",
35
- :boolean => true
36
-
37
- option :help,
38
- :short => "-h",
39
- :long => "--help",
40
- :description => "Show this message",
41
- :on => :tail,
42
- :boolean => true,
43
- :show_options => true,
44
- :exit => 0
45
-
46
- option :serverurl,
47
- :short => "-s URL",
48
- :long => "--server-url URL",
49
- :description => "Specify the Chef Server URL"
50
-
51
- option :knifeconfig,
52
- :short => "-c CONFIG",
53
- :long => "--knifeconfig CONFIG",
54
- :description => "Specify the knife.rb configuration file"
55
-
56
- option :novalidation,
57
- :long => "--novalidation",
58
- :description => "Disable validation",
59
- :boolean => true
60
-
61
- option :parallel,
62
- :long => "--parallel",
63
- :description => "Use the GNU 'parallel' command to parallelize 'knife VENDOR server create' commands that are not order-dependent",
64
- :boolean => true
65
-
66
- option :rebuild,
67
- :short => "-r",
68
- :long => "--rebuild",
69
- :description => "Print the knife commands to be delete and recreate the infrastructure",
70
- :boolean => true
71
-
72
- option :siteinstall,
73
- :long => "--siteinstall",
74
- :description => "Use the 'install' command with 'knife cookbook site' instead of the default 'download'",
75
- :boolean => true
76
-
77
- option :version,
78
- :short => "-v",
79
- :long => "--version",
80
- :description => "Show spiceweasel version",
81
- :boolean => true,
82
- :proc => lambda {|v| puts "Spiceweasel: #{Spiceweasel::VERSION}" },
83
- :exit => 0
1
+ #
2
+ # Author:: Matt Ray (<matt@opscode.com>)
3
+ #
4
+ # Copyright:: 2011-2012, Opscode, Inc <legal@opscode.com>
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
84
18
 
19
+ require 'mixlib/cli'
20
+ require 'json'
21
+ require 'yaml'
22
+
23
+ require 'spiceweasel'
24
+ require 'spiceweasel/cookbooks'
25
+ require 'spiceweasel/environments'
26
+ require 'spiceweasel/roles'
27
+ require 'spiceweasel/data_bags'
28
+ require 'spiceweasel/nodes'
29
+ require 'spiceweasel/clusters'
30
+ require 'spiceweasel/extract_local'
31
+ require 'spiceweasel/execute'
32
+
33
+ module Spiceweasel
34
+ class CLI
35
+ include Mixlib::CLI
36
+
37
+ banner('Usage: spiceweasel [option] file
38
+ spiceweasel [option] --extractlocal')
39
+
40
+ option :clusterfile,
41
+ :long => '--cluster-file file',
42
+ :description => 'Specify an additional cluster manifest file, overriding any other node or cluster definitions'
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 delete the infrastructure',
53
+ :boolean => true
54
+
55
+ option :execute,
56
+ :short => '-e',
57
+ :long => '--execute',
58
+ :description => 'Execute the knife commands to create the infrastructure directly',
59
+ :boolean => true
60
+
61
+ option :extractlocal,
62
+ :long => '--extractlocal',
63
+ :description => 'Use contents of local chef repository directories to generate knife commands to build infrastructure'
64
+
65
+ option :extractjson,
66
+ :long => '--extractjson',
67
+ :description => 'Use contents of local chef repository directories to generate JSON spiceweasel manifest'
68
+
69
+ option :extractyaml,
70
+ :long => '--extractyaml',
71
+ :description => 'Use contents of local chef repository directories to generate YAML spiceweasel manifest'
72
+
73
+ option :help,
74
+ :short => '-h',
75
+ :long => '--help',
76
+ :description => 'Show this message',
77
+ :on => :tail,
78
+ :boolean => true,
79
+ :show_options => true,
80
+ :exit => 0
81
+
82
+ option :knifeconfig,
83
+ :short => '-c CONFIG',
84
+ :long => '--knifeconfig CONFIG',
85
+ :description => 'Specify the knife.rb configuration file'
86
+
87
+ option :log_level,
88
+ :short => "-l LEVEL",
89
+ :long => "--log_level LEVEL",
90
+ :description => "Set the log level (debug, info, warn, error, fatal)",
91
+ :proc => lambda { |l| l.to_sym }
92
+
93
+ option :log_location,
94
+ :short => "-L LOGLOCATION",
95
+ :long => "--logfile LOGLOCATION",
96
+ :description => "Set the log file location, defaults to STDOUT",
97
+ :proc => nil
98
+
99
+ option :novalidation,
100
+ :long => '--novalidation',
101
+ :description => 'Disable validation',
102
+ :boolean => true
103
+
104
+ option :parallel,
105
+ :long => '--parallel',
106
+ :description => "Use the GNU 'parallel' command to parallelize 'knife VENDOR server create' commands where applicable",
107
+ :boolean => true
108
+
109
+ option :rebuild,
110
+ :short => '-r',
111
+ :long => '--rebuild',
112
+ :description => 'Print the knife commands to delete and recreate the infrastructure',
113
+ :boolean => true
114
+
115
+ option :serverurl,
116
+ :short => '-s URL',
117
+ :long => '--server-url URL',
118
+ :description => 'Specify the Chef Server URL'
119
+
120
+ option :siteinstall,
121
+ :long => '--siteinstall',
122
+ :description => "Use the 'install' command with 'knife cookbook site' instead of the default 'download'",
123
+ :boolean => true
124
+
125
+ option :version,
126
+ :short => '-v',
127
+ :long => '--version',
128
+ :description => 'Show spiceweasel version',
129
+ :boolean => true,
130
+ :proc => lambda { |v| puts "Spiceweasel: #{::Spiceweasel::VERSION}" },
131
+ :exit => 0
132
+
133
+ def run
134
+ if Spiceweasel::Config[:extractlocal] || Spiceweasel::Config[:extractjson] || Spiceweasel::Config[:extractyaml]
135
+ manifest = Spiceweasel::ExtractLocal.parse_objects
136
+ else
137
+ manifest = parse_and_validate_input(ARGV.last)
138
+ if Spiceweasel::Config[:clusterfile]
139
+ # if we have a cluster file, override any nodes or clusters in the original manifest
140
+ manifest['nodes'] = manifest['clusters'] = {}
141
+ manifest.merge!(parse_and_validate_input(Spiceweasel::Config[:clusterfile]))
142
+ end
143
+ end
144
+ Spiceweasel::Log.debug("file manifest: #{manifest}")
145
+
146
+ cookbooks = Cookbooks.new(manifest['cookbooks'])
147
+ environments = Environments.new(manifest['environments'], cookbooks)
148
+ roles = Roles.new(manifest['roles'], environments, cookbooks)
149
+ data_bags = DataBags.new(manifest['data bags'])
150
+ nodes = Nodes.new(manifest['nodes'], cookbooks, environments, roles)
151
+ clusters = Clusters.new(manifest['clusters'], cookbooks, environments, roles)
152
+
153
+ create = cookbooks.create + environments.create + roles.create + data_bags.create + nodes.create + clusters.create
154
+ delete = cookbooks.delete + environments.delete + roles.delete + data_bags.delete + nodes.delete + clusters.delete
155
+
156
+ #trim trailing whitespace
157
+ create.each {|x| x.rstrip!}
158
+ delete.each {|x| x.rstrip!}
159
+
160
+ if Spiceweasel::Config[:extractjson]
161
+ puts JSON.pretty_generate(manifest)
162
+ elsif Spiceweasel::Config[:extractyaml]
163
+ puts manifest.to_yaml
164
+ elsif Spiceweasel::Config[:delete]
165
+ if Spiceweasel::Config[:execute]
166
+ Execute.new(delete)
167
+ else
168
+ puts delete unless delete.empty?
169
+ end
170
+ elsif Spiceweasel::Config[:rebuild]
171
+ if Spiceweasel::Config[:execute]
172
+ Execute.new(delete)
173
+ Execute.new(create)
174
+ else
175
+ puts delete unless delete.empty?
176
+ puts create unless create.empty?
177
+ end
178
+ else
179
+ if Spiceweasel::Config[:execute]
180
+ Execute.new(create)
181
+ else
182
+ puts create unless create.empty?
183
+ end
184
+ end
185
+ exit 0
186
+ end
187
+
188
+ def initialize(argv=[])
189
+ super()
190
+ parse_and_validate_options
191
+ Config.merge!(@config)
192
+ configure_logging
193
+ Spiceweasel::Log.debug("Validation of the manifest has been turned off.") if Spiceweasel::Config[:novalidation]
194
+ end
195
+
196
+ def parse_and_validate_options
197
+ ARGV << "-h" if ARGV.empty?
198
+ begin
199
+ parse_options
200
+ if Spiceweasel::Config[:knifeconfig]
201
+ Spiceweasel::Config[:knife_options] = "-c #{Spiceweasel::Config[:knifeconfig]} "
202
+ end
203
+ if Spiceweasel::Config[:serverurl]
204
+ Spiceweasel::Config[:knife_options] += "--server-url #{Spiceweasel::Config[:serverurl]} "
205
+ end
206
+ rescue OptionParser::InvalidOption => e
207
+ STDERR.puts e.message
208
+ puts opt_parser.to_s
209
+ exit(-1)
210
+ end
211
+ end
212
+
213
+ def configure_logging
214
+ Spiceweasel::Log.init(Spiceweasel::Config[:log_location])
215
+ Spiceweasel::Log.level = Spiceweasel::Config[:log_level]
216
+ Spiceweasel::Log.level = :debug if Spiceweasel::Config[:debug]
217
+ end
218
+
219
+ def parse_and_validate_input(file)
220
+ begin
221
+ Spiceweasel::Log.debug("file: #{file}")
222
+ if !File.file?(file)
223
+ STDERR.puts "ERROR: #{file} is an invalid manifest file, please check your path."
224
+ exit(-1)
225
+ end
226
+ if (file.end_with?(".yml"))
227
+ output = YAML.load_file(file)
228
+ elsif (file.end_with?(".json"))
229
+ output = JSON.parse(File.read(file))
230
+ else
231
+ STDERR.puts "ERROR: #{file} is an unknown file type, please use a file ending with either '.json' or '.yml'."
232
+ exit(-1)
233
+ end
234
+ rescue Psych::SyntaxError => e
235
+ STDERR.puts e.message
236
+ STDERR.puts "ERROR: Parsing error in #{file}."
237
+ exit(-1)
238
+ rescue JSON::ParserError => e
239
+ STDERR.puts e.message
240
+ STDERR.puts "ERROR: Parsing error in #{file}."
241
+ exit(-1)
242
+ rescue Exception
243
+ STDERR.puts "ERROR: No manifest .json or .yml file provided."
244
+ puts opt_parser.to_s
245
+ exit(-1)
246
+ end
247
+ output
248
+ end
249
+
250
+ end
85
251
  end