cheftacular 2.0.0

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