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.
- checksums.yaml +7 -0
- data/bin/cft +4 -0
- data/bin/cftclr +4 -0
- data/bin/cheftacular +4 -0
- data/bin/client-list +4 -0
- data/lib/cheftacular/README.md +416 -0
- data/lib/cheftacular/actions/check.rb +32 -0
- data/lib/cheftacular/actions/console.rb +62 -0
- data/lib/cheftacular/actions/database.rb +13 -0
- data/lib/cheftacular/actions/db_console.rb +67 -0
- data/lib/cheftacular/actions/deploy.rb +40 -0
- data/lib/cheftacular/actions/log.rb +47 -0
- data/lib/cheftacular/actions/migrate.rb +57 -0
- data/lib/cheftacular/actions/run.rb +64 -0
- data/lib/cheftacular/actions/scale.rb +94 -0
- data/lib/cheftacular/actions/tail.rb +55 -0
- data/lib/cheftacular/actions.rb +14 -0
- data/lib/cheftacular/auditor.rb +46 -0
- data/lib/cheftacular/chef/data_bag.rb +104 -0
- data/lib/cheftacular/cheftacular.rb +55 -0
- data/lib/cheftacular/decryptors.rb +45 -0
- data/lib/cheftacular/encryptors.rb +48 -0
- data/lib/cheftacular/getters.rb +153 -0
- data/lib/cheftacular/helpers.rb +296 -0
- data/lib/cheftacular/initializers.rb +451 -0
- data/lib/cheftacular/parsers.rb +199 -0
- data/lib/cheftacular/remote_helpers.rb +30 -0
- data/lib/cheftacular/stateless_action.rb +16 -0
- data/lib/cheftacular/stateless_actions/add_ssh_key_to_bag.rb +44 -0
- data/lib/cheftacular/stateless_actions/arguments.rb +68 -0
- data/lib/cheftacular/stateless_actions/backups.rb +116 -0
- data/lib/cheftacular/stateless_actions/bootstrappers/centos_bootstrap.rb +7 -0
- data/lib/cheftacular/stateless_actions/bootstrappers/coreos_bootstrap.rb +7 -0
- data/lib/cheftacular/stateless_actions/bootstrappers/fedora_bootstrap.rb +7 -0
- data/lib/cheftacular/stateless_actions/bootstrappers/redhat_bootstrap.rb +7 -0
- data/lib/cheftacular/stateless_actions/bootstrappers/ubuntu_bootstrap.rb +102 -0
- data/lib/cheftacular/stateless_actions/bootstrappers/vyatta_bootstrap.rb +7 -0
- data/lib/cheftacular/stateless_actions/chef_bootstrap.rb +40 -0
- data/lib/cheftacular/stateless_actions/chef_environment.rb +21 -0
- data/lib/cheftacular/stateless_actions/clean_cookbooks.rb +104 -0
- data/lib/cheftacular/stateless_actions/clean_sensu_plugins.rb +19 -0
- data/lib/cheftacular/stateless_actions/clean_server_passwords.rb +14 -0
- data/lib/cheftacular/stateless_actions/cleanup_log_files.rb +14 -0
- data/lib/cheftacular/stateless_actions/client_list.rb +89 -0
- data/lib/cheftacular/stateless_actions/cloud.rb +107 -0
- data/lib/cheftacular/stateless_actions/cloud_bootstrap.rb +109 -0
- data/lib/cheftacular/stateless_actions/compile_audit_log.rb +60 -0
- data/lib/cheftacular/stateless_actions/compile_readme.rb +41 -0
- data/lib/cheftacular/stateless_actions/create_git_key.rb +67 -0
- data/lib/cheftacular/stateless_actions/disk_report.rb +75 -0
- data/lib/cheftacular/stateless_actions/environment.rb +100 -0
- data/lib/cheftacular/stateless_actions/fetch_file.rb +24 -0
- data/lib/cheftacular/stateless_actions/fix_known_hosts.rb +70 -0
- data/lib/cheftacular/stateless_actions/full_bootstrap.rb +30 -0
- data/lib/cheftacular/stateless_actions/get_active_ssh_connections.rb +18 -0
- data/lib/cheftacular/stateless_actions/get_haproxy_log.rb +55 -0
- data/lib/cheftacular/stateless_actions/get_log_from_bag.rb +38 -0
- data/lib/cheftacular/stateless_actions/get_pg_pass.rb +61 -0
- data/lib/cheftacular/stateless_actions/help.rb +71 -0
- data/lib/cheftacular/stateless_actions/initialize_data_bag_contents.rb +220 -0
- data/lib/cheftacular/stateless_actions/knife_upload.rb +23 -0
- data/lib/cheftacular/stateless_actions/pass.rb +49 -0
- data/lib/cheftacular/stateless_actions/reinitialize.rb +46 -0
- data/lib/cheftacular/stateless_actions/remove_client.rb +81 -0
- data/lib/cheftacular/stateless_actions/replication_status.rb +103 -0
- data/lib/cheftacular/stateless_actions/restart_swap.rb +55 -0
- data/lib/cheftacular/stateless_actions/rvm.rb +14 -0
- data/lib/cheftacular/stateless_actions/server_update.rb +99 -0
- data/lib/cheftacular/stateless_actions/service.rb +14 -0
- data/lib/cheftacular/stateless_actions/test_env.rb +82 -0
- data/lib/cheftacular/stateless_actions/update_split_branches.rb +64 -0
- data/lib/cheftacular/stateless_actions/update_tld.rb +62 -0
- data/lib/cheftacular/stateless_actions/upload_nodes.rb +120 -0
- data/lib/cheftacular/stateless_actions/upload_roles.rb +24 -0
- data/lib/cheftacular/version.rb +5 -0
- data/lib/cheftacular.rb +4 -0
- data/lib/cloud_interactor/authentication.rb +56 -0
- data/lib/cloud_interactor/cloud_interactor.rb +23 -0
- data/lib/cloud_interactor/domain/create.rb +17 -0
- data/lib/cloud_interactor/domain/create_record.rb +27 -0
- data/lib/cloud_interactor/domain/destroy.rb +17 -0
- data/lib/cloud_interactor/domain/destroy_record.rb +23 -0
- data/lib/cloud_interactor/domain/list.rb +9 -0
- data/lib/cloud_interactor/domain/list_records.rb +22 -0
- data/lib/cloud_interactor/domain/read.rb +23 -0
- data/lib/cloud_interactor/domain/read_record.rb +27 -0
- data/lib/cloud_interactor/domain/update.rb +18 -0
- data/lib/cloud_interactor/domain/update_record.rb +42 -0
- data/lib/cloud_interactor/domain.rb +18 -0
- data/lib/cloud_interactor/flavor.rb +27 -0
- data/lib/cloud_interactor/helpers.rb +70 -0
- data/lib/cloud_interactor/image.rb +27 -0
- data/lib/cloud_interactor/parser.rb +37 -0
- data/lib/cloud_interactor/server/attach_volume.rb +33 -0
- data/lib/cloud_interactor/server/create.rb +39 -0
- data/lib/cloud_interactor/server/destroy.rb +11 -0
- data/lib/cloud_interactor/server/detach_volume.rb +21 -0
- data/lib/cloud_interactor/server/list.rb +7 -0
- data/lib/cloud_interactor/server/list_volumes.rb +25 -0
- data/lib/cloud_interactor/server/poll.rb +22 -0
- data/lib/cloud_interactor/server/read.rb +9 -0
- data/lib/cloud_interactor/server/read_volume.rb +24 -0
- data/lib/cloud_interactor/server.rb +17 -0
- data/lib/cloud_interactor/version.rb +4 -0
- data/lib/cloud_interactor/volume/create.rb +13 -0
- data/lib/cloud_interactor/volume/destroy.rb +11 -0
- data/lib/cloud_interactor/volume/list.rb +7 -0
- data/lib/cloud_interactor/volume/read.rb +9 -0
- data/lib/cloud_interactor/volume.rb +20 -0
- data/lib/ridley/monkeypatches.rb +11 -0
- data/lib/sshkit/actions/start_commit_check.rb +19 -0
- data/lib/sshkit/actions/start_deploy.rb +25 -0
- data/lib/sshkit/actions/start_log_fetch.rb +91 -0
- data/lib/sshkit/actions/start_task.rb +29 -0
- data/lib/sshkit/getters.rb +67 -0
- data/lib/sshkit/helpers.rb +13 -0
- data/lib/sshkit/monkeypatches.rb +19 -0
- 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,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,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
|