Class: Cheftacular::Action
- Inherits:
-
Object
- Object
- Cheftacular::Action
- Defined in:
- lib/cheftacular/action.rb,
lib/cheftacular/actions/log.rb,
lib/cheftacular/actions/run.rb,
lib/cheftacular/actions/tail.rb,
lib/cheftacular/actions/check.rb,
lib/cheftacular/actions/scale.rb,
lib/cheftacular/actions/deploy.rb,
lib/cheftacular/actions/console.rb,
lib/cheftacular/actions/migrate.rb,
lib/cheftacular/actions/db_console.rb
Instance Method Summary collapse
- #check(commit_hash = {}, have_revisions = false, have_changed_orgs = false) ⇒ Object
- #console ⇒ Object
- #console_all ⇒ Object
- #console_nodejs ⇒ Object
- #console_ruby_on_rails ⇒ Object
- #console_wordpress ⇒ Object
- #db_console ⇒ Object
- #db_console_ ⇒ Object
- #db_console_mongodb ⇒ Object (also: #mongo)
- #db_console_mysql ⇒ Object
- #db_console_none ⇒ Object
- #db_console_postgresql ⇒ Object (also: #psql)
- #deploy ⇒ Object
-
#initialize(options, config) ⇒ Action
constructor
A new instance of Action.
- #log ⇒ Object
- #migrate(nodes = []) ⇒ Object
- #migrate_(nodes = []) ⇒ Object
- #migrate_all(nodes = []) ⇒ Object
- #migrate_nodejs(nodes = []) ⇒ Object
- #migrate_ruby_on_rails(nodes = []) ⇒ Object
- #migrate_wordpress(nodes = []) ⇒ Object
- #run ⇒ Object
- #run_ ⇒ Object
- #run_all ⇒ Object
- #run_nodejs ⇒ Object
- #run_ruby_on_rails ⇒ Object
- #run_wordpress ⇒ Object
- #scale(type = "up", num_to_scale = 1) ⇒ Object
- #tail(pattern_to_match = '') ⇒ Object
Constructor Details
#initialize(options, config) ⇒ Action
Returns a new instance of Action.
10 11 12 |
# File 'lib/cheftacular/action.rb', line 10 def initialize , config , @config = , config end |
Instance Method Details
#check(commit_hash = {}, have_revisions = false, have_changed_orgs = false) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/cheftacular/actions/check.rb', line 18 def check commit_hash={}, have_revisions=false, have_changed_orgs=false @config['filesystem'].cleanup_file_caches('current-nodes') nodes = @config['getter'].get_true_node_objects #this must always precede on () calls so they have the instance variables they need , locs, ridley, logs_bag_hash, pass_bag_hash, bundle_command, cheftacular, passwords = @config['helper'].set_local_instance_vars on ( nodes.map { |n| @config['cheftacular']['deploy_user'] + "@" + n.public_ipaddress } ), in: :parallel do |host| n = get_node_from_address(nodes, host.hostname) puts("Beginning commit check run for #{ n.name } (#{ n.public_ipaddress }) on role #{ options['role'] }") unless ['quiet'] commit_hash[n.name] = start_commit_check( n.name, n.public_ipaddress, , locs, cheftacular) if n.normal_attributes.has_key?(['repository']) commit_hash[n.name]['branch'] = n.normal_attributes[['repository']]['repo_branch'] if n.normal_attributes[['repository']].has_key?('repo_branch') commit_hash[n.name]['organization'] = n.normal_attributes[['repository']]['repo_group'] if n.normal_attributes[['repository']].has_key?('repo_group') end have_revisions = true if commit_hash[n.name].has_key?('branch') have_changed_orgs = true if commit_hash[n.name].has_key?('organization') end puts "\n#{ 'name'.ljust(21) }#{ 'deployed_on'.ljust(22) } #{ 'commit'.ljust(40) } #{'revision'.ljust(29) if have_revisions } #{'organization'.ljust(30) if have_changed_orgs }" nodes.each do |n| unless commit_hash[n.name]['name'].blank? out = [] out << n.name.ljust(20, '_') out << commit_hash[n.name]['time'].ljust(21) out << commit_hash[n.name]['name'].ljust(39) out << commit_hash[n.name]['branch'].ljust(29) if commit_hash[n.name].has_key?('branch') out << commit_hash[n.name]['organization'].ljust(30) if commit_hash[n.name].has_key?('organization') puts out.join(' ') end end end |
#console ⇒ Object
17 18 19 |
# File 'lib/cheftacular/actions/console.rb', line 17 def console self.send("console_#{ @config['getter'].get_current_stack }") end |
#console_all ⇒ Object
42 43 44 |
# File 'lib/cheftacular/actions/console.rb', line 42 def console_all raise "You attempted to create a console for the all role, this is not possible." end |
#console_nodejs ⇒ Object
34 35 36 |
# File 'lib/cheftacular/actions/console.rb', line 34 def console_nodejs raise "Not yet implemented" end |
#console_ruby_on_rails ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/cheftacular/actions/console.rb', line 21 def console_ruby_on_rails nodes = @config['getter'].get_true_node_objects #must have rails stack to run migrations and not be a db, only want ONE node nodes = @config['parser'].exclude_nodes( nodes, [{ unless: "role[#{ @options['role'] }]" }, { unless: 'role[rails]' }], true ) nodes.each do |n| puts("Beginning console run for #{ n.name } (#{ n.public_ipaddress }) on role #{ @options['role'] }") unless ['quiet'] start_console_ruby_on_rails(n.public_ipaddress, n.run_list) end end |
#console_wordpress ⇒ Object
38 39 40 |
# File 'lib/cheftacular/actions/console.rb', line 38 def console_wordpress raise "Not yet implemented" end |
#db_console ⇒ Object
21 22 23 |
# File 'lib/cheftacular/actions/db_console.rb', line 21 def db_console self.send("db_console_#{ @config['getter'].get_current_database }") end |
#db_console_ ⇒ Object
63 64 65 66 67 |
# File 'lib/cheftacular/actions/db_console.rb', line 63 def db_console_ puts "db_console method tried to create a db_console for the role \"#{ @options['role'] }\" but it doesn't appear to have a repository set! Skipping..." return false end |
#db_console_mongodb ⇒ Object Also known as: mongo
42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/cheftacular/actions/db_console.rb', line 42 def db_console_mongodb nodes = @config['getter'].get_true_node_objects(true) #must have mongo db, only want ONE node mongoable_nodes = @config['parser'].exclude_nodes( nodes, [{ unless: "role[#{ @options['role'] }]" }, { if: { not_env: ['env'] } }], true ) mongoable_nodes.each do |n| puts("Beginning database console run for #{ n.name } (#{ n.public_ipaddress }) on role #{ @options['role'] }") unless ['quiet'] start_console_mongodb(n.public_ipaddress) end end |
#db_console_mysql ⇒ Object
55 56 57 |
# File 'lib/cheftacular/actions/db_console.rb', line 55 def db_console_mysql raise "Not yet implemented" end |
#db_console_none ⇒ Object
59 60 61 |
# File 'lib/cheftacular/actions/db_console.rb', line 59 def db_console_none raise "You attempted to create a database console for a role that had no database type attached to it, this is not possible." end |
#db_console_postgresql ⇒ Object Also known as: psql
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/cheftacular/actions/db_console.rb', line 25 def db_console_postgresql nodes = @config['getter'].get_true_node_objects(true) #must have rails stack to run migrations and not be a db, only want ONE node psqlable_nodes = @config['parser'].exclude_nodes( nodes, [{ unless: "role[#{ @options['role'] }]" }, { unless: 'role[rails]' }, { if: { not_env: ['env'] } }], true ) database_host = @config['parser'].exclude_nodes( nodes, [{ unless: "role[#{ @config['getter'].get_current_repo_config['db_primary_host_role'] }]"}, { if: { not_env: ['env'] } }], true).first private_database_host_address = @config['getter'].get_address_hash(database_host.name)[database_host.name]['priv'] psqlable_nodes.each do |n| puts("Beginning database console run for #{ n.name } (#{ n.public_ipaddress }) on role #{ @options['role'] }") unless ['quiet'] start_console_postgresql(n.public_ipaddress, private_database_host_address ) end end |
#deploy ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/cheftacular/actions/deploy.rb', line 29 def deploy nodes = @config['getter'].get_true_node_objects false, true #when this is run in scaling we'll need to make sure we deploy to new nodes nodes = @config['parser'].exclude_nodes( nodes, [{ if: "role[#{ @options['negative_role'] }]" }]) if ['negative_role'] #this must always precede on () calls so they have the instance variables they need , locs, ridley, logs_bag_hash, pass_bag_hash, bundle_command, cheftacular, passwords = @config['helper'].set_local_instance_vars #on is namespaced to SSHKit::Backend::Netssh.on on ( nodes.map { |n| @config['cheftacular']['deploy_user'] + "@" + n.public_ipaddress } ), in: :groups, limit: 10, wait: 5 do |host| n = get_node_from_address(nodes, host.hostname) puts("Beginning chef client run for #{ n.name } (#{ n.public_ipaddress }) on role #{ options['role'] }") unless ['quiet'] log_data, , exit_status = start_deploy( n.name, n.public_ipaddress, , locs, passwords) logs_bag_hash["#{ n.name }-#{ __method__ }"] = { "text" => log_data.scrub_pretty_text, "timestamp" => , "exit_status" => exit_status } end @config['helper'].send_log_bag_hash_slack_notification(logs_bag_hash, __method__) @config['ChefDataBag'].save_logs_bag unless ['debug'] #We don't really need to store entire chef runs in the logs bag migrate(nodes) if @config['getter'].get_current_repo_config['database'] != 'none' && !['run_migration_already'] split_nodes_hash = {} if @config['cheftacular']['run_list_environments'].has_key?(['env']) @config['cheftacular']['run_list_environments'][['env']].each_key do |role_name| split_nodes_hash[role_name] = @config['parser'].exclude_nodes( nodes, [{ unless: "role[#{ role_name }]" }]) end split_nodes_hash.each_pair do |role, split_nodes| next if split_nodes.empty? unless ["run_#{ role }_migrations_already"] ["run_#{ role }_migrations_already"] = true if @config['getter'].get_current_repo_config['database'] != 'none' puts("Running migration on split environment #{ role }...") if !['quiet'] migrate(split_nodes) end end end end end |
#log ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/cheftacular/actions/log.rb', line 27 def log nodes = @config['getter'].get_true_node_objects nodes = @config['parser'].exclude_nodes( nodes, [{ unless: "role[#{ @options['role'] }]" }] ) nodes = @config['parser'].exclude_nodes( nodes, [{ if: "role[#{ @options['negative_role'] }]" }]) if ['negative_role'] #this must always precede on () calls so they have the instance variables they need , locs, ridley, logs_bag_hash, pass_bag_hash, bundle_command, cheftacular, passwords = @config['helper'].set_local_instance_vars getter = @config['getter'] on ( nodes.map { |n| @config['cheftacular']['deploy_user'] + "@" + n.public_ipaddress } ), in: :parallel do |host| n = get_node_from_address(nodes, host.hostname) puts("Beginning log fetch run for #{ n.name } (#{ n.public_ipaddress }) on role #{ options['role'] }") unless ['quiet'] if has_run_list_in_role_map?(n.run_list, cheftacular['role_maps']) start_log_role_map( n.name, n.public_ipaddress, getter.get_current_role_map(n.run_list)['log_location'], , locs, cheftacular, passwords) else self.send("start_log_fetch_#{ getter.get_current_stack }", n.name, n.public_ipaddress, n.run_list, , locs, cheftacular, passwords) end end end |
#migrate(nodes = []) ⇒ Object
19 20 21 |
# File 'lib/cheftacular/actions/migrate.rb', line 19 def migrate nodes=[] self.send("migrate_#{ @config['getter'].get_current_stack }", nodes) end |
#migrate_(nodes = []) ⇒ Object
70 71 72 73 74 |
# File 'lib/cheftacular/actions/migrate.rb', line 70 def migrate_ nodes=[] puts "Migrate method tried to migrate the role \"#{ @options['role'] }\" but it doesn't appear to have a repository set! Skipping..." return false end |
#migrate_all(nodes = []) ⇒ Object
66 67 68 |
# File 'lib/cheftacular/actions/migrate.rb', line 66 def migrate_all nodes=[] raise "You attempted to migrate the all role, this is not possible." end |
#migrate_nodejs(nodes = []) ⇒ Object
60 61 62 63 64 |
# File 'lib/cheftacular/actions/migrate.rb', line 60 def migrate_nodejs nodes=[] puts "Method #{ __method__ } is not yet implemented" exit end |
#migrate_ruby_on_rails(nodes = []) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/cheftacular/actions/migrate.rb', line 23 def migrate_ruby_on_rails nodes=[] nodes = @config['getter'].get_true_node_objects if nodes.empty? #must have rails stack to run migrations, only want ONE node nodes = @config['parser'].exclude_nodes(nodes, [{ unless: "role[#{ @options['role'] }]" }, { unless: 'role[rails]' }], true) log_data = "" #this must always precede on () calls so they have the instance variables they need , locs, ridley, logs_bag_hash, pass_bag_hash, bundle_command, cheftacular, passwords = @config['helper'].set_local_instance_vars on ( nodes.map { |n| @config['cheftacular']['deploy_user'] + "@" + n.public_ipaddress } ) do |host| n = get_node_from_address(nodes, host.hostname) puts("Beginning migration run for #{ n.name } (#{ n.public_ipaddress }) on role #{ options['role'] }") unless ['quiet'] log_data, , exit_status = start_task( n.name, n.public_ipaddress, n.run_list, "#{ bundle_command } exec rake db:migrate", , locs, cheftacular) logs_bag_hash["#{ n.name }-#{ __method__ }"] = { "text" => log_data.scrub_pretty_text, "timestamp" => , "exit_status" => exit_status } end @config['ChefDataBag'].save_logs_bag @config['helper'].send_log_bag_hash_slack_notification(logs_bag_hash, __method__, 'Failing migration detected, please fix this and deploy again, exiting...') ['run_migration_already'] = true #restart the servers again after a deploy with a migration just in case deploy if !log_data.empty? && log_data != @config['cheftacular']['repositories'][['role']]['not_a_migration_message'] end |
#migrate_wordpress(nodes = []) ⇒ Object
54 55 56 57 58 |
# File 'lib/cheftacular/actions/migrate.rb', line 54 def migrate_wordpress nodes=[] puts "Method #{ __method__ } is not yet implemented" exit end |
#run ⇒ Object
28 29 30 |
# File 'lib/cheftacular/actions/run.rb', line 28 def run self.send("run_#{ @config['getter'].get_current_stack }") end |
#run_ ⇒ Object
71 72 73 74 75 |
# File 'lib/cheftacular/actions/run.rb', line 71 def run_ puts "Run method tried to run a command for the role \"#{ @options['role'] }\" but it doesn't appear to have a repository set! Skipping..." return false end |
#run_all ⇒ Object
67 68 69 |
# File 'lib/cheftacular/actions/run.rb', line 67 def run_all raise "You attempted to run a command for the all role, this is not possible." end |
#run_nodejs ⇒ Object
59 60 61 |
# File 'lib/cheftacular/actions/run.rb', line 59 def run_nodejs raise "Not yet implemented" end |
#run_ruby_on_rails ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/cheftacular/actions/run.rb', line 32 def run_ruby_on_rails nodes = @config['getter'].get_true_node_objects command = @config['parser'].parse_runtime_arguments 0, 'range' #must have rails stack to run migrations and not be a db, only want ONE node nodes = @config['parser'].exclude_nodes( nodes, [{ unless: "role[#{ @options['role'] }]" }], !['run_on_all'] ) nodes = @config['parser'].exclude_nodes( nodes, [{ if: "role[#{ @options['negative_role'] }]" }]) if ['negative_role'] #this must always precede on () calls so they have the instance variables they need , locs, ridley, logs_bag_hash, pass_bag_hash, bundle_command, cheftacular, passwords = @config['helper'].set_local_instance_vars on ( nodes.map { |n| @config['cheftacular']['deploy_user'] + "@" + n.public_ipaddress } ) do |host| n = get_node_from_address(nodes, host.hostname) puts("Beginning task run for #{ n.name } (#{ n.public_ipaddress }) on role #{ options['role'] }") unless ['quiet'] log_data, , exit_status = start_task( n.name, n.public_ipaddress, n.run_list, "#{ bundle_command } exec #{ command }", , locs, cheftacular) logs_bag_hash["#{ n.name }-#{ __method__ }"] = { "text" => log_data.scrub_pretty_text, "timestamp" => , "exit_status" => exit_status } end @config['ChefDataBag'].save_logs_bag @config['helper'].send_log_bag_hash_slack_notification(logs_bag_hash, __method__, 'Failing command detected, exiting...') end |
#run_wordpress ⇒ Object
63 64 65 |
# File 'lib/cheftacular/actions/run.rb', line 63 def run_wordpress raise "Not yet implemented" end |
#scale(type = "up", num_to_scale = 1) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/cheftacular/actions/scale.rb', line 23 def scale type="up", num_to_scale=1 type = ARGV[1] if ARGV[1] num_to_scale = ARGV[2] if ARGV[2] raise "Unknown type for scaling: #{ type }" unless (type =~ /up|down/) == 0 raise "Unknown scaling: #{ num_to_scale }" unless num_to_scale.is_a?(Fixnum) && num_to_scale >= 1 nodes = @config['getter'].get_true_node_objects base_node_names = {} nodes = @config['parser'].exclude_nodes( nodes, [{ unless: 'role[scalable]' }] ) nodes.each do |n| #names are stored alphabetically so this will always put the result hash in the form of {base_name => highest N} base_node_names[n.name.gsub(/\d/,'')] ||= {} base_node_names[n.name.gsub(/\d/,'')][n.name] = n.name.gsub(/[^\d]/,'') if base_node_names[n.name.gsub(/\d/,'')][n.name] > base_node_names[n.name.gsub(/\d/,'')]['highest_val'] || base_node_names[n.name.gsub(/\d/,'')]['highest_val'].nil? base_node_names[n.name.gsub(/\d/,'')]['highest_val'] = n.name.gsub(/[^\d]/,'').to_i end end base_node_names.each_pair do |base_name, nodes_under_name_hash| raise "Cannot scale lower than 1" if (nodes_under_name_hash.keys-1).count <= num_to_scale && type == 'down' end if base_node_names.empty? puts("There are no nodes for #{ @options['role'] } in env #{ @options['env'] } that have scaling enabled.") unless ['quiet'] end ['force_yes'] = true ['in_scaling'] = true scaling_node_defaults = @config['cheftacular']['scaling_nodes'] (1..num_to_scale).each do |i| case type when 'up' base_node_names.each_pair do |base_name, nodes_under_name_hash| ['node_name'] = base_name + ( node_under_name_hash['highest_val'] + i ).to_s.rjust(2, '0') if scaling_node_defaults.has_key?(base_name) ['flavor_name'] = scaling_node_defaults[base_name].has_key?('flavor') ? scaling_node_defaults[base_name]['flavor'] : @config['cheftacular']['default_flavor_name'] ['descriptor'] = scaling_node_defaults[base_name].has_key?('descriptor') ? scaling_node_defaults[base_name]['descriptor'] : ['node_name'] else ['flavor_name'] = @config['cheftacular']['default_flavor_name'] ['descriptor'] = ['node_name'] end puts("Preparing to scale #{ type } server #{ @options['node_name'] } on role #{ @options['role'] }!") unless ['quiet'] @config['stateless_action'].cloud_bootstrap end when 'down' base_node_names.each_pair do |base_name, nodes_under_name_hash| ['node_name'] = base_name + ( node_under_name_hash['highest_val'] + i ).to_s.rjust(2, '0') puts("Preparing to scale #{ type } server #{ @options['node_name'] } on role #{ @options['role'] }!") unless ['quiet'] remove_client true end end sleep 15 if num_to_scale > 1 end @config['ChefDataBag'].save_server_passwords_bag #we must save the auth bag here and not in the individual rax_bootstrap runs so they don't corrupt the bags ['node_name'] = nil #if this is not nil deploy_role will try to deploy to a single server instead of the group @config['action'].deploy end |
#tail(pattern_to_match = '') ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/cheftacular/actions/tail.rb', line 25 def tail pattern_to_match='' pattern_to_match = ARGV[1] if pattern_to_match.blank? nodes = @config['getter'].get_true_node_objects nodes = @config['parser'].exclude_nodes( nodes, [{ unless: "role[#{ @options['role'] }]" }], true ) nodes = @config['parser'].exclude_nodes( nodes, [{ if: "role[#{ @options['negative_role'] }]" }], true) if ['negative_role'] nodes.each do |n| puts("Beginning tail run for #{ n.name } (#{ n.public_ipaddress }) on role #{ @options['role'] }") unless ['quiet'] if @config['dummy_sshkit'].has_run_list_in_role_map?(n.run_list, @config['cheftacular']['role_maps']) start_tail_role_map( n.public_ipaddress, n.run_list, pattern_to_match ) else self.send("start_tail_#{ @config['getter'].get_current_stack }", n.public_ipaddress, n.run_list, pattern_to_match ) end end end |