Last active
June 13, 2018 23:00
-
-
Save mattkasa/89fbd7a88fbb24f1f59758fe392a600d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'chef' | |
require 'fileutils' | |
app_name = ARGV[0] | |
run_list = ARGV[1] | |
if ENV.has_key?('CHEF_ENVIRONMENTS') && (!ENV.has_key?('TEST_GROUP') || ENV['TEST_GROUP'] == '1') | |
environments = ENV['CHEF_ENVIRONMENTS'].split(/\s+/) | |
branch = ENV.has_key?('TRAVIS_BRANCH') ? ENV['TRAVIS_BRANCH'] : ENV['BRANCH_NAME'] | |
revision = ENV.has_key?('TRAVIS_COMMIT') ? ENV['TRAVIS_COMMIT'] : ENV['GIT_COMMIT'] | |
if revision.nil? || revision == 'null' | |
puts "Cannot deploy without a revision (restarting deploy builds is not supported)" | |
exit(false) | |
end | |
environment = $1 if branch && branch =~ /^environment\/(.*)$/ | |
if environment && environments.include?(environment) | |
suffix = environment.upcase | |
if %W(CHEF_SERVER_#{suffix} CHEF_USER_#{suffix} CHEF_CLIENT_#{suffix}).all? { |k| ENV.has_key?(k) } | |
# Get the configuration from the environment | |
chef_server = ENV["CHEF_SERVER_#{suffix}"] | |
chef_org = chef_server.sub(/^.*\//, '') | |
chef_user = ENV["CHEF_USER_#{suffix}"] | |
chef_client = ENV["CHEF_CLIENT_#{suffix}"] | |
# Configure knife and write client key | |
chef_dir = File.join(Dir.pwd, '.chef') | |
FileUtils.rm_rf(chef_dir) if Dir.exist?(chef_dir) | |
exit(1) unless Dir.mkdir(chef_dir) | |
File.write(File.join(chef_dir, "#{chef_user}.pem"), chef_client.gsub(/\\n/, "\n")) | |
File.open(File.join(chef_dir, 'knife.rb'), 'w') do |file| | |
file << "current_dir = File.dirname(__FILE__)\n\n" | |
file << "log_level :info\n" | |
file << "log_location STDOUT\n\n" | |
file << "node_name '#{chef_user}'\n" | |
file << "client_key \"\#{current_dir}/#{chef_user}.pem\"\n" | |
file << "chef_server_url '#{chef_server}'\n\n" | |
file << "ssl_verify_mode :verify_none\n" | |
file << "knife[:ssh_user] = '#{chef_user}'\n" | |
end | |
# Load chef and config | |
chef_configs = ['.chef/knife.rb', '~/.chef/knife.rb', '/etc/chef/knife.rb'] | |
@chef_client_token ||= Chef::Config.from_file(chef_configs.find { |p| File.exists?(File.expand_path(p)) }) | |
# Deploy | |
search_environments = Chef::Environment.list.keys.select { |e| e =~ /^[a-z]{4}#{environment[0]}$/ } | |
search = "(#{search_environments.map { |e| "chef_environment:#{e}" }.join(' OR ')}) AND #{run_list}" | |
puts "Searching for nodes matching #{search}" | |
query = Chef::Search::Query.new | |
results = query.search(:node, search) | |
nodes = results.first | |
nodes.each do |node| | |
current_revision = node[app_name]['revision'] if node[app_name] && node[app_name]['revision'] | |
if current_revision == revision | |
puts "#{node.name} already at #{revision}" | |
else | |
printf '%s', "Updating #{node.name} from #{current_revision} to #{revision}" | |
succeeded = false | |
(1..5).each do |try| | |
begin | |
printf "%s\n", '.' | |
node.normal[app_name]['revision'] = revision | |
saved_node = node.save; | |
loaded_node = Chef::Node.load(node.name); | |
if saved_node[app_name]['revision'] == revision && loaded_node[app_name]['revision'] == revision | |
succeeded = true | |
break | |
end | |
rescue | |
end | |
end | |
if succeeded | |
printf "%s\n", 'done' | |
system("ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 #{chef_user}@#{node['fqdn']} \"sudo chef-client\"") | |
else | |
printf "%s\n", 'FAILED' | |
end | |
end | |
end | |
# TODO: knife ssh | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment