cheftacular 2.5.0 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
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']