Skip to content

Instantly share code, notes, and snippets.

@manchunlam
Last active October 2, 2015 01:58
Show Gist options
  • Save manchunlam/2149277 to your computer and use it in GitHub Desktop.
Save manchunlam/2149277 to your computer and use it in GitHub Desktop.
Script for Common Scalr Tasks
#!/usr/bin/env ruby
require 'getoptlong'
KNIFE_SSH_OPT = '-x deploy -i ~/.ssh/id_rsa -a ec2.public_hostname'
VERSION = "1.1.0"
@project = ""
@env = "staging"
@instance_type = ""
@error_only = true
# Help onto stdout
def print_usage
usage = <<-END_USAGE.gsub(/^( {4})/, '')
scalr is a tool to perform common tasks for projects hosted in Scalr
Usage:
scalr [options] [instance_type]
where [options] are:
--project, -p <s>: Project name
--env, -e <s>: Set <environment>, defaults to "staging" if switch is not present
--tail, -t: Tail <environment>.log
--util-services: See running services on utility servers
--deploy: Deploy project to <environment>
--deployed-version: Check SHA of code-base in <environment>
--node-list: List node names and instance-roles
--version, -v: Print version
--help, -h: Show this message
where [instance_type] is:
--all: (default) run command on all servers
--app-servers: run command on Application Servers
--utilities: run command on Utility Servers
END_USAGE
example = <<-END_EXAMPLE.gsub(/^( {4})/, '')
Example:
To deploy: ./scalr.rb --project tabs --deploy
To tail log on staging: ./scalr.rb --project tabs --tail
To see deployed code version: ./scalr.rb --project --deployed-version
To change target environment to production: ./scalr.rb --project tabs --env production --tail
END_EXAMPLE
puts usage
puts example
end
# Build knife search_query string
def knife_ssh_query(type='all')
base = "knife ssh 'applications:#{@project} AND app_environment:#{@env}'"
case type
when '', 'all'
base.gsub(/'$/, " AND ( instance_role:ap* OR instance_role:uti* )'")
when 'app-servers'
base.gsub(/'$/, " AND instance_role:ap*'")
when 'utilities'
base.gsub(/'$/, " AND instance_role:uti*'")
end
end
# Build complete shell command string
def knife_ssh(ssh_cmd)
"#{knife_ssh_query(@instance_type)} '#{ssh_cmd}' #{KNIFE_SSH_OPT}"
end
opts = GetoptLong.new(
[ '--app-servers', GetoptLong::NO_ARGUMENT ],
[ '--utilities', GetoptLong::NO_ARGUMENT ],
[ '--all', GetoptLong::NO_ARGUMENT ],
[ '--project', '-p', GetoptLong::REQUIRED_ARGUMENT ],
[ '--env', '-e', GetoptLong::OPTIONAL_ARGUMENT ],
[ '--tail', '-t', GetoptLong::NO_ARGUMENT ],
[ '--util-services', GetoptLong::NO_ARGUMENT ],
[ '--deploy', GetoptLong::NO_ARGUMENT ],
[ '--deployed-version', GetoptLong::NO_ARGUMENT ],
[ '--version', '-v', GetoptLong::NO_ARGUMENT ],
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
[ '--show-all', GetoptLong::NO_ARGUMENT ],
[ '--node-list', GetoptLong::NO_ARGUMENT ]
)
# Output command result to stdout
def show_line(line, regex=nil, keys_to_print=[])
unless regex
puts line
else
matched = regex.match(line)
if matched
if keys_to_print.empty?
puts line
else
if ( matched.names & keys_to_print ) == keys_to_print
output = ""
keys_to_print.map {|k|
output << "#{matched[k]} "
}
puts output
end
end
end
end
end
# Execute the command
def tail_command(command, regex=nil, keys_to_print=[])
begin
IO.popen(command) do |f|
while line = f.gets
show_line(line, regex, keys_to_print)
end
end
rescue => e
puts e.inspect
rescue SignalException
puts 'Execution halted by user'
end
end
# Generate log-tailing command string
def tail_log
ssh_cmd = "tail -n 100 -f /data/#{@project}/current/log/#{@env}.log"
knife_ssh(ssh_cmd)
end
# Generate project-deployment command string
def deploy
ssh_cmd = 'sudo chef-client -j /etc/chef/chef.default.json'
knife_ssh(ssh_cmd)
end
# Prompt to deploy confirmation
def deploy_prompt
message = <<-END_MSG.gsub(/^( {4})/, '')
You are about to deploy, please confirm the following params:
project: #{@project}
env: #{@env}
command: #{@shell_cmd}
Do you want to deploy? (y|n)
END_MSG
puts message
confirmed = gets.chomp.downcase
%w(y yes).include?(confirmed)
end
# Generate version-check command string
def check_version
ssh_cmd = "cd /data/#{@project} && ls -al"
knife_ssh(ssh_cmd)
end
# Generate show-util-services command string
def see_util_services
ssh_cmd = 'sudo monit summary'
knife_ssh(ssh_cmd)
end
# Generate show-hostname command string
def show_hostname
ssh_cmd = 'hostname'
knife_ssh(ssh_cmd)
end
# Error regex
def error_regex
if @error_only
/role\[staging\]|error/i
else
nil
end
end
# Check if `knife` exists
def knife_installed?
`which knife`
$?.success?
end
# Prompt for knife installation
def install_knife_msg
message = <<-END_MSG.gsub(/^( {4})/, '')
`knife` command is not found. It is a dependency for this script.
Please install it by `gem install chef`
END_MSG
puts message
end
begin
if ARGV.length == 0
print_usage
opts.terminate
end
unless knife_installed?
install_knife_msg
opts.terminate
end
@func = ''
opts.each do |opt, arg|
case opt
when '--project'
@project = arg
when "--env"
if arg != ''
@env = arg
end
when '--tail'
@func = 'tail_log'
when "--util-services"
@func = 'see_util_services'
when "--deploy"
@func = 'deploy'
when "--deployed-version"
@func = 'check_version'
when '--node-list'
@func = 'show_hostname'
when '--all'
@instance_type = 'all'
when '--app-servers'
@instance_type = 'app-servers'
when '--utilities'
@instance_type = 'utilities'
when '--show-all'
@error_only = false
when "--version"
puts VERSION
when "--help"
print_usage
end
end
if @shell_cmd = eval(@func)
case @func
when 'deploy'
tail_command(@shell_cmd, error_regex) if deploy_prompt
when 'check_version'
version_regex = /(?<machine>.*\.amazonaws\.com).*current.*releases\/(?<sha>[a-zA-Z0-9]*)/
tail_command(@shell_cmd, version_regex, ["machine", "sha"])
else
tail_command(@shell_cmd)
end
end
rescue => e
puts e.inspect
end
@manchunlam
Copy link
Author

check_version returns SHA for both app and util servers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment