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