cheftacular 2.1.2 → 2.2.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 +40 -28
- data/lib/cheftacular/{actions.rb → action.rb} +0 -0
- data/lib/cheftacular/actions/deploy.rb +2 -1
- data/lib/cheftacular/actions/migrate.rb +3 -1
- data/lib/cheftacular/{decryptors.rb → decryptor.rb} +0 -0
- data/lib/cheftacular/dns.rb +283 -0
- data/lib/cheftacular/{encryptors.rb → encryptor.rb} +0 -0
- data/lib/cheftacular/{getters.rb → getter.rb} +2 -2
- data/lib/cheftacular/{helpers.rb → helper.rb} +6 -14
- data/lib/cheftacular/{initializers.rb → initializer.rb} +3 -2
- data/lib/cheftacular/{parsers.rb → parser.rb} +6 -0
- data/lib/cheftacular/stateless_actions/arguments.rb +2 -4
- data/lib/cheftacular/stateless_actions/client_list.rb +6 -6
- data/lib/cheftacular/stateless_actions/cloud.rb +1 -1
- data/lib/cheftacular/stateless_actions/cloud_bootstrap.rb +8 -34
- data/lib/cheftacular/stateless_actions/compile_readme.rb +4 -2
- data/lib/cheftacular/stateless_actions/get_pg_pass.rb +0 -2
- data/lib/cheftacular/stateless_actions/get_shorewall_allowed_connections.rb +65 -0
- data/lib/cheftacular/stateless_actions/help.rb +1 -1
- data/lib/cheftacular/stateless_actions/initialize_data_bag_contents.rb +6 -0
- data/lib/cheftacular/stateless_actions/remove_client.rb +6 -20
- data/lib/cheftacular/stateless_actions/replication_status.rb +0 -1
- data/lib/cheftacular/stateless_actions/slack.rb +8 -1
- data/lib/cheftacular/stateless_actions/update_cloudflare.rb +16 -51
- data/lib/cheftacular/stateless_actions/update_tld.rb +22 -19
- data/lib/cheftacular/stateless_actions/upload_nodes.rb +3 -1
- data/lib/cheftacular/version.rb +1 -1
- data/lib/cloud_interactor/domain/create_record.rb +7 -5
- data/lib/cloud_interactor/domain/list_records.rb +3 -1
- data/lib/cloud_interactor/domain/update_record.rb +4 -2
- data/lib/cloudflare/monkeypatches.rb +24 -0
- metadata +12 -10
- data/lib/cheftacular/remote_helpers.rb +0 -30
File without changes
|
@@ -111,9 +111,9 @@ class Cheftacular
|
|
111
111
|
ret
|
112
112
|
end
|
113
113
|
|
114
|
-
def get_addresses_hash env='staging', ret_hash={}
|
114
|
+
def get_addresses_hash env='staging', ret_hash={}, mode=""
|
115
115
|
@config[env]['addresses_bag_hash']['addresses'].each do |serv_hash|
|
116
|
-
ret_hash[serv_hash['public']] =
|
116
|
+
ret_hash[serv_hash['public']] = serv_hash
|
117
117
|
|
118
118
|
end if @config[env].has_key?('addresses_bag_hash')
|
119
119
|
|
@@ -10,14 +10,6 @@ class Cheftacular
|
|
10
10
|
Cheftacular.to_s.underscore.dasherize
|
11
11
|
end
|
12
12
|
|
13
|
-
#[TODO] Refactor to more accurate solution
|
14
|
-
def running_in_gem?
|
15
|
-
File.expand_path('.', __FILE__).split('/').include?('.rvm') ||
|
16
|
-
(File.exist?(File.expand_path("#{ Dir.getwd }/.ruby-gemset")) &&
|
17
|
-
File.read(File.expand_path("#{ Dir.getwd }/.ruby-gemset")) != 'hiplogiq-deploy')
|
18
|
-
end
|
19
|
-
|
20
|
-
#TODO add command check
|
21
13
|
def is_command? command
|
22
14
|
@config['action'].public_methods(false).include?(command.to_sym)
|
23
15
|
end
|
@@ -30,7 +22,6 @@ class Cheftacular
|
|
30
22
|
!@config['action'].public_methods(false).include?(command.to_sym) && !@config['stateless_action'].public_methods(false).include?(command.to_sym)
|
31
23
|
end
|
32
24
|
|
33
|
-
#[TODO] Refactor to running_on_chef_node?
|
34
25
|
def running_on_chef_node?
|
35
26
|
Dir.entries('/etc').include?('chef')
|
36
27
|
rescue StandardError => e
|
@@ -275,7 +266,7 @@ class Cheftacular
|
|
275
266
|
end
|
276
267
|
end
|
277
268
|
|
278
|
-
def does_cheftacular_config_have? key_array
|
269
|
+
def does_cheftacular_config_have? key_array
|
279
270
|
cheftacular = @config['cheftacular']
|
280
271
|
key_array = [key_array] if key_array.is_a?(String)
|
281
272
|
key_checks = []
|
@@ -289,16 +280,16 @@ class Cheftacular
|
|
289
280
|
|
290
281
|
def recursive_hash_check keys, hash
|
291
282
|
if hash.has_key?(keys[0])
|
292
|
-
case hash[keys[0]].class
|
293
|
-
when Hash
|
283
|
+
case hash[keys[0]].class.to_s
|
284
|
+
when 'Hash'
|
294
285
|
if !hash[keys[0]].empty?
|
295
286
|
recursive_hash_check keys[1..keys.count-1], hash[keys[0]]
|
296
287
|
else
|
297
288
|
return true
|
298
289
|
end
|
299
|
-
when String
|
290
|
+
when 'String'
|
300
291
|
return !hash[keys[0]].blank?
|
301
|
-
when Array
|
292
|
+
when 'Array'
|
302
293
|
return !hash[keys[0]].empty?
|
303
294
|
end
|
304
295
|
else
|
@@ -306,6 +297,7 @@ class Cheftacular
|
|
306
297
|
end
|
307
298
|
end
|
308
299
|
|
300
|
+
#this must be in helpers because parser class is not yet loaded at the time this method is needed.
|
309
301
|
def parse_node_name_from_client_file ret=""
|
310
302
|
config = File.read(File.expand_path("#{ @config['locs']['chef'] }/client.rb"))
|
311
303
|
|
@@ -356,8 +356,8 @@ class Cheftacular
|
|
356
356
|
rescue StandardError => e
|
357
357
|
msg = [
|
358
358
|
"Please run this in the root of your application directory,",
|
359
|
-
"
|
360
|
-
]
|
359
|
+
"a ruby string to run commands against was not found in either your cheftacular.yml file or your .ruby-version file."
|
360
|
+
].join(' ')
|
361
361
|
|
362
362
|
@config['helper'].exception_output msg, e
|
363
363
|
end
|
@@ -424,6 +424,7 @@ class Cheftacular
|
|
424
424
|
@config['action_documentation'] = Cheftacular::ActionDocumentation.new(@options, @config)
|
425
425
|
@config['stateless_action_documentation'] = Cheftacular::StatelessActionDocumentation.new(@options, @config)
|
426
426
|
@config['dummy_sshkit'] = SSHKit::Backend::Netssh.new(SSHKit::Host.new('127.0.0.1'))
|
427
|
+
@config['DNS'] = Cheftacular::DNS.new(@options, @config)
|
427
428
|
end
|
428
429
|
|
429
430
|
def initialize_directories
|
@@ -195,5 +195,11 @@ class Cheftacular
|
|
195
195
|
|
196
196
|
dns_string.gsub('NODE_NAME', @options['node_name']).gsub('ENV_TLD', @config[@options['env']]['config_bag_hash']['tld'])
|
197
197
|
end
|
198
|
+
|
199
|
+
def parse_repository_hash_from_string string
|
200
|
+
@config['getter'].get_repo_names_for_repositories.each do |repository, repository_hash|
|
201
|
+
return repository_hash if string.include?(repository)
|
202
|
+
end
|
203
|
+
end
|
198
204
|
end
|
199
205
|
end
|
@@ -46,13 +46,11 @@ 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-revision` will unset a custom revision specified in the arg below and make the codebase utilize the default
|
49
|
+
'2. `-z|--unset-revision` 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 or a branch name.",
|
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.'
|
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.',
|
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.'
|
56
54
|
]
|
57
55
|
end
|
58
56
|
end
|
@@ -38,7 +38,7 @@ class Cheftacular
|
|
38
38
|
|
39
39
|
env_nodes = @config['parser'].exclude_nodes(nodes, [{ if: { not_env: env } }])
|
40
40
|
puts "\nFound #{ env_nodes.count } #{ env } nodes:"
|
41
|
-
out = " #{ 'name'.ljust(22) } #{ 'ip_address'.ljust(
|
41
|
+
out = " #{ 'name'.ljust(22) } #{ 'ip_address'.ljust(20) }"
|
42
42
|
out << "#{ 'private_address'.ljust(21) }" if @options['with_private']
|
43
43
|
out << "#{ 'pass?'.ljust(5) } #{ 'domain'.ljust(41) }" if @options['verbose']
|
44
44
|
out << "#{ 'deploy_password'.ljust(21) }" if @options['verbose']
|
@@ -48,15 +48,15 @@ class Cheftacular
|
|
48
48
|
|
49
49
|
auth_hash = @config[env]['server_passwords_bag_hash']
|
50
50
|
|
51
|
-
|
51
|
+
addresses_hash = @config['getter'].get_addresses_hash env
|
52
52
|
|
53
53
|
env_nodes.each do |node|
|
54
54
|
#client = @ridley.client.find(options['node_name'])
|
55
55
|
out = " #{ node.chef_id.ljust(22,'_') }_#{ node.public_ipaddress.ljust(20,'_') }"
|
56
56
|
|
57
57
|
if @options['with_private']
|
58
|
-
if
|
59
|
-
out <<
|
58
|
+
if addresses_hash.has_key?(node.public_ipaddress)
|
59
|
+
out << addresses_hash[node.public_ipaddress]['address'].ljust(20,'_')
|
60
60
|
else
|
61
61
|
out << ''.ljust(20,'_')
|
62
62
|
end
|
@@ -66,8 +66,8 @@ class Cheftacular
|
|
66
66
|
|
67
67
|
out << "_" + auth_hash.has_key?("#{ node.public_ipaddress }-deploy-pass").to_s.ljust(5,'_') + "_"
|
68
68
|
|
69
|
-
if
|
70
|
-
out <<
|
69
|
+
if addresses_hash.has_key?(node.public_ipaddress)
|
70
|
+
out << addresses_hash[node.public_ipaddress]['dn'].ljust(40,'_')
|
71
71
|
else
|
72
72
|
out << ''.ljust(40,'_')
|
73
73
|
end
|
@@ -3,7 +3,7 @@ class Cheftacular
|
|
3
3
|
class StatelessActionDocumentation
|
4
4
|
def cloud
|
5
5
|
@config['documentation']['stateless_action'] << [
|
6
|
-
"`cft cloud <FIRST_LEVEL_ARG> [<SECOND_LEVEL_ARG>[:<SECOND_LEVEL_ARG_QUERY>]*] ` this command handles talking to various cloud
|
6
|
+
"`cft cloud <FIRST_LEVEL_ARG> [<SECOND_LEVEL_ARG>[:<SECOND_LEVEL_ARG_QUERY>]*] ` this command handles talking to various cloud APIs. " +
|
7
7
|
"If no args are passed nothing will happen.",
|
8
8
|
|
9
9
|
[
|
@@ -31,7 +31,6 @@ class Cheftacular
|
|
31
31
|
@options['node_name'] = ARGV[1] unless @options['node_name']
|
32
32
|
@options['flavor_name'] = ARGV[2] unless @options['flavor_name']
|
33
33
|
@options['descriptor'] = ARGV[3] if ARGV[3] && !@options['descriptor']
|
34
|
-
full_domain = ""
|
35
34
|
|
36
35
|
if `which sshpass`.empty?
|
37
36
|
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)"
|
@@ -58,47 +57,22 @@ class Cheftacular
|
|
58
57
|
return false
|
59
58
|
end
|
60
59
|
|
61
|
-
if @options['with_dn']
|
62
|
-
domain_obj = PublicSuffix.parse @options['with_dn']
|
63
|
-
|
64
|
-
@config['stateless_action'].cloud "domain", "create_record:#{ domain_obj.domain }:#{ domain_obj.trd }:#{ @options['address'] }"
|
65
|
-
|
66
|
-
sleep 5
|
67
|
-
|
68
|
-
@config['stateless_action'].cloud "domain", "create_record:#{ domain_obj.domain }:local.#{ domain_obj.trd }:#{ @options['private_address'] }"
|
69
|
-
|
70
|
-
full_domain = @options['with_dn']
|
71
|
-
|
72
|
-
#set the wildcard domain for frontend load balancers
|
73
|
-
@config['stateless_action'].cloud "domain", "create_record:#{ domain_obj.domain }:*:#{ @options['address'] }" if ( @options['node_name'] =~ /mysc.*lb/ ) == 0
|
74
|
-
end
|
75
|
-
|
76
60
|
tld = @config[@options['env']]['config_bag_hash'][@options['sub_env']]['tld']
|
77
61
|
|
78
|
-
@config['
|
79
|
-
|
80
|
-
sleep 5
|
62
|
+
target_serv_index = @config[@options['env']]['addresses_bag_hash']['addresses'].count
|
81
63
|
|
82
|
-
|
64
|
+
compile_args = ['set_all_attributes']
|
83
65
|
|
84
|
-
|
66
|
+
compile_args << "set_specific_domain:#{ @options['with_dn'] }" if @options['with_dn']
|
85
67
|
|
86
|
-
|
68
|
+
address_hash = @config['DNS'].compile_address_hash_for_server_from_options(*compile_args)
|
87
69
|
|
88
|
-
|
70
|
+
@config['DNS'].create_dns_record_for_domain_from_address_hash(@options['with_dn'], address_hash, "specific_domain_mode") if @options['with_dn']
|
89
71
|
|
90
|
-
@config[
|
91
|
-
target_serv_index = @config[@options['env']]['addresses_bag_hash']['addresses'].index(serv_hash) if serv_hash['name'] == @options['node_name']
|
92
|
-
end
|
93
|
-
|
94
|
-
#EX: "name": "api1", "public": "1.2.3.4", "address": "10.208.1.2", "dn":"api1.example.com", "descriptor": "lb:my-backend-codebase"
|
95
|
-
@config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index] ||= {}
|
96
|
-
@config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index]['name'] = @options['node_name']
|
97
|
-
@config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index]['public'] = @options['address']
|
98
|
-
@config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index]['address'] = @options['private_address']
|
99
|
-
@config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index]['dn'] = full_domain
|
100
|
-
@config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index]['descriptor'] = @options['descriptor'].nil? ? @options['node_name'] : @options['descriptor']
|
72
|
+
@config['DNS'].create_dns_record_for_domain_from_address_hash(tld, address_hash)
|
101
73
|
|
74
|
+
@config[@options['env']]['addresses_bag_hash'] = @config[@options['env']]['addresses_bag'].reload.to_hash
|
75
|
+
|
102
76
|
@config['ChefDataBag'].save_addresses_bag
|
103
77
|
|
104
78
|
@options['dont_remove_address_or_server'] = true #flag to make sure our entry isnt removed in addresses bag
|
@@ -19,11 +19,11 @@ class Cheftacular
|
|
19
19
|
|
20
20
|
out << '# Table of Contents for Cheftacular Commands'
|
21
21
|
|
22
|
-
out << '1. [Cheftacular Arguments and Flags](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#arguments-and-flags-for-cheftacular)
|
22
|
+
out << '1. [Cheftacular Arguments and Flags](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#arguments-and-flags-for-cheftacular)'
|
23
23
|
|
24
24
|
out << '2. [Application Commands](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#commands-that-can-be-run-in-the-application-context)'
|
25
25
|
|
26
|
-
out << '3. [DevOps Commands](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#commands-that-can-only-be-run-in-the-devops-context)
|
26
|
+
out << '3. [DevOps Commands](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#commands-that-can-only-be-run-in-the-devops-context)' + "\n"
|
27
27
|
|
28
28
|
out << @config['documentation']['arguments']
|
29
29
|
|
@@ -35,6 +35,8 @@ class Cheftacular
|
|
35
35
|
|
36
36
|
out << @config['helper'].compile_documentation_lines('stateless_action')
|
37
37
|
|
38
|
+
FileUtils.rm("#{ @config['locs']['chef-log'] }/README.md") if File.exist?("#{ @config['locs']['chef-log'] }/README.md")
|
39
|
+
|
38
40
|
File.open("#{ @config['locs']['chef-log'] }/README.md", "w") { |f| f.write(out.flatten.join("\n\n")) }
|
39
41
|
end
|
40
42
|
end
|
@@ -31,8 +31,6 @@ class Cheftacular
|
|
31
31
|
database = repo_hash.has_key?('custom_database_name') ? repo_hash['custom_database_name'] : repo_hash['repo_name']
|
32
32
|
password = @config[@options['env']]['chef_passwords_bag_hash']['pg_pass']
|
33
33
|
|
34
|
-
ap @config[@options['env']]['chef_passwords_bag_hash']
|
35
|
-
|
36
34
|
if @config[@options['env']]['chef_passwords_bag_hash'].has_key?(repo_hash['repo_name']) && @config[@options['env']]['chef_passwords_bag_hash'][repo_hash['repo_name']].has_key?('pg_pass')
|
37
35
|
password = @config[@options['env']]['chef_passwords_bag_hash'][repo_hash['repo_name']]['pg_pass'] unless @config[@options['env']]['chef_passwords_bag_hash'][repo_hash['repo_name']]['pg_pass'].empty?
|
38
36
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
class Cheftacular
|
2
|
+
class StatelessActionDocumentation
|
3
|
+
def get_shorewall_allowed_connections
|
4
|
+
@config['documentation']['stateless_action'] << [
|
5
|
+
"`cft get_shorewall_allowed_connections` command will query a single server and return all of its ACCEPT connections " +
|
6
|
+
"from shorewall in it's syslog and return the results in a CSV format. Useful for tracking IP activity.",
|
7
|
+
|
8
|
+
[
|
9
|
+
" 1. This command will attempt to `dig` each ip address to give you the most likely culprit."
|
10
|
+
]
|
11
|
+
]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class StatelessAction
|
16
|
+
def get_shorewall_allowed_connections
|
17
|
+
#TODO find and load syslog files from nodes!
|
18
|
+
log_data << File.read(File.expand_path("#{ @locs['chef-log'] }/marketing_site_syslog_2.txt"))
|
19
|
+
log_data << File.read(File.expand_path("#{ @locs['chef-log'] }/marketing_site_syslog_1.txt"))
|
20
|
+
log_data << File.read(File.expand_path("#{ @locs['chef-log'] }/marketing_site_syslog.txt"))
|
21
|
+
|
22
|
+
exit
|
23
|
+
|
24
|
+
addresses = {}
|
25
|
+
|
26
|
+
log_data.join("\n").scan(/^.*Shorewall:net2fw:ACCEPT.*SRC=([\d]+\.[\d]+\.[\d]+\.[\d]+) DST.*DPT=80.*$/).each do |ip_address|
|
27
|
+
addresses[ip_address] ||= 0
|
28
|
+
addresses[ip_address] += 1
|
29
|
+
end
|
30
|
+
|
31
|
+
final_addresses = {}
|
32
|
+
check_count = 0
|
33
|
+
addresses.each_pair do |address, count|
|
34
|
+
domain = `dig +short -x #{ address[0] }`.chomp.split("\n").join('|')
|
35
|
+
domain = domain[0..(domain.length-2)]
|
36
|
+
|
37
|
+
domain = address[0] if domain.blank?
|
38
|
+
|
39
|
+
final_addresses[domain] ||= {}
|
40
|
+
final_addresses[domain]['addresses'] ||= []
|
41
|
+
final_addresses[domain]['addresses'] << address[0] unless final_addresses[domain]['addresses'].include?(address[0])
|
42
|
+
final_addresses[domain]['count'] = count unless final_addresses[domain].has_key?('count')
|
43
|
+
final_addresses[domain]['count'] += count if final_addresses[domain].has_key?('count')
|
44
|
+
|
45
|
+
check_count += 1
|
46
|
+
|
47
|
+
puts "Processed #{ check_count } addresses (#{ address[0] }):#{ domain }:#{ count }"
|
48
|
+
end
|
49
|
+
|
50
|
+
final_addresses = final_addresses.sort_by {|key, value_hash| value_hash['count']}.to_h
|
51
|
+
|
52
|
+
final_addresses = Hash[final_addresses.to_a.reverse]
|
53
|
+
|
54
|
+
ap(final_addresses)
|
55
|
+
|
56
|
+
log_loc, timestamp = @config['helper'].set_log_loc_and_timestamp
|
57
|
+
|
58
|
+
CSV.open(File.expand_path("#{ @locs['chef-log'] }/#{ @options['node_name'] }-shorewall-parse-#{ timestamp }.csv"), "wb") do |csv|
|
59
|
+
final_addresses.each_pair do |dns, info_hash|
|
60
|
+
csv << [dns, info_hash['addresses'].join('|'), info_hash['count']]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -56,7 +56,7 @@ class Cheftacular
|
|
56
56
|
puts @config['helper'].compile_documentation_lines('devops').flatten.join("\n\n") if target_command == 'devops'
|
57
57
|
|
58
58
|
if inference_modes.empty? && @config['helper'].is_not_command_or_stateless_command?(target_command)
|
59
|
-
methods = @config['action_documentation'].public_methods(false) + @config['
|
59
|
+
methods = @config['action_documentation'].public_methods(false) + @config['stateless_action_documentation'].public_methods(false)
|
60
60
|
|
61
61
|
sorted_methods = methods.uniq.sort_by { |method| @config['helper'].compare_strings(target_command, method.to_s)}
|
62
62
|
|
@@ -196,6 +196,12 @@ class Cheftacular
|
|
196
196
|
|
197
197
|
save_on_finish = true
|
198
198
|
end
|
199
|
+
|
200
|
+
unless hash[env].has_key?('cloudflare_activated_domains')
|
201
|
+
hash[env]['cloudflare_activated_domains'] = []
|
202
|
+
|
203
|
+
save_on_finish = true
|
204
|
+
end
|
199
205
|
end
|
200
206
|
|
201
207
|
@config['ChefDataBag'].save_config_bag(main_env) if save_on_finish
|
@@ -2,7 +2,7 @@
|
|
2
2
|
class Cheftacular
|
3
3
|
class StatelessActionDocumentation
|
4
4
|
def remove_client
|
5
|
-
@config['documentation']['
|
5
|
+
@config['documentation']['stateless_action'] << [
|
6
6
|
"`cft remove_client -n NODE_NAME` removes a client (and its node data) from the chef-server. " +
|
7
7
|
"It also removes its dns records from the cloud service (if possible). " +
|
8
8
|
"This should not be done lightly as you will have to wipe the server and trigger another chef-client run to get it to register again"
|
@@ -16,9 +16,11 @@ class Cheftacular
|
|
16
16
|
@options['delete_server_on_remove'] = ARGV[2] if !@options['delete_server_on_remove'] && !@options['dont_remove_address_or_server'] && ARGV[2]
|
17
17
|
@options['delete_server_on_remove'] = 'destroy' if delete_server || @options['delete_server_on_remove']
|
18
18
|
|
19
|
+
raise "This action can only be performed if the mode is set to devops" if !@config['helper'].running_in_mode?('devops') && !@options['in_scaling']
|
20
|
+
|
19
21
|
raise "The only valid argument for the 2nd argument of this command is 'destroy', please enter this or leave it blank." if ARGV[2] && ARGV[2] != 'destroy' && !@options['dont_remove_address_or_server']
|
20
22
|
|
21
|
-
raise "
|
23
|
+
raise "Invalid arguments! Node name is blank. Please call this script as cft remove_client <node_name>" unless @options['node_name']
|
22
24
|
|
23
25
|
nodes = @config['getter'].get_true_node_objects(false, true)
|
24
26
|
|
@@ -47,27 +49,11 @@ class Cheftacular
|
|
47
49
|
if @options['delete_server_on_remove'] == 'destroy'
|
48
50
|
@config['stateless_action'].cloud "server", "destroy:#{ @options['env'] }_#{ n.name }"
|
49
51
|
end
|
50
|
-
end
|
51
|
-
|
52
|
-
@config[@options['env']]['addresses_bag_hash'] = @config[@options['env']]['addresses_bag'].reload.to_hash
|
53
|
-
|
54
|
-
target_serv_index = nil
|
55
|
-
|
56
|
-
@config[@options['env']]['addresses_bag_hash']['addresses'].each do |serv_hash|
|
57
|
-
target_serv_index = @config[@options['env']]['addresses_bag_hash']['addresses'].index(serv_hash) if serv_hash['name'] == @options['node_name']
|
58
52
|
end
|
59
53
|
|
60
|
-
|
61
|
-
puts("Found entry in addresses data bag corresponding to #{ @options['node_name'] } for #{ @options['env'] }, removing...") unless @options['quiet']
|
62
|
-
|
63
|
-
domain_obj = PublicSuffix.parse @config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index]['dn']
|
64
|
-
|
65
|
-
#delete the domain on rax if its a domain we host there for its environment
|
66
|
-
@config['stateless_action'].cloud "domain", "destroy_record:#{ domain_obj.tld }:#{ domain_obj.trd }" if domain_obj.tld == @config[@options['env']]['config_bag_hash'][@options['sub_env']]['tld']
|
54
|
+
@config[@options['env']]['addresses_bag_hash'] = @config[@options['env']]['addresses_bag'].reload.to_hash
|
67
55
|
|
68
|
-
|
69
|
-
@config[@options['env']]['addresses_bag_hash']['addresses'] = @config[@options['env']]['addresses_bag_hash']['addresses'].compact
|
70
|
-
end
|
56
|
+
@config['DNS'].compile_address_hash_for_server_from_options('set_hash_to_nil')
|
71
57
|
|
72
58
|
@config['ChefDataBag'].save_addresses_bag
|
73
59
|
end
|
@@ -4,6 +4,13 @@ class Cheftacular
|
|
4
4
|
@config['documentation']['stateless_action'] << [
|
5
5
|
"`cft slack \"MESSAGE\" [CHANNEL]` will attempt to post the message to the webhook set in your cheftacular.yml. " +
|
6
6
|
"Slack posts to your default channel by default but if the CHANNEL argument is supplied the message will post there.",
|
7
|
+
|
8
|
+
[
|
9
|
+
" 1. NOTE: To prevent confusing spam from many possible sources, the username posted to slack will always be " +
|
10
|
+
"*Cheftacular*. This can be overloaded in the StatelessAction method \"slack\" but this is not recommended.",
|
11
|
+
|
12
|
+
" 2. Remember, if you have auditing turned on in your cheftacular.yml, you can track who sends what to slack."
|
13
|
+
]
|
7
14
|
]
|
8
15
|
end
|
9
16
|
end
|
@@ -12,7 +19,7 @@ class Cheftacular
|
|
12
19
|
def slack
|
13
20
|
notifier = Slack::Notifier.new @config['cheftacular']['slack_webhook'], username: 'Cheftacular'
|
14
21
|
|
15
|
-
notifier.channel =
|
22
|
+
notifier.channel = ARGV[2] ? ARGV[2] : '#default'
|
16
23
|
notifier.ping ARGV[1]
|
17
24
|
end
|
18
25
|
end
|