lib/awsssh.rb in awsssh-2.2.2 vs lib/awsssh.rb in awsssh-3.0.0.rc1
- old
+ new
@@ -1,211 +1,114 @@
require "awsssh/version"
-require 'net/ssh'
-require 'json'
-require "aws-sdk"
-# Bundler.require(:default, :development)
-require "inifile"
require "thor"
+require "inifile"
+require "aws-sdk"
+
module Awsssh
class Awsssh < Thor
- CONFIG_DIR = ENV['AWSSSH_CONFIG_DIR'] || "/Users/#{ENV['USER']}/.aws/"
- CONF_FILE = ENV['AWSSSH_CONFIG_FILE'] || "aws_config_"
- desc "-s SERVER [-a ACCOUNT]", "connect to a server"
- option :server, :aliases => '-s', :desc => "(required) The server name to connect with"
- option :account, :aliases => '-a', :desc => "Specify a account for a connection. Needet if the account don't came from the server name"
- option :list, :aliases => '-l', :desc => "List any items use with -s for Servers or -a ACCOUNT for accounts", :type => :boolean
- option :check, :aliases => '-c', :desc => "Alerts when -c STATE comes up for -s SERVER"
- option :version, :aliases => '-v', :desc => "Version"
- long_desc <<-LONGDESC
- # Connect to a Server:
-
-
- > $ awsssh -s SERVER
- \x5 This will connect you to a Server. This will work only if the first part of the server name is the same as the account name.
-
- > $ awsssh -s SERVER -a ACCOUNT
- \x5 With -a you can spezify a account to connect with. The server name don't play any role.
-
- # List all Account:
-
- > $ awsssh -l -a
- \x5 This will list all Accounts
-
- # List all Servers for a Account
-
- > $ awsssh -l -s ACCOUNT
- \x5 List all Servers vor Account ACCOUNT
-
- # Check Server Status
-
- LONGDESC
- def connect
- if options[:list] && options[:account]
- list_accounts
- elsif options[:list] && options[:server]
- list_servers(options[:server])
- elsif options[:server]
- connecting(options[:server], options[:account])
- elsif options[:version]
- puts VERSION
- else
- help "connect"
+ desc "list_profiles", "List all your avavible profiles"
+ def list_profiles()
+ credentials = open_credantial_file
+ puts "List of all known AWS Accounts"
+ puts
+ credentials.sections.each do |section|
+ puts " #{section}"
end
end
- def help(*args)
- super("connect")
- end
+ desc "list_server PROFILE", "List all Server for given profile"
+ def list_server(profile)
+ credentials = open_credantial_file
+ raise "Profile `#{profile}` not found. Please try `awsssh list_profiles`" if credentials[profile].empty?
+ aws_connection(profile, credentials)
- private
+ puts "Stacks and instances for profile `#{profile}`"
+ puts
- ##
- # List stacks for a account
- #
- # * *Args* :
- # - +account+ -> Account name
- #
- # * *Returns* :
- # - [Array] StackIDs
- def list_stacks(account)
- ow = awscfg(account)
- stacks = ow.client.describe_stacks[:stacks]
- stack_ids = []
- stacks.each do |stack|
- stack_ids << stack[:stack_id]
+ @client.describe_stacks.stacks.each do |stack|
+ puts "##### Stack: #{stack.name}"
+ @client.describe_instances({stack_id: stack.stack_id}).instances.each do |instance|
+ printf " %-20s status: %-11s %s\n" % [instance.hostname, instance.status, public_dns(instance)]
end
- return stack_ids
+ puts ""
end
+ end
+ desc "connect SERVERNAME", "Connect to Hostname"
+ option :profile, :desc => "specify a profile - see `awsssh list_profiles`"
+ def connect (hostname)
+ hostname_parts = hostname.split("-")
+ profile = options[:profile] || hostname_parts[0]
+ credentials = open_credantial_file
+ puts "Profile `#{profile}` not found. Try `awsssh SERVERNAME --profile PROFILE`" if credentials[profile].empty?
+ exit -1 if credentials[profile].empty?
- ##
- # Read Stack
- #
- # * *Args* :
- # - +stackid+ -> Stack ID
- # - +account+ -> Account name
- #
- # * *Returns* :
- # - Stecks JSON
- #
- def read_stack(stackid, account)
- ow = awscfg(account)
- ow.client.describe_instances({:stack_id => stackid})
- # JSON.parse(`aws opsworks describe-instances --stack-id #{stackid}`)
+ aws_connection(profile, credentials)
+ puts "looking for hostname `#{hostname}` in profile `#{profile}`. This may take a while..."
+ puts
+ public_dns = find_server(@client.describe_stacks.stacks, hostname)
+ if public_dns.nil?
+ puts "`#{hostname}` was not found or has no public ip."
+ puts "Try `awsssh list_server PROFILE`"
+ puts "checking your local ssh config..."
+ puts
+ exec "ssh #{hostname}"
+ exit -1
+ else
+ puts "start ssh connection to `#{hostname}`..."
+ puts
+ exec "ssh #{public_dns}"
+ exit 0
end
+ end
- ##
- # Lists all AWS Accounts
- #
- # * *Returns* :
- # - [String]
- # This are the known AWS Accounts:
- # - account
- def list_accounts
- length = 30
- puts "This are the known AWS Accounts:"
- config_files = Dir.entries(CONFIG_DIR)
- config_files.each do |file|
- if file[0,CONF_FILE.length] == CONF_FILE
- file_part = file.split("_")
- unless file_part.last.nil?
- printf "\t- %-#{length}s\n", file_part[2]
- end
- end
- end
- end
+ desc "version", "Version"
+ def version
+ puts "version #{VERSION}"
+ end
- ##
- # Server Name
- #
- # * *Args* :
- # - +stack+ -> Stack as JSON
- #
- # * *Returns* :
- # - [String]
- # - <servername> (<status>)
- def server_name(stack)
- stack[:instances].each do |instance|
- host = build_hostname(instance)
- printf "\t- %-20s %s \t %-15s \t %s\n", instance[:hostname], instance[:status], host[:ip], host[:hostname]
- end
- end
- ##
- # List all Servers for a given AWS Account
- #
- # * *Args* :
- # - +account+ -> AWS Account name
- #
- def list_servers(account)
- stacks = list_stacks account
- stacks.each do |stack_id|
- stack = read_stack stack_id, account
- server_name stack
- end
- end
+ private
- ##
- # Establish the connection
- #
- # * *Args* :
- # - +server+ -> Server name
- #
- def connecting(server, account=nil)
- public_dns = nil
- host = server.split("-")
- ac = account || host[0]
- stack_ids = list_stacks ac
- stack_ids.each do |stack_id|
- stack = read_stack(stack_id, ac)
- stack.instances.each do |i|
- if i[:hostname] == server
- public_dns = build_hostname(i)[:hostname]
- break
- end
- end
- break unless public_dns.nil?
- end
+ ##
+ # open and check credential file
+ #
+ def open_credantial_file()
+ raise "Enviroment variable `AWS_CREDENTIAL_FILE` not set" if ENV['AWS_CREDENTIAL_FILE'].nil?
+ raise "Credential File not found. Please check path `#{ENV['AWS_CREDENTIAL_FILE']}`" unless File.exist?(ENV['AWS_CREDENTIAL_FILE'])
+ IniFile.load(ENV['AWS_CREDENTIAL_FILE'])
+ end
- if public_dns.nil?
- puts "Server '#{server}' not found. Try ssh"
- exec "ssh #{server}"
- exit -1
- end
+ ##
+ #
+ def aws_connection(profile, credentials = nil)
+ credentials ||= open_credantial_file
+ @client = Aws::OpsWorks::Client.new({
+ region: credentials[profile]["region"],
+ credentials: Aws::Credentials.new(
+ credentials[profile]["aws_access_key_id"],
+ credentials[profile]["aws_secret_access_key"]
+ )
+ })
+ end
- puts "Connecting to #{server} (#{public_dns})"
- exec "ssh #{public_dns}"
+ def public_dns(instance)
+ public_ip = instance.public_ip || instance.elastic_ip
+ return nil if public_ip == nil
+ "ec2-#{public_ip.gsub(".", "-")}.#{instance.availability_zone.chop}.compute.amazonaws.com"
+ end
- end
-
- def build_hostname(instance)
- host = {}
- if instance[:status] != 'online'
- host[:ip] = host[:hostname] = nil
- return host
+ def find_server(stacks, hostname)
+ stacks.each do |stack|
+ @client.describe_instances({stack_id: stack.stack_id}).instances.each do |instance|
+ return public_dns(instance) if instance.hostname == hostname
end
- az = (instance[:availability_zone][-1].match(/[a-z]/)) ?
- instance[:availability_zone][0..-2] :
- instance[:availability_zone]
- host[:ip] = instance[:public_ip] || instance[:elastic_ip]
- host[:hostname] = "ec2-#{host[:ip].gsub("\.", "\-")}.#{az}.compute.amazonaws.com"
- host
end
+ return nil
+ end
- def awscfg(account)
- if cnf = IniFile.load(CONFIG_DIR + CONF_FILE + account)
- cnf = cnf['default']
- return AWS::OpsWorks.new(
- access_key_id: cnf['aws_access_key_id'],
- secret_access_key: cnf['aws_secret_access_key'],
- region: cnf['region']
- )
- else
- puts "No config #{CONF_FILE}#{account} found. Maybe use -a to specify a account."
- exit -1
- end
- end
+
default_task :connect
end
end