chef-solo-wrapper 0.0.8 → 0.0.9
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/cs +201 -52
- data/lib/config_helper.rb +86 -71
- data/lib/cookbooks_fetcher.rb +24 -11
- metadata +4 -4
data/bin/cs
CHANGED
@@ -16,12 +16,13 @@
|
|
16
16
|
# See the License for the specific language governing permissions and
|
17
17
|
# limitations under the License.
|
18
18
|
|
19
|
-
CHEF_SOLO_WRAPPER_VERSION = '0.0.
|
19
|
+
CHEF_SOLO_WRAPPER_VERSION = '0.0.9'
|
20
20
|
COOKBOOKS_SRC_DEST = '/usr/src/chef-cookbooks'
|
21
21
|
|
22
22
|
require 'rubygems'
|
23
23
|
require 'trollop'
|
24
24
|
require 'json'
|
25
|
+
require 'yaml'
|
25
26
|
|
26
27
|
opts = Trollop::options do
|
27
28
|
version 'chef-solo-wrapper '+CHEF_SOLO_WRAPPER_VERSION+' (c) 2011 Chris Fordham'
|
@@ -33,6 +34,7 @@ Usage:
|
|
33
34
|
where [options] are:
|
34
35
|
EOS
|
35
36
|
opt :server, "Use attribute data from a RightScale server by nickname or ID.", :short => "-s", :type => String # flag --server, default false
|
37
|
+
opt :template, "Use attribute data from a RightScale ServerTemplate by nickname or ID.", :type => String # flag --template, default false
|
36
38
|
opt :sandbox, "Use the Ruby environment in the local RightLink sandbox." # flag --sandbox, default false
|
37
39
|
opt :config, "Use alternate Chef Solo configuration (default used, ~/solo.rb.)", :short => "-c" # flag --config, default false
|
38
40
|
opt :json, "Use alternate Chef Solo JSON data (default used, ~/node.json.)", :short => "-j", :type => String # flag --json, default false
|
@@ -41,17 +43,18 @@ EOS
|
|
41
43
|
opt :install, "Installs tools such as Git.", :type => String # flag --test, default false
|
42
44
|
opt :defaults, "Setups up configuration for default/initial.", :default => false # flag --test, default false
|
43
45
|
opt :fetch, "Fetches cookbooks.", :short => "-f", :type => String # flag --fetch, default false
|
44
|
-
opt :dry, "Dry run only, don't run chef-solo.", :short => "-d"
|
46
|
+
opt :dry, "Dry run only, don't run chef-solo.", :short => "-d", :default => false # flag --dry, default false
|
45
47
|
opt :run, "Use alernative run_list for chef-solo run.", :short => "-r", :type => String # flag --run, default false
|
48
|
+
opt :env, "Environment variables to start with e.g. for input values.", :short => "-e", :type => String
|
46
49
|
opt :write, "Write back to local JSON file.", :short => "-w" # flag --write, default false
|
47
50
|
opt :loglevel, "The Chef log level to use: debug, info, warn, error, fatal", :short => "-l", :default => "info", :type => String # flag --loglevel, default info
|
48
51
|
opt :verbose, "Verbose mode.", :short => "-v" # flag --verbose, default false
|
49
|
-
opt :debug, "Debug mode.", :default => false # flag --debug, default
|
50
|
-
opt :
|
52
|
+
opt :debug, "Debug mode.", :default => false # flag --debug, default false
|
53
|
+
opt :quiet, "Quiet mode.", :default => false # flag --quiet, default false
|
54
|
+
opt :archive, "Checkout cookbooks in archive mode." # flag --archive, default false
|
51
55
|
opt :help, "Print usage info and exit.", :short => "-h"
|
52
56
|
end
|
53
|
-
puts "
|
54
|
-
puts "chef-solo-wrapper #{CHEF_SOLO_WRAPPER_VERSION}"
|
57
|
+
puts "chef-solo-wrapper #{CHEF_SOLO_WRAPPER_VERSION}\n" unless opts[:quiet]
|
55
58
|
|
56
59
|
if opts[:defaults]
|
57
60
|
SETUP_DEFAULTS = true
|
@@ -61,18 +64,60 @@ end
|
|
61
64
|
|
62
65
|
if opts[:debug]
|
63
66
|
DEBUG = true
|
67
|
+
log_level = 'debug'
|
68
|
+
elsif opts[:verbose]
|
69
|
+
log_level = 'verbose' unless opts[:debug]
|
70
|
+
DEBUG = false
|
64
71
|
else
|
72
|
+
log_level = 'info'
|
65
73
|
DEBUG = false
|
66
74
|
end
|
67
75
|
|
76
|
+
require File.join(File.dirname(__FILE__), '../lib/chef_solo_wrapper.rb')
|
77
|
+
require File.join(File.dirname(__FILE__), "../lib/easy_logger.rb")
|
78
|
+
require File.join(File.dirname(__FILE__), '../lib/config_helper.rb')
|
79
|
+
require File.join(File.dirname(__FILE__), "../lib/cookbooks_fetcher.rb")
|
80
|
+
|
81
|
+
logger = EasyLogger.new(log_level.to_s)
|
82
|
+
config = ConfigHelper.new(SETUP_DEFAULTS, DEBUG, log_level)
|
83
|
+
|
84
|
+
logger.log "cli_options: #{opts.to_json}", 'verbose'
|
85
|
+
puts "options: #{opts.to_json}" if opts[:help]
|
86
|
+
|
68
87
|
solo = false
|
69
88
|
server = false
|
89
|
+
rs_home = File.expand_path('~')+'/.rightscale'
|
90
|
+
env_file = rs_home+'/chef_env.sh'
|
70
91
|
|
71
92
|
json_file = '/etc/chef/node.json'
|
72
93
|
solo_file = '/etc/chef/solo.rb'
|
94
|
+
|
95
|
+
# env/inputs
|
96
|
+
if opts[:env]
|
97
|
+
logger.log("--env: #{opts[:env]}", 'debug')
|
98
|
+
|
99
|
+
pairs = opts[:env].split(' ')
|
100
|
+
vars = Hash.new
|
101
|
+
Dir.mkdir(rs_home) unless File.exists?(rs_home)
|
73
102
|
|
74
|
-
|
75
|
-
|
103
|
+
# store each key/value pair
|
104
|
+
fh = File.new(env_file, "w")
|
105
|
+
pairs.each { |pair|
|
106
|
+
var = "#{pair.split('=')[0]}"
|
107
|
+
val = "#{pair.split('=')[1]}"
|
108
|
+
fh.write pair
|
109
|
+
vars[var] = val
|
110
|
+
}
|
111
|
+
fh.close
|
112
|
+
|
113
|
+
logger.log "Environment variables: #{vars.to_json}", [ 'verbose', 'debug' ]
|
114
|
+
# merge the chef env with ENV
|
115
|
+
logger.log "Merging environment variables.", 'debug'
|
116
|
+
CS_ENV = vars.merge(ENV)
|
117
|
+
logger.log "Cumulative Environment: #{CS_ENV.inspect}", 'debug'
|
118
|
+
else
|
119
|
+
CS_ENV = {}
|
120
|
+
end
|
76
121
|
|
77
122
|
# Test mode (exits after test)
|
78
123
|
if opts[:test]
|
@@ -86,7 +131,15 @@ if opts[:install]
|
|
86
131
|
when 'git'
|
87
132
|
# requires chef
|
88
133
|
system('rm -Rf /usr/src/git*; rm -Rf /usr/src/chef-cookbooks/git*')
|
89
|
-
|
134
|
+
logger.log "[wget] Fetching git cookbook from GitHub..."
|
135
|
+
fetch_cmd = "mkdir -p /usr/src/chef-cookbooks && wget --no-check-certificate https://github.com/opscode-cookbooks/git/tarball/master -O /usr/src/git_cookbook.tar 2>&1 && cd /usr/src && tar zxvf /usr/src/git_cookbook.tar && mv -v /usr/src/opscode-cookbooks-git-* /usr/src/chef-cookbooks/git"
|
136
|
+
install = "[git_install] " + `#{fetch_cmd}`; result=$?.success?
|
137
|
+
if result
|
138
|
+
logger.log install, 'verbose'
|
139
|
+
else
|
140
|
+
logger.log install, 'error'
|
141
|
+
raise "Failed to fetch the git cookbook from GitHub.!"
|
142
|
+
end
|
90
143
|
File.open('/etc/chef/install_git.json', "w") {|f| f.write '{ "run_list": [ "recipe[git::default]" ] }' }
|
91
144
|
File.open('/etc/chef/install_git_solo.rb', "w") {|f| f.write 'file_cache_path "/var/chef-solo"'+"\n"+'cookbook_path [ "/usr/src/chef-cookbooks" ]'+"\n"'json_attribs "/etc/chef/node.json"'+"\n"}
|
92
145
|
system("chef-solo -c /etc/chef/install_git_solo.rb -j /etc/chef/install_git.json")
|
@@ -105,6 +158,13 @@ if opts[:setup]
|
|
105
158
|
config.setup_solo_rb(solo_file)
|
106
159
|
when 'config-sandbox'
|
107
160
|
config.setup_solo_rb_sandbox(solo_file)
|
161
|
+
when 'config-oss'
|
162
|
+
l = Logger.new(log_level)
|
163
|
+
l.log 'Setting up for OSS (flaccid) cookbooks...', 'verbose'
|
164
|
+
fetcher = CookbooksFetcher.new(log_level)
|
165
|
+
fetcher.fetch "git://github.com/flaccid/cookbooks_public.git"
|
166
|
+
fetcher.fetch "git://github.com/flaccid/cookbooks.git"
|
167
|
+
File.open(solo_file, "w") {|f| f.write 'file_cache_path "/var/chef-solo"'+"\n"+'cookbook_path [ "/usr/src/chef-cookbooks/cookbooks_public/cookbooks", "/usr/src/chef-cookbooks/cookbooks/cookbooks" ]'+"\n"'json_attribs "/etc/chef/node.json"'+"\n"}
|
108
168
|
when 'node'
|
109
169
|
config.setup_node_json(json_file)
|
110
170
|
when 'all'
|
@@ -116,7 +176,7 @@ if opts[:setup]
|
|
116
176
|
config.show(solo_file, json_file)
|
117
177
|
exit
|
118
178
|
end
|
119
|
-
|
179
|
+
logger.log "Setup complete."
|
120
180
|
exit
|
121
181
|
end
|
122
182
|
|
@@ -132,7 +192,7 @@ config.pre_checks
|
|
132
192
|
|
133
193
|
# get json if available
|
134
194
|
if opts[:json]
|
135
|
-
|
195
|
+
logger.log "Using provided json: #{opts[:json]}", 'debug'
|
136
196
|
attributes = File.new(opts[:json], "r").read
|
137
197
|
else
|
138
198
|
if File.file?(json_file)
|
@@ -151,75 +211,158 @@ end
|
|
151
211
|
# when a rs server is specified
|
152
212
|
if opts[:server]
|
153
213
|
# import rest_connection
|
154
|
-
|
214
|
+
logger.log 'Importing RestConnection RubyGem.', 'verbose'
|
155
215
|
require 'rest_connection'
|
156
216
|
|
157
217
|
# fetch server via rest_connection
|
158
218
|
if opts.server.to_i > 0
|
159
|
-
|
219
|
+
logger.log "Finding server: #{opts.server}."
|
160
220
|
server = Server.find(opts.server.to_i)
|
161
221
|
else
|
162
|
-
|
222
|
+
logger.log "Finding server: '%#{opts.server}%'"
|
163
223
|
server = Server.find(:first) { |s| s.nickname =~ /#{opts.server}/ }
|
164
224
|
end
|
165
|
-
|
166
|
-
|
225
|
+
logger.log "Found server, '#{server.nickname}'."
|
226
|
+
logger.log server.to_yaml, 'verbose'
|
167
227
|
|
168
228
|
# get current instance of server
|
169
229
|
server.reload_current
|
170
|
-
|
230
|
+
logger.log JSON.pretty_generate(server.settings), 'debug'
|
171
231
|
|
172
232
|
# assign inputs from server params
|
173
233
|
inputs = server.parameters
|
174
|
-
|
234
|
+
logger.log "#{JSON.pretty_generate(inputs)}", 'debug'
|
175
235
|
server_attributes = Hash.new
|
176
236
|
inputs.each { |input,v|
|
177
237
|
if inputs.to_s =~ /^[A-Z]+$/
|
178
|
-
|
238
|
+
logger.log "right_script input #{k} discarded.", 'debug'
|
179
239
|
else
|
180
|
-
|
240
|
+
logger.log "#{input} => #{v}", 'debug'
|
181
241
|
keys = input.split("/")
|
182
242
|
if keys.count == 2
|
183
243
|
type = v.split(':')[0]
|
184
244
|
value = v.split(':')[1]
|
185
245
|
value = '' unless value != "$ignore"
|
186
246
|
if keys[0] != 'rightscale'
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
247
|
+
logger.log "node attribute #{keys[1]} detected for cookbook, #{keys[0]}.", 'debug'
|
248
|
+
logger.log "attribute:#{keys[0]}[\"#{keys[1]}\"] type:#{type} value:#{value}", 'debug'
|
249
|
+
logger.log "[#{keys[0]}][#{keys[1]}] => type: #{type}", 'debug'
|
250
|
+
logger.log "[#{keys[0]}][#{keys[1]}] => value: #{value}", 'debug'
|
191
251
|
server_attributes["#{keys[0]}"] = {} unless server_attributes["#{keys[0]}"]
|
192
252
|
server_attributes["#{keys[0]}"]["#{keys[1]}"] = "#{value}"
|
193
253
|
end
|
194
254
|
end
|
195
255
|
end
|
196
256
|
}
|
197
|
-
|
257
|
+
logger.log "\n#{p server_attributes}", 'debug'
|
258
|
+
elsif opts[:template]
|
259
|
+
# steal inputs from ST
|
260
|
+
|
261
|
+
logger.log "Importing rest_connection Rubygem.."
|
262
|
+
require 'rest_connection'
|
263
|
+
|
264
|
+
template = false
|
265
|
+
|
266
|
+
if opts[:template].to_i > 0
|
267
|
+
logger.log "Finding ServerTemplate: #{opts[:template]}"
|
268
|
+
template = ServerTemplate.find(opts[:template].to_i)
|
269
|
+
else
|
270
|
+
logger.log "Finding ServerTemplate: '%#{opts[:template]}%'"
|
271
|
+
#puts ServerTemplate.find(:first).inspect; exit
|
272
|
+
template = ServerTemplate.find(:first) { |s| s.nickname =~ /"#{opts[:template]}"/ }
|
273
|
+
end
|
274
|
+
|
275
|
+
if template
|
276
|
+
logger.log "ServerTemplate: #{template.to_yaml}", 'debug'
|
277
|
+
executables = template.executables
|
278
|
+
recipes = Array.new
|
279
|
+
executables.each { |exec|
|
280
|
+
if exec['apply'] == 'boot' and exec['recipe']
|
281
|
+
logger.log "detected recipe: #{exec['recipe']}", 'debug'
|
282
|
+
recipes.push(exec['recipe'])
|
283
|
+
end
|
284
|
+
}
|
285
|
+
logger.log "Recipes array: #{recipes.to_json}", 'debug'
|
286
|
+
run_list = "[ #{recipes.map {|element| '"'+"recipe[#{element}]"+'"' }.join(', ')} ]"
|
287
|
+
logger.log "Run List from ST: #{run_list}", 'verbose'
|
288
|
+
opts[:run] = run_list
|
289
|
+
#puts opts[:run]
|
290
|
+
else
|
291
|
+
logger.log "No template found."
|
292
|
+
exit 1
|
293
|
+
end
|
198
294
|
end
|
199
295
|
|
200
296
|
# merge attributes
|
201
297
|
if server_attributes
|
202
298
|
puts server_attributes.to_json
|
203
|
-
|
299
|
+
logger.log "Merging attributes.", 'debug'
|
204
300
|
attributes = server_attributes.merge(attributes)
|
205
301
|
else
|
206
|
-
|
302
|
+
logger.log "No server attributes to merge.", 'debug'
|
207
303
|
end
|
208
304
|
|
209
|
-
# override runlist
|
305
|
+
# override runlist if set
|
210
306
|
if opts[:run]
|
211
|
-
|
307
|
+
logger.log "Overriding run_list with: #{opts[:run]}", 'verbose'
|
212
308
|
attributes['run_list'] = "#{opts[:run]}"
|
213
309
|
end
|
214
310
|
|
215
|
-
|
216
|
-
|
311
|
+
if opts[:env]
|
312
|
+
# replace any global env vars
|
313
|
+
logger.log "Overriding node attributes with any found environment variables.", [ 'verbose', 'debug' ]
|
314
|
+
|
315
|
+
def collect_item_attributes(attribs,needle,path=nil)
|
316
|
+
result = {}
|
317
|
+
path = {}
|
318
|
+
attribs.each do |k, v|
|
319
|
+
#puts "recipe[#{k}] attr[#{v}]"
|
320
|
+
if v == needle
|
321
|
+
#puts " DEBUG: found value, #{v}"
|
322
|
+
result[k] = "#{v}"
|
323
|
+
elsif v.is_a? Hash
|
324
|
+
#puts 'its a hash'
|
325
|
+
collect_item_attributes(attribs[k],needle,path).each do |k, v|
|
326
|
+
result[k] = "#{path}#{v}"
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
result
|
331
|
+
end
|
332
|
+
|
333
|
+
env_vars = CS_ENV.merge(ENV)
|
334
|
+
logger.log "Search env: "+env_vars.to_json, 'debug'
|
335
|
+
logger.log "Attributes: "+attributes.to_json , 'debug'
|
336
|
+
|
337
|
+
env_vars.each { |key|
|
338
|
+
result = {}
|
339
|
+
logger.log "Processing env var: #{key.to_json}", 'debug'
|
340
|
+
logger.log "Search attribute values for #{key[0]} to assign #{key[1]}", 'debug'
|
341
|
+
result = collect_item_attributes(attributes, "#{key[0]}")
|
342
|
+
unless result.empty?
|
343
|
+
#puts "result: #{result.to_json}"
|
344
|
+
attributes.invert.select{ |k,v|
|
345
|
+
att = result.invert[key[0]]
|
346
|
+
logger.log "invert[#{result.invert[key[0]]}] key0[#{key[0]}] v[#{v}] k[#{k}] att[#{att}]", 'debug'
|
347
|
+
if k[att] == key[0]
|
348
|
+
logger.log "Found match for [#{v}] -> [#{result.invert["#{key[0]}"]}] ( [#{k.to_json}] ), updating attributes", 'debug'
|
349
|
+
attributes[v][att] = CS_ENV[key[0]]
|
350
|
+
else
|
351
|
+
logger.log "No match for #{key[0]} under #{v}", 'debug'
|
352
|
+
end
|
353
|
+
}
|
354
|
+
end
|
355
|
+
}
|
356
|
+
end
|
357
|
+
|
358
|
+
# Final/new attributes
|
359
|
+
logger.log "Final attributes: #{attributes.to_json}", 'debug'
|
217
360
|
|
218
361
|
# write attributes back to local node.json
|
219
|
-
if
|
362
|
+
if attributes
|
220
363
|
node_json = JSON.pretty_generate(attributes)
|
221
|
-
|
222
|
-
|
364
|
+
logger.log "Node Attributes: \n #{node_json}", 'debug'
|
365
|
+
logger.log "Writing attributes to #{json_file}", 'debug'
|
223
366
|
begin
|
224
367
|
# open file for write back
|
225
368
|
fh = File.new(json_file, "w")
|
@@ -229,7 +372,7 @@ if opts[:write] and attributes
|
|
229
372
|
end
|
230
373
|
|
231
374
|
# debug for final node.json
|
232
|
-
|
375
|
+
logger.log "== node.json ==\n#{File.open(json_file, "r").read}\n==", [ 'verbose', 'debug' ]
|
233
376
|
|
234
377
|
# pre append options
|
235
378
|
chef_config = " -c #{opts[:config]}" if opts[:config]
|
@@ -237,7 +380,7 @@ chef_json = " -j #{opts[:json]}" if opts[:json]
|
|
237
380
|
|
238
381
|
# set the chef-solo command depending if rs sandbox
|
239
382
|
if opts[:sandbox]
|
240
|
-
|
383
|
+
logger.log "Using sandbox ruby/chef.", 'debug'
|
241
384
|
cs = '/opt/rightscale/sandbox/bin/ruby /opt/rightscale/sandbox/bin/chef-solo'
|
242
385
|
else
|
243
386
|
cs = 'chef-solo'
|
@@ -245,28 +388,34 @@ end
|
|
245
388
|
|
246
389
|
# build chef solo command
|
247
390
|
cmd = "#{cs}#{chef_config}#{chef_json} --log_level #{opts.loglevel}"
|
391
|
+
# prepend env
|
392
|
+
cmd = "#{File.open(env_file, "r").read.strip} #{cmd}" if opts[:env]
|
248
393
|
|
249
394
|
# import chef
|
250
|
-
|
251
|
-
|
252
|
-
|
395
|
+
logger.log 'Importing Chef RubyGem.', 'verbose'
|
396
|
+
begin
|
397
|
+
require 'chef'
|
398
|
+
rescue
|
399
|
+
logger.log "FATAL: Error requiring chef RubyGem!"
|
400
|
+
end
|
401
|
+
|
253
402
|
# prepend sudo if not run as root
|
254
403
|
if Process.uid != 0
|
255
|
-
|
404
|
+
logger.log "Non-root user, appending sudo \(#{cmd}\).", 'debug'
|
256
405
|
cmd.insert(0, 'sudo ')
|
406
|
+
else
|
407
|
+
logger.log "User is root.", 'debug'
|
257
408
|
end
|
258
409
|
|
259
|
-
|
260
|
-
|
261
|
-
unless opts[:dry]
|
262
|
-
begin
|
263
|
-
puts " DEBUG: running #{cmd}" if opts[:debug]
|
264
|
-
system(cmd)
|
265
|
-
rescue
|
266
|
-
puts 'Chef run failed!'
|
267
|
-
exit 1
|
268
|
-
end
|
269
|
-
else
|
270
|
-
puts 'Dry run only, exiting.'
|
410
|
+
if opts[:dry]
|
411
|
+
logger.log "Dry run only, exiting."
|
271
412
|
exit
|
413
|
+
end
|
414
|
+
|
415
|
+
# finally, run chef-solo
|
416
|
+
logger.log 'Starting Chef Solo.'
|
417
|
+
logger.log "executing cmd[#{cmd}]", 'verbose'
|
418
|
+
system(cmd)
|
419
|
+
if $? != 0
|
420
|
+
raise 'Chef run failed!'
|
272
421
|
end
|
data/lib/config_helper.rb
CHANGED
@@ -1,16 +1,41 @@
|
|
1
|
-
class ConfigHelper
|
1
|
+
class ConfigHelper < ChefSoloWrapper
|
2
|
+
|
2
3
|
# constructor method
|
3
|
-
def initialize(setup_defaults, debug)
|
4
|
-
|
4
|
+
def initialize(setup_defaults, debug, facility_log_level)
|
5
|
+
|
6
|
+
@setup_defaults = setup_defaults
|
7
|
+
@debug = debug
|
8
|
+
@facility_log_level = facility_log_level
|
9
|
+
|
10
|
+
super(facility_log_level)
|
11
|
+
|
12
|
+
@l = EasyLogger.new(facility_log_level)
|
5
13
|
end
|
6
14
|
|
7
15
|
# accessor methods
|
16
|
+
|
17
|
+
def command?(command)
|
18
|
+
system("which #{ command} > /dev/null 2>&1")
|
19
|
+
end
|
20
|
+
|
8
21
|
def install_gem(gem)
|
9
22
|
install_opts = '--no-rdoc --no-ri'
|
10
23
|
system("gem install #{gem} #{install_opts}")
|
11
24
|
Gem.clear_paths
|
12
25
|
end
|
13
26
|
|
27
|
+
def install_rubygem(gem)
|
28
|
+
begin
|
29
|
+
@l.log "[Gem] #{gem} already installed, version: #{Gem::Specification.find_by_name(gem).version}."
|
30
|
+
rescue Gem::LoadError
|
31
|
+
install_gem(gem)
|
32
|
+
rescue
|
33
|
+
install_gem(gem) unless Gem.available?(gem)
|
34
|
+
rescue
|
35
|
+
raise "Failed to install #{chef} Rubygem!"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
14
39
|
def show(solo_file, json_file)
|
15
40
|
puts
|
16
41
|
puts '* Chef Solo Setup *'
|
@@ -25,76 +50,76 @@ class ConfigHelper
|
|
25
50
|
puts File.open(json_file, "r").read
|
26
51
|
puts '--'
|
27
52
|
puts
|
28
|
-
|
29
|
-
|
53
|
+
end
|
54
|
+
|
55
|
+
def install_chef_opscode
|
56
|
+
if ! system("dpkg -l | grep chef")
|
57
|
+
system("DEBIAN_FRONTEND=noninteractive")
|
58
|
+
system("sudo mkdir -p /etc/apt/trusted.gpg.d")
|
59
|
+
system("gpg --keyserver keys.gnupg.net --recv-keys 83EF826A")
|
60
|
+
system("gpg --export packages@opscode.com | sudo tee /etc/apt/trusted.gpg.d/opscode-keyring.gpg > /dev/null")
|
61
|
+
system('echo "deb http://apt.opscode.com/ $(lsb_release -cs)-0.10 main" > /etc/apt/sources.list.d/opscode.list')
|
62
|
+
system("sudo apt-get -y update")
|
63
|
+
system("sudo apt-get -y upgrade")
|
64
|
+
system("sudo apt-get -y install chef")
|
65
|
+
else
|
66
|
+
@l.log "[dpkg] Chef already installed, skipping."
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
30
70
|
def install_chef
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
lsb_release = `lsb_release -si`
|
35
|
-
lsb_release.strip!
|
71
|
+
@l.log "Setting up Chef Solo."
|
72
|
+
if command?('lsb_release')
|
73
|
+
lsb_release = `lsb_release -si`.strip
|
36
74
|
else
|
37
|
-
|
75
|
+
@l.log "lsb_release command not found, os detection skipped.", 'debug'
|
38
76
|
lsb_release = 'none'
|
39
77
|
end
|
40
|
-
case "#{lsb_release
|
78
|
+
case "#{lsb_release}"
|
41
79
|
when 'Ubuntu'
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
system("sudo mkdir -p /etc/apt/trusted.gpg.d")
|
46
|
-
system("gpg --keyserver keys.gnupg.net --recv-keys 83EF826A")
|
47
|
-
system("gpg --export packages@opscode.com | sudo tee /etc/apt/trusted.gpg.d/opscode-keyring.gpg > /dev/null")
|
48
|
-
system('echo "deb http://apt.opscode.com/ $(lsb_release -cs)-0.10 main" > /etc/apt/sources.list.d/opscode.list')
|
49
|
-
system("sudo apt-get -y update")
|
50
|
-
system("sudo apt-get -y upgrade")
|
51
|
-
system("sudo apt-get -y install chef")
|
52
|
-
else
|
53
|
-
puts 'Chef already installed, skipping.'
|
54
|
-
end
|
55
|
-
exit
|
80
|
+
@l.log 'Ubuntu detected; installing from opscode apt.', 'debug'
|
81
|
+
install_chef_opscode_apt
|
82
|
+
return
|
56
83
|
else
|
57
|
-
puts
|
58
|
-
|
59
|
-
|
60
|
-
puts "#{gem} already installed, version: #{Gem::Specification.find_by_name(gem).version}."
|
61
|
-
rescue Gem::LoadError
|
62
|
-
install_gem(gem)
|
63
|
-
rescue
|
64
|
-
install_gem(gem) unless Gem.available?(gem)
|
65
|
-
rescue
|
66
|
-
raise 'Failed to install Chef Rubygem!'
|
67
|
-
end
|
84
|
+
puts " DEBUG: == RubyGems Sources ==\n#{`gem sources`}\n==\n" if @debug
|
85
|
+
@l.log 'Installing Chef RubyGem...'
|
86
|
+
install_rubygem('chef')
|
68
87
|
end
|
69
88
|
end
|
70
89
|
|
71
90
|
def setup_solo_rb_sandbox(file, sandbox_version=5.8)
|
72
91
|
raise "RightScale cookbooks cache, /var/cache/rightscale/cookbooks not found!" unless File.exists?('/var/cache/rightscale/cookbooks')
|
73
|
-
|
92
|
+
@l.log "Setting up #{file}."
|
74
93
|
if sandbox_version.to_s == '5.8'
|
75
94
|
cookbooks_cache = '/var/cache/rightscale/cookbooks/default'
|
76
95
|
else
|
77
96
|
cookbooks_cache = '/var/cache/rightscale/cookbooks'
|
78
97
|
end
|
79
98
|
system('mkdir -p /etc/chef')
|
80
|
-
cookbooks_path = Dir.glob("#{cookbooks_cache}/*").map {|element| "\"#{element}\"" }.join(', ')
|
81
|
-
File.open(file, "w") {|f| f.write 'file_cache_path "/var/chef-solo"'+"\n"+'cookbook_path [
|
99
|
+
cookbooks_path = Dir.glob("#{cookbooks_cache}/*").map {|element| "\"#{element}/cookbooks\"" }.join(', ')
|
100
|
+
File.open(file, "w") {|f| f.write 'file_cache_path "/var/chef-solo"'+"\n"+'cookbook_path [ '+"#{cookbooks_path}"+' ]'+"\n"'json_attribs "/etc/chef/node.json"'+"\n"}
|
82
101
|
end
|
83
102
|
|
84
103
|
def setup_solo_rb(file, auto=@setup_defaults)
|
85
|
-
|
104
|
+
@l.log "Setting up #{file}."
|
86
105
|
if auto
|
87
|
-
default_solo =
|
106
|
+
default_solo = 'y'
|
88
107
|
else
|
89
|
-
puts ' Use default solo.rb [y/n] <enter> ?'
|
90
|
-
default_solo =
|
108
|
+
puts ' Use default solo.rb or edit existing [y/n/e] <enter> ?'
|
109
|
+
default_solo = 'n'
|
91
110
|
default_solo = gets.chomp
|
92
111
|
end
|
93
|
-
if default_solo
|
112
|
+
if default_solo == 'y'
|
94
113
|
File.open(file, "w") {|f| f.write 'file_cache_path "/var/chef-solo"'+"\n"+'cookbook_path [ "/usr/src/chef-cookbooks/default" ]'+"\n"'json_attribs "/etc/chef/node.json"'+"\n"}
|
95
114
|
system("mkdir -p /usr/src/chef-cookbooks/default")
|
96
115
|
File.new('/usr/src/chef-cookbooks/default/chefignore', "w").close
|
97
116
|
return
|
117
|
+
elsif default_solo == 'e'
|
118
|
+
editor = `which nano`.strip # fallback
|
119
|
+
editor = ENV['EDITOR'] if ENV['EDITOR']
|
120
|
+
puts " DEBUG: Using #{editor}"
|
121
|
+
system("#{editor} /etc/chef/solo.rb")
|
122
|
+
return
|
98
123
|
end
|
99
124
|
puts " Type or paste your solo.rb (type EOF then press <enter> to finish):"
|
100
125
|
$/ = "EOF"
|
@@ -103,18 +128,18 @@ class ConfigHelper
|
|
103
128
|
end
|
104
129
|
|
105
130
|
def setup_node_json(file, auto=@setup_defaults)
|
106
|
-
|
131
|
+
@l.log "Setting up #{file}."
|
107
132
|
if auto
|
108
133
|
create_empty = 'y'
|
109
134
|
else
|
110
|
-
puts '
|
135
|
+
puts 'Create empty node.json [y/n] <enter> ?'
|
111
136
|
create_empty = 'n'
|
112
137
|
create_empty = gets.chomp
|
113
138
|
end
|
114
139
|
if create_empty.downcase == 'y'
|
115
140
|
json = '{}'
|
116
141
|
else
|
117
|
-
puts "
|
142
|
+
puts "Type or paste your node.json (type EOF then press <enter> to finish):"
|
118
143
|
$/ = "EOF"
|
119
144
|
json = STDIN.gets
|
120
145
|
end
|
@@ -122,41 +147,31 @@ class ConfigHelper
|
|
122
147
|
end
|
123
148
|
|
124
149
|
def install_rest_connection(auto=false)
|
125
|
-
|
150
|
+
@l.log 'Setting up rest_connection.'
|
126
151
|
begin
|
127
152
|
if auto or @setup_defaults
|
128
153
|
install_rc = 'y'
|
129
154
|
else
|
130
|
-
puts '
|
155
|
+
puts 'Install rest_connection [y/n] <enter> ?'
|
131
156
|
install_rc = 'n'
|
132
157
|
install_rc = gets.chomp
|
133
158
|
end
|
134
159
|
if install_rc.downcase == 'y'
|
135
|
-
|
136
|
-
|
137
|
-
begin
|
138
|
-
puts "#{gem} already installed, version: #{Gem::Specification.find_by_name(gem).version}."
|
139
|
-
rescue Gem::LoadError
|
140
|
-
install_gem(gem)
|
141
|
-
rescue
|
142
|
-
install_gem(gem) unless Gem.available?(gem)
|
143
|
-
rescue
|
144
|
-
raise 'Failed to install rest_connection!'
|
145
|
-
end
|
160
|
+
@l.log 'Installing rest_connection RubyGem...'
|
161
|
+
install_rubygem('rest_connection')
|
146
162
|
end
|
147
163
|
end
|
148
|
-
puts
|
149
164
|
end
|
150
165
|
|
151
166
|
def test_setup
|
152
167
|
begin
|
153
|
-
|
168
|
+
@l.log 'Testing require of chef.'
|
154
169
|
require 'chef'
|
155
170
|
rescue
|
156
|
-
|
171
|
+
@l.log 'Failed to require Chef RubyGem!'
|
157
172
|
exit 1
|
158
173
|
end
|
159
|
-
|
174
|
+
@l.log 'Test passed.'
|
160
175
|
exit
|
161
176
|
end
|
162
177
|
|
@@ -165,22 +180,22 @@ class ConfigHelper
|
|
165
180
|
if File.file?('/etc/chef/solo.rb')
|
166
181
|
solo = '/etc/chef/solo.rb'
|
167
182
|
else
|
168
|
-
|
183
|
+
@l.log "/etc/chef/solo.rb: not found.", 'debug'
|
169
184
|
end
|
170
185
|
if File.file?("#{ENV['HOME']}/solo.rb")
|
171
186
|
solo = "#{ENV['HOME']}/solo.rb"
|
172
|
-
|
187
|
+
@l.log "Using #{ENV['HOME']}/solo.rb as preferred.", 'debug'
|
173
188
|
end
|
174
189
|
unless solo
|
175
|
-
|
190
|
+
raise 'FATAL: No solo.rb file found (see http://wiki.opscode.com/display/chef/Chef+Solo), exiting.'
|
176
191
|
exit 1
|
177
192
|
else
|
178
|
-
|
193
|
+
@l.log "DEBUG: Using #{solo}.", 'debug'
|
179
194
|
if File.zero?(solo) then
|
180
|
-
|
195
|
+
raise "FATAL: #{solo} is empty, exiting."
|
181
196
|
exit 1
|
182
197
|
end
|
183
|
-
|
198
|
+
@l.log "== solo.rb ==\n#{File.new(solo, 'r').read.strip}\n==", 'debug'
|
184
199
|
end
|
185
200
|
end
|
186
201
|
|
data/lib/cookbooks_fetcher.rb
CHANGED
@@ -1,22 +1,35 @@
|
|
1
|
-
class CookbooksFetcher
|
1
|
+
class CookbooksFetcher < EasyLogger
|
2
|
+
|
2
3
|
# constructor method
|
3
|
-
def initialize()
|
4
|
-
|
4
|
+
def initialize(facility_log_level)
|
5
|
+
@facility_log_level = facility_log_level
|
6
|
+
super(facility_log_level)
|
5
7
|
end
|
6
8
|
|
7
|
-
def fetch(cookbooks_src, cookbooks_dest, archive=true)
|
9
|
+
def fetch(cookbooks_src, cookbooks_dest='/usr/src/chef-cookbooks', archive=true)
|
10
|
+
l = Logger.new(@facility_log_level)
|
8
11
|
if Process.uid != 0
|
9
|
-
|
12
|
+
cookbooks_dest = "#{File.expand_path("~")}/chef-cookbooks"
|
10
13
|
end
|
11
14
|
system("mkdir -p #{cookbooks_dest}")
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
l.log "Cookbooks destination: #{cookbooks_dest}.", [ 'verbose', 'debug' ]
|
16
|
+
repos_name = File.basename(cookbooks_src).gsub('.git', '')
|
17
|
+
if File.exists?("#{cookbooks_dest}/#{repos_name}/.git")
|
18
|
+
l.log "Pulling '#{repos_name}' (instead of cloning)..", 'verbose'
|
19
|
+
pull_cmd = "cd #{cookbooks_dest}/#{repos_name} && git pull 2>&1"
|
20
|
+
pull = "[git] " + `#{pull_cmd}`; result=$?.success?
|
21
|
+
if result
|
22
|
+
l.log pull
|
23
|
+
else
|
24
|
+
l.log pull, 'error'
|
25
|
+
raise "Failed to pull git repository!"
|
26
|
+
end
|
27
|
+
elsif archive
|
28
|
+
system("cd #{cookbooks_dest}; git clone --depth=1 #{cookbooks_src}")
|
29
|
+
#system("git archive --format=tar --remote=#{opts[:fetch]} master | tar -xf -")
|
16
30
|
else
|
17
31
|
system("cd #{cookbooks_dest}; git clone #{cookbooks_src}")
|
18
32
|
end
|
19
|
-
exit
|
20
33
|
end
|
21
|
-
|
34
|
+
|
22
35
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-solo-wrapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 9
|
10
|
+
version: 0.0.9
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Chris Fordham
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-06-
|
18
|
+
date: 2012-06-04 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: json
|