cheftacular 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. checksums.yaml +7 -0
  2. data/bin/cft +4 -0
  3. data/bin/cftclr +4 -0
  4. data/bin/cheftacular +4 -0
  5. data/bin/client-list +4 -0
  6. data/lib/cheftacular/README.md +416 -0
  7. data/lib/cheftacular/actions/check.rb +32 -0
  8. data/lib/cheftacular/actions/console.rb +62 -0
  9. data/lib/cheftacular/actions/database.rb +13 -0
  10. data/lib/cheftacular/actions/db_console.rb +67 -0
  11. data/lib/cheftacular/actions/deploy.rb +40 -0
  12. data/lib/cheftacular/actions/log.rb +47 -0
  13. data/lib/cheftacular/actions/migrate.rb +57 -0
  14. data/lib/cheftacular/actions/run.rb +64 -0
  15. data/lib/cheftacular/actions/scale.rb +94 -0
  16. data/lib/cheftacular/actions/tail.rb +55 -0
  17. data/lib/cheftacular/actions.rb +14 -0
  18. data/lib/cheftacular/auditor.rb +46 -0
  19. data/lib/cheftacular/chef/data_bag.rb +104 -0
  20. data/lib/cheftacular/cheftacular.rb +55 -0
  21. data/lib/cheftacular/decryptors.rb +45 -0
  22. data/lib/cheftacular/encryptors.rb +48 -0
  23. data/lib/cheftacular/getters.rb +153 -0
  24. data/lib/cheftacular/helpers.rb +296 -0
  25. data/lib/cheftacular/initializers.rb +451 -0
  26. data/lib/cheftacular/parsers.rb +199 -0
  27. data/lib/cheftacular/remote_helpers.rb +30 -0
  28. data/lib/cheftacular/stateless_action.rb +16 -0
  29. data/lib/cheftacular/stateless_actions/add_ssh_key_to_bag.rb +44 -0
  30. data/lib/cheftacular/stateless_actions/arguments.rb +68 -0
  31. data/lib/cheftacular/stateless_actions/backups.rb +116 -0
  32. data/lib/cheftacular/stateless_actions/bootstrappers/centos_bootstrap.rb +7 -0
  33. data/lib/cheftacular/stateless_actions/bootstrappers/coreos_bootstrap.rb +7 -0
  34. data/lib/cheftacular/stateless_actions/bootstrappers/fedora_bootstrap.rb +7 -0
  35. data/lib/cheftacular/stateless_actions/bootstrappers/redhat_bootstrap.rb +7 -0
  36. data/lib/cheftacular/stateless_actions/bootstrappers/ubuntu_bootstrap.rb +102 -0
  37. data/lib/cheftacular/stateless_actions/bootstrappers/vyatta_bootstrap.rb +7 -0
  38. data/lib/cheftacular/stateless_actions/chef_bootstrap.rb +40 -0
  39. data/lib/cheftacular/stateless_actions/chef_environment.rb +21 -0
  40. data/lib/cheftacular/stateless_actions/clean_cookbooks.rb +104 -0
  41. data/lib/cheftacular/stateless_actions/clean_sensu_plugins.rb +19 -0
  42. data/lib/cheftacular/stateless_actions/clean_server_passwords.rb +14 -0
  43. data/lib/cheftacular/stateless_actions/cleanup_log_files.rb +14 -0
  44. data/lib/cheftacular/stateless_actions/client_list.rb +89 -0
  45. data/lib/cheftacular/stateless_actions/cloud.rb +107 -0
  46. data/lib/cheftacular/stateless_actions/cloud_bootstrap.rb +109 -0
  47. data/lib/cheftacular/stateless_actions/compile_audit_log.rb +60 -0
  48. data/lib/cheftacular/stateless_actions/compile_readme.rb +41 -0
  49. data/lib/cheftacular/stateless_actions/create_git_key.rb +67 -0
  50. data/lib/cheftacular/stateless_actions/disk_report.rb +75 -0
  51. data/lib/cheftacular/stateless_actions/environment.rb +100 -0
  52. data/lib/cheftacular/stateless_actions/fetch_file.rb +24 -0
  53. data/lib/cheftacular/stateless_actions/fix_known_hosts.rb +70 -0
  54. data/lib/cheftacular/stateless_actions/full_bootstrap.rb +30 -0
  55. data/lib/cheftacular/stateless_actions/get_active_ssh_connections.rb +18 -0
  56. data/lib/cheftacular/stateless_actions/get_haproxy_log.rb +55 -0
  57. data/lib/cheftacular/stateless_actions/get_log_from_bag.rb +38 -0
  58. data/lib/cheftacular/stateless_actions/get_pg_pass.rb +61 -0
  59. data/lib/cheftacular/stateless_actions/help.rb +71 -0
  60. data/lib/cheftacular/stateless_actions/initialize_data_bag_contents.rb +220 -0
  61. data/lib/cheftacular/stateless_actions/knife_upload.rb +23 -0
  62. data/lib/cheftacular/stateless_actions/pass.rb +49 -0
  63. data/lib/cheftacular/stateless_actions/reinitialize.rb +46 -0
  64. data/lib/cheftacular/stateless_actions/remove_client.rb +81 -0
  65. data/lib/cheftacular/stateless_actions/replication_status.rb +103 -0
  66. data/lib/cheftacular/stateless_actions/restart_swap.rb +55 -0
  67. data/lib/cheftacular/stateless_actions/rvm.rb +14 -0
  68. data/lib/cheftacular/stateless_actions/server_update.rb +99 -0
  69. data/lib/cheftacular/stateless_actions/service.rb +14 -0
  70. data/lib/cheftacular/stateless_actions/test_env.rb +82 -0
  71. data/lib/cheftacular/stateless_actions/update_split_branches.rb +64 -0
  72. data/lib/cheftacular/stateless_actions/update_tld.rb +62 -0
  73. data/lib/cheftacular/stateless_actions/upload_nodes.rb +120 -0
  74. data/lib/cheftacular/stateless_actions/upload_roles.rb +24 -0
  75. data/lib/cheftacular/version.rb +5 -0
  76. data/lib/cheftacular.rb +4 -0
  77. data/lib/cloud_interactor/authentication.rb +56 -0
  78. data/lib/cloud_interactor/cloud_interactor.rb +23 -0
  79. data/lib/cloud_interactor/domain/create.rb +17 -0
  80. data/lib/cloud_interactor/domain/create_record.rb +27 -0
  81. data/lib/cloud_interactor/domain/destroy.rb +17 -0
  82. data/lib/cloud_interactor/domain/destroy_record.rb +23 -0
  83. data/lib/cloud_interactor/domain/list.rb +9 -0
  84. data/lib/cloud_interactor/domain/list_records.rb +22 -0
  85. data/lib/cloud_interactor/domain/read.rb +23 -0
  86. data/lib/cloud_interactor/domain/read_record.rb +27 -0
  87. data/lib/cloud_interactor/domain/update.rb +18 -0
  88. data/lib/cloud_interactor/domain/update_record.rb +42 -0
  89. data/lib/cloud_interactor/domain.rb +18 -0
  90. data/lib/cloud_interactor/flavor.rb +27 -0
  91. data/lib/cloud_interactor/helpers.rb +70 -0
  92. data/lib/cloud_interactor/image.rb +27 -0
  93. data/lib/cloud_interactor/parser.rb +37 -0
  94. data/lib/cloud_interactor/server/attach_volume.rb +33 -0
  95. data/lib/cloud_interactor/server/create.rb +39 -0
  96. data/lib/cloud_interactor/server/destroy.rb +11 -0
  97. data/lib/cloud_interactor/server/detach_volume.rb +21 -0
  98. data/lib/cloud_interactor/server/list.rb +7 -0
  99. data/lib/cloud_interactor/server/list_volumes.rb +25 -0
  100. data/lib/cloud_interactor/server/poll.rb +22 -0
  101. data/lib/cloud_interactor/server/read.rb +9 -0
  102. data/lib/cloud_interactor/server/read_volume.rb +24 -0
  103. data/lib/cloud_interactor/server.rb +17 -0
  104. data/lib/cloud_interactor/version.rb +4 -0
  105. data/lib/cloud_interactor/volume/create.rb +13 -0
  106. data/lib/cloud_interactor/volume/destroy.rb +11 -0
  107. data/lib/cloud_interactor/volume/list.rb +7 -0
  108. data/lib/cloud_interactor/volume/read.rb +9 -0
  109. data/lib/cloud_interactor/volume.rb +20 -0
  110. data/lib/ridley/monkeypatches.rb +11 -0
  111. data/lib/sshkit/actions/start_commit_check.rb +19 -0
  112. data/lib/sshkit/actions/start_deploy.rb +25 -0
  113. data/lib/sshkit/actions/start_log_fetch.rb +91 -0
  114. data/lib/sshkit/actions/start_task.rb +29 -0
  115. data/lib/sshkit/getters.rb +67 -0
  116. data/lib/sshkit/helpers.rb +13 -0
  117. data/lib/sshkit/monkeypatches.rb +19 -0
  118. metadata +375 -0
@@ -0,0 +1,16 @@
1
+
2
+ class Cheftacular
3
+ class StatelessActionDocumentation
4
+ def initialize options, config
5
+ @options, @config = options, config
6
+ end
7
+ end
8
+
9
+ class StatelessAction
10
+ include RbConfig
11
+
12
+ def initialize options, config
13
+ @options, @config = options, config
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,44 @@
1
+ #refresh the authorized_keys in the authentication data bag from the chef server
2
+ class Cheftacular
3
+ class StatelessActionDocumentation
4
+ def add_ssh_key_to_bag
5
+ @config['documentation']['stateless_action'] << [
6
+ "`cft add_ssh_key_to_bag \"<NEW SSH PUB KEY>\" [SPECIFIC_REPOSITORY]` this command will add the given ssh key to the default authentication data bag. " +
7
+ "After this your server recipes should read the contents of the 'default' 'authentication' bag for the authorized_keys array.",
8
+
9
+ [
10
+ " 1. `SPECIFIC_REPOSITORY` is a special argument, if left blank the key will be placed in the authorized_keys array in the bag, otherwise it will " +
11
+ "be placed in the specific_authorized_keys hash under a key named for the repository that is passed. The script will error if SPECIFIC_REPOSITORY " +
12
+ "does not exist in the cheftacular.yml respositories hash. You can then use this data to give users selective ssh access to certain servers."
13
+ ]
14
+ ]
15
+ end
16
+ end
17
+
18
+ class StatelessAction
19
+ #TODO key for environment specific deploys?
20
+ def add_ssh_key_to_bag specific_repository=""
21
+ raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops')
22
+
23
+ raise "Please put quotes around your SSH public key!" if ARGV[1].length < 25 #TODO REFACTOR to accurate length of shortest key
24
+
25
+ specific_repository = ARGV[2] if ARGV[2] && specific_repository.empty?
26
+
27
+ unless @config['helper'].get_array_of_repo_names_for_repositories.include?(specific_repository)
28
+ puts "The repository passed (#{ specific_repository }) is not listed in the cheftacular.yml repositories hash! Please update the hash or check your spelling!"
29
+
30
+ return false
31
+ end
32
+
33
+ public_ssh_key = ARGV[1]
34
+
35
+ if specific_repository.blank?
36
+ @config['default']['authentication_bag_hash']["authorized_keys"] << pub_ssh_key
37
+ else
38
+ @config['default']['authentication_bag_hash']["specific_authorized_keys"] << pub_ssh_key
39
+ end
40
+
41
+ @config['ChefDataBag'].save_authentication_bag
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,68 @@
1
+ class Cheftacular
2
+ class StatelessActionDocumentation
3
+ def arguments
4
+ @config['documentation']['arguments'] << [
5
+ '## Arguments and flags for cheftacular',
6
+
7
+ '### Environment flags',
8
+
9
+ '1. `-d|--dev-remote` toggles on dev-remote mode. Commands passed to cft will hit the devremote server(s) instead of the default server(s)',
10
+
11
+ '2. `--env ENV` sets the environment commands hit to one you specify instead of the default one.',
12
+
13
+ '3. `-p|--prod` toggles on production mode. Commands passed to cft will hit the production server(s) instead of the default server(s)',
14
+
15
+ '4. `-Q|--qa` toggles on QA mode. Commands passed to cft will hit the QA server(s) instead of the default server(s)',
16
+
17
+ '5. `-s|--staging` toggles on staging mode. Commands passed to cft will hit the staging server(s) instead of the default server(s)',
18
+
19
+ '6. `--split-env SPLIT_ENV_NAME` sets the sub-environment to SPLIT_ENV_NAME. This only slightly affects certain commands.',
20
+
21
+ '7. `-t|--test` toggles on test mode. Commands passed to cft will hit the test server(s) instead of the default server(s)',
22
+
23
+ '### General Flags',
24
+
25
+ '1. `-a|--address ADDRESS` will force the command to only run against the specified address if it belongs to a node',
26
+
27
+ '2. `-D|--debug` toggles on extremely verbose logging. Chef-client runs will generate ~10 times the amounts of logs including any additional effects that the `-v` flag will activate',
28
+
29
+ '3. `--no-logs` will make the cft commands not generate log files, you must still specify `-v` if you want output of most verbose commands to your terminal.',
30
+
31
+ '4. `-n|--node-name NODE_NAME` will force the command to only run against the specified name if it belongs to a node',
32
+
33
+ '5. `-q|--quiet` will make the cft commands only output information that is a direct result of the command being run',
34
+
35
+ "6. `-r|--role-name ROLE_NAME` will force the command to only run against the specified role if it exists (this argument is generally not needed though it can be used to deploy a codebase for an application you're not currently cd'd into when running this as a gem)",
36
+
37
+ '7. `-R|--repository NAME` will make the command run against a specific repository or context (automatically set for application mode)',
38
+
39
+ '8. `-v|--verbose` toggles on verbose logging. All commands that write logs will also output to terminal AND write the logs.',
40
+
41
+ '### Help Related',
42
+
43
+ '1. `-h|--help` Displays the full readme and exits.',
44
+
45
+ '### Action Flags',
46
+
47
+ '1. `-e|--except-role ROLE_NAME` will *prevent* any server with this role from being *deployed to* for the deploy command. Other commands will ignore this argument.',
48
+
49
+ '2. `-z|--unset-revision` will unset a custom revision specified in the arg below and make the codebase utilize the default (staging branch for staging and master for production)',
50
+
51
+ "3. `-Z|--revision REVISION` will force the role you're deploying to to utilize the revision specified here. This can be a specific commit or a branch name.",
52
+
53
+ ' 1. Note: The system does not check if the revision exists, if you pass a non-existent revision no one will be able to deploy to that role until -Z with a correction revision or -z is passed.',
54
+
55
+ ' 2. *You will not be able to set a custom revision for beta environments.* The beta environments are tied to split-staging and splita/b/c/d respectively.',
56
+ ]
57
+ end
58
+
59
+ alias_method :stateless_arguments, :arguments
60
+ end
61
+
62
+ class StatelessAction
63
+ def arguments
64
+ #TODO point this command to it's help and display?
65
+ raise "This command currently does nothing, do not try to run it."
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,116 @@
1
+
2
+ class Cheftacular
3
+ class StatelessActionDocumentation
4
+ def backups
5
+ @config['documentation']['stateless_action'] << [
6
+ "`cft backup [activate|deactivate]` this command " +
7
+ "sets the fetch_backups and restore_backups flags in your config data bag for an environment. " +
8
+ "These can be used to give application developers a way to trigger / untrigger restores in an environment"
9
+ ]
10
+
11
+ @config['documentation']['application'] << @config['documentation']['stateless_action'].last
12
+ end
13
+ end
14
+
15
+ class StatelessAction
16
+ def backups force_fetch_and_restore=false
17
+ fetch_backup = @config[@options['env']]['config_bag_hash'][@options['sub_env']]['fetch_backups']
18
+ restore_backup = @config[@options['env']]['config_bag_hash'][@options['sub_env']]['restore_backups']
19
+
20
+ puts "For #{ @options['env'] } (sub-env: #{ @options['sub_env'] }) fetch backups was set to #{ fetch_backup ? 'on' : 'off' } and restoring backups was set to #{ restore_backup ? 'on' : 'off' }"
21
+
22
+ case ARGV[1]
23
+ when 'activate' then restore_backup, fetch_backup = true, true
24
+ when 'deactivate' then restore_backup, fetch_backup = false, false
25
+ end
26
+
27
+ puts "For #{ @options['env'] } (sub-env: #{ @options['sub_env'] }) fetch backups is now set to #{ fetch_backup ? 'on' : 'off' } and restoring backups is now set to #{ restore_backup ? 'on' : 'off' }"
28
+
29
+ @config[@options['env']]['config_bag_hash'][@options['sub_env']]['fetch_backups'] = fetch_backup
30
+ @config[@options['env']]['config_bag_hash'][@options['sub_env']]['restore_backups'] = restore_backup
31
+
32
+ @config['ChefDataBag'].save_config_bag
33
+
34
+ if force_fetch_and_restore
35
+ nodes = @config['getter'].get_true_node_objects true
36
+
37
+ db_primary_nodes = @config['parser'].exclude_nodes( nodes, [{ unless: 'role[db_primary]' }, { if: { not_env: 'production' } }])
38
+
39
+ backup_slave_local_ip = @config['cheftacular']['backup_server']
40
+
41
+ if backup_slave_local_ip == 'first_production_slave'
42
+ backup_slave = @config['parser'].exclude_nodes( nodes, [{ unless: 'role[db_slave]' }, { if: { not_env: 'production' } }], true)
43
+
44
+ backup_slave_local_ip = @config['getter'].get_address_hash(backup_slave.first.hostname)['priv']
45
+ end
46
+
47
+ options, locs, ridley, logs_bag_hash, pass_bag_hash, bundle_command, cheftacular, passwords = set_local_instance_vars
48
+
49
+ on ( db_primary_nodes.map { |n| "deploy@" + n.public_ipaddress } ) do |host|
50
+ n = get_node_from_address(nodes, host.hostname)
51
+
52
+ puts("Beginning db fetch_and_restore for #{ n.name } (#{ n.public_ipaddress }) for env #{ options['env'] }") unless options['quiet']
53
+
54
+ start_db_fetch_and_restore( n.name, n.public_ipaddress, options, locs, cheftacular, passwords, backup_slave_local_ip)
55
+ end
56
+
57
+ @config['action'].migrate
58
+ else
59
+ puts "Triggering deploy on databases to refresh backup setting..."
60
+
61
+ @options['role'] = 'db_primary'
62
+
63
+ @config['action'].deploy
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ module SSHKit
70
+ module Backend
71
+ class Netssh
72
+ def start_db_fetch_and_restore name, ip_address, options, locs, cheftacular, passwords, global_backup_ip, out=[]
73
+ log_loc, timestamp = set_log_loc_and_timestamp(locs)
74
+
75
+ puts("Generating pg_restore log file for #{ name } (#{ ip_address }) at #{ log_loc }/#{ name }-fetch-and-restore-#{ timestamp }.txt") unless options['quiet']
76
+
77
+ cheftacular['db_primary_backup_database_stacks'].each do |target_database_stack|
78
+ compile_database_backups_hash(cheftacular, target_database_stack, global_backup_ip).each_pair do |app_name, app_hash|
79
+
80
+ out << sudo_capture( passwords[ip_address], 'scp', "#{ cheftacular['deploy_user'] }@#{ app_hash['backup_server'] }:#{ location }", backup_dir )
81
+
82
+ puts(out.last) if options['output'] || options['verbose']
83
+
84
+ commands = [
85
+ "pg_restore --verbose --clean --no-acl --no-owner -j 4 -h localhost -U #{ cheftacular['deploy_user'] } -d #{ app_hash['repo_name'] }_#{ options['env'] } #{ app_hash['restore_backup_file_name'] }",
86
+ "service postgresql restart"
87
+ ]
88
+
89
+ commands.each do |command|
90
+ out << sudo_capture( passwords[ip_address], command )
91
+
92
+ puts(out.last) if options['output'] || options['verbose']
93
+ end
94
+ end
95
+ end
96
+
97
+ #TODO fetch and restore other database types
98
+
99
+ ::File.open("#{ log_loc }/#{ name }-fetch-and-restore-#{ timestamp }.txt", "w") { |f| f.write(out.join("\n").scrub_pretty_text) } unless options['no_logs']
100
+
101
+ puts "Succeeded fetch and restore of #{ name } (#{ ip_address })"
102
+
103
+ [out.join("\n"), timestamp]
104
+ end
105
+
106
+ def compile_database_backups_hash cheftacular, target_database_stack, global_backup_ip, ret={}
107
+ cheftacular['repositories'].each_pair do |app_name, app_hash|
108
+ ret[app_name] = app_hash if app_hash['restore_backup_file_name'] && app_hash['database'] == target_database_stack
109
+ ret[app_name]['backup_server'] = global_backup_ip unless ret[app_name]['backup_server']
110
+ end
111
+
112
+ ret
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,7 @@
1
+ class Cheftacular
2
+ class StatelessAction
3
+ def redhat_bootstrap out=[]
4
+ raise "Not yet implemented!"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class Cheftacular
2
+ class StatelessAction
3
+ def coreos_bootstrap out=[]
4
+ raise "Not yet implemented!"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class Cheftacular
2
+ class StatelessAction
3
+ def fedora_bootstrap out=[]
4
+ raise "Not yet implemented!"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class Cheftacular
2
+ class StatelessAction
3
+ def redhat_bootstrap out=[]
4
+ raise "Not yet implemented!"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,102 @@
1
+ class Cheftacular
2
+ class StatelessActionDocumentation
3
+ def ubuntu_bootstrap
4
+ @config['documentation']['stateless_action'] << [
5
+ "`cft ubuntu_bootstrap ADDRESS ROOT_PASS` This command will bring a fresh server to a state " +
6
+ "where chef-client can be run on it via `cft chef-bootstrap`. It should be noted that it is in "+
7
+ "this step where a server's randomized deploy_user sudo password is generated."
8
+ ]
9
+ end
10
+ end
11
+
12
+ class StatelessAction
13
+ def ubuntu_bootstrap out=[]
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
+
16
+ @options['address'] = ARGV[1] unless @options['address']
17
+ @options['client_pass'] = ARGV[2] unless @options['address']
18
+
19
+ if `which sshpass`.empty?
20
+ raise "sshpass not installed! Please run brew install https://raw.github.com/eugeneoden/homebrew/eca9de1/Library/Formula/sshpass.rb (or get it from your repo for linux)"
21
+ end
22
+
23
+ new_deploy_pass = @config['helper'].gen_pass(@config['cheftacular']['server_pass_length'])
24
+
25
+ deploy_user = @config['cheftacular']['deploy_user']
26
+
27
+ root_commands = [
28
+ "cd /home",
29
+ "adduser #{ deploy_user } --gecos \",,,,\" --disabled-password",
30
+ "echo #{ deploy_user }:#{ new_deploy_pass } | chpasswd",
31
+ "adduser #{ deploy_user } www-data",
32
+ "adduser #{ deploy_user } sudo",
33
+ "mkdir -p /home/#{ deploy_user }/.ssh",
34
+ "touch /home/#{ deploy_user }/.ssh/authorized_keys && touch /home/#{ deploy_user }/.ssh/known_hosts",
35
+ "chown -R #{ deploy_user }:www-data /home/#{ deploy_user }/.ssh",
36
+ 'sed -i "s/StrictModes yes/StrictModes yes\nPasswordAuthentication no\nUseDNS no\nAllowUsers deploy postgres\n/" /etc/ssh/sshd_config'.gsub('deploy', deploy_user),
37
+ 'sed -i "s/PermitRootLogin yes/PermitRootLogin no/" /etc/ssh/sshd_config'
38
+ ]
39
+
40
+ @config['default']['authentication_bag_hash']['authorized_keys'].each do |line|
41
+ root_commands << "echo \"#{ line }\" >> /home/#{ deploy_user }/.ssh/authorized_keys"
42
+ end
43
+
44
+ sudo = "echo #{ new_deploy_pass } | sudo -S"
45
+
46
+ deploy_commands = [
47
+ "#{ sudo } apt-get update",
48
+ "#{ sudo } apt-get install curl git-core shorewall -y",
49
+ "#{ sudo } apt-get upgrade -y"
50
+ ]
51
+
52
+ final_commands = []
53
+
54
+ if @config['cheftacular']['install_rvm_on_boot'] == 'true'
55
+ deploy_commands << "gpg --keyserver hkp://keys.gnupg.net --recv-keys #{ @config['cheftacular']['rvm_gpg_key'] }"
56
+ deploy_commands << "curl -L https://get.rvm.io | bash -s stable"
57
+
58
+ final_commands
59
+
60
+ rvm_source = "source /home/deploy/.rvm/scripts/rvm &&"
61
+
62
+ final_commands = [
63
+ "#{ rvm_source } echo '#{ new_deploy_pass }' | rvmsudo -S rvm requirements",
64
+ "#{ 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
66
+ ]
67
+ end
68
+
69
+ out << `sshpass -p "#{ @options['client_pass'] }" ssh -t -oStrictHostKeyChecking=no root@#{ @options['address'] } '#{ root_commands.join(' && ') } && service ssh restart'`
70
+
71
+ puts("Finished initial setup...stage 1 of 3 for server #{ @options['address'] }") if @options['in_scaling']
72
+
73
+ puts(out.last) unless @options['quiet'] || @options['in_scaling']
74
+
75
+ deploy_commands.each do |cmnd|
76
+ puts("(#{ @options['address'] }) Running #{ cmnd.gsub("#{ new_deploy_pass }", "sudo password") }") unless @options['quiet'] || @options['in_scaling']
77
+ out << `ssh -t -oStrictHostKeyChecking=no #{ deploy_user }@#{ @options['address'] } "#{ cmnd }"`
78
+
79
+ puts(out.last) unless @options['quiet'] || @options['in_scaling']
80
+ end
81
+
82
+ puts("Finished deploy setup....stage 2 of 3 for server #{ @options['address'] }") if @options['in_scaling']
83
+
84
+ final_commands.each do |cmnd|
85
+ puts "(#{ @options['address'] }) Running #{ cmnd.gsub("#{ new_deploy_pass }", "sudo password") }"
86
+ out << `ssh -t -oStrictHostKeyChecking=no #{ deploy_user }@#{ @options['address'] } "#{ cmnd }"`
87
+
88
+ puts(out.last) unless @options['quiet'] || @options['in_scaling']
89
+ end
90
+
91
+ puts("Finished ruby setup......stage 3 of 3 for server #{ @options['address'] }") if @options['in_scaling']
92
+
93
+ @config[@options['env']]['server_passwords_bag_hash']["#{ @options['address'] }-root-pass"] = @options['client_pass']
94
+
95
+ @config[@options['env']]['server_passwords_bag_hash']["#{ @options['address'] }-deploy-pass"] = new_deploy_pass
96
+
97
+ @config[@options['env']]['server_passwords_bag_hash']["#{ @options['address'] }-name"] = @options['node_name'] if @options['node_name']
98
+
99
+ @config['ChefDataBag'].save_server_passwords_bag unless @options['in_scaling']
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,7 @@
1
+ class Cheftacular
2
+ class StatelessAction
3
+ def vyatta_bootstrap out=[]
4
+ raise "Not yet implemented!"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,40 @@
1
+
2
+ class Cheftacular
3
+ class StatelessActionDocumentation
4
+ def chef_bootstrap
5
+ @config['documentation']['stateless_action'] << [
6
+ "`cft chef_bootstrap ADDRESS NODE_NAME` allows you to register a node in the chef system, " +
7
+ "remove any lingering data that may be associated with it and update the node's runlist if it has an entry in nodes_dir for its NODE_NAME."
8
+ ]
9
+ end
10
+ end
11
+
12
+ class StatelessAction
13
+ def chef_bootstrap out=[]
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
+
16
+ @options['address'] = ARGV[1] unless @options['address']
17
+ @options['node_name'] = ARGV[2] unless @options['node_name']
18
+
19
+ @config['stateless_action'].remove_client #just in case
20
+
21
+ puts("Starting chef-client initialization...") unless @options['quiet']
22
+
23
+ out << `#{ @config['helper'].knife_bootstrap_command }`
24
+
25
+ puts(out.last) unless @options['quiet'] || @options['in_scaling']
26
+
27
+ puts("Sending up data_bag_key file...") unless @options['quiet']
28
+
29
+ out << `scp -oStrictHostKeyChecking=no #{ @config['locs']['chef'] }/#{ @config['cheftacular']['data_bag_key_file'] } #{ @config['cheftacular']['deploy_user'] }@#{ @options['address'] }:/home/#{ @config['cheftacular']['deploy_user'] }`
30
+
31
+ puts("Moving key file to chef directory on server...") unless @options['quiet']
32
+
33
+ out << `ssh -t -oStrictHostKeyChecking=no #{ @config['cheftacular']['deploy_user'] }@#{ @options['address'] } "#{ @config['helper'].sudo(@options['address']) } mv -f /home/#{ @config['cheftacular']['deploy_user'] }/#{ @config['cheftacular']['data_bag_key_file'] } /etc/chef"`
34
+
35
+ @options['force_yes'] = true # have the upload_nodes grab the new nodes
36
+
37
+ @config['stateless_action'].upload_nodes
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ class Cheftacular
2
+ class StatelessActionDocumentation
3
+ def chef_environment
4
+ @config['documentation']['action'] << [
5
+ "`cft chef_environment ENVIRONMENT_NAME [create|destroy]` will allow you to interact with chef environments on the chef server.",
6
+
7
+ [
8
+ " 1. `create` will create an environment if it does not exist.",
9
+
10
+ " 2. `destroy` will destroy a chef environment *IF IT HAS NO NODES*"
11
+ ]
12
+ ]
13
+ end
14
+ end
15
+
16
+ class StatelessAction
17
+ def chef_environment
18
+ #TODO
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,104 @@
1
+
2
+ class Cheftacular
3
+ class StatelessActionDocumentation
4
+ def clean_cookbooks
5
+ @config['documentation']['stateless_action'] << [
6
+ "`cft clean_cookbooks [force] [remove_cookbooks]` allows you to update the internal chef-repo's cookbooks easily. " +
7
+ "By default this script will force you to decide what to do with each cookbook individually (shows version numbers and whether to overwrite it to cookbooks or not).",
8
+
9
+ [
10
+ " 1. `force` argument will cause the downloaded cookbooks to *always* overwrite the chef-repo's cookbooks as long as the downloaded cookbook has a higher version number.",
11
+
12
+ " 2. If you would like to remove all the cookbooks on the chef server, run `knife cookbook bulk delete '.*' -p -c ~/.chef/knife.rb`"
13
+ ]
14
+ ]
15
+ end
16
+ end
17
+
18
+ class StatelessAction
19
+ def clean_cookbooks local_options={'interactive' => true}
20
+ raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops')
21
+
22
+ ARGV.each do |arg|
23
+ case arg
24
+ when "force" then local_options['interactive'] = false
25
+ end
26
+ end
27
+
28
+ @config['cheftacular']['wrapper_cookbooks'].split(',').each do |wrapper_cookbook|
29
+ wrapper_cookbook_loc = "#{ @config['locs']['cookbooks'] }/#{ wrapper_cookbook }"
30
+ FileUtils.rm(File.expand_path("#{ wrapper_cookbook_loc }/Berksfile.lock")) if File.exists?(File.expand_path("#{ wrapper_cookbook_loc }/Berksfile.lock"))
31
+ FileUtils.rm_rf(File.expand_path("#{ @config['locs']['berks'] }/cookbooks")) if File.exists?(File.expand_path("#{ @config['locs']['berks'] }/cookbooks"))
32
+
33
+ Dir.chdir wrapper_cookbook_loc
34
+ puts "Installing new cookbooks..."
35
+ out = `berks install`
36
+ puts "#{out}\nFinished... Beginning directory scanning and conflict resolution..."
37
+
38
+ berkshelf_cookbooks = {}
39
+
40
+ Dir.foreach(@config['locs']['berks']) do |berkshelf_cookbook|
41
+ next if @config['helper'].is_junk_filename?(berkshelf_cookbook)
42
+ skip = false
43
+
44
+ berkshelf_cookbooks.keys.each do |processed_berkshelf_cookbook|
45
+ if processed_berkshelf_cookbook.rpartition('-').first == berkshelf_cookbook.rpartition('-').first
46
+ cookbook_mtime = File.mtime(File.expand_path("#{ @config['locs']['berks'] }/#{ berkshelf_cookbook }"))
47
+ pcookbook_mtime = File.mtime(File.expand_path("#{ @locs['locs']['berks'] }/#{ processed_berkshelf_cookbook }"))
48
+
49
+ skip = true if cookbook_mtime < pcookbook_mtime #get only the latest version, berkshelf pulls in multiple commits from git repos for SOME REASON
50
+ end
51
+ end
52
+
53
+ next if skip
54
+
55
+ berkshelf_cookbooks[berkshelf_cookbook] = if File.exists?(File.expand_path("#{ @config['locs']['berks'] }/#{ berkshelf_cookbook }/metadata.rb"))
56
+ File.read(File.expand_path("#{ @config['locs']['berks'] }/#{ berkshelf_cookbook }/metadata.rb")).gsub('"',"'").gsub(/^version[\s]*('\d[.\d]+')/).peek[/('\d[.\d]+')/].gsub("'",'')
57
+ else
58
+ berkshelf_cookbook.split('-').last
59
+ end
60
+ end
61
+
62
+ chef_repo_cookbooks = {}
63
+
64
+ Dir.foreach(@config['locs']['cookbooks']) do |chef_repo_cookbook|
65
+ next if @config['helper'].is_junk_filename?(berkshelf_cookbook)
66
+
67
+ new_name = chef_repo_cookbook.rpartition('-').first
68
+
69
+ chef_repo_cookbooks[chef_repo_cookbook] = if File.exists?(File.expand_path("#{ @config['locs']['cookbooks'] }/#{ chef_repo_cookbook }/metadata.rb"))
70
+ File.read(File.expand_path("#{ @config['locs']['cookbooks'] }/#{ chef_repo_cookbook }/metadata.rb")).gsub('"',"'").gsub(/^version[\s]*('\d[.\d]+')/).peek[/('\d[.\d]+')/].gsub("'",'')
71
+ else
72
+ JSON.parse(File.read(File.expand_path("#{ @config['locs']['cookbooks'] }/#{ chef_repo_cookbook }/metadata.json"))).to_hash['version']
73
+ end
74
+ end
75
+
76
+ berkshelf_cookbooks.each_pair do |berkshelf_cookbook, version|
77
+ new_name = berkshelf_cookbook.rpartition('-').first
78
+
79
+ if chef_repo_cookbooks.has_key?(new_name) || chef_repo_cookbooks.has_key?(berkshelf_cookbook) #don't overwrite cookbooks without user input
80
+ if local_options['interactive']
81
+ puts "COOKBOOK::~~~~#{ new_name }~~~~::VERSION::~~~~~~~~#{ version } VS #{ chef_repo_cookbooks[new_name] }"
82
+ puts "\nEnter O | o | overwrite to overwrite ~~~~#{ new_name }~~~~ in the chef-repo (THIS SHOULD NOT BE DONE LIGHTLY)"
83
+ puts "Enter N | n | no to skip to the next conflict"
84
+ puts "If you pass force to this script, it will always overwrite."
85
+ #puts "If you pass a STRING of comma delimited cookbooks, it will skip these cookbooks automatically and overwrite others"
86
+ #puts "Example: ruby ./executables/clean-cookbooks 'application_ruby,wordpress'"
87
+ puts "Input:"
88
+ input = STDIN.gets.chomp
89
+
90
+ next if (input =~ /N|n|no/) == 0
91
+ end
92
+
93
+ next if @config['helper'].is_higher_version?(chef_repo_cookbooks[new_name], version)
94
+ end
95
+
96
+ cmnd = "#{ @config['locs']['berks'] }/#{ berkshelf_cookbook } #{ @config['locs']['cookbooks'] }/#{ new_name }"
97
+ puts "Moving #{ cmnd } (#{ version }:#{ chef_repo_cookbooks[new_name] })" if @options['verbose']
98
+ `rm -Rf #{ @config['locs']['cookbooks'] }/#{ new_name }`
99
+ `cp -Rf #{ cmnd }`
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,19 @@
1
+ class Cheftacular
2
+ class StatelessActionDocumentation
3
+ def clean_sensu_plugins
4
+ @config['documentation']['stateless_action'] << [
5
+ "`cft clean_sensu_plugins` [NYI] will checkout / update the sensu community plugins github repo on your " +
6
+ "local machine and sync any sensu plugin files in your wrapper cookbook directory with what is in the repo."
7
+ ]
8
+ end
9
+ end
10
+
11
+ class StatelessAction
12
+ def clean_sensu_plugins
13
+ raise "This method is not yet implemented"
14
+ raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops')
15
+
16
+ #TODO use this to keep the cookbook files directory up to date with the sensu community plugins repo
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+
2
+ class Cheftacular
3
+ class StatelessActionDocumentation
4
+ def clean_server_passwords
5
+
6
+ end
7
+ end
8
+
9
+ class StatelessAction
10
+ def clean_server_passwords
11
+ #TODO clean up non-existent entries in all envs server_password bags
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+
2
+ class Cheftacular
3
+ class StatelessActionDocumentation
4
+ def cleanup_log_files
5
+
6
+ end
7
+ end
8
+
9
+ class StatelessAction
10
+ def cleanup_log_files
11
+ #TODO
12
+ end
13
+ end
14
+ end