Class: Cheftacular::StatelessAction
- Inherits:
-
Object
- Object
- Cheftacular::StatelessAction
- Includes:
- RbConfig
- Defined in:
- lib/cheftacular/stateless_action.rb,
lib/cheftacular/stateless_actions/rvm.rb,
lib/cheftacular/stateless_actions/file.rb,
lib/cheftacular/stateless_actions/help.rb,
lib/cheftacular/stateless_actions/pass.rb,
lib/cheftacular/stateless_actions/cloud.rb,
lib/cheftacular/stateless_actions/slack.rb,
lib/cheftacular/stateless_actions/backups.rb,
lib/cheftacular/stateless_actions/service.rb,
lib/cheftacular/stateless_actions/test_env.rb,
lib/cheftacular/stateless_actions/arguments.rb,
lib/cheftacular/stateless_actions/reset_bag.rb,
lib/cheftacular/stateless_actions/update_tld.rb,
lib/cheftacular/stateless_actions/chef_server.rb,
lib/cheftacular/stateless_actions/client_list.rb,
lib/cheftacular/stateless_actions/disk_report.rb,
lib/cheftacular/stateless_actions/environment.rb,
lib/cheftacular/stateless_actions/get_pg_pass.rb,
lib/cheftacular/stateless_actions/role_toggle.rb,
lib/cheftacular/stateless_actions/clear_caches.rb,
lib/cheftacular/stateless_actions/knife_upload.rb,
lib/cheftacular/stateless_actions/reinitialize.rb,
lib/cheftacular/stateless_actions/restart_swap.rb,
lib/cheftacular/stateless_actions/upload_nodes.rb,
lib/cheftacular/stateless_actions/upload_roles.rb,
lib/cheftacular/stateless_actions/remove_client.rb,
lib/cheftacular/stateless_actions/server_update.rb,
lib/cheftacular/stateless_actions/chef_bootstrap.rb,
lib/cheftacular/stateless_actions/compile_readme.rb,
lib/cheftacular/stateless_actions/create_git_key.rb,
lib/cheftacular/stateless_actions/full_bootstrap.rb,
lib/cheftacular/stateless_actions/clean_cookbooks.rb,
lib/cheftacular/stateless_actions/cloud_bootstrap.rb,
lib/cheftacular/stateless_actions/fix_known_hosts.rb,
lib/cheftacular/stateless_actions/get_haproxy_log.rb,
lib/cheftacular/stateless_actions/get_log_from_bag.rb,
lib/cheftacular/stateless_actions/location_aliases.rb,
lib/cheftacular/stateless_actions/cleanup_log_files.rb,
lib/cheftacular/stateless_actions/compile_audit_log.rb,
lib/cheftacular/stateless_actions/add_ssh_key_to_bag.rb,
lib/cheftacular/stateless_actions/cheftacular_config.rb,
lib/cheftacular/stateless_actions/replication_status.rb,
lib/cheftacular/stateless_actions/update_chef_client.rb,
lib/cheftacular/stateless_actions/cheftacular_yml_help.rb,
lib/cheftacular/stateless_actions/list_toggleable_roles.rb,
lib/cheftacular/stateless_actions/update_split_branches.rb,
lib/cheftacular/stateless_actions/clean_server_passwords.rb,
lib/cheftacular/stateless_actions/check_cheftacular_yml_keys.rb,
lib/cheftacular/stateless_actions/get_active_ssh_connections.rb,
lib/cheftacular/stateless_actions/initialize_cheftacular_yml.rb,
lib/cheftacular/stateless_actions/initialize_data_bag_contents.rb,
lib/cheftacular/stateless_actions/update_thecheftacularcookbook.rb,
lib/cheftacular/stateless_actions/bootstrappers/centos_bootstrap.rb,
lib/cheftacular/stateless_actions/bootstrappers/coreos_bootstrap.rb,
lib/cheftacular/stateless_actions/bootstrappers/fedora_bootstrap.rb,
lib/cheftacular/stateless_actions/bootstrappers/redhat_bootstrap.rb,
lib/cheftacular/stateless_actions/bootstrappers/ubuntu_bootstrap.rb,
lib/cheftacular/stateless_actions/bootstrappers/vyatta_bootstrap.rb,
lib/cheftacular/stateless_actions/update_cloudflare_dns_from_cloud.rb,
lib/cheftacular/stateless_actions/get_shorewall_allowed_connections.rb
Instance Method Summary collapse
-
#add_ssh_key_to_bag(specific_repository = "") ⇒ Object
TODO key for environment specific deploys?.
- #arguments ⇒ Object
- #backups(command = '') ⇒ Object
- #check_cheftacular_yml_keys(out = [], exit_on_missing = false, warn_on_missing = false) ⇒ Object
- #chef_bootstrap(out = []) ⇒ Object
- #chef_server ⇒ Object
- #cheftacular_config(command = '') ⇒ Object
- #cheftacular_yml_help(command = '') ⇒ Object (also: #yaml_help)
- #clean_cookbooks(local_options = {'interactive' => true}) ⇒ Object
- #clean_server_passwords ⇒ Object
- #cleanup_log_files ⇒ Object
- #clear_caches ⇒ Object
- #client_list ⇒ Object
- #cloud(*args) ⇒ Object (also: #aws, #rax)
- #cloud_bootstrap ⇒ Object
- #compile_audit_log(out = []) ⇒ Object
- #compile_readme(out = []) ⇒ Object
- #coreos_bootstrap(out = []) ⇒ Object
- #create_git_key(oauth_key = "") ⇒ Object
- #disk_report(disk_hash = {}, out = []) ⇒ Object
- #environment(type = "boot", ask_on_destroy = false, remove = true) ⇒ Object
- #fedora_bootstrap(out = []) ⇒ Object
- #file(location = '', file_name = '', mode = '') ⇒ Object
- #fix_known_hosts ⇒ Object
- #full_bootstrap ⇒ Object
- #get_active_ssh_connections ⇒ Object
- #get_haproxy_log ⇒ Object
- #get_log_from_bag ⇒ Object
- #get_pg_pass(clip = false, target_repos = []) ⇒ Object
- #get_shorewall_allowed_connections(master_log_data = '') ⇒ Object
- #help(inference_modes = []) ⇒ Object
-
#initialize(options, config) ⇒ StatelessAction
constructor
A new instance of StatelessAction.
- #initialize_cheftacular_yml(example_file_to_load = 'cheftacular.yml') ⇒ Object
- #initialize_data_bag_contents(env = "") ⇒ Object
- #knife_upload ⇒ Object
- #list_toggleable_roles(possible_toggles = []) ⇒ Object
- #location_aliases ⇒ Object
- #pass ⇒ Object
- #redhat_bootstrap(out = []) ⇒ Object
- #reinitialize(out = []) ⇒ Object
- #remove_client(delete_server = false, remove = true) ⇒ Object (also: #remove_node)
- #replication_status(rep_status_hash = {}, out = []) ⇒ Object
- #reset_bag(bag_name = '', bag_env = '') ⇒ Object
- #restart_swap ⇒ Object
- #role_toggle(state_toggle = '', target_run_list = [], skip_confirm = false) ⇒ Object
- #rvm(command = '') ⇒ Object
-
#server_update ⇒ Object
TODO refactor to handling multiple server types.
- #service ⇒ Object
- #slack(message = '', channel = '') ⇒ Object
- #test_env(split_env = "splitstaging", type = "boot") ⇒ Object
- #ubuntu_bootstrap(out = []) ⇒ Object
- #update_chef_client ⇒ Object
- #update_cloudflare_dns_from_cloud ⇒ Object
- #update_split_branches ⇒ Object
- #update_thecheftacularcookbook(local_options = {'interactive' => true}) ⇒ Object
- #update_tld(target_tld = "") ⇒ Object
- #upload_nodes(invalidate_file_node_cache = false) ⇒ Object
- #upload_roles ⇒ Object
- #vyatta_bootstrap(out = []) ⇒ Object
Constructor Details
#initialize(options, config) ⇒ StatelessAction
Returns a new instance of StatelessAction.
12 13 14 |
# File 'lib/cheftacular/stateless_action.rb', line 12 def initialize , config @options, @config = , config end |
Instance Method Details
#add_ssh_key_to_bag(specific_repository = "") ⇒ Object
TODO key for environment specific deploys?
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/cheftacular/stateless_actions/add_ssh_key_to_bag.rb', line 23 def add_ssh_key_to_bag specific_repository="" raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') raise "Please put quotes around your SSH public key!" if ARGV[1].length < 25 #TODO REFACTOR to accurate length of shortest key specific_repository = ARGV[2] if ARGV[2] && specific_repository.empty? if !specific_repository.empty? && @config['getter'].get_repo_names_for_repositories.include?(specific_repository) puts "The repository passed (#{ specific_repository }) is not listed in the cheftacular.yml repositories hash! Please update the hash or check your spelling!" return false end public_ssh_key = ARGV[1] if specific_repository.blank? @config['default']['authentication_bag_hash']["authorized_keys"] << public_ssh_key.gsub("'",'') else @config['default']['authentication_bag_hash']["specific_authorized_keys"] << public_ssh_key.gsub("'",'') end @config['ChefDataBag'].save_authentication_bag end |
#arguments ⇒ Object
70 71 72 73 74 |
# File 'lib/cheftacular/stateless_actions/arguments.rb', line 70 def arguments @config['stateless_action_documentation'].arguments puts @config['documentation']['arguments'] end |
#backups(command = '') ⇒ Object
30 31 32 33 34 35 36 |
# File 'lib/cheftacular/stateless_actions/backups.rb', line 30 def backups command='' command = ARGV[1] if command.blank? raise "Unsupported command (#{ command }) for cft backups" unless command =~ /activate|deactivate|load|restore/ self.send("backups_#{ command }") end |
#check_cheftacular_yml_keys(out = [], exit_on_missing = false, warn_on_missing = false) ⇒ Object
16 17 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 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 96 97 98 99 100 |
# File 'lib/cheftacular/stateless_actions/check_cheftacular_yml_keys.rb', line 16 def check_cheftacular_yml_keys out=[], exit_on_missing=false, warn_on_missing=false = "Your cheftacular.yml is missing the key KEY, its default value is being set to DEFAULT for this run." #############################2.9.0################################################ unless @config['cheftacular']['slack'].has_key?('notify_on_deployment_args') #backup_config:global_backup_role_name .gsub('KEY', 'notify_on_deployment_args').gsub('DEFAULT', 'false') @config['cheftacular']['slack']['notify_on_deployment_args'] = false warn_on_missing = true end #############################2.7.0################################################ unless @config['cheftacular'].has_key?('backup_config') #backup_config:global_backup_role_name .gsub('KEY', 'backup_config').gsub('DEFAULT', 'nil') warn_on_missing = true end #############################2.6.0################################################ unless @config['cheftacular'].has_key?('route_dns_changes_via') puts .gsub('KEY', 'route_dns_changes_via').gsub('DEFAULT', @options['preferred_cloud']) @config['cheftacular']['route_dns_changes_via'] = @options['preferred_cloud'] warn_on_missing = true end unless @config['cheftacular'].has_key?('node_name_separator') puts .gsub('KEY', 'node_name_separator').gsub('DEFAULT', '-') @config['cheftacular']['node_name_separator'] = '-' warn_on_missing = true end unless @config['cheftacular'].has_key?('cloud_authentication') puts (.gsub('KEY', 'cloud_authentication').split(',').first + ', this is a critical issue and must be fixed.') exit_on_missing = true end if !@config['cheftacular'].has_key?('chef_server') && @options['command'] == 'chef_server' puts (.gsub('KEY', 'chef_server').split(',').first + ', this is a critical issue and must be fixed to run the chef_server command.') exit_on_missing = true end unless @config['cheftacular'].has_key?('chef_version') puts (.gsub('KEY', 'chef_version').split(',').first + ', this is a critical issue and must be fixed.') exit_on_missing = true end unless @config['cheftacular'].has_key?('pre_install_packages') puts .gsub('KEY', 'pre_install_packages').gsub('DEFAULT', '') @config['cheftacular']['pre_install_packages'] = '' warn_on_missing = true end unless @config['cheftacular'].has_key?('role_toggling') puts .gsub('KEY', 'role_toggling').gsub('DEFAULT', "it's default nested keys") @config['cheftacular']['role_toggling'] = {} @config['cheftacular']['role_toggling']['deactivated_role_suffix'] = '_deactivated' @config['cheftacular']['role_toggling']['strict_roles'] = true @config['cheftacular']['role_toggling']['skip_confirm'] = false @config['cheftacular']['role_toggling']['do_not_allow_toggling'] = true warn_on_missing = true end if warn_on_missing || exit_on_missing puts "Please enter your missing keys into your cheftacular.yml based off of the cheftacular.yml at" puts "\n https://github.com/SocialCentivPublic/cheftacular/blob/master/examples/cheftacular.yml" end exit if exit_on_missing || @options['command'] == __method__ end |
#chef_bootstrap(out = []) ⇒ Object
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 56 57 58 59 60 61 |
# File 'lib/cheftacular/stateless_actions/chef_bootstrap.rb', line 20 def chef_bootstrap out=[] raise "This action can only be performed if the mode is set to devops" if !@config['helper'].running_in_mode?('devops') && !@options['in_scaling'] @options['address'] = ARGV[1] unless @options['address'] @options['node_name'] = ARGV[2] unless @options['node_name'] #@config['stateless_action'].remove_client #just in case if @config['cheftacular']['chef_version'].to_i >= 12 puts("Starting chef-client installation...") unless @options['quiet'] commands = [ "curl -L https://www.opscode.com/chef/install.sh > ~/chef-install.sh", "#{ @config['helper'].sudo(@options['address']) } bash /home/deploy/chef-install.sh", "rm ~/chef-install.sh" ] commands.each do |command| out << `ssh -t -oStrictHostKeyChecking=no #{ @config['cheftacular']['deploy_user'] }@#{ @options['address'] } "#{ command }"` puts(out.last) unless @options['quiet'] || @options['in_scaling'] end end puts("Starting chef bootstrap...") unless @options['quiet'] out << `#{ @config['helper'].knife_bootstrap_command }` puts(out.last) unless @options['quiet'] || @options['in_scaling'] puts("Sending up data_bag_key file...") unless @options['quiet'] out << `scp -oStrictHostKeyChecking=no #{ @config['locs']['chef'] }/#{ @config['cheftacular']['data_bag_key_file'] } #{ @config['cheftacular']['deploy_user'] }@#{ @options['address'] }:/home/#{ @config['cheftacular']['deploy_user'] }` puts("Moving key file to chef directory on server...") unless @options['quiet'] out << `ssh -t -oStrictHostKeyChecking=no #{ @config['cheftacular']['deploy_user'] }@#{ @options['address'] } "#{ @config['helper'].sudo(@options['address']) } mv -f /home/#{ @config['cheftacular']['deploy_user'] }/#{ @config['cheftacular']['data_bag_key_file'] } /etc/chef"` @options['force_yes'] = true # have the upload_nodes grab the new nodes @config['stateless_action'].upload_nodes(true) end |
#chef_server ⇒ Object
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 |
# File 'lib/cheftacular/stateless_actions/chef_server.rb', line 37 def chef_server raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') if @config['cheftacular']['chef_server'].nil? || !@config['cheftacular']['chef_server']['interactable'] raise "Chef server is not currently set to be interactable with the chef-server command" end command = ARGV[1] raise "Unsupported command (#{ command }) for cft chef_server" unless command =~ /restart|processes|memory/ command_prefix = case @config['cheftacular']['chef_server']['ssh_user'] when 'root' then '' else "echo #{ @config['cheftacular']['chef_server']['sudo_pass'] } | sudo -S " end command = case command when 'restart' then command_prefix + 'chef-server-ctl restart' when 'processes' then 'ps aux' when 'memory' then 'free -m' end = @options on ( @config['cheftacular']['chef_server']['ssh_user'] + "@" + @config['parser'].parse_base_chef_server_url ) do |host| puts "Beginning chef-server #{ command } run" start_chef_server_interactor(command, ) end end |
#cheftacular_config(command = '') ⇒ Object
27 28 29 30 31 32 33 |
# File 'lib/cheftacular/stateless_actions/cheftacular_config.rb', line 27 def cheftacular_config command='' command = ARGV[1] if command.blank? raise "Unsupported command (#{ command }) for cft cheftacular_config" unless command =~ /display|sync|overwrite/ self.send("cheftacular_config_#{ command }") end |
#cheftacular_yml_help(command = '') ⇒ Object Also known as: yaml_help
22 23 24 25 |
# File 'lib/cheftacular/stateless_actions/cheftacular_yml_help.rb', line 22 def cheftacular_yml_help command='' raise "Not Yet Implemented" end |
#clean_cookbooks(local_options = {'interactive' => true}) ⇒ Object
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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/cheftacular/stateless_actions/clean_cookbooks.rb', line 22 def clean_cookbooks ={'interactive' => true} raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') ARGV.each do |arg| case arg when "force" then ['interactive'] = false end end @config['cheftacular']['wrapper_cookbooks'].split(',').each do |wrapper_cookbook| wrapper_cookbook_loc = "#{ @config['locs']['cookbooks'] }/#{ wrapper_cookbook }" FileUtils.rm(File.("#{ wrapper_cookbook_loc }/Berksfile.lock")) if File.exists?(File.("#{ wrapper_cookbook_loc }/Berksfile.lock")) FileUtils.rm_rf(File.("#{ @config['locs']['berks'] }/cookbooks")) if File.exists?(File.("#{ @config['locs']['berks'] }/cookbooks")) Dir.chdir wrapper_cookbook_loc puts "Installing new cookbooks..." out = `berks install` puts "#{out}\nFinished... Beginning directory scanning and conflict resolution..." berkshelf_cookbooks = @config['filesystem'].parse_latest_berkshelf_cookbook_versions chef_repo_cookbooks = @config['filesystem'].parse_chef_repo_cookbook_versions berkshelf_cookbooks.each_pair do |berkshelf_cookbook, version| new_name = berkshelf_cookbook.rpartition('-').first if chef_repo_cookbooks.has_key?(new_name) || chef_repo_cookbooks.has_key?(berkshelf_cookbook) #don't overwrite cookbooks without user input if ['interactive'] puts "COOKBOOK::~~~~#{ new_name }~~~~::VERSION::~~~~~~~~#{ version } VS #{ chef_repo_cookbooks[new_name] }" puts "\nEnter O | o | overwrite to overwrite ~~~~#{ new_name }~~~~ in the chef-repo (THIS SHOULD NOT BE DONE LIGHTLY)" puts "Enter N | n | no to skip to the next conflict" puts "If you pass force to this script, it will always overwrite." #puts "If you pass a STRING of comma delimited cookbooks, it will skip these cookbooks automatically and overwrite others" #puts "Example: ruby ./executables/clean-cookbooks 'application_ruby,wordpress'" puts "Input:" input = STDIN.gets.chomp next if (input =~ /N|n|no/) == 0 end next if @config['helper'].is_higher_version?(chef_repo_cookbooks[new_name], version) end cmnd = "#{ @config['locs']['berks'] }/#{ berkshelf_cookbook } #{ @config['locs']['cookbooks'] }/#{ new_name }" puts "Moving #{ cmnd } (#{ version }:#{ chef_repo_cookbooks[new_name] })" if @options['verbose'] `rm -Rf #{ @config['locs']['cookbooks'] }/#{ new_name }` `cp -Rf #{ cmnd }` end end end |
#clean_server_passwords ⇒ Object
10 11 12 13 14 |
# File 'lib/cheftacular/stateless_actions/clean_server_passwords.rb', line 10 def clean_server_passwords #TODO clean up non-existent entries in all envs server_password bags raise "This method is not yet implemented" raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') end |
#cleanup_log_files ⇒ Object
10 11 12 13 |
# File 'lib/cheftacular/stateless_actions/cleanup_log_files.rb', line 10 def cleanup_log_files #TODO raise "This method is not yet implemented" end |
#clear_caches ⇒ Object
27 28 29 |
# File 'lib/cheftacular/stateless_actions/clear_caches.rb', line 27 def clear_caches @config['filesystem'].cleanup_file_caches('all') end |
#client_list ⇒ Object
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 |
# File 'lib/cheftacular/stateless_actions/client_list.rb', line 28 def client_list @config['filesystem'].cleanup_file_caches('current-nodes') nodes = @config['getter'].get_true_node_objects(true) @config['chef_environments'].each do |env| @config['initializer'].initialize_data_bags_for_environment env, false, ['addresses', 'server_passwords'] end environments = nodes.map { |n| n.chef_environment } environments.uniq.each do |env| next if env == '_default' env_nodes = @config['parser'].exclude_nodes(nodes, [{ if: { not_env: env } }]) puts "\nFound #{ env_nodes.count } #{ env } nodes:" out = " #{ 'name'.ljust(22) } #{ 'ip_address'.ljust(21) }" out << "#{ 'private_address'.ljust(21) }" if @options['with_private'] out << "#{ 'pass?'.ljust(5) } #{ 'domain'.ljust(41) }" if @options['verbose'] out << "#{ 'deploy_password'.ljust(21) }" if @options['verbose'] out << "run_list" puts out auth_hash = @config[env]['server_passwords_bag_hash'] addresses_hash = @config['getter'].get_addresses_hash env env_nodes.each do |node| #client = @ridley.client.find(options['node_name']) out = " #{ node.chef_id.ljust(22,'_') }_#{ node.public_ipaddress.ljust(20,'_') }" if @options['with_private'] if addresses_hash.has_key?(node.public_ipaddress) out << addresses_hash[node.public_ipaddress]['address'].ljust(20,'_') else out << ''.ljust(20,'_') end end if @options['verbose'] out << "_" + auth_hash.has_key?("#{ node.public_ipaddress }-deploy-pass").to_s.ljust(5,'_') + "_" if addresses_hash.has_key?(node.public_ipaddress) out << addresses_hash[node.public_ipaddress]['dn'].ljust(40,'_') else out << ''.ljust(40,'_') end if auth_hash.has_key?("#{ node.public_ipaddress }-deploy-pass") out << "_" + auth_hash["#{ node.public_ipaddress }-deploy-pass"] else out << "_" + ''.ljust(@config['cheftacular']['server_password_length'],'_') end end out << "_#{ node.run_list.join(', ') }" puts out end end end |
#cloud(*args) ⇒ Object Also known as: aws, rax
124 125 126 127 128 129 130 131 132 |
# File 'lib/cheftacular/stateless_actions/cloud.rb', line 124 def cloud *args raise "This action can only be performed if the mode is set to devops" if !@config['helper'].running_in_mode?('devops') && !@options['in_scaling'] args = ARGV[1..ARGV.length] if args.empty? @config['cloud_interactor'] ||= CloudInteractor.new(@config['cheftacular'], @options) @config['cloud_interactor'].run args end |
#cloud_bootstrap ⇒ Object
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 |
# File 'lib/cheftacular/stateless_actions/cloud_bootstrap.rb', line 31 def cloud_bootstrap raise "This action can only be performed if the mode is set to devops" if !@config['helper'].running_in_mode?('devops') && !@options['in_scaling'] @options['node_name'] = ARGV[1] unless @options['node_name'] @options['flavor_name'] = ARGV[2] unless @options['flavor_name'] @options['descriptor'] = ARGV[3] if ARGV[3] && !@options['descriptor'] if `which sshpass`.empty? 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)" end real_node_name = @config['getter'].get_current_real_node_name #the output of the cloud command is a hash, this hash is UPDATED every time a rax command is run so you only need to grab it when you need it @config['stateless_action'].cloud "server", "create:#{ real_node_name }:#{ @options['flavor_name'] }" status_hash = @config['stateless_action'].cloud "server", "poll:#{ real_node_name }" status_hash['created_servers'].each do |server_hash| next unless server_hash['name'] == "#{ real_node_name }" @options['address'], @options['private_address'] = @config['cloud_provider'].parse_addresses_from_server_create_hash server_hash end @options['client_pass'] = @config['cloud_provider'].parse_server_root_password_from_server_create_hash status_hash, real_node_name tld = @config[@options['env']]['config_bag_hash'][@options['sub_env']]['tld'] target_serv_index = @config[@options['env']]['addresses_bag_hash']['addresses'].count compile_args = ['set_all_attributes'] compile_args << "set_specific_domain:#{ @options['with_dn'] }" if @options['with_dn'] address_hash = @config['DNS'].(*compile_args) @config['DNS'].create_dns_record_for_domain_from_address_hash(@options['with_dn'], address_hash, "specific_domain_mode") if @options['with_dn'] @config['DNS'].create_dns_record_for_domain_from_address_hash(tld, address_hash) @config['ChefDataBag'].save_addresses_bag @options['dont_remove_address_or_server'] = true #flag to make sure our entry isnt removed in addresses bag @config['stateless_action'].full_bootstrap #bootstrap server with ruby and attach it to the chef server end |
#compile_audit_log(out = []) ⇒ Object
16 17 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 56 57 58 59 60 |
# File 'lib/cheftacular/stateless_actions/compile_audit_log.rb', line 16 def compile_audit_log out=[] compiled_audit_hash = {} @config['chef_environments'].each do |env| @config['initializer'].initialize_data_bags_for_environment env, false, ['audit'] @config['initializer'].initialize_audit_bag_contents env @config[env]['audit_bag_hash']['audit_log'].each_pair do |day, time_log_hash| compiled_audit_hash[day] ||= {} time_log_hash.each_pair do |time, log_array| compiled_audit_hash[day][time] ||= [] compiled_audit_hash[day][time] << log_array end end end compiled_audit_hash.keys.sort.each do |day| out << "# Audit Log Entries for #{ Date.parse(day) }" entry_count, int_times = 1, [] compiled_audit_hash[day].keys.sort.each do |time| out << "#{ entry_count }. #{ time }" log_array_entry_count = 1 compiled_audit_hash[day][time].each do |log_arr| log_arr.each do |log_hash| out << " #{ log_array_entry_count }. #{ log_hash['command'] }" out << " 1. Hostname: #{ log_hash['hostname'] }" out << " 3. Arguments: #{ log_hash['arguments'] }" out << " 4. Options: #{ log_hash['options'].to_hash }" out << "" log_array_entry_count += 1 end end if compiled_audit_hash[day].has_key?(time) entry_count += 1 end end File.open("#{ @config['locs']['chef-log'] }/audit-log-#{ Time.now.strftime("%Y%m%d%H%M%S") }.md", "w") { |f| f.write(out.join("\n")) } end |
#compile_readme(out = []) ⇒ Object
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 |
# File 'lib/cheftacular/stateless_actions/compile_readme.rb', line 20 def compile_readme out=[] @config['action_documentation'].public_methods(false).each do |method| @config['action_documentation'].send(method) end @config['stateless_action_documentation'].public_methods(false).each do |method| @config['stateless_action_documentation'].send(method) end out << '# Table of Contents for Cheftacular Commands' out << '1. [Cheftacular Arguments and Flags](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#arguments-and-flags-for-cheftacular)' out << '2. [Application Commands](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#commands-that-can-be-run-in-the-application-context)' 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" out << @config['documentation']['arguments'] out << "\n## Commands that can be run in the application context" out << @config['helper'].compile_documentation_lines('application') out << "\n## Commands that can ONLY be run in the devops context" out << @config['helper'].compile_documentation_lines('stateless_action') FileUtils.rm("#{ @config['locs']['chef-log'] }/README.md") if File.exist?("#{ @config['locs']['chef-log'] }/README.md") File.open("#{ @config['locs']['chef-log'] }/README.md", "w") { |f| f.write(out.flatten.join("\n\n")) } end |
#coreos_bootstrap(out = []) ⇒ Object
3 4 5 |
# File 'lib/cheftacular/stateless_actions/bootstrappers/coreos_bootstrap.rb', line 3 def coreos_bootstrap out=[] raise "Not yet implemented!" end |
#create_git_key(oauth_key = "") ⇒ Object
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 |
# File 'lib/cheftacular/stateless_actions/create_git_key.rb', line 24 def create_git_key oauth_key="" raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') case ARGV[1] when nil then raise "Too few arguments, please enter the filename of the id_rsa file you want to use" when 'id_rsa' then raise "Sorry, you can't use your default id_rsa" else key_file = ARGV[1] end case ARGV[2] when nil then display_oauth_notice = true else oauth_key = ARGV[2] end data = File.read("#{ @config['locs']['chef'] }/#{ key_file }") data_pub = File.read("#{ @config['locs']['chef'] }/#{ key_file }.pub") hash = @config['default']['authentication_bag_hash'] if hash.has_key?('private_key') puts "Overwrite current git key in default data bag? (Y/y/N/n)" input = STDIN.gets.chomp overwrite = (input =~ /Y|y|yes/) == 0 else overwrite = true end if overwrite hash['git_private_key'] = data hash['git_public_key'] = data_pub hash['git_OAuth'] = oauth_key @config['ChefDataBag'].save_authentication_bag if oauth_key.blank? puts "REMEMBER! You need to put a OAuth token into this data bag item!" puts "You need to go to github and get the auth_token for the hiplogiq deploy user!" puts "Copy the key and paste it inbetween the quotes.\n" puts "\"Oauth\": \"<PASTE YOUR OAUTH KEY HERE>\"\n\n" puts "Please run \nknife data bag edit default authentication --secret-file #{ @config['locs']['chef'] }/#{ @config['cheftacular']['data_bag_key_file'] }\n" end end end |
#disk_report(disk_hash = {}, out = []) ⇒ Object
16 17 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 56 57 58 59 |
# File 'lib/cheftacular/stateless_actions/disk_report.rb', line 16 def disk_report disk_hash={}, out=[] nodes = @config['getter'].get_true_node_objects(true) nodes = @config['parser'].exclude_nodes( nodes, [{ if: { env: '_default' }}] ) @config['chef_environments'].each do |env| @config['initializer'].initialize_data_bags_for_environment env, false, ['addresses', 'server_passwords'] @config['initializer'].initialize_passwords env end , 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: :groups, limit: 5, wait: 2 do |host| n = get_node_from_address(nodes, host.hostname) puts "Beginning disk report run for #{ n.name } (#{ n.public_ipaddress })" disk_hash[n.name] = start_disk_report( n.name, n.public_ipaddress, , locs, passwords) end disk_hash.each_pair do |serv_name, output| out << "#{ serv_name }:" line_count = 1 output.join("\n").split("\n").each do |line| out << line_count == 1 ? " #{ line }" : " #{ line }" line_count += 1 end out << "\n" end puts(out) if @options['no_logs'] || @options['verbose'] log_loc, = @config['helper']. puts("Generating log file for disk report at #{ log_loc }/disk-report-#{ }.txt") unless @options['quiet'] File.open("#{ log_loc }/disk-report-#{ }.txt", "w") { |f| f.write(out.join("\n").scrub_pretty_text) } unless @options['no_logs'] end |
#environment(type = "boot", ask_on_destroy = false, remove = true) ⇒ Object
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 96 97 98 99 100 101 102 103 104 |
# File 'lib/cheftacular/stateless_actions/environment.rb', line 26 def environment type="boot", ask_on_destroy=false, remove=true ask_on_destroy = case @options['env'] when 'staging' then true when 'production' then true else false end type = ARGV[1] if ARGV[1] raise "Unknown type: #{ type }, can only be 'boot' or 'destroy'" unless (type =~ /boot|destroy/) == 0 nodes = @config['getter'].get_true_node_objects(true) nodes = @config['parser'].exclude_nodes( nodes, [{ unless: { env: @options['env'] }}]) @options['force_yes'] = true @options['in_scaling'] = true initial_servers = @config['cheftacular']['env_boot_nodes']["#{ @options['env'] }_nodes"] if initial_servers.empty? puts "There are no servers defined for #{ @options['env'] } in the env_boot_nodes hash in your cheftacular.yml... Exiting" exit end case type when 'boot' initial_servers.each_pair do |name, config_hash| next if nodes.map { |n| n.name }.include?(name) config_hash ||= {} @options['node_name'] = name @options['flavor_name'] = config_hash.has_key?('flavor') ? config_hash['flavor'] : @config['cheftacular']['default_flavor_name'] @options['descriptor'] = config_hash.has_key?('descriptor') ? config_hash['descriptor'] : name @options['with_dn'] = config_hash.has_key?('dns_config') ? @config['parser'].parse_to_dns(config_hash['dns_config']) : @config['parser'].parse_to_dns('NODE_NAME.ENV_TLD') puts("Preparing to boot server #{ @options['node_name'] } for #{ @options['env'] }!") unless @options['quiet'] @config['stateless_action'].cloud_bootstrap sleep 15 end @config['ChefDataBag'].save_server_passwords_bag @options['node_name'] = nil @options['role'] = 'all' @config['action'].deploy #TODO INTEGRATE backups TO LOAD DATA INTO THE NEWLY BOOTED ENV when 'destroy' raise "This action can only be performed if the mode is set to devops" if !@config['helper'].running_in_mode?('devops') if ask_on_destroy puts "Preparing to delete nodes in #{ @options['env'] }.\nEnter Y/y to confirm." input = STDIN.gets.chomp remove = false unless ( input =~ /y|Y|yes|Yes/ ) == 0 end return false unless remove @options['delete_server_on_remove'] = true nodes.each do |node| @options['node_name'] = node.name puts("Preparing to destroy server #{ @options['node_name'] } for #{ @options['env'] }!") unless @options['quiet'] @config['stateless_action'].remove_client sleep 15 end end end |
#fedora_bootstrap(out = []) ⇒ Object
3 4 5 |
# File 'lib/cheftacular/stateless_actions/bootstrappers/fedora_bootstrap.rb', line 3 def fedora_bootstrap out=[] raise "Not yet implemented!" end |
#file(location = '', file_name = '', mode = '') ⇒ Object
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 |
# File 'lib/cheftacular/stateless_actions/file.rb', line 52 def file location='', file_name='',mode='' @options['node_name'] = ARGV[1] unless @options['node_name'] location = ARGV[2] if location.blank? mode = ARGV[3] if mode.blank? file_name = ARGV[4] if file_name.blank? nodes = @config['error'].is_valid_node_name_option? mode = 'display' if mode.nil? mode = 'list' if file_name.nil? || file_name.blank? interaction_mode = case mode.split(':').first when 'cat' then 'sshkit' when 'display' then 'sshkit' when 'edit' then 'ssh' when /fetch|scp/ then 'scp' when 'list' then 'sshkit' when 'tail' then 'sshkit' when 'tail-f' then 'ssh' else raise "Unsupported Mode for cft file: #{ mode }, " end location = @config['parser'].parse_location_alias(location) command = @config['parser'].parse_mode_into_command(mode) nodes = @config['parser'].exclude_nodes( nodes, [{ unless: { env: @options['env'] }}], true ) case interaction_mode when 'sshkit' then file_sshkit_execute(nodes, command, location, file_name) when 'ssh' then file_ssh_execute(nodes, mode, command, location, file_name) when 'scp' then file_scp_execute(nodes, command, location, file_name) end end |
#fix_known_hosts ⇒ Object
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 56 57 58 59 60 61 62 |
# File 'lib/cheftacular/stateless_actions/fix_known_hosts.rb', line 22 def fix_known_hosts targets = ["all"] if ARGV[1].class == String targets = [ARGV[1]] end if targets.first == 'all' nodes = @config['getter'].get_true_node_objects(true) arr = [] @config['chef_environments'].each do |env| @config['initializer'].initialize_data_bags_for_environment env, false, ['addresses'] @config['initializer'].initialize_addresses_bag_contents env @config[env]['addresses_bag_hash']['addresses'].each do |serv_hash| arr << serv_hash['dn'] arr << serv_hash['public'] end end targets = arr.uniq end targets.each do |target| puts "clearing #{ target }" case CONFIG['host_os'] when /mswin|windows/i raise "#{ __method__ } does not support this operating system at this time" when /linux|arch/i puts "#{ __method__ } does not support this operating system at this time" when /sunos|solaris/i raise "#{ __method__ } does not support this operating system at this time" when /darwin/i cleanup_known_hosts_for_BSD_linux_architecture target else raise "#{ __method__ } does not support this operating system at this time" end end end |
#full_bootstrap ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/cheftacular/stateless_actions/full_bootstrap.rb', line 21 def full_bootstrap raise "This action can only be performed if the mode is set to devops" if !@config['helper'].running_in_mode?('devops') && !@options['in_scaling'] @options['address'] = ARGV[1] unless @options['address'] @options['client_pass'] = ARGV[2] unless @options['client_pass'] @options['node_name'] = ARGV[3] unless @options['node_name'] case @config['cheftacular']['preferred_cloud_os'] when 'ubuntu' || 'debian' then @config['stateless_action'].ubuntu_bootstrap else @config['stateless_action'].instance_eval("#{ @config['cheftacular']['preferred_cloud_os'] }_bootstrap") end @config['initializer'].initialize_passwords @options['env'] #reset the passwords var to contain the new deploy pass set in ubuntu_bootstrap @config['helper'].install_rvm_sh_file if @config['cheftacular']['install_rvm_on_boot'] @config['stateless_action'].chef_bootstrap end |
#get_active_ssh_connections ⇒ Object
14 15 16 17 |
# File 'lib/cheftacular/stateless_actions/get_active_ssh_connections.rb', line 14 def get_active_ssh_connections # netstat -atn | grep ':22' raise "Not yet implemented" end |
#get_haproxy_log ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/cheftacular/stateless_actions/get_haproxy_log.rb', line 22 def get_haproxy_log nodes = @config['getter'].get_true_node_objects true nodes = @config['parser'].exclude_nodes( nodes, [{ unless: "role[#{ @config['cheftacular']['haproxy_config']['role_name'] }]" }, { if: { not_env: @options['env'] } }]) #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 } ) do |host| n = get_node_from_address(nodes, host.hostname) puts("Beginning haproxy log generation run for #{ n.name } (#{ n.public_ipaddress })") unless ['quiet'] start_haproxy_log_generator( n.name, n.public_ipaddress, , locs, cheftacular, passwords) end end |
#get_log_from_bag ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/cheftacular/stateless_actions/get_log_from_bag.rb', line 18 def get_log_from_bag #TODO https://stackoverflow.com/questions/17882463/compressing-large-string-in-ruby log_loc, = @config['helper']. @options['role'] = 'all' unless @options['role'] nodes = @config['getter'].get_true_node_objects(true) nodes = @config['parser'].exclude_nodes( nodes, [{ unless: { env: @options['env'] }}]) nodes.each do |node| if @config[@options['env']]['logs_bag_hash'].has_key?("#{ node.name }-run") 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'] File.open("#{ log_loc }/stashedlog/#{ node.name }-deploystash-#{@config[@options['env']]['logs_bag_hash']["#{ node.name }-run"][:timestamp] }.txt", "w") do |f| f.write(@config[@options['env']]['logs_bag_hash']["#{ node.name }-run"][:text]) end puts(@config[@options['env']]['logs_bag_hash']["#{ node.name }-run"][:text]) if @options['verbose'] end end end |
#get_pg_pass(clip = false, target_repos = []) ⇒ 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 56 57 58 59 60 |
# File 'lib/cheftacular/stateless_actions/get_pg_pass.rb', line 18 def get_pg_pass clip=false, target_repos=[] @config['parser'].parse_role(@options['role']) clip = ARGV[1] == 'clip' if @options['role'] target_repos << @config['cheftacular']['repositories'][@options['role']] else @config['cheftacular']['repositories'].each_pair do |short_repo_name, repo_hash| target_repos << repo_hash if repo_hash['database'] == 'postgresql' end end target_repos.each do |repo_hash| db_user = repo_hash['application_database_user'] database = repo_hash.has_key?('custom_database_name') ? repo_hash['custom_database_name'] : repo_hash['repo_name'] password = @config[@options['env']]['chef_passwords_bag_hash']['pg_pass'] 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') 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? end puts "postgres password for user #{ db_user } in database #{ database }_#{ @options['env'] } is #{ password }" end if clip && target_repos.count == 1 case CONFIG['host_os'] when /mswin|windows/i raise "#{ __method__ } does not support this operating system at this time" when /linux|arch/i raise "#{ __method__ } does not support this operating system at this time" when /sunos|solaris/i raise "#{ __method__ } does not support this operating system at this time" when /darwin/i `echo '#{ password }' | pbcopy` else raise "#{ __method__ } does not support this operating system at this time" end elsif clip && target_repos.count > 1 puts "Unable to insert database string into clipboard, please copy paste as normal" end end |
#get_shorewall_allowed_connections(master_log_data = '') ⇒ Object
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 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 |
# File 'lib/cheftacular/stateless_actions/get_shorewall_allowed_connections.rb', line 21 def get_shorewall_allowed_connections master_log_data='' if ARGV[1].nil? raise "Please pass a NODE_NAME with -n NODE_NAME" if @options['node_name'].nil? || @options['node_name'].empty? nodes = @config['getter'].get_true_node_objects true nodes = @config['parser'].exclude_nodes(nodes, [{ unless: { env: @options['env'] }}, { unless: { node: @options['node_name'] }}], true) #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 } ) do |host| n = get_node_from_address(nodes, host.hostname) puts("Beginning shorewall log capture run for #{ n.name } (#{ n.public_ipaddress })") unless ['quiet'] master_log_data = start_shorewall_log_capture( n.name, n.public_ipaddress, , locs, cheftacular, passwords) end else master_log_file = ARGV[1] raise "File not found! Did you enter the path correctly?" unless File.exist?(master_log_file) master_log_data = File.read(File.(master_log_file)) end puts("Parsing addresses from log data...") unless @options['quiet'] addresses = {} master_log_data.scan(/^.*Shorewall:net2fw:ACCEPT.*SRC=([\d]+\.[\d]+\.[\d]+\.[\d]+) DST.*DPT=80.*$/).each do |ip_address| addresses[ip_address] ||= 0 addresses[ip_address] += 1 end final_addresses = {} check_count = 0 addresses.each_pair do |address, count| next if count < 100 domain = `dig +short -x #{ address[0] }`.chomp.split("\n").join('|') domain = domain[0..(domain.length-2)] domain = address[0] if domain.blank? final_addresses[domain] ||= {} final_addresses[domain]['addresses'] ||= [] final_addresses[domain]['addresses'] << address[0] unless final_addresses[domain]['addresses'].include?(address[0]) final_addresses[domain]['count'] = count unless final_addresses[domain].has_key?('count') final_addresses[domain]['count'] += count if final_addresses[domain].has_key?('count') check_count += 1 puts("Processed #{ check_count } addresses (#{ address[0] }):#{ domain }:#{ count }") unless @options['quiet'] end final_addresses = final_addresses.sort_by {|key, value_hash| value_hash['count']}.to_h final_addresses = Hash[final_addresses.to_a.reverse] ap(final_addresses) if @options['verbose'] log_loc, = @config['helper']. CSV.open(File.("#{ @config['locs']['chef-log'] }/shorewall-parse-#{ }.csv"), "wb") do |csv| final_addresses.each_pair do |dns, info_hash| csv << [dns, info_hash['addresses'].join('|'), info_hash['count']] end end end |
#help(inference_modes = []) ⇒ Object
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 |
# File 'lib/cheftacular/stateless_actions/help.rb', line 24 def help inference_modes=[] target_command = @options['command'] == 'help' ? ARGV[1] : ARGV[0] target_command = @config['cheftacular']['mode'] if target_command == 'current' target_command ||= '' case target_command when 'action' then inference_modes << 'action' when 'application' || 'devops' then inference_modes << 'both' when 'stateless_action' then inference_modes << 'stateless_action' when '' then inference_modes << 'short_context_descriptions' end if @config['helper'].is_command? target_command @config['action_documentation'].send(target_command) puts @config['documentation']['action'][target_command.to_sym]['long_description'].flatten.join("\n\n") elsif @config['helper'].is_stateless_command? target_command @config['stateless_action_documentation'].send(target_command) puts @config['documentation']['stateless_action'][target_command.to_sym]['long_description'].flatten.join("\n\n") end if inference_modes.include?('action') || inference_modes.include?('both') || inference_modes.include?('short_context_descriptions') @config['action_documentation'].public_methods(false).each do |method| @config['action_documentation'].send(method) end end if inference_modes.include?('action') || inference_modes.include?('both') || inference_modes.include?('short_context_descriptions') @config['stateless_action_documentation'].public_methods(false).each do |method| @config['stateless_action_documentation'].send(method) end end puts @config['documentation']['arguments'].flatten.join("\n\n") if target_command == 'arguments' if inference_modes.include?('short_context_descriptions') if @config['helper'].running_in_mode?('devops') puts @config['helper'].compile_short_context_descriptions(@config['documentation']['action'].merge(@config['documentation']['stateless_action']), 35) else puts @config['helper'].compile_short_context_descriptions(@config['documentation']['action'].merge(@config['documentation']['application'])) end end puts @config['helper'].compile_documentation_lines(target_command).flatten.join("\n\n") if target_command =~ /action|stateless_action|application|devops/ if inference_modes.empty? && @config['helper'].is_not_command_or_stateless_command?(target_command) methods = @config['action_documentation'].public_methods(false) + @config['stateless_action_documentation'].public_methods(false) sorted_methods = methods.uniq.sort_by { |method| @config['helper'].compare_strings(target_command, method.to_s)} puts "Unable to find documentation for #{ target_command }, did you mean:" puts " #{ sorted_methods.at(0) }" puts " #{ sorted_methods.at(1) }" puts " #{ sorted_methods.at(2) }\n" puts "If so, please run 'cft help COMMAND' with one of the above commands or run 'cft help #{ @config['cheftacular']['mode'] }' to see a list of commands" end end |
#initialize_cheftacular_yml(example_file_to_load = 'cheftacular.yml') ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/cheftacular/stateless_actions/initialize_cheftacular_yml.rb', line 29 def initialize_cheftacular_yml example_file_to_load='cheftacular.yml' example_file_to_load = 'thecheftacularcookbook.cheftacular.yml' if ARGV[1] == 'TheCheftacularCookbook' example_file_to_load = 'application.cheftacular.yml' if ARGV[1] == 'application' FileUtils.mkdir_p(File.join(@config['locs']['chef-repo'], "config")) if File.exist?(File.join(@config['locs']['chef-repo'], "config", "cheftacular.yml")) @config['helper'].write_config_cheftacular_yml_file('cheftacular.example.yml', example_file_to_load ) else @config['helper'].write_config_cheftacular_yml_file('cheftacular.yml', example_file_to_load) end end |
#initialize_data_bag_contents(env = "") ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/cheftacular/stateless_actions/initialize_data_bag_contents.rb', line 15 def initialize_data_bag_contents env="" raise "Environment #{ env } does not exist on chef server!" if !env.blank? && !@config['chef_environments'].include?(env) env = ARGV[1] if env.blank? @config['initializer'].initialize_audit_bag_contents env @config['initializer'].initialize_authentication_bag_contents @config['initializer'].initialize_chef_passwords_bag_contents env @config['initializer'].initialize_config_bag_contents env #@config['initializer'].initialize_server_passwords_bag_contents env @config['initializer'].initialize_addresses_bag_contents env #@config['initializer'].initialize_logs_bag_contents env #@config['ChefDataBag'].initialize_node_roles_bag_contents env @config['initializer'].initialize_environment_config_bag_contents if @config['helper'].running_in_mode?('devops') exit if @options['command'] == __method__ end |
#knife_upload ⇒ Object
16 17 18 19 20 21 22 23 24 |
# File 'lib/cheftacular/stateless_actions/knife_upload.rb', line 16 def knife_upload raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') puts("Starting upload...") unless @options['quiet'] out = `knife upload / --chef-repo-path #{ @config['locs']['chef-repo'] }` puts out end |
#list_toggleable_roles(possible_toggles = []) ⇒ Object
17 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 |
# File 'lib/cheftacular/stateless_actions/list_toggleable_roles.rb', line 17 def list_toggleable_roles possible_toggles=[] @options['node_name'] = ARGV[1] unless @options['node_name'] raise "You have yet to fully configure your role toggling settings! Exiting..." if @config['cheftacular']['role_toggling'].has_key?('do_not_allow_toggling') nodes = @config['error'].is_valid_node_name_option? suffix = @config['cheftacular']['role_toggling']['deactivated_role_suffix'] nodes.first.run_list.each do |role| role = role.gsub('role[','').gsub(']','') if !role.include?(suffix) && @config['parser'].parse_role("#{ role }#{ suffix }", 'boolean') possible_toggles << role possible_toggles << "#{ role }#{ suffix }" elsif role.include?(suffix) && @config['parser'].parse_role("#{ role.gsub(suffix,'') }", 'boolean') possible_toggles << role possible_toggles << role.gsub(suffix,'') end end puts "The current run_list for #{ @options['node_name'] } is:" ap nodes.first.run_list puts "\nThe possible toggles for #{ @options['node_name'] } are:" ap possible_toggles end |
#location_aliases ⇒ Object
23 24 25 |
# File 'lib/cheftacular/stateless_actions/location_aliases.rb', line 23 def location_aliases ap @config['cheftacular']['location_aliases'] end |
#pass ⇒ 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 |
# File 'lib/cheftacular/stateless_actions/pass.rb', line 18 def pass @options['node_name'] = ARGV[1] unless @options['node_name'] nodes = @config['error'].is_valid_node_name_option? if nodes.first.chef_environment != @options['env'] @config['initializer'].initialize_data_bags_for_environment nodes.first.chef_environment, false, ['server_passwords'] end puts "The password for #{ nodes.first.name }(#{ nodes.first.public_ipaddress }) for env #{ nodes.first.chef_environment }" + " is #{ @config[nodes.first.chef_environment]['server_passwords_bag_hash']["#{ nodes.first.public_ipaddress }-deploy-pass"] }" case CONFIG['host_os'] when /mswin|windows/i #raise "#{ __method__ } does not support this operating system at this time" when /linux|arch/i #raise "#{ __method__ } does not support this operating system at this time" when /sunos|solaris/i #raise "#{ __method__ } does not support this operating system at this time" when /darwin/i puts "Copying #{ nodes.first.name } (#{ nodes.first.public_ipaddress }) sudo password into your clipboard" `echo '#{ @config[nodes.first.chef_environment]['server_passwords_bag_hash']["#{ nodes.first.public_ipaddress }-deploy-pass"] }' | pbcopy` else #raise "#{ __method__ } does not support this operating system at this time" end end |
#redhat_bootstrap(out = []) ⇒ Object
3 4 5 |
# File 'lib/cheftacular/stateless_actions/bootstrappers/centos_bootstrap.rb', line 3 def redhat_bootstrap out=[] raise "Not yet implemented!" end |
#reinitialize(out = []) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/cheftacular/stateless_actions/reinitialize.rb', line 16 def reinitialize out=[] raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') @options['address'] = ARGV[1] unless @options['address'] @options['node_name'] = ARGV[2] unless @options['node_name'] puts("Sending up validator file...") unless @options['quiet'] chef_user = @config['cheftacular']['deploy_user'] out << `scp -oStrictHostKeyChecking=no #{ @config['locs']['chef'] }/chef-validator.pem #{ chef_user }@#{ @options['address'] }:/home/#{ chef_user }` puts("Moving validator file to chef directory on server...") unless @options['quiet'] out << `ssh -t -oStrictHostKeyChecking=no #{ chef_user }@#{ @options['address'] } "#{ sudo(@options['address']) } mv -f /home/#{ chef_user }/chef-validator.pem /etc/chef/validator.pem"` puts("Removing original client.pem file from server...") unless @options['quiet'] out << `ssh -t -oStrictHostKeyChecking=no #{ chef_user }@#{ @options['address'] } "#{ sudo(@options['address']) } rm /etc/chef/client.pem"` puts("Starting reinitialization...") unless @options['quiet'] out << `#{ @config['helper'].knife_bootstrap_command }` puts(out.last) unless @options['quiet'] end |
#remove_client(delete_server = false, remove = true) ⇒ Object Also known as: remove_node
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 |
# File 'lib/cheftacular/stateless_actions/remove_client.rb', line 24 def remove_client delete_server=false, remove=true @options['node_name'] = ARGV[1] unless @options['node_name'] @options['delete_server_on_remove'] = ARGV[2] if !@options['delete_server_on_remove'] && !@options['dont_remove_address_or_server'] && ARGV[2] @options['delete_server_on_remove'] = 'destroy' if delete_server || @options['delete_server_on_remove'] raise "This action can only be performed if the mode is set to devops" if !@config['helper'].running_in_mode?('devops') && !@options['in_scaling'] 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'] raise "Invalid arguments! Node name is blank. Please call this script as cft remove_client <node_name>" unless @options['node_name'] nodes = @config['getter'].get_true_node_objects(false, true) nodes.each do |n| begin client = @config['ridley'].client.find(@options['node_name']) rescue StandardError => e puts "Client #{ @options['node_name'] } not found." return false end if @options['env'] == 'production' && !@options['force_yes'] puts "Preparing to delete #{ @options['node_name'] } (#{ n.public_ipaddress }).\nEnter Y/y to confirm." input = STDIN.gets.chomp remove = false unless ( input =~ /y|Y|yes|Yes/ ) == 0 end if remove puts "Removing #{ n.name } (#{ n.public_ipaddress }) from node and client list" @config['ridley'].node.delete(n) @config['ridley'].client.delete(client) if @options['delete_server_on_remove'] == 'destroy' @config['stateless_action'].cloud "server", "destroy:#{ @config['getter'].get_current_real_node_name(n.name) }" end @config[@options['env']]['addresses_bag_hash'] = @config[@options['env']]['addresses_bag'].reload.to_hash @config['DNS'].('set_hash_to_nil') @config['ChefDataBag'].save_addresses_bag end end puts("Done. Please verify that the output of the next line(s) match your expectations (running client-list)") if @options['verbose'] puts(`client-list`) if @options['verbose'] end |
#replication_status(rep_status_hash = {}, out = []) ⇒ Object
16 17 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 56 57 58 59 60 61 62 63 64 |
# File 'lib/cheftacular/stateless_actions/replication_status.rb', line 16 def replication_status rep_status_hash={}, out=[] nodes = @config['getter'].get_true_node_objects(true) primary_nodes = @config['parser'].exclude_nodes( nodes, [{ if: { env: '_default' }}, { unless: "role[db_primary]"}] ) slave_nodes = @config['parser'].exclude_nodes( nodes, [{ if: { env: '_default' }}, { unless: "role[db_slave]"}] ) (primary_nodes + slave_nodes).map {|n| n.chef_environment}.uniq.each do |env| @config['initializer'].initialize_data_bags_for_environment env, false, ['server_passwords'] @config['initializer'].initialize_passwords env end #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 ( primary_nodes.map { |n| @config['cheftacular']['deploy_user'] + "@" + n.public_ipaddress } ) do |host| n = get_node_from_address(nodes, host.hostname) puts "Beginning replication status report run for #{ n.name } (#{ n.public_ipaddress })" env = n.name.split('_').first rep_status_hash[n.name] = start_replication_report( n.name, n.public_ipaddress, , locs, passwords) end on ( slave_nodes.map { |n| @config['cheftacular']['deploy_user'] + "@" + n.public_ipaddress } ) do |host| n = get_node_from_address(nodes, host.hostname) puts "Beginning slave replication status report run for #{ n.name } (#{ n.public_ipaddress })" env = n.name.split('_').first rep_status_hash[n.name] = start_slave_replication_report( n.name, n.public_ipaddress, , locs, passwords) end rep_status_hash.each_pair do |serv_name, output| out << "#{ serv_name }:" output.join("\n").split("\n").each do |line| out << " #{ line }\n" end out << "\n" end puts(out) end |
#reset_bag(bag_name = '', bag_env = '') ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/cheftacular/stateless_actions/reset_bag.rb', line 16 def reset_bag bag_name='', bag_env='' raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') bag_name = ARGV[1] if bag_name.blank? bag_env = @options['env'] if bag_env.blank? begin @config['ChefDataBag'].send("reset_#{ bag_name }_bag") puts "Successfully reset bag #{ bag_name }." rescue NoMethodError => e puts "You are not able to reset the bag \"#{ bag_name }\" via reset_bag, please use knife to edit the contents.\n #{ e }" end @config['stateless_action'].clear_caches end |
#restart_swap ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/cheftacular/stateless_actions/restart_swap.rb', line 20 def restart_swap nodes = @config['getter'].get_true_node_objects(true) nodes = @config['parser'].exclude_nodes( nodes, [{ if: { env: '_default' }}] ) #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: :groups, limit: 5, wait: 2 do |host| n = get_node_from_address(nodes, host.hostname) puts "Beginning swap restart run for #{ n.name } (#{ n.public_ipaddress })" start_swap_restart( n.name, n.public_ipaddress, , locs, cheftacular, passwords) end end |
#role_toggle(state_toggle = '', target_run_list = [], skip_confirm = false) ⇒ Object
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 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/cheftacular/stateless_actions/role_toggle.rb', line 39 def role_toggle state_toggle='', target_run_list=[], skip_confirm=false @options['node_name'] = ARGV[1] unless @options['node_name'] @config['parser'].parse_role(ARGV[2]) state_toggle = ARGV[3] if state_toggle.blank? raise "You have yet to fully configure your role toggling settings! Exiting..." if @config['cheftacular']['role_toggling'].has_key?('do_not_allow_toggling') raise "You may only enter activate or deactivate for the state toggle argument for the #{ __method__ } command." unless (state_toggle =~ /activate|deactivate/) == 0 @config['initializer'].initialize_data_bags_for_environment @options['env'], false, ['node_roles'] @config['initializer'].initialize_node_roles_bag_contents @options['env'] @config['filesystem'].cleanup_file_caches('current-nodes') nodes = @config['error'].is_valid_node_name_option? suffix = @config['cheftacular']['role_toggling']['deactivated_role_suffix'] if @options['role'].include?(suffix) unless @config['parser'].parse_role("#{ @options['role'].gsub(suffix,'') }", 'boolean') puts "Role #{ @options['role'] } does not have an activated role! There is no #{ @options['role'].gsub(suffix,'') } role!" return false end else unless @config['parser'].parse_role("#{ @options['role'] }#{ suffix }", 'boolean') puts "Role #{ @options['role'] } does not have a deactivated role! There is no #{ @options['role'] }#{ suffix } role!" return false end end current_node_roles = nodes.first.run_list if current_node_roles.include?("role[#{ @options['role'] }]") && !@options['role'].include?(suffix) if state_toggle == 'activate' puts "The role #{ @options['role'] } is already activated for #{ nodes.first.name }!" else puts "The role #{ @options['role'] } is currently activated, setting it to #{ @options['role'] }#{ suffix }" target_run_list = current_node_roles.map {|r| r.gsub(@options['role'], "#{ @options['role'] }#{ suffix }") if current_node_roles.include?("role[#{ @options['role'] }]") } end elsif current_node_roles.include?("role[#{ @options['role'] }]") && @options['role'].include?(suffix) if state_toggle == 'activate' puts "The role #{ @options['role'] } is currently deactivated, setting it to #{ @options['role'].gsub(suffix, '') }" target_run_list = current_node_roles.map {|r| r.gsub(@options['role'], "#{ @options['role'].gsub(suffix, '') }") if current_node_roles.include?("role[#{ @options['role'] }]") } else puts "The role #{ @options['role'] } is already deactivated for #{ nodes.first.name }!" end elsif current_node_roles.include?("role[#{ @options['role'] }#{ suffix }]") #they passed in the reverse of a role that was already deactivated if state_toggle == 'activate' puts "The role #{ @options['role'] } is currently deactivated, setting it to it's activated state" target_run_list = current_node_roles.map {|r| r.gsub("#{ @options['role'] }#{ suffix }", "#{ @options['role'] }") if current_node_roles.include?("role[#{ @options['role'] }#{ suffix }]") } else puts "The role #{ @options['role'] } is already deactivated for #{ nodes.first.name }!" end elsif current_node_roles.include?("role[#{ @options['role'].gsub(suffix, '') }]") #they passed in the reverse of a role that was already activated if state_toggle == 'activate' puts "The role #{ @options['role'] } is already activated for #{ nodes.first.name }!" else puts "The role #{ @options['role'] } is currently activated, setting it to it's deactivated state" target_run_list = current_node_roles.map {|r| r.gsub("#{ @options['role'].gsub('suffix','') }", "#{ @options['role'] }") if current_node_roles.include?("role[#{ @options['role'].gsub('suffix','') }]") } end elsif !current_node_roles.include?("role[#{ @options['role'] }]") && @config['cheftacular']['role_toggling']['strict_roles'] puts "The node does not have #{ @options['role'] } and strict roles is set to true, exiting..." return false elsif !current_node_roles.include?("role[#{ @options['role'] }]") && !@config['cheftacular']['role_toggling']['strict_roles'] puts "The node does not have #{ @options['role'] } and strict roles is set to false, setting this new role..." target_run_list = current_node_roles + "role[#{ @options['role'] }" end unless target_run_list.empty? puts "Updating node run list for #{ nodes.first.name } from" ap current_node_roles puts "to:" ap target_run_list if skip_confirm || !@config['cheftacular']['role_toggling']['skip_confirm'] puts "Enter Y/y to confirm." input = STDIN.gets.chomp return false unless ( input =~ /y|Y|yes|Yes/ ) == 0 end @config[@options['env']]['node_roles_bag_hash']['node_roles'][nodes.first.name.gsub(/\d/,'')]['run_list'] = target_run_list nodes.first.send("run_list=", target_run_list) nodes.first.save @config['ChefDataBag'].save_node_roles_bag @options['env'] @config['filesystem'].cleanup_file_caches('current-nodes') puts "Triggering deploy to set the new role..." @config['action'].deploy end end |
#rvm(command = '') ⇒ Object
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 |
# File 'lib/cheftacular/stateless_actions/rvm.rb', line 41 def rvm command='' raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') command = case ARGV[1] when nil then 'list' when /list|list_rubies/ then 'list rubies' when 'install' then "install #{ ARGV[2] }" when 'run' then ARGV[2..(ARGV.length-1)].join(' ') when 'all_environments' then ARGV[2..(ARGV.length-1)].join(' ') when 'test' then ARGV[2..(ARGV.length-1)].join(' ') when 'upgrade_rvm' then 'get stable --auto-dotfiles' else 'list' end if @config['cheftacular']['rvm_gpg_key'].nil? || @config['cheftacular']['rvm_gpg_key'].blank? raise "GPG Key not found in cheftacular.yml! Please update your rvm_gpg_key in the file!" end nodes = ARGV[1] == 'test' ? @config['getter'].get_true_node_objects : @config['getter'].get_true_node_objects(true) nodes = @config['parser'].exclude_nodes( nodes, [{ unless: { env: @options['env'] }}] ) unless ARGV[1] == 'all_servers' @config['chef_environments'].each do |env| @config['initializer'].initialize_data_bags_for_environment env, false, ['addresses', 'server_passwords'] @config['initializer'].initialize_passwords env end if ARGV[1] == 'all_servers' , 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: :groups, limit: 5, wait: 2 do |host| n = get_node_from_address(nodes, host.hostname) puts "Beginning run of \"rvm #{ command }\" for #{ n.name } (#{ n.public_ipaddress })" start_rvm( n.name, n.public_ipaddress, , locs, passwords, command, cheftacular ) end end |
#server_update ⇒ Object
TODO refactor to handling multiple server types
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 56 57 58 59 60 61 62 63 |
# File 'lib/cheftacular/stateless_actions/server_update.rb', line 22 def server_update raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') @options['rolling_restart'] = true if ARGV[1] && ARGV[1] == 'restart' if @options['rolling_restart'] puts "Preparing to do a rolling restart for all servers in env: #{ @options['env'] } (potential data loss).\nEnter Y/y to confirm, Q/q to exit completely." input = STDIN.gets.chomp @options['rolling_restart'] = false unless ( input =~ /y|Y|yes|Yes/ ) == 0 exit if ( input =~ /y|Y|quit|Quit/ ) == 0 end nodes = @config['getter'].get_true_node_objects true nodes = @config['parser'].exclude_nodes( nodes, [{ unless: { env: @options['env'] }}] ) #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: :groups, limit: 5, wait: 5 do |host| n = get_node_from_address(nodes, host.hostname) puts "Beginning apt-get run for #{ n.name } (#{ n.public_ipaddress })" log_data, = start_apt_updater( n.name, n.public_ipaddress, , locs, passwords) logs_bag_hash["#{ n.name }-upgrade"] = { text: log_data.scrub_pretty_text, timestamp: } end on ( nodes.map { |n| @config['cheftacular']['deploy_user'] + "@" + n.public_ipaddress } ), in: :groups, limit: 5, wait: 120 do |host| n = get_node_from_address(nodes, host.hostname) puts "Beginning restart run for #{ n.name } (#{ n.public_ipaddress })" start_sys_restarter( n.name, n.public_ipaddress, , locs, passwords) end if @options['rolling_restart'] @config['ChefDataBag'].save_logs_bag end |
#service ⇒ Object
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 |
# File 'lib/cheftacular/stateless_actions/service.rb', line 25 def service raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') command = case ARGV[1] when nil then 'list' when /list/ then 'list' when 'restart' then "#{ ARGV[2] } restart" when 'stop' then "#{ ARGV[2] } stop" when 'start' then "#{ ARGV[2] } start" else 'list' end raise "You did not pass a service to #{ ARGV[1] }" if ARGV[1] =~ /restart|stop|start/ && ARGV[2].nil? service_location = "#{ ARGV[2] }.conf" nodes = @config['getter'].get_true_node_objects nodes = @config['parser'].exclude_nodes( nodes, [{ unless: { env: @options['env'] }}], true ) , 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 run of \"service #{ command }\" for #{ n.name } (#{ n.public_ipaddress })" start_service_run( n.name, n.public_ipaddress, , locs, passwords, command, cheftacular, service_location ) end end |
#slack(message = '', channel = '') ⇒ Object
22 23 24 25 26 27 28 29 30 |
# File 'lib/cheftacular/stateless_actions/slack.rb', line 22 def slack ='', channel='' @slack_notifier ||= Slack::Notifier.new @config['cheftacular']['slack']['webhook'], username: 'Cheftacular' = ARGV[1] if .blank? channel = ARGV[2] if channel.blank? @slack_notifier.channel = channel.nil? ? @config['cheftacular']['slack']['default_channel'] : channel @slack_notifier.ping end |
#test_env(split_env = "splitstaging", type = "boot") ⇒ 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 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 |
# File 'lib/cheftacular/stateless_actions/test_env.rb', line 27 def test_env split_env="splitstaging", type="boot" raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') env_index = @options['env'] == 'staging' ? 1 : 2 split_env = ARGV[1] unless @options['env'] == 'staging' type = ARGV[env_index] if ARGV[env_index] split_envs = @config['cheftacular']['run_list_environments'][@options['env']] raise "Unknown split_env: #{ split_env }, can only be #{ split_envs.values.join(', ') }" unless (split_env =~ /#{ split_envs.values.join('|') }/) == 0 raise "Unknown type: #{ type }, can only be 'boot' or 'destroy'" unless (type =~ /boot|destroy/) == 0 nodes = @config['getter'].get_true_node_objects(true) nodes = @config['parser'].exclude_nodes( nodes, [{ unless: "role[#{ split_env.split('split').join('split_') }]" }, { unless: { env: @options['env'] }}]) @options['force_yes'] = true @options['in_scaling'] = true case type when 'boot' @config['cheftacular']['split_env_nodes'].each_pair do |name, config_hash| config_hash ||= {} true_name = name.gsub('SPLITENV', split_env) @options['sub_env'] = split_env @options['node_name'] = "#{ true_name }#{ 'p' if @options['env'] == 'production' }" @options['flavor_name'] = config_hash.has_key?('flavor') ? config_hash['flavor'] : @config['cheftacular']['default_flavor_name'] @options['descriptor'] = config_hash.has_key?('descriptor') ? "#{ config_hash['descriptor'] }-#{ split_env }" : name @options['with_dn'] = config_hash.has_key?('dns_config') ? @config['parser'].parse_to_dns(config_hash['dns_config']) : @config['parser'].parse_to_dns('NODE_NAME.ENV_TLD') next if nodes.map { |n| n.name }.include?(@options['node_name']) puts("Preparing to boot server #{ @options['node_name'] } for #{ @options['env'] }'s #{ split_env } environment!") unless @options['quiet'] @config['stateless_action'].cloud_bootstrap sleep 15 end @config['ChefDataBag'].save_server_passwords_bag when 'destroy' @options['delete_server_on_remove'] = true nodes.each do |node| @options['node_name'] = node.name puts("Preparing to destroy server #{ @options['node_name'] } for #{ @options['env'] }'s #{ split_env } environment!") unless @options['quiet'] @config['stateless_action'].remove_client sleep 15 end end end |
#ubuntu_bootstrap(out = []) ⇒ Object
16 17 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 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 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/cheftacular/stateless_actions/bootstrappers/ubuntu_bootstrap.rb', line 16 def ubuntu_bootstrap out=[] raise "This action can only be performed if the mode is set to devops" if !@config['helper'].running_in_mode?('devops') && !@options['in_scaling'] @options['address'] = ARGV[1] unless @options['address'] @options['client_pass'] = ARGV[2] unless @options['address'] if `which sshpass`.empty? 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)" end new_deploy_pass = @config['helper'].gen_pass(@config['cheftacular']['server_pass_length']) deploy_user = @config['cheftacular']['deploy_user'] root_commands = [ "cd /home", "adduser #{ deploy_user } --gecos \",,,,\" --disabled-password", "echo #{ deploy_user }:#{ new_deploy_pass } | chpasswd", "adduser #{ deploy_user } www-data", "adduser #{ deploy_user } sudo", "mkdir -p /home/#{ deploy_user }/.ssh", "touch /home/#{ deploy_user }/.ssh/authorized_keys && touch /home/#{ deploy_user }/.ssh/known_hosts", "chown -R #{ deploy_user }:www-data /home/#{ deploy_user }/.ssh", 'sed -i "s/StrictModes yes/StrictModes yes\nPasswordAuthentication no\nUseDNS no\nAllowUsers deploy postgres\n/" /etc/ssh/sshd_config'.gsub('deploy', deploy_user), 'sed -i "s/PermitRootLogin yes/PermitRootLogin no/" /etc/ssh/sshd_config' ] @config['default']['authentication_bag_hash']['authorized_keys'].each do |line| root_commands << "echo \"#{ line }\" >> /home/#{ deploy_user }/.ssh/authorized_keys" end sudo = "echo #{ new_deploy_pass } | sudo -S" deploy_commands = [ "#{ sudo } apt-get update", "#{ sudo } apt-get install curl #{ @config['cheftacular']['pre_install_packages'] } -y", "#{ sudo } apt-get upgrade -y" ] final_commands = [] if @config['cheftacular']['install_rvm_on_boot'] deploy_commands << "gpg --keyserver hkp://keys.gnupg.net --recv-keys #{ @config['cheftacular']['rvm_gpg_key'] }" deploy_commands << "curl -L https://get.rvm.io | bash -s stable" rvm_source = "source /home/deploy/.rvm/bin/rvm &&" final_commands = [ "#{ rvm_source } echo '#{ new_deploy_pass }' | rvmsudo -S rvm requirements", "#{ rvm_source } rvm install #{ @config['cheftacular']['ruby_version'] }", "#{ rvm_source } rvm alias create default #{ @config['cheftacular']['ruby_version'] }", "#{ rvm_source } rvm gemset empty --force" ] final_commands << "#{ rvm_source } rvm install 1.9.3-p327" if @config['cheftacular']['chef_version'].to_i < 12 end root_execute_string = "sshpass -p \"#{ @options['client_pass'] }\" ssh -t -oStrictHostKeyChecking=no root@#{ @options['address'] } '#{ root_commands.join(' && ') } && service ssh restart'" while system(root_execute_string) != true tries ||= 5 puts "Unable to complete step 1 of setup process, trying again in 60 seconds, there are #{ tries } more tries" sleep 60 tries -= 1 raise "Unable to complete step 1 of setup process!" if tries <= 0 end out << $?.to_s #output from the system command above puts("Finished initial setup...stage 1 of 3 for server #{ @options['address'] }") if @options['in_scaling'] puts(out.last) unless @options['quiet'] || @options['in_scaling'] deploy_commands.each do |cmnd| puts("(#{ @options['address'] }) Running #{ cmnd.gsub("#{ new_deploy_pass }", "sudo password") }") unless @options['quiet'] || @options['in_scaling'] out << `ssh -t -oStrictHostKeyChecking=no #{ deploy_user }@#{ @options['address'] } "#{ cmnd }"` puts(out.last) unless @options['quiet'] || @options['in_scaling'] end puts("Finished deploy setup....stage 2 of 3 for server #{ @options['address'] }") if @options['in_scaling'] final_commands.each do |cmnd| puts "(#{ @options['address'] }) Running #{ cmnd.gsub("#{ new_deploy_pass }", "sudo password") }" out << `ssh -t -oStrictHostKeyChecking=no #{ deploy_user }@#{ @options['address'] } "#{ cmnd }"` puts(out.last) unless @options['quiet'] || @options['in_scaling'] end puts("Finished ruby setup......stage 3 of 3 for server #{ @options['address'] }") if @options['in_scaling'] @config[@options['env']]['server_passwords_bag_hash']["#{ @options['address'] }-root-pass"] = @options['client_pass'] @config[@options['env']]['server_passwords_bag_hash']["#{ @options['address'] }-deploy-pass"] = new_deploy_pass @config[@options['env']]['server_passwords_bag_hash']["#{ @options['address'] }-name"] = @options['node_name'] if @options['node_name'] @config['ChefDataBag'].save_server_passwords_bag unless @options['in_scaling'] end |
#update_chef_client ⇒ Object
14 15 16 17 |
# File 'lib/cheftacular/stateless_actions/update_chef_client.rb', line 14 def update_chef_client raise "Not Yet Implemented" raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') end |
#update_cloudflare_dns_from_cloud ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/cheftacular/stateless_actions/update_cloudflare_dns_from_cloud.rb', line 26 def update_cloudflare_dns_from_cloud raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') target_domain = @config[@options['env']]['config_bag_hash'][@options['sub_env']]['tld'] @config['stateless_action'].update_tld 'self' unless ARGV[1] == 'skip_update_tld' target_domain_records = @config['stateless_action'].cloud('domain', "read:#{ target_domain }")["records_for_#{ target_domain }"] @config['DNS'].update_cloudflare_from_array_of_domain_hashes target_domain, target_domain_records end |
#update_split_branches ⇒ Object
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 |
# File 'lib/cheftacular/stateless_actions/update_split_branches.rb', line 28 def update_split_branches target_loc = @config['helper'].running_in_mode?('application') ? @config['locs']['app-root'] : "#{ @config['locs']['root'] }/#{ @options['repository'] }" current_revision = `cd #{ target_loc } && git rev-parse --abbrev-ref HEAD` puts "Preparing to run merges..." split_branch_repos = @config['getter'].get_split_branch_hash raise "unsupported codebase, please run in #{ split_branch_repos.keys.join(', ') } only!" if ( @options['repository'] =~ /#{ split_branch_repos.keys.join('|') }/ ) == 0 test_for_changes = `cd #{ target_loc } && git diff --exit-code` unless test_for_changes.empty? puts "You have changes in your current working tree for #{ target_loc }. Please commit these changes before running this command." exit end commands = [ "cd #{ target_loc }", "git checkout master", "git pull origin master", "git fetch origin", ] @config['run_list_environments'].each_pair do |env, branch_hash| branch_hash.keys.each do |branch_name| true_branch_name = branch_name.gsub('_','-') commands << ["git checkout #{ true_branch_name }", "git pull origin #{ true_branch_name }", 'git merge master --no-edit', "git push origin #{ true_branch_name }"] end end commands << "git checkout #{ current_revision }" puts `#{ commands.flatten.join(' && ') }` unless @options['quiet'] puts "Update split branches complete. You have been returned to the branch you were on before which was \"#{ current_revision.chomp }\"." end |
#update_thecheftacularcookbook(local_options = {'interactive' => true}) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/cheftacular/stateless_actions/update_thecheftacularcookbook.rb', line 15 def update_thecheftacularcookbook ={'interactive' => true} raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') @config['cheftacular']['wrapper_cookbooks'].split(',').each do |wrapper_cookbook| wrapper_cookbook_loc = "#{ @config['locs']['cookbooks'] }/#{ wrapper_cookbook }" FileUtils.rm_rf(File.("#{ @config['locs']['berks'] }/cookbooks")) if File.exists?(File.("#{ @config['locs']['berks'] }/cookbooks")) Dir.chdir wrapper_cookbook_loc puts "Installing new cookbooks..." out = `berks install` puts "#{out}\nFinished fetching cookbooks, moving TheCheftacularCookbook into local chef repo" cheftacular_cookbook = @config['filesystem'].parse_latest_berkshelf_cookbook_versions.select {|key| key.include?('TheCheftacularCookbook')}['TheCheftacularCookbook'] puts "Moving TheCheftacularCookbook (#{ cheftacular_cookbook['version'] })[#{ cheftacular_cookbook['mtime'] }] to your chef-repo!" `rm -Rf #{ @config['locs']['cookbooks'] }/TheCheftacularCookbook` if File.exists?(File.("#{ @config['locs']['cookbooks'] }/TheCheftacularCookbook")) `cp -Rf #{ @config['locs']['berks'] }/#{ cheftacular_cookbook['location'] } #{ @config['locs']['cookbooks'] }/TheCheftacularCookbook` break end end |
#update_tld(target_tld = "") ⇒ Object
17 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 56 57 58 59 60 61 62 |
# File 'lib/cheftacular/stateless_actions/update_tld.rb', line 17 def update_tld target_tld="" raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops') raise "Undefined new tld to migrate to" if ARGV.length <= 1 && target_tld.blank? nodes = @config['getter'].get_true_node_objects(true) #We need to manually update beta nodes as they share the same env space as their non-beta counterparts TODO Refactor? nodes = @config['parser'].exclude_nodes( nodes, [{ unless: { env: @options['env'] }}] ) address_hash = @config['getter'].get_addresses_hash @options['env'] target_tld = ARGV[1] if target_tld.blank? old_tld = @config[@options['env']]['config_bag_hash'][@options['sub_env']]['tld'] target_tld = old_tld if target_tld == 'self' nodes.each do |n| @options['node_name'] = n.name domain_obj = PublicSuffix.parse address_hash[n.public_ipaddress]['dn'] next unless domain_obj.domain == old_tld #we can't create records for domains not managed under the environment's tld #TODO CHECK CLOUD IF TLD EXISTS specific_domain = "#{ domain_obj.trd }.#{ target_tld }" if specific_domain != "#{ @options['node_name'] }.#{ target_tld }" @config['DNS'].create_dns_record_for_domain_from_address_hash(specific_domain, address_hash[n.public_ipaddress], "specific_domain_mode") end @config['DNS'].create_dns_record_for_domain_from_address_hash(target_tld, address_hash[n.public_ipaddress]) @config['DNS'].("set_specific_domain_name:#{ specific_domain }") sleep 1 #prepare for next domain end @config[@options['env']]['config_bag_hash'][@options['sub_env']]['tld'] = target_tld @config['ChefDataBag'].save_config_bag @config['ChefDataBag'].save_addresses_bag end |
#upload_nodes(invalidate_file_node_cache = false) ⇒ Object
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 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/cheftacular/stateless_actions/upload_nodes.rb', line 30 def upload_nodes invalidate_file_node_cache=false @config['filesystem'].cleanup_file_caches('current-nodes') if invalidate_file_node_cache raise "This action can only be performed if the mode is set to devops" if !@config['helper'].running_in_mode?('devops') && !@options['in_scaling'] @config['chef_environments'].each do |env| @config['initializer'].initialize_data_bags_for_environment env, false, ['node_roles'] @config['initializer'].initialize_node_roles_bag_contents env end nodes = @options['multi-step'] ? @config['getter'].get_true_node_objects(true,true) : @config['getter'].get_true_node_objects(true) node_roles_hash, bag_hash, allowed_changes_hash = {},{},{} Dir.foreach(@config['locs']['nodes']) do |fr| next if @config['filesystem'].is_junk_filename?(fr) Dir.foreach("#{ @config['locs']['nodes'] }/#{ fr }") do |f| next if @config['filesystem'].is_junk_filename?(f) node_roles_hash[f.split('.json').first] = JSON.parse(File.read("#{ @config['locs']['nodes'] }/#{ fr }/#{ f }")) end end if @config['helper'].running_in_mode?('devops') #only devops modes should have a nodes_dir @config['chef_environments'].each do |env| @config[env]['node_roles_bag_hash']['node_roles'].each_pair do |role_name, role_hash| bag_hash[role_hash['name']] = role_hash.to_hash #hashes from chef server are stored as hashie objects until forced into hashes end end if !@options['force_yes'] && @config['helper'].running_in_mode?('devops') node_roles_hash.each_pair do |role_name, role_hash| overwrite = false if bag_hash[role_name] != role_hash puts "Detected difference between saved roles hash and updated node_roles json hash for #{ role_name }." puts "Saved roles hash:" ap(bag_hash[role_name]) puts "New roles hash:" ap(role_hash) puts "Preparing to overwrite the saved roles hash with the node_roles hash, enter Y/y to confirm." input = STDIN.gets.chomp overwrite = true if ( input =~ /y|Y|yes|Yes/ ) == 0 allowed_changes_hash[role_name] = role_hash if overwrite else #bag_hash does not have a key for that role, populate it. allowed_changes_hash[role_name] = role_hash end @config[role_hash['chef_environment']]['node_roles_bag_hash']['node_roles'][role_name] = role_hash end else allowed_changes_hash = bag_hash end #force add any roles that are not in the bag in the event force yes is turned on (node_roles_hash.keys - bag_hash.keys).each do |role_not_in_node_roles_bag| new_role = node_roles_hash[role_not_in_node_roles_bag] allowed_changes_hash[role_not_in_node_roles_bag] = bag_hash[role_not_in_node_roles_bag] @config[new_role['chef_environment']]['node_roles_bag_hash']['node_roles'][new_role['name']] = new_role end if @options['force_yes'] && @config['helper'].running_in_mode?('devops') nodes.each do |node| # if there is a node_roles file that completely matches the name of the file, use it changes_for_current_node = false if allowed_changes_hash[node.name] allowed_changes_hash[node.name].each_pair do |node_key, node_val| if (node_key =~ /name/) != 0 && node.send(node_key) != node_val puts("Updating #{ node.name } with attribute #{ node_key } = #{ node_val } from #{ node.name }.json") unless @options['quiet'] node.send("#{ node_key }=", node_val) changes_for_current_node, invalidate_file_node_cache = true, true end end elsif allowed_changes_hash.keys.include?(node.name.gsub(/\d/,'')) #if there is a template file that matches the stripped down name, use it allowed_changes_hash[node.name.gsub(/\d/,'')].each_pair do |node_key, node_val| if (node_key =~ /name/) != 0 && node.send(node_key) != node_val puts("Updating #{ node.name } with attribute #{ node_key } = #{ node_val } from template json file") unless @options['quiet'] node.send("#{ node_key }=", node_val) changes_for_current_node, invalidate_file_node_cache = true, true end end end node.save if changes_for_current_node end @config['chef_environments'].each do |env| @config['ChefDataBag'].save_node_roles_bag env end if !@options['force_yes'] && @config['helper'].running_in_mode?('devops') @config['filesystem'].cleanup_file_caches('current-nodes') if invalidate_file_node_cache end |
#upload_roles ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/cheftacular/stateless_actions/upload_roles.rb', line 15 def upload_roles raise "This action can only be performed if the mode is set to devops" if !@config['helper'].running_in_mode?('devops') && !@options['in_scaling'] Dir.foreach(@config['locs']['roles']) do |rd| next if @config['filesystem'].is_junk_filename?(rd) puts("Loading in role from file #{ rd }") if @options['verbose'] puts `knife role from file "#{ @config['locs']['roles'] }/#{ rd }"` end end |
#vyatta_bootstrap(out = []) ⇒ Object
3 4 5 |
# File 'lib/cheftacular/stateless_actions/bootstrappers/vyatta_bootstrap.rb', line 3 def vyatta_bootstrap out=[] raise "Not yet implemented!" end |