cheftacular 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +7 -0
  2. data/bin/cft +4 -0
  3. data/bin/cftclr +4 -0
  4. data/bin/cheftacular +4 -0
  5. data/bin/client-list +4 -0
  6. data/lib/cheftacular/README.md +416 -0
  7. data/lib/cheftacular/actions/check.rb +32 -0
  8. data/lib/cheftacular/actions/console.rb +62 -0
  9. data/lib/cheftacular/actions/database.rb +13 -0
  10. data/lib/cheftacular/actions/db_console.rb +67 -0
  11. data/lib/cheftacular/actions/deploy.rb +40 -0
  12. data/lib/cheftacular/actions/log.rb +47 -0
  13. data/lib/cheftacular/actions/migrate.rb +57 -0
  14. data/lib/cheftacular/actions/run.rb +64 -0
  15. data/lib/cheftacular/actions/scale.rb +94 -0
  16. data/lib/cheftacular/actions/tail.rb +55 -0
  17. data/lib/cheftacular/actions.rb +14 -0
  18. data/lib/cheftacular/auditor.rb +46 -0
  19. data/lib/cheftacular/chef/data_bag.rb +104 -0
  20. data/lib/cheftacular/cheftacular.rb +55 -0
  21. data/lib/cheftacular/decryptors.rb +45 -0
  22. data/lib/cheftacular/encryptors.rb +48 -0
  23. data/lib/cheftacular/getters.rb +153 -0
  24. data/lib/cheftacular/helpers.rb +296 -0
  25. data/lib/cheftacular/initializers.rb +451 -0
  26. data/lib/cheftacular/parsers.rb +199 -0
  27. data/lib/cheftacular/remote_helpers.rb +30 -0
  28. data/lib/cheftacular/stateless_action.rb +16 -0
  29. data/lib/cheftacular/stateless_actions/add_ssh_key_to_bag.rb +44 -0
  30. data/lib/cheftacular/stateless_actions/arguments.rb +68 -0
  31. data/lib/cheftacular/stateless_actions/backups.rb +116 -0
  32. data/lib/cheftacular/stateless_actions/bootstrappers/centos_bootstrap.rb +7 -0
  33. data/lib/cheftacular/stateless_actions/bootstrappers/coreos_bootstrap.rb +7 -0
  34. data/lib/cheftacular/stateless_actions/bootstrappers/fedora_bootstrap.rb +7 -0
  35. data/lib/cheftacular/stateless_actions/bootstrappers/redhat_bootstrap.rb +7 -0
  36. data/lib/cheftacular/stateless_actions/bootstrappers/ubuntu_bootstrap.rb +102 -0
  37. data/lib/cheftacular/stateless_actions/bootstrappers/vyatta_bootstrap.rb +7 -0
  38. data/lib/cheftacular/stateless_actions/chef_bootstrap.rb +40 -0
  39. data/lib/cheftacular/stateless_actions/chef_environment.rb +21 -0
  40. data/lib/cheftacular/stateless_actions/clean_cookbooks.rb +104 -0
  41. data/lib/cheftacular/stateless_actions/clean_sensu_plugins.rb +19 -0
  42. data/lib/cheftacular/stateless_actions/clean_server_passwords.rb +14 -0
  43. data/lib/cheftacular/stateless_actions/cleanup_log_files.rb +14 -0
  44. data/lib/cheftacular/stateless_actions/client_list.rb +89 -0
  45. data/lib/cheftacular/stateless_actions/cloud.rb +107 -0
  46. data/lib/cheftacular/stateless_actions/cloud_bootstrap.rb +109 -0
  47. data/lib/cheftacular/stateless_actions/compile_audit_log.rb +60 -0
  48. data/lib/cheftacular/stateless_actions/compile_readme.rb +41 -0
  49. data/lib/cheftacular/stateless_actions/create_git_key.rb +67 -0
  50. data/lib/cheftacular/stateless_actions/disk_report.rb +75 -0
  51. data/lib/cheftacular/stateless_actions/environment.rb +100 -0
  52. data/lib/cheftacular/stateless_actions/fetch_file.rb +24 -0
  53. data/lib/cheftacular/stateless_actions/fix_known_hosts.rb +70 -0
  54. data/lib/cheftacular/stateless_actions/full_bootstrap.rb +30 -0
  55. data/lib/cheftacular/stateless_actions/get_active_ssh_connections.rb +18 -0
  56. data/lib/cheftacular/stateless_actions/get_haproxy_log.rb +55 -0
  57. data/lib/cheftacular/stateless_actions/get_log_from_bag.rb +38 -0
  58. data/lib/cheftacular/stateless_actions/get_pg_pass.rb +61 -0
  59. data/lib/cheftacular/stateless_actions/help.rb +71 -0
  60. data/lib/cheftacular/stateless_actions/initialize_data_bag_contents.rb +220 -0
  61. data/lib/cheftacular/stateless_actions/knife_upload.rb +23 -0
  62. data/lib/cheftacular/stateless_actions/pass.rb +49 -0
  63. data/lib/cheftacular/stateless_actions/reinitialize.rb +46 -0
  64. data/lib/cheftacular/stateless_actions/remove_client.rb +81 -0
  65. data/lib/cheftacular/stateless_actions/replication_status.rb +103 -0
  66. data/lib/cheftacular/stateless_actions/restart_swap.rb +55 -0
  67. data/lib/cheftacular/stateless_actions/rvm.rb +14 -0
  68. data/lib/cheftacular/stateless_actions/server_update.rb +99 -0
  69. data/lib/cheftacular/stateless_actions/service.rb +14 -0
  70. data/lib/cheftacular/stateless_actions/test_env.rb +82 -0
  71. data/lib/cheftacular/stateless_actions/update_split_branches.rb +64 -0
  72. data/lib/cheftacular/stateless_actions/update_tld.rb +62 -0
  73. data/lib/cheftacular/stateless_actions/upload_nodes.rb +120 -0
  74. data/lib/cheftacular/stateless_actions/upload_roles.rb +24 -0
  75. data/lib/cheftacular/version.rb +5 -0
  76. data/lib/cheftacular.rb +4 -0
  77. data/lib/cloud_interactor/authentication.rb +56 -0
  78. data/lib/cloud_interactor/cloud_interactor.rb +23 -0
  79. data/lib/cloud_interactor/domain/create.rb +17 -0
  80. data/lib/cloud_interactor/domain/create_record.rb +27 -0
  81. data/lib/cloud_interactor/domain/destroy.rb +17 -0
  82. data/lib/cloud_interactor/domain/destroy_record.rb +23 -0
  83. data/lib/cloud_interactor/domain/list.rb +9 -0
  84. data/lib/cloud_interactor/domain/list_records.rb +22 -0
  85. data/lib/cloud_interactor/domain/read.rb +23 -0
  86. data/lib/cloud_interactor/domain/read_record.rb +27 -0
  87. data/lib/cloud_interactor/domain/update.rb +18 -0
  88. data/lib/cloud_interactor/domain/update_record.rb +42 -0
  89. data/lib/cloud_interactor/domain.rb +18 -0
  90. data/lib/cloud_interactor/flavor.rb +27 -0
  91. data/lib/cloud_interactor/helpers.rb +70 -0
  92. data/lib/cloud_interactor/image.rb +27 -0
  93. data/lib/cloud_interactor/parser.rb +37 -0
  94. data/lib/cloud_interactor/server/attach_volume.rb +33 -0
  95. data/lib/cloud_interactor/server/create.rb +39 -0
  96. data/lib/cloud_interactor/server/destroy.rb +11 -0
  97. data/lib/cloud_interactor/server/detach_volume.rb +21 -0
  98. data/lib/cloud_interactor/server/list.rb +7 -0
  99. data/lib/cloud_interactor/server/list_volumes.rb +25 -0
  100. data/lib/cloud_interactor/server/poll.rb +22 -0
  101. data/lib/cloud_interactor/server/read.rb +9 -0
  102. data/lib/cloud_interactor/server/read_volume.rb +24 -0
  103. data/lib/cloud_interactor/server.rb +17 -0
  104. data/lib/cloud_interactor/version.rb +4 -0
  105. data/lib/cloud_interactor/volume/create.rb +13 -0
  106. data/lib/cloud_interactor/volume/destroy.rb +11 -0
  107. data/lib/cloud_interactor/volume/list.rb +7 -0
  108. data/lib/cloud_interactor/volume/read.rb +9 -0
  109. data/lib/cloud_interactor/volume.rb +20 -0
  110. data/lib/ridley/monkeypatches.rb +11 -0
  111. data/lib/sshkit/actions/start_commit_check.rb +19 -0
  112. data/lib/sshkit/actions/start_deploy.rb +25 -0
  113. data/lib/sshkit/actions/start_log_fetch.rb +91 -0
  114. data/lib/sshkit/actions/start_task.rb +29 -0
  115. data/lib/sshkit/getters.rb +67 -0
  116. data/lib/sshkit/helpers.rb +13 -0
  117. data/lib/sshkit/monkeypatches.rb +19 -0
  118. metadata +375 -0
@@ -0,0 +1,33 @@
1
+ class CloudInteractor
2
+ class Server
3
+ #handles self and create_and_attach case
4
+ def attach_volume args
5
+ @classes['volume'].read args['volume_name'], false
6
+
7
+ if @main_obj['specific_volumes'].nil? || @main_obj['specific_volumes'].nil?
8
+
9
+ create_hash = { "display_name" => args['volume_name'] }
10
+ create_hash['size'] = args['size'] if args['size']
11
+ create_hash['volume_type'] = args['volume_type'] ? args['volume_type'] : 'SATA'
12
+
13
+ @classes['volume'].create create_hash
14
+
15
+ sleep 5
16
+
17
+ @classes['volume'].read args
18
+ end
19
+
20
+ puts "Attaching #{ args['volume_name'] } to #{ args['server_name'] } in #{ IDENTITY }..."
21
+
22
+ read args, false, 'name', 'server_name'
23
+
24
+ specific_fog_object = @classes['auth'].auth_service(RESOURCE).instance_eval(IDENTITY).get @main_obj["specific_#{ IDENTITY }"].last['id']
25
+
26
+ if args['device_location']
27
+ specific_fog_object.attach_volume @main_obj['specific_volumes'].first['id'], args['device_location']
28
+ else
29
+ specific_fog_object.attach_volume @main_obj['specific_volumes'].first['id']
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,39 @@
1
+
2
+ class CloudInteractor
3
+ class Server #http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Servers-d1e2073.html
4
+ def create args
5
+ @classes['image'].read @options['preferred_cloud_image'], false
6
+
7
+ #Note, if no flavor is passed it defaults to a 512MB standard!
8
+ @classes['flavor'].read args['flavor']
9
+
10
+ read args, false
11
+
12
+ unless @main_obj["specific_#{ IDENTITY }"].empty?
13
+ puts "#{ IDENTITY } #{ args['name'] } already exists... returning."
14
+
15
+ return false
16
+ end
17
+
18
+ puts "Creating #{ args['name'] } in #{ IDENTITY }..."
19
+
20
+ final_create_args = {
21
+ name: args['name'],
22
+ flavor_id: @main_obj['specific_flavors'].first['id'],
23
+ image_id: @main_obj['specific_images'].first['id']
24
+ }
25
+
26
+ @main_obj["#{ IDENTITY }_create_request"] = JSON.parse(@classes['auth'].auth_service(RESOURCE).instance_eval(IDENTITY).create(final_create_args).to_json)
27
+
28
+ @main_obj["#{ IDENTITY }_created_passwords"] ||= {}
29
+ @main_obj["#{ IDENTITY }_created_passwords"][args['name']] = @main_obj["#{ IDENTITY }_create_request"]['password']
30
+
31
+ @main_obj["#{ IDENTITY }_created_details"] ||= {}
32
+ @main_obj["#{ IDENTITY }_created_details"][args['name']] = @main_obj["#{ IDENTITY }_create_request"]
33
+
34
+ puts "Successfully created #{ args['name'] } with pass #{ @main_obj["#{ IDENTITY }_created_passwords"][args['name']] }"
35
+
36
+ @main_obj['output']['admin_passwords'] = { args['name'] => @main_obj["#{ IDENTITY }_created_passwords"][args['name']] }
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,11 @@
1
+ class CloudInteractor
2
+ class Server
3
+ def destroy args
4
+ read args, false
5
+
6
+ #TODO strict checking on servers to ensure a server can't be destroyed while it still has volumes attached (which can corrupt the volume)
7
+
8
+ @classes['helper'].generic_destroy_parse args, IDENTITY, RESOURCE
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ class CloudInteractor
2
+ class Server
3
+ def detach_volume args, out=""
4
+ read args, false, 'name', 'server_name'
5
+
6
+ read_volume args, false, true
7
+
8
+ puts "Detaching #{ args['volume_name'] } from #{ args['server_name'] } in #{ IDENTITY }..."
9
+
10
+ specific_fog_object = @classes['auth'].auth_service(RESOURCE).instance_eval(IDENTITY).get @main_obj["specific_#{ IDENTITY }"].last['id']
11
+
12
+ specific_fog_object.attachments.each do |attachment|
13
+ next unless attachment.volume_id == @main_obj["specific_attached_volumes"].first['id']
14
+
15
+ out << attachment.detach.to_s
16
+ end
17
+
18
+ puts "The state of the volume detachment is #{ out } for #{ args['server_name'] } in #{ IDENTITY }"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,7 @@
1
+ class CloudInteractor
2
+ class Server
3
+ def list args={}, output=true
4
+ @classes['helper'].generic_list_call IDENTITY, RESOURCE, output
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ class CloudInteractor
2
+ class Server
3
+ def list_volumes args, output=true
4
+ puts "Returning list of volumes for #{ args['server_name'] } in #{ IDENTITY }..."
5
+
6
+ read(args, false, 'name', 'server_name') if @main_obj["specific_#{ IDENTITY }"].nil?
7
+
8
+ specific_fog_object = @classes['auth'].auth_service(RESOURCE).instance_eval(IDENTITY).get @main_obj["specific_#{ IDENTITY }"].last['id']
9
+
10
+ @main_obj["#{ IDENTITY }_volume_list_request"] = JSON.parse(specific_fog_object.attachments.all.to_json)
11
+
12
+ @main_obj['server_attached_volumes'] ||= {}
13
+
14
+ @main_obj['server_attached_volumes'][args['server_name']] ||= []
15
+
16
+ @main_obj["#{ IDENTITY }_volume_list_request"].each do |volume_hash|
17
+ @classes['volume'].read volume_hash, false, 'id'
18
+
19
+ @main_obj['server_attached_volumes'][args['server_name']] << @main_obj['specific_volumes'].last
20
+ end
21
+
22
+ ap( @main_obj['server_attached_volumes'][args['server_name']] ) if output
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ class CloudInteractor
2
+ class Server
3
+ def poll args
4
+ read args, false
5
+
6
+ raise "Server #{ args['name'] } does not exist!" if @main_obj["specific_#{ IDENTITY }"].empty?
7
+
8
+ puts "Polling #{ args['name'] } for status...(execution will continue when the server is finished building)"
9
+
10
+ specific_fog_object = @classes['auth'].auth_service(RESOURCE).instance_eval(IDENTITY).get @main_obj["specific_#{ IDENTITY }"].last['id']
11
+
12
+ #specific_servers is an ARRAY, the latest status of the server is the LAST ENTRY
13
+ duration_hash = specific_fog_object.wait_for { ready? }
14
+
15
+ @main_obj['output']["created_servers"] ||= []
16
+
17
+ @main_obj['output']["created_servers"] << JSON.parse(specific_fog_object.reload.to_json)
18
+
19
+ puts "#{ args['name'] } became active in #{ duration_hash[:duration] } seconds!"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ class CloudInteractor
2
+ class Server
3
+ def read args, output=true, mode="name", search_key="name"
4
+ list [], false
5
+
6
+ @classes['helper'].generic_read_parse args, IDENTITY, output, mode, search_key
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,24 @@
1
+ class CloudInteractor
2
+ class Server
3
+ def read_volume args, output=true, strict_match=false
4
+ specific_volume = args['volume_name']
5
+
6
+ raise "Volume not passed! Value for volume name is: #{ specific_volume }" if specific_volume.nil?
7
+
8
+ list_volumes args, false
9
+
10
+ @main_obj['server_attached_volumes'][args['server_name']].each do |volume_hash|
11
+ next if strict_match && volume_hash['display_name'] != (specific_volume)
12
+ next if !strict_match && !volume_hash['display_name'].include?(specific_volume)
13
+
14
+ @main_obj["specific_attached_volumes"] ||= []
15
+
16
+ @main_obj["specific_attached_volumes"] << volume_hash
17
+
18
+ ap(volume_hash) if output
19
+ end
20
+
21
+ puts("#{ specific_volume } not attached to #{ args['server_name'] }!") if @main_obj["specific_attached_volumes"].nil?
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+
2
+ class CloudInteractor
3
+ class Server #http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Servers-d1e2073.html
4
+ IDENTITY = 'servers'
5
+ RESOURCE = 'compute'
6
+
7
+ def initialize main_obj, classes, options={}
8
+ @main_obj = main_obj
9
+ @options = options
10
+ @classes = classes
11
+ end
12
+
13
+ def run method, args
14
+ self.send(method, args)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,4 @@
1
+ class CloudInteractor
2
+ #major_version.minor_version.bugfixes
3
+ VERSION = "1.0.0"
4
+ end
@@ -0,0 +1,13 @@
1
+ class CloudInteractor
2
+ class Volume
3
+ def create args
4
+ puts "Creating #{ args['display_name'] } in #{ IDENTITY }..."
5
+
6
+ puts("Creating #{ IDENTITY.singularize } with args #{ ap(args) }") if @options['verbose']
7
+
8
+ args['volume_type'] = 'SSD' unless args['volume_type']
9
+
10
+ @main_obj["#{ IDENTITY }_create_request"] = JSON.parse(@classes['auth'].auth_service(RESOURCE).instance_eval(IDENTITY).create(args).to_json)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ class CloudInteractor
2
+ class Volume
3
+ def destroy args
4
+ read args, false
5
+
6
+ #TODO strict checking on volumes to ensure a volume can't be destroyed when it is still attached
7
+
8
+ @classes['helper'].generic_destroy_parse args, IDENTITY, RESOURCE, 'display_name'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ class CloudInteractor
2
+ class Volume
3
+ def list args={}, output=true
4
+ @classes['helper'].generic_list_call IDENTITY, RESOURCE, output
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ class CloudInteractor
2
+ class Volume
3
+ def read args, output=true, mode="display_name"
4
+ list([], false) if @main_obj["specific_#{ IDENTITY }"].nil?
5
+
6
+ @classes['helper'].generic_read_parse args, IDENTITY, output, mode
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,20 @@
1
+
2
+ class CloudInteractor
3
+ class Volume #http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/volumes.html
4
+ IDENTITY = 'volumes'
5
+ RESOURCE = 'volume'
6
+
7
+ def initialize main_obj, classes, options={}
8
+ @main_obj = main_obj
9
+ @options = options
10
+ @classes = classes
11
+ end
12
+
13
+ def run method, args, mode="name"
14
+ case method
15
+ when "read" then self.send(method, args, mode)
16
+ else self.send(method, args)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ #https://github.com/reset/ridley/blob/master/lib/ridley/chef_objects/data_bag_item_obect.rb
2
+ #This monkeypatch fixes decrypt being unable to return unencrypted data for encrypted bags with nested hashes in hashes
3
+ module Ridley
4
+ class DataBagItemObject < ChefObject
5
+ def decrypt
6
+ decrypted_hash = Hash[_attributes_.map { |key, value| [key, key == "id" ? value : decrypt_value(value)] }]
7
+
8
+ Hashie::Mash.new(decrypted_hash) #old:mass_assign(decrypted_hash)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module SSHKit
2
+ module Backend
3
+ class Netssh
4
+ def start_commit_check name, ip_address, options, locs, cheftacular, out={'name'=>'', 'time'=> ''}
5
+ app_loc = "#{ cheftacular['base_file_path'] }/#{ options['repository'] }/releases"
6
+
7
+ if test("[ -d #{ app_loc } ]") #true if file exists
8
+ within app_loc do
9
+ out['name'] = capture( :ls, '-rt', :|, :tail, '-1' )
10
+
11
+ out['time'] = Time.parse(capture( :stat, out['name'], '--printf=%y' )).strftime('%Y-%m-%d %I:%M:%S %p')
12
+ end
13
+ end
14
+
15
+ out
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ module SSHKit
2
+ module Backend
3
+ class Netssh
4
+ def start_deploy name, ip_address, options, locs, passwords, out=""
5
+ log_loc, timestamp = set_log_loc_and_timestamp(locs)
6
+
7
+ puts "Generating log file for #{ name } (#{ ip_address }) at #{ log_loc }/#{ name }-deploy-#{ timestamp }.txt"
8
+
9
+ capture_args = [ "chef-client" ]
10
+ capture_args << [ '-l', 'debug' ] if options['debug']
11
+ #capture_args << [ '>', '/dev/tty']
12
+
13
+ out << sudo_capture( passwords[ip_address], *capture_args.flatten )
14
+
15
+ ::File.open("#{ log_loc }/#{ name }-deploy-#{ timestamp }.txt", "w") { |f| f.write(out.scrub_pretty_text) } unless options['no_logs']
16
+
17
+ puts(out) if options['output'] || options['verbose']
18
+
19
+ puts "Succeeded deploy of #{ name } (#{ ip_address }) on role #{ options['role'] }"
20
+
21
+ [out, timestamp] #return out to send to logs_bag
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,91 @@
1
+ module SSHKit
2
+ module Backend
3
+ class Netssh
4
+ def start_log_role_map name, ip_address, target_log_loc, options, locs, cheftacular, passwords, out=""
5
+ log_loc, timestamp = set_log_loc_and_timestamp(locs)
6
+ log_cmnd, log_lines = get_log_command_and_lines(options)
7
+
8
+ if !test("[ -e #{ target_log_loc }]") #true if file exists
9
+ puts "#{ name } (#{ ip_address }) does not have a log file for #{ options['env'] } at the moment..."
10
+
11
+ else
12
+ puts "Fetching log file(s) for #{ name } (#{ ip_address }). Outputting to #{ log_loc }/#{ name }-#{ options['role'] }-log-#{ timestamp }.txt"
13
+
14
+ target_log_loc.split(',').each do |parsed_log_loc|
15
+ parsed_log_loc = parsed_log_loc.gsub('|current_repo_location|', "#{ cheftacular['base_file_path'] }/#{ options['repository'] }/current")
16
+ if log_lines.nil?
17
+ out << sudo_capture(passwords[ip_address], log_cmnd.to_sym, parsed_log_loc)
18
+
19
+ else
20
+ out << sudo_capture(passwords[ip_address], log_cmnd.to_sym, log_lines, parsed_log_loc)
21
+ end
22
+ end
23
+
24
+ ::File.open("#{ log_loc }/#{ name }-#{ options['role'] }-log-#{ timestamp }.txt", "w") { |f| f.write(out.scrub_pretty_text) } unless options['no_logs']
25
+ end
26
+ end
27
+
28
+ def start_log_fetch_ruby_on_rails name, ip_address, run_list, options, locs, cheftacular, passwords, out=""
29
+ log_loc, timestamp = set_log_loc_and_timestamp(locs)
30
+ true_env = get_true_environment run_list, cheftacular['run_list_environments'], options['env']
31
+ app_log_loc = "#{ cheftacular['base_file_path'] }/#{ options['repository'] }/current/log"
32
+ log_cmnd, log_lines = get_log_command_and_lines(options)
33
+
34
+ if !test("[ -e /#{ app_log_loc }/#{ true_env }.log ]") #true if file exists
35
+ puts "#{ name } (#{ ip_address }) does not have a log file for #{ true_env } at the moment..."
36
+
37
+ else
38
+
39
+ puts "Fetching log file(s) for #{ name } (#{ ip_address }). Outputting to #{ log_loc }/#{ name }-applog-#{ timestamp }.txt"
40
+
41
+ within app_log_loc do
42
+ if log_lines.nil?
43
+ out << capture(log_cmnd.to_sym, "#{ true_env }.log")
44
+
45
+ else
46
+ out << capture(log_cmnd.to_sym, log_lines, "#{ true_env }.log")
47
+ end
48
+ end
49
+
50
+ #To create the file locally you must namespace like this
51
+ ::File.open("#{ log_loc }/#{ name }-applog-#{ timestamp }.txt", "w") { |f| f.write(out.scrub_pretty_text) } unless options['no_logs']
52
+ end
53
+
54
+ out << start_log_fetch_nginx(name, log_loc, log_cmnd, timestamp, options, out) if run_list.include?('role[web]') && options['get_nginx_logs']
55
+
56
+ out << start_log_role_map(name, ip_address, get_role_map(cheftacular, get_worker_role(cheftacular))['log_location'], log_cmnd, app_log_loc, timestamp, options) if run_list.include?("role[#{ get_worker_role(cheftacular) }]")
57
+
58
+ puts(out) if options['verbose']
59
+ end
60
+
61
+ def start_log_fetch_nginx name, log_loc, log_cmnd, timestamp, options, out=""
62
+ out = "" unless options['no_logs']
63
+
64
+ nginx_log_loc = "/var/log/nginx/#{ options['repository'] }_access.log"
65
+
66
+ puts "Fetching nginx log file... Outputting to #{ log_loc }/#{ name }-nginxlog-#{ timestamp }.txt "
67
+
68
+ if log_lines.nil?
69
+ out << capture(log_cmnd.to_sym, nginx_log_loc)
70
+
71
+ else
72
+ out << capture(log_cmnd.to_sym, log_lines, nginx_log_loc)
73
+ end
74
+
75
+ ::File.open("#{ log_loc }/#{ name }-nginxlog-#{ timestamp }.txt", "w") { |f| f.write(out.scrub_pretty_text) } unless options['no_logs']
76
+
77
+ out
78
+ end
79
+
80
+ private
81
+
82
+ def get_log_command_and_lines options
83
+ log_cmnd = options['get_full_logs'] ? 'cat' : 'tail'
84
+
85
+ log_lines = options['get_full_logs'] ? nil : "-" + ( options['get_log_lines'] ? options['get_log_lines'] : "500" )
86
+
87
+ [log_cmnd, log_lines]
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,29 @@
1
+ module SSHKit
2
+ module Backend
3
+ class Netssh
4
+ def start_task name, ip_address, run_list, command, options, locs, cheftacular, out=""
5
+ log_loc, timestamp = set_log_loc_and_timestamp(locs)
6
+ true_env = get_true_environment cheftacular['run_list_environments'], run_list, options['env']
7
+
8
+ puts "Running #{ command } for #{ name } (#{ ip_address }) (Run with with --debug to generate a log as well)"
9
+
10
+ mig_loc = "/var/www/vhosts/#{ options['repository'] }/current"
11
+
12
+ capture_args = ["RAILS_ENV=#{ true_env }"]
13
+ capture_args << command.split(' ')
14
+
15
+ within mig_loc do
16
+ out << capture( *capture_args.flatten )
17
+ end
18
+
19
+ ::File.open("#{ log_loc }/#{ name }-task-#{ timestamp }.txt", "w") {|f| f.write(out.scrub_pretty_text) } if options['debug']
20
+
21
+ puts out
22
+
23
+ puts("Nothing to migrate for #{ options['role'] }...") if out.empty? || out == 'config/local.yml file detected. Its environment variables will be merged on top of those from config/application.yml.'
24
+
25
+ [out, timestamp] #return out to send to logs_bag
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,67 @@
1
+ module SSHKit
2
+ module Backend
3
+ class Netssh
4
+ def get_repository_from_role_name name, repositories, *args
5
+ args = args.flatten
6
+
7
+ repo_role_name = ""
8
+
9
+ repositories.each_pair { |key, repo_hash| repo_role_name = key if repo_hash['repo_name'] == name }
10
+
11
+ if repositories.has_key?(name) && args.empty?
12
+ return repositories[name]['repo_name']
13
+ elsif !repo_role_name.empty? && args.empty?
14
+ return repo_role_name
15
+ end
16
+
17
+ if args.include?('has_key?')
18
+ return repositories.has_key?(name)
19
+ elsif args.include?('has_value?')
20
+ return !repo_role_name.empty?
21
+ end
22
+
23
+ raise "Unknown repository or rolename for #{ name }"
24
+ end
25
+
26
+ def get_node_from_address nodes, address, ret_node = nil
27
+ nodes.each do |n|
28
+ if n.public_ipaddress == address
29
+ ret_node = n
30
+
31
+ break
32
+ end
33
+ end
34
+
35
+ ret_node
36
+ end
37
+
38
+ def get_true_environment run_list, chef_env_roles, default_env
39
+ chef_env_roles.each_pair do |role, env|
40
+ if run_list.include?("role[#{ role }]")
41
+ default_env = env
42
+
43
+ break
44
+ end
45
+ end
46
+
47
+ default_env
48
+ end
49
+
50
+ def get_worker_role cheftacular, ret=""
51
+ cheftacular['role_maps'].each_pair do |main_role, role_hash|
52
+ ret = role_hash['role_name'] if main_role.include?('worker')
53
+ end
54
+
55
+ ret
56
+ end
57
+
58
+ def get_role_map cheftacular, target_role, ret=""
59
+ cheftacular['role_maps'].each_pair do |main_role, role_hash|
60
+ ret = role_hash if role_hash['role_name'] == target_role
61
+ end
62
+
63
+ ret
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,13 @@
1
+ module SSHKit
2
+ module Backend
3
+ class Netssh
4
+ def set_log_loc_and_timestamp locs
5
+ [locs['chef-log'], Time.now.strftime("%Y%m%d%H%M%S")]
6
+ end
7
+
8
+ def sudo_capture pass, *args
9
+ capture :echo, pass, :|, :sudo, '-S', *args
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ module SSHKit
2
+ class Command
3
+ #returns the full contents of stdout when an error occurs rather than just the first line (needed for chef debugging)
4
+ def exit_status=(new_exit_status)
5
+ @finished_at = Time.now
6
+ @exit_status = new_exit_status
7
+
8
+ if options[:raise_on_non_zero_exit] && exit_status > 0
9
+ message = ""
10
+ message += "#{command} exit status: " + exit_status.to_s + "\n"
11
+ message += "#{command} stdout: " + (full_stdout.strip || "Nothing written") + "\n"
12
+
13
+ stderr_message = [stderr.strip, full_stderr.strip].delete_if(&:empty?).first
14
+ message += "#{command} stderr: " + (full_stderr.strip || 'Nothing written') + "\n\n"
15
+ raise Failed, message
16
+ end
17
+ end
18
+ end
19
+ end