cheftacular 2.2.2 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 29520ff1bae99c83bce312f6f5f582505776a007
4
- data.tar.gz: 7f79d595110a8850083c5314671129d08709560b
3
+ metadata.gz: cacccbd73021b45400cb3eda03bb8cb22f1ba9fe
4
+ data.tar.gz: 70f82785708bd038080088e905a0ef5cf4f84598
5
5
  SHA512:
6
- metadata.gz: a52cf49de433628aab008679c6df07a7f42a9ca290f7895ee2e780a21db5481be3cefc09c9887981b9b4c089c7a1e8b418fb5bfc123102cd81fa5965c77999ef
7
- data.tar.gz: cb443b1cc185d8ce16f4987415b396f8eb14473f9d66615612cfea10daab85972c38b8ce43c4a59390ebbc5339be8f6e7ecc052db81d8af33e295fcdf0e39f1f
6
+ metadata.gz: 08b9fbaee4acc4edebff56241cdf369a30fc1684dbee05f37021c4e3d85002f267fd9c942303d6003fcbd095010d34a0a1a775d30c8e73c71f2cbca3134d8b2b
7
+ data.tar.gz: 2dee13991458ac134f24af9b2685e2c9e389934a5214a100d737612a23220d9d4ef5eca643a652c1be978471d685b1bcb93d90e7a9784b742bf4dce2a923583a
@@ -220,8 +220,8 @@
220
220
  2. NOTE! Most flavors have spaces in them, you must use quotes at the command line to utilize them!
221
221
 
222
222
  4. `destroy:SERVER_NAME` destroys the server on the cloud. This must be an exact match of the server's actual name or the script will error.
223
-
224
-   5. `poll:SERVER_NAME` polls the cloud's server for the status of the SERVER_NAME. This command will stop polling if / when the status of the server is ACTIVE and its build progress is 100%.
223
+
224
+ 5. `poll:SERVER_NAME` polls the cloud's server for the status of the SERVER_NAME. This command will stop polling if / when the status of the server is ACTIVE and its build progress is 100%.
225
225
 
226
226
  6. `attach_volume:SERVER_NAME:VOLUME_NAME[:VOLUME_SIZE[:DEVICE_LOCATION]]` If VOLUME_NAME exists it will attach it if it is unattached otherwise it will create it
227
227
 
@@ -303,9 +303,13 @@
303
303
 
304
304
  21. `cft get_pg_pass ['clip']` command will output the current environment's pg_password to your terminal. Optionally you can pass in clip like `cft get_pg_pass clip` to have it also copy the pass to your clipboard.
305
305
 
306
- 22. `cft get_shorewall_allowed_connections` command will query a single server and return all of its ACCEPT connections from shorewall in it's syslog and return the results in a CSV format. Useful for tracking IP activity.
306
+ 22. `cft get_shorewall_allowed_connections [PATH_TO_LOCAL_FILE] -n NODE_NAME` command will query a single server and return all of its ACCEPT connections from shorewall in it's syslog and return the results in a CSV format. Useful for tracking IP activity.
307
+
308
+ 1. You must pass in a node name to query with `-n NODE_NAME`
307
309
 
308
- 1. This command will attempt to `dig` each ip address to give you the most likely culprit.
310
+ 2. This command will attempt to `dig` each ip address to give you the most likely culprit.
311
+
312
+ 3. If `PATH_TO_LOCAL_FILE` is not blank, the command will use that file instead of building a file on the remote server
309
313
 
310
314
  23. `cft help COMMAND|MODE` this command returns the documentation for a specific command if COMMAND matches the name of a command. Alternatively, it can be passed `action|arguments|application|current|devops|stateless_action` to fetch the commands for a specific mode.Misspellings of commands will display near hits.
311
315
 
@@ -369,12 +373,14 @@
369
373
 
370
374
  35. `cft ubuntu_bootstrap ADDRESS ROOT_PASS` This command will bring a fresh server to a state where chef-client can be run on it via `cft chef-bootstrap`. It should be noted that it is in this step where a server's randomized deploy_user sudo password is generated.
371
375
 
372
- 36. `cft update_cloudflare_dns_from_cloud` command will force a full dns update for cloudflare.
376
+ 36. `cft update_cloudflare_dns_from_cloud [skip_update_tld]` command will force a full dns update for cloudflare.
373
377
 
374
378
  1. It will ensure all the subdomain entries are correct (based on the contents of the addresses data bag) and update them if they are not. It will also create the local subdomain for the entry as well if it does exist and point it to the correct private address for an environment.
375
379
 
376
380
  2. This command will also ensure any dns records on your cloud are also migrated over to cloudflare as well. This also includes the reverse in the event you would like to turn off cloudflare.
377
381
 
382
+ 3. The argument `skip_update_tld` will stop the long process of checking and updating all the server domains _before_ cloudflare is updated. Only skip if you believe your domain info on your cloud is accurate.
383
+
378
384
  37. `cft update_split_branches` will perform a series of git commands that will merge all the split branches for your split_branch enabled repositories with what is currently on master and push them.
379
385
 
380
386
  1. Repository must be set with `-R REPOSITORY_NAME` for this command to work.
@@ -33,7 +33,7 @@ class Cheftacular
33
33
  logs_bag_hash["#{ n.name }-deploy"] = { text: log_data.scrub_pretty_text, timestamp: timestamp }
34
34
  end
35
35
 
36
- @config['ChefDataBag'].save_logs_bag unless @options['debug'] #the debug chef-client runs are literally too large to POST
36
+ #@config['ChefDataBag'].save_logs_bag unless @options['debug'] #We don't really need to store entire chef runs in the logs bag
37
37
 
38
38
  migrate(nodes) if @config['getter'].get_current_repo_config['database'] != 'none' && !@options['run_migration_already']
39
39
  end
@@ -43,7 +43,7 @@ class Cheftacular
43
43
  end
44
44
 
45
45
  def migrate_wordpress nodes=[]
46
- puts "Method #{ __migrate_wordpress__ } isb ot yet implemented"
46
+ puts "Method #{ __method__ } is not yet implemented"
47
47
 
48
48
  exit
49
49
  end
@@ -39,6 +39,8 @@ class Cheftacular
39
39
 
40
40
  item.attributes = @config[env]['logs_bag_hash'].keep_if {|key,val| key == 'id'}
41
41
 
42
+ sleep 5
43
+
42
44
  item.save
43
45
 
44
46
  @config[env]['logs_bag_hash'] = @config[env]['logs_bag'].reload.to_hash
@@ -22,6 +22,7 @@ require 'timeout'
22
22
  require 'slack-notifier'
23
23
  require 'cloudflare'
24
24
  require 'zlib'
25
+ require 'csv'
25
26
 
26
27
  Dir["#{File.dirname(__FILE__)}/../**/*.rb"].each { |f| require f }
27
28
 
@@ -29,6 +30,8 @@ class Cheftacular
29
30
  def initialize options={'env'=>'staging'}, config={}
30
31
  @options, @config = options, config
31
32
 
33
+ SSHKit.config.format = :blackhole
34
+
32
35
  @config['start_time'] = Time.now
33
36
 
34
37
  @config['helper'] = Helper.new(@options, @config)
@@ -180,12 +180,12 @@ class Cheftacular
180
180
  if !target_serv_index.nil? && target_serv_index.is_a?(Fixnum) && !@options['dont_remove_address_or_server'] && args.include?('set_hash_to_nil')
181
181
  puts("Found entry in addresses data bag corresponding to #{ @options['node_name'] } for #{ @options['env'] }, removing...") unless @options['quiet']
182
182
 
183
+ domain_obj = PublicSuffix.parse @config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index]['dn']
184
+
183
185
  @config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index] = nil
184
186
 
185
187
  @config[@options['env']]['addresses_bag_hash']['addresses'] = @config[@options['env']]['addresses_bag_hash']['addresses'].compact
186
188
 
187
- domain_obj = PublicSuffix.parse @config[@options['env']]['addresses_bag_hash']['addresses'][target_serv_index]['dn']
188
-
189
189
  @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']
190
190
  end
191
191
 
@@ -397,7 +397,7 @@ class Cheftacular
397
397
 
398
398
  exit
399
399
  else
400
- unless File.exists?( current_version_file_path )
400
+ unless File.exists?( @config['helper'].current_version_file_path )
401
401
  puts "Creating file cache for #{ Time.now.strftime("%Y%m%d") } (#{ detected_version }). No new version detected."
402
402
 
403
403
  @config['helper'].write_version_file detected_version
@@ -15,7 +15,7 @@ class Cheftacular
15
15
 
16
16
  class StatelessAction
17
17
  def chef_environment
18
- #TODO
18
+ raise "Not yet Implemented"
19
19
  end
20
20
  end
21
21
  end
@@ -7,7 +7,7 @@ class Cheftacular
7
7
  "If no args are passed nothing will happen.",
8
8
 
9
9
  [
10
- " 1. `domain` 1st level argument for interacting with cloud domains",
10
+ " 1. `domain` first level argument for interacting with cloud domains",
11
11
 
12
12
  " 1. `list` default behavior",
13
13
 
@@ -28,7 +28,7 @@ class Cheftacular
28
28
 
29
29
  " 9. `update_record:TOP_LEVEL_DOMAIN:SUBDOMAIN_NAME:IP_ADDRESS[:RECORD_TYPE[:TTL]]` similar to `create_record`.",
30
30
 
31
- " 2. `server` 1st level argument for interacting with cloud servers, " +
31
+ " 2. `server` first level argument for interacting with cloud servers, " +
32
32
  "if no additional args are passed the command will return a list of all servers on the preferred cloud.",
33
33
 
34
34
  " 1. `list` default behavior",
@@ -44,7 +44,7 @@ class Cheftacular
44
44
 
45
45
  " 4. `destroy:SERVER_NAME` destroys the server on the cloud. This must be an exact match of the server's actual name or the script will error.",
46
46
 
47
- "  5. `poll:SERVER_NAME` polls the cloud's server for the status of the SERVER_NAME. This command " +
47
+ " 5. `poll:SERVER_NAME` polls the cloud's server for the status of the SERVER_NAME. This command " +
48
48
  "will stop polling if / when the status of the server is ACTIVE and its build progress is 100%.",
49
49
 
50
50
  " 6. `attach_volume:SERVER_NAME:VOLUME_NAME[:VOLUME_SIZE[:DEVICE_LOCATION]]` " +
@@ -66,7 +66,7 @@ class Cheftacular
66
66
 
67
67
  " 9. `read_volume:SERVER_NAME:VOLUME_NAME` returns the data of VOLUME_NAME if it is attached to the server.",
68
68
 
69
- " 3. `volume` 1st level argument for interacting with cloud storage volumes, if no additional args are passed the command will return a list of all cloud storage containers.",
69
+ " 3. `volume` first level argument for interacting with cloud storage volumes, if no additional args are passed the command will return a list of all cloud storage containers.",
70
70
 
71
71
  " 1. `list` default behavior",
72
72
 
@@ -76,7 +76,7 @@ class Cheftacular
76
76
 
77
77
  " 4. `destroy:VOLUME_NAME` destroys the volume. This operation will not work if the volume is attached to a server.",
78
78
 
79
- " 4. `flavor` 1st level argument for listing the flavors available on the cloud service",
79
+ " 4. `flavor` first level argument for listing the flavors available on the cloud service",
80
80
 
81
81
  " 1. `list` default behavior",
82
82
 
@@ -75,7 +75,7 @@ class Cheftacular
75
75
 
76
76
  @options['dont_remove_address_or_server'] = true #flag to make sure our entry isnt removed in addresses bag
77
77
 
78
- full_bootstrap #bootstrap server with ruby and attach it to the chef server
78
+ @config['stateless_action'].full_bootstrap #bootstrap server with ruby and attach it to the chef server
79
79
  end
80
80
  end
81
81
  end
@@ -23,14 +23,14 @@ class Cheftacular
23
23
  nodes = @config['parser'].exclude_nodes( nodes, [{ unless: { env: @options['env'] }}])
24
24
 
25
25
  nodes.each do |node|
26
- if @config[@options['env']]['logs_bag_hash'].has_key?("#{ node.name }-deploy")
27
- puts("Found log data in logs bag. Outputting to #{ log_loc }/stashedlog/#{ node.name }-deploystash-#{ @config[@options['env']]['logs_bag_hash']["#{ node.name }-deploy"][:timestamp] }.txt") unless @options['quiet']
26
+ if @config[@options['env']]['logs_bag_hash'].has_key?("#{ node.name }-run")
27
+ puts("Found log data in logs bag. Outputting to #{ log_loc }/stashedlog/#{ node.name }-deploystash-#{ @config[@options['env']]['logs_bag_hash']["#{ node.name }-run"][:timestamp] }.txt") unless @options['quiet']
28
28
 
29
- File.open("#{ log_loc }/stashedlog/#{ node.name }-deploystash-#{@config[@options['env']]['logs_bag_hash']["#{ node.name }-deploy"][:timestamp] }.txt", "w") do |f|
30
- f.write(@config[@options['env']]['logs_bag_hash']["#{ node.name }-deploy"][:text])
29
+ File.open("#{ log_loc }/stashedlog/#{ node.name }-deploystash-#{@config[@options['env']]['logs_bag_hash']["#{ node.name }-run"][:timestamp] }.txt", "w") do |f|
30
+ f.write(@config[@options['env']]['logs_bag_hash']["#{ node.name }-run"][:text])
31
31
  end
32
32
 
33
- puts(@config[@options['env']]['logs_bag_hash']["#{ node.name }-deploy"][:text]) if @options['verbose']
33
+ puts(@config[@options['env']]['logs_bag_hash']["#{ node.name }-run"][:text]) if @options['verbose']
34
34
  end
35
35
  end
36
36
  end
@@ -2,24 +2,54 @@ class Cheftacular
2
2
  class StatelessActionDocumentation
3
3
  def get_shorewall_allowed_connections
4
4
  @config['documentation']['stateless_action'] << [
5
- "`[NYI]cft get_shorewall_allowed_connections` command will query a single server and return all of its ACCEPT connections " +
5
+ "`cft get_shorewall_allowed_connections [PATH_TO_LOCAL_FILE] -n NODE_NAME` command will query a single server and return all of its ACCEPT connections " +
6
6
  "from shorewall in it's syslog and return the results in a CSV format. Useful for tracking IP activity.",
7
7
 
8
8
  [
9
- " 1. This command will attempt to `dig` each ip address to give you the most likely culprit."
9
+ " 1. You must pass in a node name to query with `-n NODE_NAME`",
10
+
11
+ " 2. This command will attempt to `dig` each ip address to give you the most likely culprit.",
12
+
13
+ " 3. If `PATH_TO_LOCAL_FILE` is not blank, the command will use that file instead of building a file on the remote server"
10
14
  ]
11
15
  ]
12
16
  end
13
17
  end
14
18
 
15
19
  class StatelessAction
16
- def get_shorewall_allowed_connections
17
- raise "Not yet implemented"
18
- #TODO find and load syslog files from nodes!
20
+ def get_shorewall_allowed_connections master_log_data=''
21
+
22
+ if ARGV[1].nil?
23
+ raise "Please pass a NODE_NAME with -n NODE_NAME" if @options['node_name'].nil? || @options['node_name'].empty?
24
+
25
+ nodes = @config['getter'].get_true_node_objects true
26
+
27
+ nodes = @config['parser'].exclude_nodes(nodes, [{ unless: { env: @options['env'] }}, { unless: { node: @options['node_name'] }}], true)
28
+
29
+ #this must always precede on () calls so they have the instance variables they need
30
+ options, locs, ridley, logs_bag_hash, pass_bag_hash, bundle_command, cheftacular, passwords = @config['helper'].set_local_instance_vars
31
+
32
+ #on is namespaced to SSHKit::Backend::Netssh.on
33
+ on ( nodes.map { |n| "deploy@" + n.public_ipaddress } ) do |host|
34
+ n = get_node_from_address(nodes, host.hostname)
35
+
36
+ puts("Beginning shorewall log capture run for #{ n.name } (#{ n.public_ipaddress })") unless options['quiet']
37
+
38
+ master_log_data = start_shorewall_log_capture( n.name, n.public_ipaddress, options, locs, cheftacular, passwords)
39
+ end
40
+ else
41
+ master_log_file = ARGV[1]
42
+
43
+ raise "File not found! Did you enter the path correctly?" unless File.exist?(master_log_file)
44
+
45
+ master_log_data = File.read(File.expand_path(master_log_file))
46
+ end
47
+
48
+ puts("Parsing addresses from log data...") unless @options['quiet']
19
49
 
20
50
  addresses = {}
21
51
 
22
- log_data.join("\n").scan(/^.*Shorewall:net2fw:ACCEPT.*SRC=([\d]+\.[\d]+\.[\d]+\.[\d]+) DST.*DPT=80.*$/).each do |ip_address|
52
+ master_log_data.scan(/^.*Shorewall:net2fw:ACCEPT.*SRC=([\d]+\.[\d]+\.[\d]+\.[\d]+) DST.*DPT=80.*$/).each do |ip_address|
23
53
  addresses[ip_address] ||= 0
24
54
  addresses[ip_address] += 1
25
55
  end
@@ -27,6 +57,8 @@ class Cheftacular
27
57
  final_addresses = {}
28
58
  check_count = 0
29
59
  addresses.each_pair do |address, count|
60
+ next if count < 100
61
+
30
62
  domain = `dig +short -x #{ address[0] }`.chomp.split("\n").join('|')
31
63
  domain = domain[0..(domain.length-2)]
32
64
 
@@ -40,18 +72,18 @@ class Cheftacular
40
72
 
41
73
  check_count += 1
42
74
 
43
- puts "Processed #{ check_count } addresses (#{ address[0] }):#{ domain }:#{ count }"
75
+ puts("Processed #{ check_count } addresses (#{ address[0] }):#{ domain }:#{ count }") unless @options['quiet']
44
76
  end
45
77
 
46
78
  final_addresses = final_addresses.sort_by {|key, value_hash| value_hash['count']}.to_h
47
79
 
48
80
  final_addresses = Hash[final_addresses.to_a.reverse]
49
81
 
50
- ap(final_addresses)
82
+ ap(final_addresses) if @options['verbose']
51
83
 
52
84
  log_loc, timestamp = @config['helper'].set_log_loc_and_timestamp
53
85
 
54
- CSV.open(File.expand_path("#{ @locs['chef-log'] }/#{ @options['node_name'] }-shorewall-parse-#{ timestamp }.csv"), "wb") do |csv|
86
+ CSV.open(File.expand_path("#{ @config['locs']['chef-log'] }/shorewall-parse-#{ timestamp }.csv"), "wb") do |csv|
55
87
  final_addresses.each_pair do |dns, info_hash|
56
88
  csv << [dns, info_hash['addresses'].join('|'), info_hash['count']]
57
89
  end
@@ -59,3 +91,39 @@ class Cheftacular
59
91
  end
60
92
  end
61
93
  end
94
+
95
+ module SSHKit
96
+ module Backend
97
+ class Netssh
98
+ def start_shorewall_log_capture name, ip_address, options, locs, cheftacular, passwords, out=[]
99
+ log_loc, timestamp = set_log_loc_and_timestamp(locs)
100
+
101
+ puts("Generating master log file for shorewall for #{ name } (#{ ip_address }) at #{ log_loc }/#{ name }-shorewall-#{ timestamp }.html") unless options['quiet']
102
+
103
+ syslog_files = capture(:ls, '/var/log', :|, :grep, :syslog).split("\n")
104
+
105
+ puts("Found #{ syslog_files.count } syslog files to parse (#{ syslog_files.join(', ') }).\nPreparing to parse...") unless options['quiet']
106
+
107
+ syslog_files.each do |file|
108
+ puts("Parsing #{ file } into master log file...") unless options['quiet']
109
+
110
+ if file.include?('.gz')
111
+ sudo_execute(passwords[ip_address], :gunzip, '-c', "/var/log/#{ file }", '>>', '/tmp/syslog_master.log' )
112
+ else
113
+ sudo_execute(passwords[ip_address], :cat, "/var/log/#{ file }", '>>', '/tmp/syslog_master.log' )
114
+ end
115
+ end
116
+
117
+ puts("Writing master log...") unless options['quiet']
118
+
119
+ out << sudo_capture( passwords[ip_address], :cat, "/tmp/syslog_master.log" )
120
+
121
+ ::File.open("#{ log_loc }/#{ name }-shorewall-#{ timestamp }.html", "w") { |f| f.write(out.join("\n").scrub_pretty_text.gsub('[sudo] password for deploy: ', '')) } unless options['no_logs']
122
+
123
+ sudo_execute(passwords[ip_address], :rm, '-f', '/tmp/syslog_master.log')
124
+
125
+ out.join("\n")
126
+ end
127
+ end
128
+ end
129
+ end
@@ -30,7 +30,7 @@ class Cheftacular
30
30
 
31
31
  type = ARGV[env_index] if ARGV[env_index]
32
32
 
33
- raise "Unknown split_env: #{ split_env }, can only be #{ cheftacular['run_list_environments'].values.join(', ') }" unless (split_env =~ /#{ cheftacular['run_list_environments'].values.join('|') }/) == 0
33
+ raise "Unknown split_env: #{ split_env }, can only be #{ @config['cheftacular']['run_list_environments'].values.join(', ') }" unless (split_env =~ /#{ @config['cheftacular']['run_list_environments'].values.join('|') }/) == 0
34
34
 
35
35
  raise "Unknown type: #{ type }, can only be 'boot' or 'destroy'" unless (type =~ /boot|destroy/) == 0
36
36
 
@@ -41,11 +41,9 @@ class Cheftacular
41
41
  @options['force_yes'] = true
42
42
  @options['in_scaling'] = true
43
43
 
44
- initial_servers = @config['cheftacular']['split_env_nodes']
45
-
46
44
  case type
47
45
  when 'boot'
48
- initial_servers.each_pair do |name, config_hash|
46
+ @config['cheftacular']['split_env_nodes'].each_pair do |name, config_hash|
49
47
  true_name = name.gsub('SPLITENV', split_env)
50
48
  @options['node_name'] = "#{ true_name }#{ 'p' if @options['env'] == 'production' }"
51
49
  @options['flavor_name'] = config_hash.has_key?('flavor') ? config_hash['flavor'] : @config['cheftacular']['default_flavor_name']
@@ -66,7 +64,6 @@ class Cheftacular
66
64
  @options['delete_server_on_remove'] = true
67
65
 
68
66
  nodes.each do |node|
69
- next if !targets.empty? && !targets.include?(node.name)
70
67
 
71
68
  @options['node_name'] = node.name
72
69
 
@@ -1,5 +1,5 @@
1
1
  class Cheftacular
2
2
  #major_version.minor_version.bugfixes
3
- VERSION = "2.2.2"
3
+ VERSION = "2.3.0"
4
4
  RUBY_VERSION = "2.2.2"
5
5
  end
@@ -28,4 +28,4 @@ module SSHKit
28
28
  end
29
29
  end
30
30
  end
31
- end
31
+ end
@@ -9,6 +9,10 @@ module SSHKit
9
9
  capture :echo, pass, :|, :sudo, '-S', *args
10
10
  end
11
11
 
12
+ def sudo_execute pass, *args
13
+ execute :echo, pass, :|, :sudo, '-S', *args
14
+ end
15
+
12
16
  def sudo_test pass, file_location
13
17
  sudo_capture( pass, :test, '-e', file_location, '&&', :echo, 'true', { raise_on_non_zero_exit: false, verbosity: Logger::DEBUG }) == 'true'
14
18
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cheftacular
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.2
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Louis Alridge
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-13 00:00:00.000000000 Z
11
+ date: 2015-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie