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.
Files changed (4) hide show
  1. data/bin/cs +201 -52
  2. data/lib/config_helper.rb +86 -71
  3. data/lib/cookbooks_fetcher.rb +24 -11
  4. 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.8'
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" # flag --dry, default false
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 faulse
50
- opt :archive, "Checkout cookbooks in archive mode." # flag --debug, default faulse
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 "options: #{opts.to_json}" unless !(opts.verbose || opts.debug and !opts.help)
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
- require File.join(File.dirname(__FILE__), '../lib/config_helper.rb')
75
- config = ConfigHelper.new(SETUP_DEFAULTS, DEBUG)
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
- system("mkdir -p /usr/src/chef-cookbooks && wget --no-check-certificate https://github.com/opscode-cookbooks/git/tarball/master -O /usr/src/git_cookbook.tar && cd /usr/src && tar zxvf /usr/src/git_cookbook.tar && mv -v /usr/src/opscode-cookbooks-git-* /usr/src/chef-cookbooks/git")
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
- puts "\nSetup complete."
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
- puts " DEBUG: Using #{opts[:json]}."
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
- puts 'Importing RestConnection RubyGem.' unless !opts.verbose
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
- puts "Finding server: #{opts.server}."
219
+ logger.log "Finding server: #{opts.server}."
160
220
  server = Server.find(opts.server.to_i)
161
221
  else
162
- puts "Finding server: '%#{opts.server}%'"
222
+ logger.log "Finding server: '%#{opts.server}%'"
163
223
  server = Server.find(:first) { |s| s.nickname =~ /#{opts.server}/ }
164
224
  end
165
- puts "Found server, '#{server.nickname}'."
166
- puts server.to_yaml unless !opts.verbose
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
- puts JSON.pretty_generate(server.settings) unless !opts.debug
230
+ logger.log JSON.pretty_generate(server.settings), 'debug'
171
231
 
172
232
  # assign inputs from server params
173
233
  inputs = server.parameters
174
- puts " DEBUG: #{JSON.pretty_generate(inputs)}" unless !opts.debug
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
- puts " DEBUG: right_script input #{k} discarded." unless !opts.debug
238
+ logger.log "right_script input #{k} discarded.", 'debug'
179
239
  else
180
- puts " DEBUG: #{input} => #{v}" unless !opts.debug
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
- puts " DEBUG: node attribute #{keys[1]} detected for cookbook, #{keys[0]}." unless !opts.debug
188
- puts " DEBUG: attribute:#{keys[0]}[\"#{keys[1]}\"] type:#{type} value:#{value}" unless !opts.debug
189
- puts " DEBUG: [#{keys[0]}][#{keys[1]}] => type: #{type}" unless !opts.debug
190
- puts " DEBUG: [#{keys[0]}][#{keys[1]}] => value: #{value}" unless !opts.debug
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
- puts " DEBUG:\n#{p server_attributes}" if opts[:debug]
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
- puts ' DEBUG: Merging attributes.' if opts[:debug]
299
+ logger.log "Merging attributes.", 'debug'
204
300
  attributes = server_attributes.merge(attributes)
205
301
  else
206
- puts ' DEBUG: No server attributes to merge.' if opts[:debug]
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
- puts " Overriding run_list with: #{opts[:run]}" if opts[:verbose]
307
+ logger.log "Overriding run_list with: #{opts[:run]}", 'verbose'
212
308
  attributes['run_list'] = "#{opts[:run]}"
213
309
  end
214
310
 
215
- # new attributes
216
- puts " DEBUG: Final attributes: #{attributes.to_json}" if opts[:debug]
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 opts[:write] and attributes
362
+ if attributes
220
363
  node_json = JSON.pretty_generate(attributes)
221
- puts " DEBUG: Node Attributes: \n #{node_json}" if opts[:debug]
222
- puts " DEBUG: Writing attributes to #{json_file}" if opts[:debug]
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
- puts "== node.json ==\n#{File.open(json_file, "r").read}\n==" if ( opts[:debug] or opts[:verbose] )
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
- puts ' DEBUG: Using sandbox ruby/chef.' if opts[:debug]
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
- puts 'Importing Chef RubyGem.' if opts[:verbose]
251
- require 'chef'
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
- puts " DEBUG: Non-root user, appending sudo (#{cmd})." if opts[:debug]
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
- # finally, run chef-solo
260
- puts 'Starting Chef Solo.' unless !(opts[:verbose] || opts[:debug])
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
- @setup_defaults, @debug = setup_defaults, debug
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
- end
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
- puts
32
- puts '=> Setting up Chef Solo.'
33
- if system("`which lsb_release`")
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
- puts ' DEBUG: lsb_release not found.' if @debug
75
+ @l.log "lsb_release command not found, os detection skipped.", 'debug'
38
76
  lsb_release = 'none'
39
77
  end
40
- case "#{lsb_release.strip}"
78
+ case "#{lsb_release}"
41
79
  when 'Ubuntu'
42
- puts 'Ubuntu detected; installing from opscode apt.'
43
- if ! system("dpkg -l | grep chef")
44
- system("DEBIAN_FRONTEND=noninteractive")
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 'Installing Chef RubyGem...'
58
- gem = 'chef'
59
- begin
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
- puts "=> Setting up #{file}."
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 [ "'+"#{cookbooks_path}"+'" ]'+"\n"'json_attribs "/etc/chef/node.json"'+"\n"}
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
- puts "=> Setting up #{file}."
104
+ @l.log "Setting up #{file}."
86
105
  if auto
87
- default_solo = true
106
+ default_solo = 'y'
88
107
  else
89
- puts ' Use default solo.rb [y/n] <enter> ?'
90
- default_solo = false
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
- puts "=> Setting up #{file}."
131
+ @l.log "Setting up #{file}."
107
132
  if auto
108
133
  create_empty = 'y'
109
134
  else
110
- puts ' Create empty node.json [y/n] <enter> ?'
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 " Type or paste your node.json (type EOF then press <enter> to finish):"
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
- puts '=> Setting up rest_connection.'
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 ' Install rest_connection [y/n] <enter> ?'
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
- puts 'Installing rest_connection RubyGem...'
136
- gem = 'rest_connection'
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
- puts 'Testing require of chef.'
168
+ @l.log 'Testing require of chef.'
154
169
  require 'chef'
155
170
  rescue
156
- puts 'Failed to require Chef RubyGem!'
171
+ @l.log 'Failed to require Chef RubyGem!'
157
172
  exit 1
158
173
  end
159
- puts 'Test passed.'
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
- puts ' DEBUG: /etc/chef/solo.rb: not found.' if @debug
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
- puts " DEBUG: Using #{ENV['HOME']}/solo.rb as preferred." if @debug
187
+ @l.log "Using #{ENV['HOME']}/solo.rb as preferred.", 'debug'
173
188
  end
174
189
  unless solo
175
- puts 'FATAL: No solo.rb file found (see http://wiki.opscode.com/display/chef/Chef+Solo), exiting.'
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
- puts " DEBUG: Using #{solo}." if @debug
193
+ @l.log "DEBUG: Using #{solo}.", 'debug'
179
194
  if File.zero?(solo) then
180
- puts "FATAL: #{solo} is empty, exiting."
195
+ raise "FATAL: #{solo} is empty, exiting."
181
196
  exit 1
182
197
  end
183
- puts "== solo.rb ==\n#{File.new(solo, 'r').read.strip}\n==" if @debug
198
+ @l.log "== solo.rb ==\n#{File.new(solo, 'r').read.strip}\n==", 'debug'
184
199
  end
185
200
  end
186
201
 
@@ -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
- cookbooks_dest = "#{File.expand_path("~")}/chef-cookbooks"
12
+ cookbooks_dest = "#{File.expand_path("~")}/chef-cookbooks"
10
13
  end
11
14
  system("mkdir -p #{cookbooks_dest}")
12
- puts "Cookbooks destination: #{cookbooks_dest}."
13
- if archive
14
- system("cd #{cookbooks_dest}; git clone --depth=1 #{cookbooks_src}")
15
- #system("git archive --format=tar --remote=#{opts[:fetch]} master | tar -xf -")
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: 15
4
+ hash: 13
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 8
10
- version: 0.0.8
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-03 00:00:00 Z
18
+ date: 2012-06-04 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: json