cheftacular 2.5.0 → 2.6.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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cheftacular/README.md +155 -63
  3. data/lib/cheftacular/actions/db_console.rb +3 -3
  4. data/lib/cheftacular/actions/deploy.rb +18 -12
  5. data/lib/cheftacular/actions/migrate.rb +1 -1
  6. data/lib/cheftacular/actions/tail.rb +1 -1
  7. data/lib/cheftacular/auditor.rb +14 -6
  8. data/lib/cheftacular/chef/data_bag.rb +1 -4
  9. data/lib/cheftacular/cheftacular.rb +19 -15
  10. data/lib/cheftacular/cloud_provider.rb +32 -0
  11. data/lib/cheftacular/dns.rb +1 -1
  12. data/lib/cheftacular/error.rb +13 -2
  13. data/lib/cheftacular/file_system.rb +122 -0
  14. data/lib/cheftacular/files/rvm.sh +55 -0
  15. data/lib/cheftacular/getter.rb +10 -3
  16. data/lib/cheftacular/helper.rb +31 -127
  17. data/lib/cheftacular/initialization_action.rb +8 -0
  18. data/lib/cheftacular/initializer.rb +104 -44
  19. data/lib/cheftacular/parser.rb +6 -0
  20. data/lib/cheftacular/stateless_actions/add_ssh_key_to_bag.rb +2 -2
  21. data/lib/cheftacular/stateless_actions/arguments.rb +9 -2
  22. data/lib/cheftacular/stateless_actions/backups.rb +1 -1
  23. data/lib/cheftacular/stateless_actions/bootstrappers/ubuntu_bootstrap.rb +16 -5
  24. data/lib/cheftacular/stateless_actions/check_cheftacular_yml_keys.rb +79 -0
  25. data/lib/cheftacular/stateless_actions/chef_bootstrap.rb +20 -4
  26. data/lib/cheftacular/stateless_actions/chef_server.rb +78 -0
  27. data/lib/cheftacular/stateless_actions/clean_cookbooks.rb +3 -3
  28. data/lib/cheftacular/stateless_actions/clean_server_passwords.rb +3 -1
  29. data/lib/cheftacular/stateless_actions/cleanup_log_files.rb +1 -0
  30. data/lib/cheftacular/stateless_actions/client_list.rb +2 -2
  31. data/lib/cheftacular/stateless_actions/cloud.rb +30 -2
  32. data/lib/cheftacular/stateless_actions/cloud_bootstrap.rb +7 -13
  33. data/lib/cheftacular/stateless_actions/compile_audit_log.rb +1 -1
  34. data/lib/cheftacular/stateless_actions/create_git_key.rb +3 -1
  35. data/lib/cheftacular/stateless_actions/environment.rb +2 -0
  36. data/lib/cheftacular/stateless_actions/file.rb +4 -2
  37. data/lib/cheftacular/stateless_actions/fix_known_hosts.rb +2 -1
  38. data/lib/cheftacular/stateless_actions/full_bootstrap.rb +2 -0
  39. data/lib/cheftacular/stateless_actions/get_active_ssh_connections.rb +1 -1
  40. data/lib/cheftacular/stateless_actions/help.rb +9 -7
  41. data/lib/cheftacular/stateless_actions/initialize_cheftacular_yml.rb +29 -0
  42. data/lib/cheftacular/stateless_actions/initialize_data_bag_contents.rb +5 -36
  43. data/lib/cheftacular/stateless_actions/list_toggleable_roles.rb +45 -0
  44. data/lib/cheftacular/stateless_actions/location_aliases.rb +24 -0
  45. data/lib/cheftacular/stateless_actions/pass.rb +4 -4
  46. data/lib/cheftacular/stateless_actions/reinitialize.rb +0 -6
  47. data/lib/cheftacular/stateless_actions/remove_client.rb +12 -7
  48. data/lib/cheftacular/stateless_actions/role_toggle.rb +141 -0
  49. data/lib/cheftacular/stateless_actions/server_update.rb +2 -2
  50. data/lib/cheftacular/stateless_actions/update_chef_client.rb +18 -0
  51. data/lib/cheftacular/stateless_actions/upload_nodes.rb +5 -3
  52. data/lib/cheftacular/stateless_actions/upload_roles.rb +1 -1
  53. data/lib/cheftacular/version.rb +1 -1
  54. data/lib/cloud_interactor/authentication.rb +78 -40
  55. data/lib/cloud_interactor/cloud_interactor.rb +4 -1
  56. data/lib/cloud_interactor/cloud_provider.rb +19 -0
  57. data/lib/cloud_interactor/domain/create.rb +1 -1
  58. data/lib/cloud_interactor/domain/create_record.rb +1 -1
  59. data/lib/cloud_interactor/domain/destroy_record.rb +1 -1
  60. data/lib/cloud_interactor/domain/list_records.rb +1 -1
  61. data/lib/cloud_interactor/domain/update.rb +1 -1
  62. data/lib/cloud_interactor/domain/update_record.rb +6 -6
  63. data/lib/cloud_interactor/helpers.rb +1 -1
  64. data/lib/cloud_interactor/parser.rb +3 -2
  65. data/lib/cloud_interactor/region.rb +27 -0
  66. data/lib/cloud_interactor/server/create.rb +9 -0
  67. data/lib/cloud_interactor/sshkey.rb +59 -0
  68. data/lib/ridley/monkeypatches.rb +12 -0
  69. data/lib/sshkit/actions/start_task.rb +8 -2
  70. metadata +16 -2
@@ -20,39 +20,44 @@ class Cheftacular
20
20
 
21
21
  initialize_documentation_hash
22
22
 
23
- @config['helper'].completion_rate? 0, 'initializer'
23
+ initialize_ruby_config
24
24
 
25
- initialize_ridley
25
+ initialize_ridley unless @config['helper'].is_initialization_command?(ARGV[0])
26
26
 
27
- @config['helper'].completion_rate? 10, 'initializer'
27
+ initialize_classes
28
28
 
29
- initialize_ridley_environments
29
+ initialize_directories
30
30
 
31
- @config['helper'].completion_rate? 20, 'initializer'
31
+ initialize_cloud_checks
32
32
 
33
- initialize_ridley_roles_and_nodes
33
+ unless @config['helper'].is_initialization_command?(ARGV[0])
34
34
 
35
- @config['helper'].completion_rate? 30, 'initializer'
35
+ @config['helper'].completion_rate? 0, 'initializer'
36
36
 
37
- initialize_data_bags_for_environment @options['env'], true
37
+ @config['helper'].completion_rate? 10, 'initializer'
38
38
 
39
- @config['helper'].completion_rate? 90, 'initializer'
39
+ initialize_ridley_environments
40
40
 
41
- initialize_ruby_config
41
+ @config['helper'].completion_rate? 20, 'initializer'
42
42
 
43
- initialize_passwords @options['env']
43
+ initialize_ridley_roles_and_nodes
44
44
 
45
- initialize_classes
45
+ @config['helper'].completion_rate? 30, 'initializer'
46
46
 
47
- initialize_directories
47
+ initialize_data_bags_for_environment @options['env'], true
48
+
49
+ @config['helper'].completion_rate? 90, 'initializer'
50
+
51
+ initialize_passwords @options['env']
48
52
 
49
- @config['helper'].completion_rate? 100, 'initializer'
53
+ @config['helper'].completion_rate? 100, 'initializer'
50
54
 
51
- initialize_version_check if @config['cheftacular']['strict_version_checks']
55
+ initialize_version_check if @config['cheftacular']['strict_version_checks']
52
56
 
53
- initialize_auditing_checks if @config['cheftacular']['auditing']
57
+ initialize_auditing_checks if @config['cheftacular']['auditing']
54
58
 
55
- initialize_chef_repo_up_to_date if @config['cheftacular']['keep_chef_repo_cheftacular_yml_up_to_date']
59
+ initialize_chef_repo_up_to_date if @config['cheftacular']['keep_chef_repo_cheftacular_yml_up_to_date']
60
+ end
56
61
  end
57
62
 
58
63
  #changes to arguments should show up in the documentation methods in their appropriate method file
@@ -198,6 +203,10 @@ class Cheftacular
198
203
  @options['preferred_cloud'] = 'aws'
199
204
  end
200
205
 
206
+ opts.on('--do', "On cft cloud calls, set the cloud to DigitalOcean") do
207
+ @options['preferred_cloud'] = 'digitalocean'
208
+ end
209
+
201
210
  opts.on('--region REGION', 'On cft cloud calls, set the cloud region to perform operations on to this region') do |region|
202
211
  @options['preferred_cloud_region'] = region
203
212
  end
@@ -210,8 +219,12 @@ class Cheftacular
210
219
  @options['virtualization_mode'] = v_mode
211
220
  end
212
221
 
213
- #file
214
- opts.on('--save-to-file FILE_NAME', 'On cft file, this option can be used to save the output of the file display methods to your system. Also works in the fetch context') do |path|
222
+ opts.on('--route-dns-changes-via SERVICE', 'On cft cloud calls, set the default dns provider to this service') do |service|
223
+ @options['route_dns_changes_via'] = service
224
+ end
225
+
226
+ #file | chef_server
227
+ opts.on('--save-to-file FILE_NAME', 'On cft file or chef_server, this option can be used to save the output of the file display methods to your system. Also works in the fetch context') do |path|
215
228
  @options['save_to_file'] = path
216
229
  end
217
230
 
@@ -266,18 +279,21 @@ class Cheftacular
266
279
  locs['ssh'] = File.expand_path('/home/deploy/.ssh')
267
280
  end
268
281
 
269
- locs['chef-repo'] = Dir.getwd
270
- locs['roles'] = File.expand_path("#{ locs['chef-repo'] }/roles")
271
- locs['nodes'] = File.expand_path("#{ locs['chef-repo'] }/nodes_dir") #DO NOT RENAME THIS TO NODES
272
- locs['root'] = locs['chef-repo'] unless locs['root']
273
- locs['app-root'] = locs['chef-repo'] unless locs['app-root']
274
- locs['chef'] = File.expand_path("~/.chef") unless locs['chef']
275
- locs['cookbooks'] = File.expand_path("#{ locs['chef-repo'] }/cookbooks")
276
- locs['berks'] = File.expand_path('~/.berkshelf/cookbooks')
277
- locs['wrapper-cookbooks'] = @config['cheftacular']['wrapper-cookbooks']
278
- locs['ssh'] = File.expand_path('~/.ssh')
279
- locs['chef-log'] = File.expand_path("#{ locs['root']}/log") unless locs['chef-log']
280
- locs['app-tmp'] = File.expand_path("#{ locs['app-root']}/tmp")
282
+ locs['chef-repo'] = Dir.getwd
283
+ locs['roles'] = File.expand_path("#{ locs['chef-repo'] }/roles")
284
+ locs['nodes'] = File.expand_path("#{ locs['chef-repo'] }/nodes_dir") #DO NOT RENAME THIS TO NODES
285
+ locs['root'] = locs['chef-repo'] unless locs['root']
286
+ locs['app-root'] = locs['chef-repo'] unless locs['app-root']
287
+ locs['chef'] = File.expand_path("~/.chef") unless locs['chef']
288
+ locs['cookbooks'] = File.expand_path("#{ locs['chef-repo'] }/cookbooks")
289
+ locs['berks'] = File.expand_path('~/.berkshelf/cookbooks')
290
+ locs['wrapper-cookbooks'] = @config['cheftacular']['wrapper_cookbooks']
291
+ locs['ssh'] = File.expand_path('~/.ssh')
292
+ locs['chef-log'] = File.expand_path("#{ locs['root']}/log") unless locs['chef-log']
293
+ locs['app-tmp'] = File.expand_path("#{ locs['app-root']}/tmp")
294
+ locs['examples'] = File.expand_path("../../../examples", __FILE__)
295
+ locs['cheftacular-lib'] = File.expand_path("../..", __FILE__)
296
+ locs['cheftacular-lib-files'] = locs['cheftacular-lib'] + '/cheftacular/files'
281
297
 
282
298
  @config['locs'] = locs
283
299
  end
@@ -354,7 +370,7 @@ class Cheftacular
354
370
  "a ruby string to run commands against was not found in either your cheftacular.yml file or your .ruby-version file."
355
371
  ].join(' ')
356
372
 
357
- @config['helper'].exception_output msg, e
373
+ @config['error'].exception_output msg, e
358
374
  end
359
375
 
360
376
  @config['ruby_string'] = "ruby-" + @config['ruby_string'] unless @config['ruby_string'].include?('ruby-')
@@ -383,7 +399,7 @@ class Cheftacular
383
399
  def initialize_version_check detected_version=""
384
400
  current_version = Cheftacular::VERSION
385
401
 
386
- detected_version = File.exists?( @config['helper'].current_version_file_path ) ? File.read( @config['helper'].current_version_file_path ) : @config['helper'].fetch_remote_version
402
+ detected_version = File.exists?( @config['filesystem'].current_version_file_path ) ? File.read( @config['filesystem'].current_version_file_path ) : @config['helper'].fetch_remote_version
387
403
 
388
404
  if @config['helper'].is_higher_version? detected_version, current_version
389
405
  puts "\n Your Cheftacular is out of date. Currently #{ current_version } and remote version is #{ detected_version }.\n"
@@ -392,16 +408,16 @@ class Cheftacular
392
408
 
393
409
  exit
394
410
  else
395
- unless File.exists?( @config['helper'].current_version_file_path )
411
+ unless File.exists?( @config['filesystem'].current_version_file_path )
396
412
  puts "Creating file cache for #{ Time.now.strftime("%Y%m%d") } (#{ detected_version }). No new version detected."
397
413
 
398
- @config['helper'].write_version_file detected_version
414
+ @config['filesystem'].write_version_file detected_version
399
415
  end
400
416
  end
401
417
  end
402
418
 
403
419
  def initialize_auditing_checks
404
- unless File.exists? @config['helper'].current_audit_file_path
420
+ unless File.exists? @config['filesystem'].current_audit_file_path
405
421
  puts "Creating file cache for #{ Time.now.strftime("%Y%m%d") } audit data..."
406
422
 
407
423
  @config['auditor'].write_audit_cache_file
@@ -421,6 +437,7 @@ class Cheftacular
421
437
  @config['error'] = Cheftacular::Error.new(@options, @config)
422
438
  @config['dummy_sshkit'] = SSHKit::Backend::Netssh.new(SSHKit::Host.new('127.0.0.1'))
423
439
  @config['DNS'] = Cheftacular::DNS.new(@options, @config)
440
+ @config['cloud_provider'] = Cheftacular::CloudProvider.new(@options, @config)
424
441
  end
425
442
 
426
443
  def initialize_directories
@@ -430,16 +447,59 @@ class Cheftacular
430
447
 
431
448
  FileUtils.mkdir_p File.join( @config['locs']['app-tmp'], @config['helper'].declassify)
432
449
 
433
- FileUtils.mkdir_p @config['helper'].current_nodes_file_cache_path
450
+ FileUtils.mkdir_p @config['filesystem'].current_nodes_file_cache_path
451
+
452
+ @config['filesystem'].cleanup_file_caches
453
+ end
454
+
455
+ def initialize_cloud_checks exit_on_finish = false
456
+ hash = @config['cheftacular']['cloud_authentication']
457
+
458
+ unless hash.has_key?(@options['preferred_cloud'])
459
+ puts "Critical! No Cloud credentials detected for your preferred cloud #{ @options['preferred_cloud'] }, " +
460
+ "Please update the cheftacular.yml cloud_authentication:#{ @options['preferred_cloud'] } key!"
461
+
462
+ exit_on_finish = true
463
+ end
464
+
465
+ if hash.has_key?('rackspace')
466
+ if !( hash['rackspace'].has_key?('username') || hash['rackspace'].has_key?('api_key') || hash['rackspace'].has_key?('email'))
467
+
468
+ puts "Critical! No cloud credentials detected for the rackspace cloud_authentication hash! There must be both a valid username and an api_key in this hash!"
469
+ puts "Please update the cheftacular.yml cloud_authentication:rackspace key!"
470
+
471
+ exit_on_finish = true
472
+ elsif hash['rackspace']['username'].empty? || hash['rackspace']['api_key'].empty? || hash['rackspace']['email'].empty?
473
+ puts "Critical! Cloud credentials detected for the rackspace cloud_authentication hash are blank!"
474
+ puts "Please update the cheftacular.yml cloud_authentication:rackspace key!"
475
+
476
+ exit_on_finish = true
477
+ end
478
+ end
479
+
480
+ if hash.has_key?('digitalocean')
481
+ if !( hash['digitalocean'].has_key?('client_id') || hash['digitalocean'].has_key?('api_key'))
482
+
483
+ puts "Critical! No cloud credentials detected for the digitalocean cloud_authentication hash! There must be both a valid client_id and an api_key in this hash!"
484
+ puts "Please update the cheftacular.yml cloud_authentication:digitalocean key!"
485
+
486
+ exit_on_finish = true
487
+ elsif hash['digitalocean']['client_id'].empty? || hash['digitalocean']['api_key'].empty?
488
+ puts "Critical! Cloud credentials detected for the digitalocean cloud_authentication hash are blank!"
489
+ puts "Please update the cheftacular.yml cloud_authentication:digitalocean key!"
490
+
491
+ exit_on_finish = true
492
+ end
493
+ end
434
494
 
435
- @config['helper'].cleanup_file_caches
495
+ exit if exit_on_finish
436
496
  end
437
497
 
438
498
  def initialize_chef_repo_up_to_date
439
499
  if @config['helper'].running_in_mode?('devops')
440
500
  @config['cheftacular']['wrapper_cookbooks'].split(',').each do |wrapper_cookbook|
441
- parsed_hash = if File.exists?( @config['helper'].current_chef_repo_cheftacular_file_cache_path )
442
- File.read( @config['helper'].current_chef_repo_cheftacular_file_cache_path )
501
+ parsed_hash = if File.exists?( @config['filesystem'].current_chef_repo_cheftacular_file_cache_path )
502
+ File.read( @config['filesystem'].current_chef_repo_cheftacular_file_cache_path )
443
503
  else
444
504
  Digest::SHA2.hexdigest(@config['helper'].compile_chef_repo_cheftacular_yml_as_hash.to_yaml.to_s)
445
505
  end
@@ -450,20 +510,20 @@ class Cheftacular
450
510
  unless File.exist?(wrapper_cookbook_cheftacular_loc)
451
511
  puts "Wrapper cookbook \"#{ wrapper_cookbook }\" does not have a cheftacular.yml file in #{ @config['cheftacular']['location_of_chef_repo_cheftacular_yml'] }! Creating..."
452
512
 
453
- @config['helper'].write_chef_repo_cheftacular_yml_file wrapper_cookbook_cheftacular_loc
513
+ @config['filesystem'].write_chef_repo_cheftacular_yml_file wrapper_cookbook_cheftacular_loc
454
514
  end
455
515
 
456
516
  if parsed_hash == Digest::SHA2.hexdigest(File.read(wrapper_cookbook_cheftacular_loc))
457
- next if File.exists?( @config['helper'].current_chef_repo_cheftacular_file_cache_path )
517
+ next if File.exists?( @config['filesystem'].current_chef_repo_cheftacular_file_cache_path )
458
518
  else
459
519
  puts "Wrapper cookbook (#{ wrapper_cookbook }) does not have a current cheftacular.yml file in #{ @config['cheftacular']['location_of_chef_repo_cheftacular_yml'] }\"! Overwriting..."
460
520
 
461
- @config['helper'].write_chef_repo_cheftacular_yml_file wrapper_cookbook_cheftacular_loc
521
+ @config['filesystem'].write_chef_repo_cheftacular_yml_file wrapper_cookbook_cheftacular_loc
462
522
  end
463
523
 
464
524
  puts "Creating file cache for #{ Time.now.strftime("%Y%m%d") }'s cheftacular.yml."
465
525
 
466
- @config['helper'].write_chef_repo_cheftacular_cache_file parsed_hash
526
+ @config['filesystem'].write_chef_repo_cheftacular_cache_file parsed_hash
467
527
  end
468
528
  end
469
529
  end
@@ -226,5 +226,11 @@ class Cheftacular
226
226
  else mode
227
227
  end
228
228
  end
229
+
230
+ def parse_base_chef_server_url
231
+ domain = PublicSuffix.parse @config['cheftacular']['chef_server_url'].gsub('https://','').split('/').first
232
+
233
+ "#{ domain.trd }.#{ domain.domain }"
234
+ end
229
235
  end
230
236
  end
@@ -33,9 +33,9 @@ class Cheftacular
33
33
  public_ssh_key = ARGV[1]
34
34
 
35
35
  if specific_repository.blank?
36
- @config['default']['authentication_bag_hash']["authorized_keys"] << public_ssh_key
36
+ @config['default']['authentication_bag_hash']["authorized_keys"] << public_ssh_key.gsub("'",'')
37
37
  else
38
- @config['default']['authentication_bag_hash']["specific_authorized_keys"] << public_ssh_key
38
+ @config['default']['authentication_bag_hash']["specific_authorized_keys"] << public_ssh_key.gsub("'",'')
39
39
  end
40
40
 
41
41
  @config['ChefDataBag'].save_authentication_bag
@@ -55,10 +55,17 @@ class Cheftacular
55
55
  end
56
56
  end
57
57
 
58
+ class InitializationAction
59
+ def arguments
60
+
61
+ end
62
+ end
63
+
58
64
  class StatelessAction
59
65
  def arguments
60
- #TODO point this command to it's help and display?
61
- raise "This command currently does nothing, do not try to run it."
66
+ @config['stateless_action_documentation'].arguments
67
+
68
+ puts @config['documentation']['arguments']
62
69
  end
63
70
  end
64
71
  end
@@ -113,4 +113,4 @@ module SSHKit
113
113
  end
114
114
  end
115
115
  end
116
- end
116
+ end
@@ -45,7 +45,7 @@ class Cheftacular
45
45
 
46
46
  deploy_commands = [
47
47
  "#{ sudo } apt-get update",
48
- "#{ sudo } apt-get install curl git-core shorewall -y",
48
+ "#{ sudo } apt-get install curl #{ @config['cheftacular']['pre_install_packages'] } -y",
49
49
  "#{ sudo } apt-get upgrade -y"
50
50
  ]
51
51
 
@@ -55,18 +55,29 @@ class Cheftacular
55
55
  deploy_commands << "gpg --keyserver hkp://keys.gnupg.net --recv-keys #{ @config['cheftacular']['rvm_gpg_key'] }"
56
56
  deploy_commands << "curl -L https://get.rvm.io | bash -s stable"
57
57
 
58
- final_commands
59
-
60
58
  rvm_source = "source /home/deploy/.rvm/bin/rvm &&"
61
59
 
62
60
  final_commands = [
63
61
  "#{ rvm_source } echo '#{ new_deploy_pass }' | rvmsudo -S rvm requirements",
64
62
  "#{ rvm_source } rvm install #{ @config['cheftacular']['ruby_version'] }",
65
- "#{ rvm_source } rvm install 1.9.3-p327" #chef's default ruby, we'll need it in a place rvm can find it until the symlink is made
63
+ "#{ rvm_source } rvm alias create default #{ @config['cheftacular']['ruby_version'] }",
64
+ "#{ rvm_source } rvm gemset empty --force"
66
65
  ]
66
+
67
+ final_commands << "#{ rvm_source } rvm install 1.9.3-p327" if @config['cheftacular']['chef_version'].to_i < 12
68
+ end
69
+
70
+ root_execute_string = "sshpass -p \"#{ @options['client_pass'] }\" ssh -t -oStrictHostKeyChecking=no root@#{ @options['address'] } '#{ root_commands.join(' && ') } && service ssh restart'"
71
+
72
+ while system(root_execute_string) != true
73
+ tries ||= 5
74
+ puts "Unable to complete step 1 of setup process, trying again in 60 seconds, there are #{ tries } more tries"
75
+ sleep 60
76
+ tries -= 1
77
+ raise "Unable to complete step 1 of setup process!" if tries <= 0
67
78
  end
68
79
 
69
- out << `sshpass -p "#{ @options['client_pass'] }" ssh -t -oStrictHostKeyChecking=no root@#{ @options['address'] } '#{ root_commands.join(' && ') } && service ssh restart'`
80
+ out << $?.to_s #output from the system command above
70
81
 
71
82
  puts("Finished initial setup...stage 1 of 3 for server #{ @options['address'] }") if @options['in_scaling']
72
83
 
@@ -0,0 +1,79 @@
1
+
2
+ class Cheftacular
3
+ class StatelessActionDocumentation
4
+ def check_cheftacular_yml_keys
5
+ @config['documentation']['stateless_action'] << [
6
+ "`cft check_cheftacular_yml_keys` allows you to check to see if your cheftacular yml keys are valid to the current version of cheftacular. " +
7
+ "It will also set your missing keys to their likely default and let you know to update the cheftacular.yml file."
8
+ ]
9
+ end
10
+ end
11
+
12
+ class StatelessAction
13
+ def check_cheftacular_yml_keys out=[], exit_on_missing=false, warn_on_missing=false
14
+ base_message = "Your cheftacular.yml is missing the key KEY, its default value is being set to DEFAULT for this run."
15
+
16
+ #############################2.6.0################################################
17
+ unless @config['cheftacular'].has_key?('route_dns_changes_via')
18
+ puts base_message.gsub('KEY', 'route_dns_changes_via').gsub('DEFAULT', @options['preferred_cloud'])
19
+
20
+ @config['cheftacular']['route_dns_changes_via'] = @options['preferred_cloud']
21
+
22
+ warn_on_missing = true
23
+ end
24
+
25
+ unless @config['cheftacular'].has_key?('node_name_separator')
26
+ puts base_message.gsub('KEY', 'node_name_separator').gsub('DEFAULT', '-')
27
+
28
+ @config['cheftacular']['node_name_separator'] = '-'
29
+
30
+ warn_on_missing = true
31
+ end
32
+
33
+ unless @config['cheftacular'].has_key?('cloud_authentication')
34
+ puts (base_message.gsub('KEY', 'cloud_authentication').split(',').first + ', this is a critical issue and must be fixed.')
35
+
36
+ exit_on_missing = true
37
+ end
38
+
39
+ if !@config['cheftacular'].has_key?('chef_server') && @options['command'] == 'chef_server'
40
+ puts (base_message.gsub('KEY', 'chef_server').split(',').first + ', this is a critical issue and must be fixed to run the chef_server command.')
41
+
42
+ exit_on_missing = true
43
+ end
44
+
45
+ unless @config['cheftacular'].has_key?('chef_version')
46
+ puts (base_message.gsub('KEY', 'chef_version').split(',').first + ', this is a critical issue and must be fixed.')
47
+
48
+ exit_on_missing = true
49
+ end
50
+
51
+ unless @config['cheftacular'].has_key?('pre_install_packages')
52
+ puts base_message.gsub('KEY', 'pre_install_packages').gsub('DEFAULT', '')
53
+
54
+ @config['cheftacular']['pre_install_packages'] = ''
55
+
56
+ warn_on_missing = true
57
+ end
58
+
59
+ unless @config['cheftacular'].has_key?('role_toggling')
60
+ puts base_message.gsub('KEY', 'role_toggling').gsub('DEFAULT', "it's default nested keys")
61
+
62
+ @config['cheftacular']['role_toggling'] = {}
63
+ @config['cheftacular']['role_toggling']['deactivated_role_suffix'] = '_deactivated'
64
+ @config['cheftacular']['role_toggling']['strict_roles'] = true
65
+ @config['cheftacular']['role_toggling']['skip_confirm'] = false
66
+ @config['cheftacular']['role_toggling']['do_not_allow_toggling'] = true
67
+
68
+ warn_on_missing = true
69
+ end
70
+
71
+ if warn_on_missing || exit_on_missing
72
+ puts "Please enter your missing keys into your cheftacular.yml based off of the cheftacular.yml at"
73
+ puts "\n https://github.com/SocialCentivPublic/cheftacular/blob/master/examples/cheftacular.yml"
74
+ end
75
+
76
+ exit if exit_on_missing || @options['command'] == __method__
77
+ end
78
+ end
79
+ end
@@ -13,12 +13,28 @@ class Cheftacular
13
13
  def chef_bootstrap out=[]
14
14
  raise "This action can only be performed if the mode is set to devops" if !@config['helper'].running_in_mode?('devops') && !@options['in_scaling']
15
15
 
16
- @options['address'] = ARGV[1] unless @options['address']
16
+ @options['address'] = ARGV[1] unless @options['address']
17
17
  @options['node_name'] = ARGV[2] unless @options['node_name']
18
18
 
19
- @config['stateless_action'].remove_client #just in case
19
+ #@config['stateless_action'].remove_client #just in case
20
20
 
21
- puts("Starting chef-client initialization...") unless @options['quiet']
21
+ if @config['cheftacular']['chef_version'].to_i >= 12
22
+ puts("Starting chef-client installation...") unless @options['quiet']
23
+
24
+ commands = [
25
+ "curl -L https://www.opscode.com/chef/install.sh > ~/chef-install.sh",
26
+ "#{ @config['helper'].sudo(@options['address']) } bash /home/deploy/chef-install.sh",
27
+ "rm ~/chef-install.sh"
28
+ ]
29
+
30
+ commands.each do |command|
31
+ out << `ssh -t -oStrictHostKeyChecking=no #{ @config['cheftacular']['deploy_user'] }@#{ @options['address'] } "#{ command }"`
32
+
33
+ puts(out.last) unless @options['quiet'] || @options['in_scaling']
34
+ end
35
+ end
36
+
37
+ puts("Starting chef bootstrap...") unless @options['quiet']
22
38
 
23
39
  out << `#{ @config['helper'].knife_bootstrap_command }`
24
40
 
@@ -34,7 +50,7 @@ class Cheftacular
34
50
 
35
51
  @options['force_yes'] = true # have the upload_nodes grab the new nodes
36
52
 
37
- @config['stateless_action'].upload_nodes
53
+ @config['stateless_action'].upload_nodes(true)
38
54
  end
39
55
  end
40
56
  end
@@ -0,0 +1,78 @@
1
+ class Cheftacular
2
+ class StatelessActionDocumentation
3
+ def chef_server
4
+ @config['documentation']['stateless_action'] << [
5
+ "`cft chef_server [restart|processes|memory]` this command can be used to query the chef server for stats if the cheftacular.yml " +
6
+ "has the chef_server key filled out. Useful for low resource chef-servers.",
7
+
8
+ [
9
+ " 1. `restart` restarts all chef processes on the chef server which may alleviate slow cheftacular load times for some users. (NOTE) " +
10
+ "do not run this command while the chef-server is performing actions or instability may result! Not tested for high volume chef servers.",
11
+
12
+ " 2. `processes` runs `ps aux` on the server to return the running processes and their stats.",
13
+
14
+ " 3. `memory` runs `free -m` on the server to return the current memory usage.",
15
+
16
+ " 4. NOTE! This command (and all arguments to it) bypass the normal environment loading like the help command.",
17
+
18
+ " 5. NOTE 2! Cheftacular does not (and will not) support accessing your chef server over ssh with password auth. If you have done this, " +
19
+ "you should feel bad and immediately switch ssh access to key authentication..."
20
+ ]
21
+ ]
22
+
23
+ @config['documentation']['application'] << @config['documentation']['stateless_action'].last
24
+ end
25
+ end
26
+
27
+ class InitializationAction
28
+ def chef_server
29
+
30
+ end
31
+ end
32
+
33
+ class StatelessAction
34
+ def chef_server
35
+ raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops')
36
+
37
+ if @config['cheftacular']['chef_server'].nil? || !@config['cheftacular']['chef_server']['interactable']
38
+ raise "Chef server is not currently set to be interactable with the chef-server command"
39
+ end
40
+
41
+ command = ARGV[1]
42
+
43
+ raise "Unsupported command (#{ command }) for cft chef_server" unless command =~ /restart|processes|memory/
44
+
45
+ command_prefix = case @config['cheftacular']['chef_server']['ssh_user']
46
+ when 'root' then ''
47
+ else "echo #{ @config['cheftacular']['chef_server']['sudo_pass'] } | sudo -S "
48
+ end
49
+
50
+ command = case command
51
+ when 'restart' then command_prefix + 'chef-server-ctl restart'
52
+ when 'processes' then 'ps aux'
53
+ when 'memory' then 'free -m'
54
+ end
55
+
56
+ options = @options
57
+
58
+ on ( @config['cheftacular']['chef_server']['ssh_user'] + "@" + @config['parser'].parse_base_chef_server_url ) do |host|
59
+
60
+ puts "Beginning chef-server #{ command } run"
61
+
62
+ start_chef_server_interactor(command, options)
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ module SSHKit
69
+ module Backend
70
+ class Netssh
71
+ def start_chef_server_interactor command, options, out=""
72
+ puts capture( command )
73
+
74
+ puts "Succeeded chef-server interaction run" unless options['quiet']
75
+ end
76
+ end
77
+ end
78
+ end
@@ -38,7 +38,7 @@ class Cheftacular
38
38
  berkshelf_cookbooks = {}
39
39
 
40
40
  Dir.foreach(@config['locs']['berks']) do |berkshelf_cookbook|
41
- next if @config['helper'].is_junk_filename?(berkshelf_cookbook)
41
+ next if @config['filesystem'].is_junk_filename?(berkshelf_cookbook)
42
42
  skip = false
43
43
 
44
44
  berkshelf_cookbooks.keys.each do |processed_berkshelf_cookbook|
@@ -62,7 +62,7 @@ class Cheftacular
62
62
  chef_repo_cookbooks = {}
63
63
 
64
64
  Dir.foreach(@config['locs']['cookbooks']) do |chef_repo_cookbook|
65
- next if @config['helper'].is_junk_filename?(chef_repo_cookbook)
65
+ next if @config['filesystem'].is_junk_filename?(chef_repo_cookbook)
66
66
 
67
67
  new_name = chef_repo_cookbook.rpartition('-').first
68
68
 
@@ -101,4 +101,4 @@ class Cheftacular
101
101
  end
102
102
  end
103
103
  end
104
- end
104
+ end
@@ -2,13 +2,15 @@
2
2
  class Cheftacular
3
3
  class StatelessActionDocumentation
4
4
  def clean_server_passwords
5
-
5
+
6
6
  end
7
7
  end
8
8
 
9
9
  class StatelessAction
10
10
  def clean_server_passwords
11
11
  #TODO clean up non-existent entries in all envs server_password bags
12
+ raise "This method is not yet implemented"
13
+ raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops')
12
14
  end
13
15
  end
14
16
  end
@@ -9,6 +9,7 @@ class Cheftacular
9
9
  class StatelessAction
10
10
  def cleanup_log_files
11
11
  #TODO
12
+ raise "This method is not yet implemented"
12
13
  end
13
14
  end
14
15
  end
@@ -23,7 +23,7 @@ class Cheftacular
23
23
 
24
24
  class StatelessAction
25
25
  def client_list
26
- @config['helper'].cleanup_file_caches('current')
26
+ @config['filesystem'].cleanup_file_caches('current')
27
27
 
28
28
  nodes = @config['getter'].get_true_node_objects(true)
29
29
 
@@ -38,7 +38,7 @@ class Cheftacular
38
38
 
39
39
  env_nodes = @config['parser'].exclude_nodes(nodes, [{ if: { not_env: env } }])
40
40
  puts "\nFound #{ env_nodes.count } #{ env } nodes:"
41
- out = " #{ 'name'.ljust(22) } #{ 'ip_address'.ljust(20) }"
41
+ out = " #{ 'name'.ljust(22) } #{ 'ip_address'.ljust(21) }"
42
42
  out << "#{ 'private_address'.ljust(21) }" if @options['with_private']
43
43
  out << "#{ 'pass?'.ljust(5) } #{ 'domain'.ljust(41) }" if @options['verbose']
44
44
  out << "#{ 'deploy_password'.ljust(21) }" if @options['verbose']