cheftacular 2.8.0 → 2.9.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 +4 -4
- data/lib/cheftacular/README.md +92 -70
- data/lib/cheftacular/actions/check.rb +3 -2
- data/lib/cheftacular/actions/console.rb +8 -2
- data/lib/cheftacular/actions/db_console.rb +28 -4
- data/lib/cheftacular/actions/deploy.rb +6 -8
- data/lib/cheftacular/actions/log.rb +7 -2
- data/lib/cheftacular/actions/migrate.rb +16 -5
- data/lib/cheftacular/actions/run.rb +10 -3
- data/lib/cheftacular/actions/scale.rb +4 -1
- data/lib/cheftacular/actions/tail.rb +8 -3
- data/lib/cheftacular/cheftacular.rb +1 -1
- data/lib/cheftacular/cloud_provider.rb +5 -1
- data/lib/cheftacular/dns.rb +1 -1
- data/lib/cheftacular/error.rb +2 -2
- data/lib/cheftacular/file_system.rb +50 -0
- data/lib/cheftacular/getter.rb +1 -1
- data/lib/cheftacular/helper.rb +34 -5
- data/lib/cheftacular/initializer.rb +15 -25
- data/lib/cheftacular/parser.rb +2 -0
- data/lib/cheftacular/stateless_actions/add_ssh_key_to_bag.rb +4 -1
- data/lib/cheftacular/stateless_actions/arguments.rb +8 -3
- data/lib/cheftacular/stateless_actions/backups.rb +5 -2
- data/lib/cheftacular/stateless_actions/bootstrappers/ubuntu_bootstrap.rb +8 -5
- data/lib/cheftacular/stateless_actions/check_cheftacular_yml_keys.rb +15 -1
- data/lib/cheftacular/stateless_actions/chef_bootstrap.rb +9 -2
- data/lib/cheftacular/stateless_actions/chef_server.rb +5 -2
- data/lib/cheftacular/stateless_actions/cheftacular_config.rb +26 -4
- data/lib/cheftacular/stateless_actions/cheftacular_yml_help.rb +31 -0
- data/lib/cheftacular/stateless_actions/clean_cookbooks.rb +6 -37
- data/lib/cheftacular/stateless_actions/clear_caches.rb +9 -2
- data/lib/cheftacular/stateless_actions/client_list.rb +5 -2
- data/lib/cheftacular/stateless_actions/cloud.rb +4 -1
- data/lib/cheftacular/stateless_actions/cloud_bootstrap.rb +4 -1
- data/lib/cheftacular/stateless_actions/compile_audit_log.rb +4 -1
- data/lib/cheftacular/stateless_actions/compile_readme.rb +10 -1
- data/lib/cheftacular/stateless_actions/create_git_key.rb +4 -1
- data/lib/cheftacular/stateless_actions/disk_report.rb +5 -2
- data/lib/cheftacular/stateless_actions/environment.rb +5 -2
- data/lib/cheftacular/stateless_actions/file.rb +5 -2
- data/lib/cheftacular/stateless_actions/fix_known_hosts.rb +5 -2
- data/lib/cheftacular/stateless_actions/full_bootstrap.rb +10 -2
- data/lib/cheftacular/stateless_actions/get_active_ssh_connections.rb +3 -2
- data/lib/cheftacular/stateless_actions/get_haproxy_log.rb +5 -2
- data/lib/cheftacular/stateless_actions/get_log_from_bag.rb +5 -2
- data/lib/cheftacular/stateless_actions/get_pg_pass.rb +5 -2
- data/lib/cheftacular/stateless_actions/get_shorewall_allowed_connections.rb +2 -1
- data/lib/cheftacular/stateless_actions/help.rb +28 -16
- data/lib/cheftacular/stateless_actions/initialize_cheftacular_yml.rb +4 -1
- data/lib/cheftacular/stateless_actions/initialize_data_bag_contents.rb +4 -1
- data/lib/cheftacular/stateless_actions/knife_upload.rb +4 -1
- data/lib/cheftacular/stateless_actions/list_toggleable_roles.rb +5 -2
- data/lib/cheftacular/stateless_actions/location_aliases.rb +5 -2
- data/lib/cheftacular/stateless_actions/pass.rb +5 -2
- data/lib/cheftacular/stateless_actions/reinitialize.rb +4 -1
- data/lib/cheftacular/stateless_actions/remove_client.rb +9 -2
- data/lib/cheftacular/stateless_actions/replication_status.rb +4 -1
- data/lib/cheftacular/stateless_actions/reset_bag.rb +4 -1
- data/lib/cheftacular/stateless_actions/restart_swap.rb +4 -1
- data/lib/cheftacular/stateless_actions/role_toggle.rb +7 -4
- data/lib/cheftacular/stateless_actions/rvm.rb +4 -1
- data/lib/cheftacular/stateless_actions/server_update.rb +5 -2
- data/lib/cheftacular/stateless_actions/service.rb +4 -1
- data/lib/cheftacular/stateless_actions/slack.rb +4 -1
- data/lib/cheftacular/stateless_actions/test_env.rb +4 -1
- data/lib/cheftacular/stateless_actions/update_chef_client.rb +2 -1
- data/lib/cheftacular/stateless_actions/update_cloudflare_dns_from_cloud.rb +4 -1
- data/lib/cheftacular/stateless_actions/update_split_branches.rb +4 -1
- data/lib/cheftacular/stateless_actions/update_thecheftacularcookbook.rb +38 -0
- data/lib/cheftacular/stateless_actions/update_tld.rb +4 -1
- data/lib/cheftacular/stateless_actions/upload_nodes.rb +6 -3
- data/lib/cheftacular/stateless_actions/upload_roles.rb +4 -1
- data/lib/cheftacular/version.rb +1 -1
- data/lib/cloud_interactor/authentication.rb +3 -4
- data/lib/cloud_interactor/flavor.rb +7 -2
- data/lib/cloud_interactor/helpers.rb +5 -1
- data/lib/cloud_interactor/server/create.rb +7 -2
- data/lib/sshkit/actions/start_task.rb +9 -1
- metadata +6 -7
- data/bin/client-list +0 -4
- data/lib/cheftacular/stateless_actions/clean_sensu_plugins.rb +0 -19
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
class Cheftacular
|
|
2
2
|
class ActionDocumentation
|
|
3
3
|
def migrate
|
|
4
|
-
@config['documentation']['action']
|
|
4
|
+
@config['documentation']['action'][__method__] ||= {}
|
|
5
|
+
@config['documentation']['action'][__method__]['long_description'] = [
|
|
5
6
|
"`cft migrate` this command will grab the first alphabetical node for a repository " +
|
|
6
|
-
"and run a migration that will hit the database primary server."
|
|
7
|
+
"and run a migration that will hit the database primary server.",
|
|
8
|
+
|
|
9
|
+
[
|
|
10
|
+
" 1. Currently only supports rails stacks."
|
|
11
|
+
]
|
|
7
12
|
]
|
|
13
|
+
|
|
14
|
+
@config['documentation']['action'][__method__]['short_description'] = 'Creates a database migration on the current environment'
|
|
8
15
|
end
|
|
9
16
|
end
|
|
10
17
|
|
|
@@ -29,13 +36,15 @@ class Cheftacular
|
|
|
29
36
|
|
|
30
37
|
puts("Beginning migration run for #{ n.name } (#{ n.public_ipaddress }) on role #{ options['role'] }") unless options['quiet']
|
|
31
38
|
|
|
32
|
-
log_data, timestamp = start_task( n.name, n.public_ipaddress, n.run_list, "#{ bundle_command } exec rake db:migrate", options, locs, cheftacular)
|
|
39
|
+
log_data, timestamp, exit_status = start_task( n.name, n.public_ipaddress, n.run_list, "#{ bundle_command } exec rake db:migrate", options, locs, cheftacular)
|
|
33
40
|
|
|
34
|
-
logs_bag_hash["#{ n.name }
|
|
41
|
+
logs_bag_hash["#{ n.name }-#{ __method__ }"] = { "text" => log_data.scrub_pretty_text, "timestamp" => timestamp, "exit_status" => exit_status }
|
|
35
42
|
end
|
|
36
43
|
|
|
37
44
|
@config['ChefDataBag'].save_logs_bag
|
|
38
45
|
|
|
46
|
+
@config['helper'].send_log_bag_hash_slack_notification(logs_bag_hash, __method__, 'Failing migration detected, please fix this and deploy again, exiting...')
|
|
47
|
+
|
|
39
48
|
@options['run_migration_already'] = true
|
|
40
49
|
|
|
41
50
|
#restart the servers again after a deploy with a migration just in case
|
|
@@ -49,7 +58,9 @@ class Cheftacular
|
|
|
49
58
|
end
|
|
50
59
|
|
|
51
60
|
def migrate_nodejs nodes=[]
|
|
52
|
-
|
|
61
|
+
puts "Method #{ __method__ } is not yet implemented"
|
|
62
|
+
|
|
63
|
+
exit
|
|
53
64
|
end
|
|
54
65
|
|
|
55
66
|
def migrate_all nodes=[]
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
class Cheftacular
|
|
2
2
|
class ActionDocumentation
|
|
3
3
|
def run
|
|
4
|
-
@config['documentation']['action']
|
|
4
|
+
@config['documentation']['action'][__method__] ||= {}
|
|
5
|
+
@config['documentation']['action'][__method__]['long_description'] = [
|
|
5
6
|
"`cft run COMMAND [--all]` will trigger the command on the first server in the role. " +
|
|
6
7
|
"Can be used to run rake commands or anything else.",
|
|
7
8
|
|
|
@@ -18,6 +19,8 @@ class Cheftacular
|
|
|
18
19
|
'arguments in quotes like `cft run "rake -T"`'
|
|
19
20
|
]
|
|
20
21
|
]
|
|
22
|
+
|
|
23
|
+
@config['documentation']['action'][__method__]['short_description'] = 'Runs a command on the current environment for the current repository'
|
|
21
24
|
end
|
|
22
25
|
end
|
|
23
26
|
|
|
@@ -33,6 +36,8 @@ class Cheftacular
|
|
|
33
36
|
#must have rails stack to run migrations and not be a db, only want ONE node
|
|
34
37
|
nodes = @config['parser'].exclude_nodes( nodes, [{ unless: "role[#{ @options['role'] }]" }], !@options['run_on_all'] )
|
|
35
38
|
|
|
39
|
+
nodes = @config['parser'].exclude_nodes( nodes, [{ if: "role[#{ @options['negative_role'] }]" }]) if @options['negative_role']
|
|
40
|
+
|
|
36
41
|
#this must always precede on () calls so they have the instance variables they need
|
|
37
42
|
options, locs, ridley, logs_bag_hash, pass_bag_hash, bundle_command, cheftacular, passwords = @config['helper'].set_local_instance_vars
|
|
38
43
|
|
|
@@ -41,12 +46,14 @@ class Cheftacular
|
|
|
41
46
|
|
|
42
47
|
puts("Beginning task run for #{ n.name } (#{ n.public_ipaddress }) on role #{ options['role'] }") unless options['quiet']
|
|
43
48
|
|
|
44
|
-
log_data, timestamp = start_task( n.name, n.public_ipaddress, n.run_list, "#{ bundle_command } exec #{ command }", options, locs, cheftacular)
|
|
49
|
+
log_data, timestamp, exit_status = start_task( n.name, n.public_ipaddress, n.run_list, "#{ bundle_command } exec #{ command }", options, locs, cheftacular)
|
|
45
50
|
|
|
46
|
-
logs_bag_hash["#{ n.name }
|
|
51
|
+
logs_bag_hash["#{ n.name }-#{ __method__ }"] = { "text" => log_data.scrub_pretty_text, "timestamp" => timestamp, "exit_status" => exit_status }
|
|
47
52
|
end
|
|
48
53
|
|
|
49
54
|
@config['ChefDataBag'].save_logs_bag
|
|
55
|
+
|
|
56
|
+
@config['helper'].send_log_bag_hash_slack_notification(logs_bag_hash, __method__, 'Failing command detected, exiting...')
|
|
50
57
|
end
|
|
51
58
|
|
|
52
59
|
def run_nodejs
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
class Cheftacular
|
|
4
4
|
class ActionDocumentation
|
|
5
5
|
def scale
|
|
6
|
-
@config['documentation']['action']
|
|
6
|
+
@config['documentation']['action'][__method__] ||= {}
|
|
7
|
+
@config['documentation']['action'][__method__]['long_description'] = [
|
|
7
8
|
"`cft scale up|down [NUM_TO_SCALE]` will add (or remove) NUM_TO_SCALE servers from the server array. " +
|
|
8
9
|
"This command will not let you scale down below 1 server.",
|
|
9
10
|
|
|
@@ -13,6 +14,8 @@ class Cheftacular
|
|
|
13
14
|
"A failed build may require the server to be destroyed / examined by a DevOps engineer."
|
|
14
15
|
]
|
|
15
16
|
]
|
|
17
|
+
|
|
18
|
+
@config['documentation']['action'][__method__]['short_description'] = 'Scales an environment up or down (relies on roles)'
|
|
16
19
|
end
|
|
17
20
|
end
|
|
18
21
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
class Cheftacular
|
|
2
2
|
class ActionDocumentation
|
|
3
3
|
def tail
|
|
4
|
-
@config['documentation']['action']
|
|
4
|
+
@config['documentation']['action'][__method__] ||= {}
|
|
5
|
+
@config['documentation']['action'][__method__]['long_description'] = [
|
|
5
6
|
"`cft tail [PATTERN_TO_MATCH]` will tail the logs (return continuous output) of the first node if finds " +
|
|
6
7
|
"that has an application matching the repository running on it. Currently only supports rails stacks",
|
|
7
8
|
|
|
@@ -15,6 +16,8 @@ class Cheftacular
|
|
|
15
16
|
" 3. if the `PATTERN_TO_MATCH` argument exists, the tail will only return entries that have that pattern rather than everything written to the file."
|
|
16
17
|
]
|
|
17
18
|
]
|
|
19
|
+
|
|
20
|
+
@config['documentation']['action'][__method__]['short_description'] = 'Tails the logs of the first node found for the current repository'
|
|
18
21
|
end
|
|
19
22
|
end
|
|
20
23
|
|
|
@@ -26,6 +29,8 @@ class Cheftacular
|
|
|
26
29
|
|
|
27
30
|
nodes = @config['parser'].exclude_nodes( nodes, [{ unless: "role[#{ @options['role'] }]" }], true )
|
|
28
31
|
|
|
32
|
+
nodes = @config['parser'].exclude_nodes( nodes, [{ if: "role[#{ @options['negative_role'] }]" }], true) if @options['negative_role']
|
|
33
|
+
|
|
29
34
|
nodes.each do |n|
|
|
30
35
|
puts("Beginning tail run for #{ n.name } (#{ n.public_ipaddress }) on role #{ @options['role'] }") unless @options['quiet']
|
|
31
36
|
|
|
@@ -50,12 +55,12 @@ class Cheftacular
|
|
|
50
55
|
|
|
51
56
|
#special servers should be listed first as most of them will have web role
|
|
52
57
|
log_loc = "#{ @config['cheftacular']['base_file_path'] }/#{ @options['repository'] }/current/log/#{ true_env }.log"
|
|
53
|
-
|
|
58
|
+
|
|
54
59
|
`ssh -oStrictHostKeyChecking=no -tt #{ @config['cheftacular']['deploy_user'] }@#{ ip_address } "#{ @config['helper'].sudo(ip_address) } tail -f #{ log_loc } #{ get_tail_grep_string(pattern_to_match) }" > /dev/tty`
|
|
55
60
|
end
|
|
56
61
|
|
|
57
62
|
def get_tail_grep_string pattern_to_match=''
|
|
58
|
-
"| grep -i -E #{ pattern_to_match }" unless pattern_to_match.blank?
|
|
63
|
+
"| grep -i -E \\\"#{ pattern_to_match }\\\"" unless pattern_to_match.blank?
|
|
59
64
|
end
|
|
60
65
|
end
|
|
61
66
|
end
|
|
@@ -39,7 +39,7 @@ class Cheftacular
|
|
|
39
39
|
if @config['helper'].is_initialization_command?(ARGV[0])
|
|
40
40
|
@options['command'] = ARGV[0] #this is normally set by parse_context but that is not run for initialization commands
|
|
41
41
|
else
|
|
42
|
-
|
|
42
|
+
#@config['stateless_action'].cheftacular_config('sync') unless @config['helper'].running_on_chef_node?
|
|
43
43
|
|
|
44
44
|
@config['stateless_action'].initialize_data_bag_contents(@options['env']) #ensure basic structure are always maintained before each run
|
|
45
45
|
|
|
@@ -7,11 +7,15 @@ class Cheftacular
|
|
|
7
7
|
|
|
8
8
|
#public address, private address
|
|
9
9
|
def parse_addresses_from_server_create_hash server_hash
|
|
10
|
+
ap server_hash
|
|
10
11
|
case @options['preferred_cloud']
|
|
11
12
|
when 'rackspace'
|
|
12
13
|
[server_hash['ipv4_address'], server_hash['addresses']['private'][0]['addr']]
|
|
13
14
|
when 'digitalocean'
|
|
14
|
-
[
|
|
15
|
+
[
|
|
16
|
+
server_hash['networks']['v4'].select { |hash| hash['type'] == 'public' }.first['ip_address'],
|
|
17
|
+
server_hash['networks']['v4'].select { |hash| hash['type'] == 'private' }.first['ip_address']
|
|
18
|
+
]
|
|
15
19
|
else raise "CRITICAL! Encountered unsupported preferred cloud #{ @options['preferred_cloud'] }"
|
|
16
20
|
end
|
|
17
21
|
end
|
data/lib/cheftacular/dns.rb
CHANGED
|
@@ -62,7 +62,7 @@ class Cheftacular
|
|
|
62
62
|
record_hash['SRV_weight'],
|
|
63
63
|
record_hash['SRV_port'],
|
|
64
64
|
record_hash['SRV_target'],
|
|
65
|
-
(record_hash['activate_cloudflare'] ?
|
|
65
|
+
(record_hash['activate_cloudflare'] ? 1 : 0) #service_mode
|
|
66
66
|
)
|
|
67
67
|
|
|
68
68
|
print 'create'.ljust(20, '_')
|
data/lib/cheftacular/error.rb
CHANGED
|
@@ -20,10 +20,10 @@ class Cheftacular
|
|
|
20
20
|
nodes
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
def exception_output message, exception=
|
|
23
|
+
def exception_output message, exception=nil, exit_on_call=true, suppress_error_output=false
|
|
24
24
|
puts "#{ message }\n"
|
|
25
25
|
|
|
26
|
-
puts("Error message: #{ exception }\n#{ exception.backtrace.join("\n") }")
|
|
26
|
+
puts("Error message: #{ exception }\n#{ exception.backtrace.join("\n") }") if !exception.nil? && !suppress_error_output
|
|
27
27
|
|
|
28
28
|
exit if exit_on_call
|
|
29
29
|
end
|
|
@@ -89,6 +89,8 @@ class Cheftacular
|
|
|
89
89
|
FileUtils.rm_rf("#{ base_dir }/#{ entry }") if File.exists?("#{ base_dir }/#{ entry }") && File.directory?("#{ base_dir }/#{ entry }")
|
|
90
90
|
when 'current-audit-only'
|
|
91
91
|
FileUtils.rm("#{ base_dir }/#{ entry }") if File.file?("#{ base_dir }/#{ entry }") && entry.include?(Time.now.strftime("%Y%m%d"))
|
|
92
|
+
else
|
|
93
|
+
puts "Warning, received unknown mode (#{ mode })! Please post your logs as an issue on github!"
|
|
92
94
|
end
|
|
93
95
|
|
|
94
96
|
if File.exists?("#{ base_dir }/#{ entry }") && File.directory?("#{ base_dir }/#{ entry }")
|
|
@@ -135,6 +137,54 @@ class Cheftacular
|
|
|
135
137
|
File.open( File.join(@config['locs']['chef-repo'], "config", to_be_created_filename), "w") { |f| f.write(File.read(File.join(@config['locs']['examples'], example_filename))) }
|
|
136
138
|
end
|
|
137
139
|
|
|
140
|
+
def parse_latest_berkshelf_cookbook_versions berkshelf_cookbooks={}
|
|
141
|
+
|
|
142
|
+
Dir.foreach(@config['locs']['berks']) do |berkshelf_cookbook|
|
|
143
|
+
next if is_junk_filename?(berkshelf_cookbook)
|
|
144
|
+
use_current_cookbook = false
|
|
145
|
+
|
|
146
|
+
true_cookbook_name = berkshelf_cookbook.rpartition('-').first
|
|
147
|
+
cookbook_version = parse_version_from_berkshelf_cookbook(berkshelf_cookbook)
|
|
148
|
+
|
|
149
|
+
#get only the latest version, berkshelf pulls in multiple commits from git repos for SOME REASON
|
|
150
|
+
use_current_cookbook = !berkshelf_cookbooks.has_key?(true_cookbook_name)
|
|
151
|
+
use_current_cookbook = @config['helper'].is_higher_version?(cookbook_version, berkshelf_cookbooks[true_cookbook_name]['version']) if berkshelf_cookbooks.has_key?(true_cookbook_name)
|
|
152
|
+
|
|
153
|
+
if use_current_cookbook
|
|
154
|
+
berkshelf_cookbooks[true_cookbook_name] ||= {}
|
|
155
|
+
berkshelf_cookbooks[true_cookbook_name]['version'] = cookbook_version
|
|
156
|
+
berkshelf_cookbooks[true_cookbook_name]['location'] = berkshelf_cookbook
|
|
157
|
+
berkshelf_cookbooks[true_cookbook_name]['mtime'] = File.mtime(File.expand_path("#{ @config['locs']['berks'] }/#{ berkshelf_cookbook }"))
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
berkshelf_cookbooks
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def parse_chef_repo_cookbook_versions chef_repo_cookbooks={}
|
|
165
|
+
Dir.foreach(@config['locs']['cookbooks']) do |chef_repo_cookbook|
|
|
166
|
+
next if is_junk_filename?(chef_repo_cookbook)
|
|
167
|
+
|
|
168
|
+
new_name = chef_repo_cookbook.rpartition('-').first
|
|
169
|
+
|
|
170
|
+
chef_repo_cookbooks[chef_repo_cookbook] = if File.exists?(File.expand_path("#{ @config['locs']['cookbooks'] }/#{ chef_repo_cookbook }/metadata.rb"))
|
|
171
|
+
File.read(File.expand_path("#{ @config['locs']['cookbooks'] }/#{ chef_repo_cookbook }/metadata.rb")).gsub('"',"'").gsub(/^version[\s]*('\d[.\d]+')/).peek[/('\d[.\d]+')/].gsub("'",'')
|
|
172
|
+
else
|
|
173
|
+
JSON.parse(File.read(File.expand_path("#{ @config['locs']['cookbooks'] }/#{ chef_repo_cookbook }/metadata.json"))).to_hash['version']
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
chef_repo_cookbooks
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def parse_version_from_berkshelf_cookbook berkshelf_cookbook
|
|
181
|
+
if File.exists?(File.expand_path("#{ @config['locs']['berks'] }/#{ berkshelf_cookbook }/metadata.rb"))
|
|
182
|
+
File.read(File.expand_path("#{ @config['locs']['berks'] }/#{ berkshelf_cookbook }/metadata.rb")).gsub('"',"'").gsub(/^version[\s]*('\d[.\d]+')/).peek[/('\d[.\d]+')/].gsub("'",'')
|
|
183
|
+
else
|
|
184
|
+
berkshelf_cookbook.split('-').last
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
138
188
|
private
|
|
139
189
|
def current_file_path file_name, use_timestamp=true
|
|
140
190
|
File.join( @config['locs']['app-root'], 'tmp', @config['helper'].declassify, ( use_timestamp ? "#{ Time.now.strftime("%Y%m%d") }-#{ file_name }" : file_name ))
|
data/lib/cheftacular/getter.rb
CHANGED
|
@@ -23,7 +23,7 @@ class Cheftacular
|
|
|
23
23
|
true_obj = if !file_cache_nodes.empty? && @config['parser'].array_of_nodes_contains_node_name?(file_cache_nodes, n.name)
|
|
24
24
|
file_cache_nodes[@config['parser'].index_of_node_name_in_array_of_nodes(file_cache_nodes, n.name)]
|
|
25
25
|
else
|
|
26
|
-
@config['filesystem'].cleanup_file_caches('current')
|
|
26
|
+
@config['filesystem'].cleanup_file_caches('current-nodes')
|
|
27
27
|
|
|
28
28
|
@config['ridley'].node.find(n.name)
|
|
29
29
|
end
|
data/lib/cheftacular/helper.rb
CHANGED
|
@@ -30,8 +30,8 @@ class Cheftacular
|
|
|
30
30
|
|
|
31
31
|
def is_initialization_command? command=''
|
|
32
32
|
command ||= ''
|
|
33
|
-
|
|
34
|
-
@config['initialization_action'].public_methods(false).include?(command.to_sym)
|
|
33
|
+
|
|
34
|
+
@config['initialization_action'].public_methods(false).include?(command.to_sym) || command.blank?
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def running_on_chef_node? ret = false
|
|
@@ -140,12 +140,13 @@ class Cheftacular
|
|
|
140
140
|
def compile_documentation_lines mode, out=[]
|
|
141
141
|
doc_arr = case mode
|
|
142
142
|
when 'action' then @config['documentation']['action']
|
|
143
|
-
when 'application' then @config['documentation']['
|
|
143
|
+
when 'application' then @config['documentation']['application'].merge(@config['documentation']['action'])
|
|
144
144
|
when 'stateless_action' then @config['documentation']['stateless_action']
|
|
145
|
-
when 'devops' then @config['documentation']['
|
|
145
|
+
when 'devops' then @config['documentation']['stateless_action'].merge(@config['documentation']['action'])
|
|
146
146
|
end
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
doc_arr = doc_arr.to_a.map { |doc| doc[1]['long_description'] }
|
|
149
|
+
count = 1
|
|
149
150
|
|
|
150
151
|
doc_arr.sort {|a, b| a[0] <=> b[0]}.flatten(1).each do |line|
|
|
151
152
|
out << "#{ count }. #{ line }" if line.class.to_s == 'String'
|
|
@@ -158,6 +159,12 @@ class Cheftacular
|
|
|
158
159
|
out
|
|
159
160
|
end
|
|
160
161
|
|
|
162
|
+
def compile_short_context_descriptions documentation_hash, padding_length=25, out=[]
|
|
163
|
+
out << documentation_hash.to_a.map { |doc| "#{ doc[0].to_s.ljust(padding_length, '_') }_#{ doc[1]['short_description'] }" }
|
|
164
|
+
|
|
165
|
+
out.flatten.sort {|a, b| a[0] <=> b[0]}.join("\n\n")
|
|
166
|
+
end
|
|
167
|
+
|
|
161
168
|
#compares how close str1 is to str2
|
|
162
169
|
def compare_strings str1, str2
|
|
163
170
|
str1_chars = str1.split('').uniq
|
|
@@ -260,6 +267,28 @@ class Cheftacular
|
|
|
260
267
|
|
|
261
268
|
puts("Completed rvm.sh installation into /etc/profile.d/rvm.sh") unless @options['quiet']
|
|
262
269
|
end
|
|
270
|
+
|
|
271
|
+
def send_log_bag_hash_slack_notification logs_bag_hash, method, on_failing_exit_status_message=''
|
|
272
|
+
if @config['cheftacular']['slack']['webhook']
|
|
273
|
+
logs_bag_hash.each_pair do |key, hash|
|
|
274
|
+
next unless key.include?(method.to_s)
|
|
275
|
+
|
|
276
|
+
if hash['exit_status'] && hash['exit_status'] == 1
|
|
277
|
+
@config['stateless_action'].slack(hash['text'].prepend('```').insert(-1, '```'))
|
|
278
|
+
|
|
279
|
+
@config['error'].exception_output(on_failing_exit_status_message) if !on_failing_exit_status_message.blank?
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def slack_current_deploy_arguments
|
|
286
|
+
msg = "#{ Socket.gethostname } just set for the repository #{ @config['getter'].get_repository_from_role_name(@options['role']) }:\n"
|
|
287
|
+
msg << "the organization to #{ @options['deploy_organization'] }\n" if @options['deploy_organization']
|
|
288
|
+
msg << "the revision to #{ @options['target_revision'] }" if @options['target_revision']
|
|
289
|
+
|
|
290
|
+
@config['stateless_action'].slack(msg.prepend('```').insert(-1, '```'), @config['cheftacular']['slack']['notify_on_deployment_args'])
|
|
291
|
+
end
|
|
263
292
|
end
|
|
264
293
|
end
|
|
265
294
|
|
|
@@ -253,25 +253,9 @@ class Cheftacular
|
|
|
253
253
|
|
|
254
254
|
@config['ChefDataBag'].init_bag('default', 'cheftacular', false)
|
|
255
255
|
|
|
256
|
-
|
|
256
|
+
@config['initial_cheftacular_yml'] = @config['cheftacular'].deep_dup
|
|
257
257
|
|
|
258
|
-
|
|
259
|
-
diff_hash.delete(key) if value.empty? || value.nil?
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
if @config['helper'].running_in_mode?('devops') && !diff_hash.empty?
|
|
263
|
-
puts "Difference detected between local cheftacular.yml and data bag cheftacular.yml! Displaying..."
|
|
264
|
-
|
|
265
|
-
ap diff_hash
|
|
266
|
-
elsif @config['helper'].running_in_mode?('application') && @config['default']['cheftacular_bag_hash']['slack']['webhook'] && !diff_hash.empty?
|
|
267
|
-
@config['slack_queue'] << diff_hash.awesome_inspect({plain: true, indent: 2}).prepend('```').insert(-1, '```')
|
|
268
|
-
end
|
|
269
|
-
|
|
270
|
-
@config['cheftacular'] = if @config['default']['cheftacular_bag_hash']['sync_application_cheftacular_yml']
|
|
271
|
-
@config['default']['cheftacular_bag_hash'].deep_merge(@config['cheftacular'])
|
|
272
|
-
else
|
|
273
|
-
@config['cheftacular'].deep_merge(@config['default']['cheftacular_bag_hash'].except('default_repository', 'mode'))
|
|
274
|
-
end
|
|
258
|
+
@config['cheftacular'] = @config['default']['cheftacular_bag_hash'].deep_merge(@config['cheftacular'])
|
|
275
259
|
end
|
|
276
260
|
|
|
277
261
|
def initialize_default_cheftacular_options
|
|
@@ -299,10 +283,10 @@ class Cheftacular
|
|
|
299
283
|
def initialize_documentation_hash
|
|
300
284
|
@config['documentation'] ||= {}
|
|
301
285
|
@config['documentation']['arguments'] ||= []
|
|
302
|
-
@config['documentation']['action'] ||=
|
|
303
|
-
@config['documentation']['stateless_action'] ||=
|
|
304
|
-
@config['documentation']['application'] ||=
|
|
305
|
-
@config['documentation']['devops'] ||=
|
|
286
|
+
@config['documentation']['action'] ||= {}
|
|
287
|
+
@config['documentation']['stateless_action'] ||= {}
|
|
288
|
+
@config['documentation']['application'] ||= {}
|
|
289
|
+
@config['documentation']['devops'] ||= {}
|
|
306
290
|
end
|
|
307
291
|
|
|
308
292
|
def initialize_locations
|
|
@@ -419,8 +403,10 @@ class Cheftacular
|
|
|
419
403
|
@config['ruby_string'] = "ruby-" + @config['ruby_string'] unless @config['ruby_string'].include?('ruby-')
|
|
420
404
|
|
|
421
405
|
#TODO Reevaluate for non-rvm setups
|
|
422
|
-
@config['bundle_command']
|
|
423
|
-
@config['ruby_command']
|
|
406
|
+
@config['bundle_command'] = "/home/#{ @config['cheftacular']['deploy_user'] }/.rvm/gems/#{ @config['ruby_string'].chomp }@global/bin/bundle"
|
|
407
|
+
@config['ruby_command'] = "/home/#{ @config['cheftacular']['deploy_user'] }/.rvm/rubies/#{ @config['ruby_string'].chomp }/bin/ruby"
|
|
408
|
+
@config['internal_ruby_config'] = File.expand_path(__FILE__)[/(ruby\-[\d\.@\w]+)/]
|
|
409
|
+
#@config['internal_ruby_version'] = @config['internal_ruby_config'][/([\d\.]+)/] #reactivate when needed
|
|
424
410
|
end
|
|
425
411
|
|
|
426
412
|
def initialize_passwords env, refresh_bag=false
|
|
@@ -448,7 +434,11 @@ class Cheftacular
|
|
|
448
434
|
if @config['helper'].is_higher_version? detected_version, current_version
|
|
449
435
|
puts "\n Your Cheftacular is out of date. Currently #{ current_version } and remote version is #{ detected_version }.\n"
|
|
450
436
|
|
|
451
|
-
|
|
437
|
+
if @config['internal_ruby_config'].include?('@global')
|
|
438
|
+
puts "Please run rvm #{ @config['internal_ruby_config'] } do gem update cheftacular to update to the latest version"
|
|
439
|
+
else
|
|
440
|
+
puts "Please update the gemfile to #{ detected_version }, bundle install and then restart this process.\n"
|
|
441
|
+
end
|
|
452
442
|
|
|
453
443
|
exit
|
|
454
444
|
else
|
data/lib/cheftacular/parser.rb
CHANGED
|
@@ -113,6 +113,8 @@ class Cheftacular
|
|
|
113
113
|
repo_state_hash['deploy_organization'] = nil
|
|
114
114
|
end
|
|
115
115
|
|
|
116
|
+
@config['helper'].slack_current_deploy_arguments unless @config['cheftacular']['slack']['notify_on_deployment_args'].blank?
|
|
117
|
+
|
|
116
118
|
@config['ChefDataBag'].save_config_bag
|
|
117
119
|
end
|
|
118
120
|
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
class Cheftacular
|
|
3
3
|
class StatelessActionDocumentation
|
|
4
4
|
def add_ssh_key_to_bag
|
|
5
|
-
@config['documentation']['stateless_action']
|
|
5
|
+
@config['documentation']['stateless_action'][__method__] ||= {}
|
|
6
|
+
@config['documentation']['stateless_action'][__method__]['long_description'] = [
|
|
6
7
|
"`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
8
|
"After this your server recipes should read the contents of the 'default' 'authentication' bag for the authorized_keys array.",
|
|
8
9
|
|
|
@@ -12,6 +13,8 @@ class Cheftacular
|
|
|
12
13
|
"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
|
]
|
|
14
15
|
]
|
|
16
|
+
|
|
17
|
+
@config['documentation']['stateless_action'][__method__]['short_description'] = 'Adds an ssh key to your authentication bag'
|
|
15
18
|
end
|
|
16
19
|
end
|
|
17
20
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
class Cheftacular
|
|
2
2
|
class StatelessActionDocumentation
|
|
3
3
|
def arguments
|
|
4
|
-
@config['documentation']['arguments'] <<
|
|
4
|
+
@config['documentation']['arguments'] << [
|
|
5
5
|
'## Arguments and flags for cheftacular',
|
|
6
6
|
|
|
7
7
|
'### Environment flags',
|
|
@@ -46,11 +46,16 @@ class Cheftacular
|
|
|
46
46
|
|
|
47
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
48
|
|
|
49
|
-
'2. `-z|--unset-
|
|
49
|
+
'2. `-z|--unset-github-deploy-args` will unset a custom revision specified in the arg below and make the codebase utilize the default.',
|
|
50
50
|
|
|
51
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, a branch name or even a tag.",
|
|
52
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.'
|
|
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
|
+
"4. The `-O ORGANIZATION` flag can be used with TheCheftacularCookbook to set an *organization* your app can try " +
|
|
56
|
+
"deploying from, your git user needs access to these forks / organization(s).",
|
|
57
|
+
|
|
58
|
+
" 3. The `-z|--unset-github-deploy-args` option will clear your current `-Z` and `-O` flags."
|
|
54
59
|
]
|
|
55
60
|
end
|
|
56
61
|
end
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
class Cheftacular
|
|
3
3
|
class StatelessActionDocumentation
|
|
4
4
|
def backups
|
|
5
|
-
@config['documentation']['stateless_action']
|
|
5
|
+
@config['documentation']['stateless_action'][__method__] ||= {}
|
|
6
|
+
@config['documentation']['stateless_action'][__method__]['long_description'] = [
|
|
6
7
|
"`cft backups [activate|deactivate|load|restore]` this command " +
|
|
7
8
|
"sets the fetch_backups and restore_backups flags in your config data bag for an environment. " +
|
|
8
9
|
"These can be used to give application developers a way to trigger / untrigger restores in an environment",
|
|
@@ -19,7 +20,9 @@ class Cheftacular
|
|
|
19
20
|
]
|
|
20
21
|
]
|
|
21
22
|
|
|
22
|
-
@config['documentation']['
|
|
23
|
+
@config['documentation']['stateless_action'][__method__]['short_description'] = 'Runs various backup commands on your current environment'
|
|
24
|
+
|
|
25
|
+
@config['documentation']['application'][__method__] = @config['documentation']['stateless_action'][__method__]
|
|
23
26
|
end
|
|
24
27
|
end
|
|
25
28
|
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
class Cheftacular
|
|
2
2
|
class StatelessActionDocumentation
|
|
3
3
|
def ubuntu_bootstrap
|
|
4
|
-
@config['documentation']['stateless_action']
|
|
4
|
+
@config['documentation']['stateless_action'][__method__] ||= {}
|
|
5
|
+
@config['documentation']['stateless_action'][__method__]['long_description'] = [
|
|
5
6
|
"`cft ubuntu_bootstrap ADDRESS ROOT_PASS` This command will bring a fresh server to a state " +
|
|
6
7
|
"where chef-client can be run on it via `cft chef-bootstrap`. It should be noted that it is in "+
|
|
7
8
|
"this step where a server's randomized deploy_user sudo password is generated."
|
|
8
9
|
]
|
|
10
|
+
|
|
11
|
+
@config['documentation']['stateless_action'][__method__]['short_description'] = 'Updates an ubuntu server to have more secure defaults'
|
|
9
12
|
end
|
|
10
13
|
end
|
|
11
14
|
|
|
@@ -85,6 +88,7 @@ class Cheftacular
|
|
|
85
88
|
|
|
86
89
|
deploy_commands.each do |cmnd|
|
|
87
90
|
puts("(#{ @options['address'] }) Running #{ cmnd.gsub("#{ new_deploy_pass }", "sudo password") }") unless @options['quiet'] || @options['in_scaling']
|
|
91
|
+
|
|
88
92
|
out << `ssh -t -oStrictHostKeyChecking=no #{ deploy_user }@#{ @options['address'] } "#{ cmnd }"`
|
|
89
93
|
|
|
90
94
|
puts(out.last) unless @options['quiet'] || @options['in_scaling']
|
|
@@ -94,6 +98,7 @@ class Cheftacular
|
|
|
94
98
|
|
|
95
99
|
final_commands.each do |cmnd|
|
|
96
100
|
puts "(#{ @options['address'] }) Running #{ cmnd.gsub("#{ new_deploy_pass }", "sudo password") }"
|
|
101
|
+
|
|
97
102
|
out << `ssh -t -oStrictHostKeyChecking=no #{ deploy_user }@#{ @options['address'] } "#{ cmnd }"`
|
|
98
103
|
|
|
99
104
|
puts(out.last) unless @options['quiet'] || @options['in_scaling']
|
|
@@ -101,11 +106,9 @@ class Cheftacular
|
|
|
101
106
|
|
|
102
107
|
puts("Finished ruby setup......stage 3 of 3 for server #{ @options['address'] }") if @options['in_scaling']
|
|
103
108
|
|
|
104
|
-
@config[@options['env']]['server_passwords_bag_hash']["#{ @options['address'] }-root-pass"]
|
|
105
|
-
|
|
109
|
+
@config[@options['env']]['server_passwords_bag_hash']["#{ @options['address'] }-root-pass"] = @options['client_pass']
|
|
106
110
|
@config[@options['env']]['server_passwords_bag_hash']["#{ @options['address'] }-deploy-pass"] = new_deploy_pass
|
|
107
|
-
|
|
108
|
-
@config[@options['env']]['server_passwords_bag_hash']["#{ @options['address'] }-name"] = @options['node_name'] if @options['node_name']
|
|
111
|
+
@config[@options['env']]['server_passwords_bag_hash']["#{ @options['address'] }-name"] = @options['node_name'] if @options['node_name']
|
|
109
112
|
|
|
110
113
|
@config['ChefDataBag'].save_server_passwords_bag unless @options['in_scaling']
|
|
111
114
|
end
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
class Cheftacular
|
|
3
3
|
class StatelessActionDocumentation
|
|
4
4
|
def check_cheftacular_yml_keys
|
|
5
|
-
@config['documentation']['stateless_action']
|
|
5
|
+
@config['documentation']['stateless_action'][__method__] ||= {}
|
|
6
|
+
@config['documentation']['stateless_action'][__method__]['long_description'] = [
|
|
6
7
|
"`cft check_cheftacular_yml_keys` allows you to check to see if your cheftacular yml keys are valid to the current version of cheftacular. " +
|
|
7
8
|
"It will also set your missing keys to their likely default and let you know to update the cheftacular.yml file."
|
|
8
9
|
]
|
|
10
|
+
|
|
11
|
+
@config['documentation']['stateless_action'][__method__]['short_description'] = "Makes sure your cheftacular.yml has up-to-date keys for #{ Cheftacular::VERSION }"
|
|
9
12
|
end
|
|
10
13
|
end
|
|
11
14
|
|
|
@@ -13,6 +16,17 @@ class Cheftacular
|
|
|
13
16
|
def check_cheftacular_yml_keys out=[], exit_on_missing=false, warn_on_missing=false
|
|
14
17
|
base_message = "Your cheftacular.yml is missing the key KEY, its default value is being set to DEFAULT for this run."
|
|
15
18
|
|
|
19
|
+
#############################2.9.0################################################
|
|
20
|
+
|
|
21
|
+
unless @config['cheftacular']['slack'].has_key?('notify_on_deployment_args')
|
|
22
|
+
#backup_config:global_backup_role_name
|
|
23
|
+
base_message.gsub('KEY', 'notify_on_deployment_args').gsub('DEFAULT', 'false')
|
|
24
|
+
|
|
25
|
+
@config['cheftacular']['slack']['notify_on_deployment_args'] = false
|
|
26
|
+
|
|
27
|
+
warn_on_missing = true
|
|
28
|
+
end
|
|
29
|
+
|
|
16
30
|
#############################2.7.0################################################
|
|
17
31
|
|
|
18
32
|
unless @config['cheftacular'].has_key?('backup_config')
|
|
@@ -2,10 +2,17 @@
|
|
|
2
2
|
class Cheftacular
|
|
3
3
|
class StatelessActionDocumentation
|
|
4
4
|
def chef_bootstrap
|
|
5
|
-
@config['documentation']['stateless_action']
|
|
5
|
+
@config['documentation']['stateless_action'][__method__] ||= {}
|
|
6
|
+
@config['documentation']['stateless_action'][__method__]['long_description'] = [
|
|
6
7
|
"`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
|
+
"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.",
|
|
9
|
+
|
|
10
|
+
[
|
|
11
|
+
" 1. This command is part of the `cft full_bootstrap` command"
|
|
12
|
+
]
|
|
8
13
|
]
|
|
14
|
+
|
|
15
|
+
@config['documentation']['stateless_action'][__method__]['short_description'] = 'Bootstraps basic chef properties on the target server'
|
|
9
16
|
end
|
|
10
17
|
end
|
|
11
18
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
class Cheftacular
|
|
2
2
|
class StatelessActionDocumentation
|
|
3
3
|
def chef_server
|
|
4
|
-
@config['documentation']['stateless_action']
|
|
4
|
+
@config['documentation']['stateless_action'][__method__] ||= {}
|
|
5
|
+
@config['documentation']['stateless_action'][__method__]['long_description'] = [
|
|
5
6
|
"`cft chef_server [restart|processes|memory]` this command can be used to query the chef server for stats if the cheftacular.yml " +
|
|
6
7
|
"has the chef_server key filled out. Useful for low resource chef-servers.",
|
|
7
8
|
|
|
@@ -20,7 +21,9 @@ class Cheftacular
|
|
|
20
21
|
]
|
|
21
22
|
]
|
|
22
23
|
|
|
23
|
-
@config['documentation']['
|
|
24
|
+
@config['documentation']['stateless_action'][__method__]['short_description'] = 'Allows you to check the state of the primary Chef server'
|
|
25
|
+
|
|
26
|
+
@config['documentation']['application'][__method__] = @config['documentation']['stateless_action'][__method__]
|
|
24
27
|
end
|
|
25
28
|
end
|
|
26
29
|
|