#!/usr/local/bin/ruby

# = Rudy EC2
# 
# === A Rudy interface to Amazon EC2
#
# 
# 
# See rudy-ec2 -h for usage
# 

$:.unshift File.join(File.dirname(__FILE__), '..', 'lib') # Put our local lib in first place

begin
  require 'drydock'
  require 'rudy'
  require 'rudy/cli'
rescue Interrupt
  exit
end

# Command-line interface for bin/rudy-ec2
module RudyCLI_EC2
  extend Drydock
  
  debug :off
  default :instances
  
  # -----------------------------------  AMAZON EC2 COMMANDS  --------
  # ------------------------------------------------------------------
  
  about "Amazon EC2 Elastic IP addresses"
  usage "rudy-ec2 addresses"
  usage "rudy-ec2 addresses -C"
  usage "rudy-ec2 addresses -A -i instance-id address"
  usage "rudy-ec2 addresses -A -i instance-id -n"
  usage "rudy-ec2 addresses -N address"
  usage "rudy-ec2 addresses -D address"
  option :i, :instance, String, "Instance ID"
  option :n, :newaddress, "Create and assign a new elastic IP"
  action :A, :associate, "Associate an IP address to a running instance"
  action :N, :disassociate, "Disassociate an IP address from an instance"
  action :C, :create, "Request an IP address from Amazon"
  action :D, :destroy, "Return an IP address to Amazon (this is permanent!)"
  argv :ipaddress
  command :addresses => Rudy::CLI::AWS::EC2::Addresses
  command_alias :addresses, :address
  command_alias :addresses, :a
  
  about "Amazon EC2 instance console output"
  usage "rudy-ec2 console [-g group] [instance ID]"
  usage "rudy-ec2 [-k path/2/privatekey] console [instance ID]"
  usage "NOTE: Private key is required only for Windows instances"
  option :g, :group, String, "A security group name"
  argv :awsid
  command :consoles => Rudy::CLI::AWS::EC2::Instances
  command_alias :consoles, :console
  command_alias :consoles, :c
  
  about "Copy files to or from machines."
  usage "rudy-ec2 copy [-p] [-r] source target"
  usage "rudy-ec2 [-u user] [-k path/2/privatekey] upload local-source target"
  usage "rudy-ec2 download remote-source target"
  usage "NOTE: Use quotes when using a tilda or asterisk in remote paths ('~/')."
  usage "rudy-ec2 download '~/*' /tmp/"
  #option :r, :recursive, "Recursively copy entire directories"
  #option :p, :preserve, "Preserve atimes and ctimes."
  option :g, :group, String, "A security group name"
  option :i, :awsid, String, "An instance ID"
  command :copy => Rudy::CLI::AWS::EC2::Candy 
  command_alias :copy, :ul
  command_alias :copy, :dl
  command_alias :copy, :scp
  command_alias :copy, :upload
  command_alias :copy, :download
  
  about "Amazon EC2 EC2 Security Groups"
  usage "rudy-ec2 groups"
  usage "rudy-ec2 groups -C [-p ports] [-a addresses] [-r protocols] name"
  usage "rudy-ec2 groups -A [-p ports] [-a addresses] [-r protocols] name"
  usage "rudy-ec2 groups -A -p 81,8000-9000 -a 127.0.0.1,127.0.0.2 name"
  usage "rudy-ec2 groups -A -g default -o 123456789012 name"
  usage "rudy-ec2 groups -R -g default name"
  usage "rudy-ec2 groups -D name"
  option :all, "Display all security groups"
  option :r, :protocols, Array, "List of protocols. One of: tcp (default), udp, icmp"
  option :p, :ports, Array, "List of port ranges (default: 22,80,443)"
  option :a, :addresses, Array, "List of IP addresses (default: your current external IP)"
  option :g, :group, String, "Other group to authorize or revoke. Use with -o!"
  option :o, :owner, String, "Other group owner ID (account number). Use with -g!"
  option :d, :description, String, "A group description"
  action :C, :create, "Create a security group"
  action :D, :destroy, "Destroy a security group"
  action :A, :authorize, "Authorize a rule for a security group"
  action :R, :revoke, "Revoke a rule for a security group"
  argv :name
  command :groups => Rudy::CLI::AWS::EC2::Groups
  command_alias :groups, :group
  command_alias :groups, :g
  
  about "Amazon EC2 Machine Images (AMIs)"
  usage "rudy-ec2 images"
  usage "rudy-ec2 images image-id"
  usage "rudy-ec2 images -o 123456789012"
  usage "rudy-ec2 images -o amazon"
  usage "rudy-ec2 images -o self"
  usage "rudy-ec2 images -R bucket/ami-name.manifest.xml"
  option :o, :owner, String, "Amazon Account Number or one of: amazon, self"
  option :l, :all, "Display all registered machine images (warning: slow)"
  #option :p, :private, "Private images only"
  option :r, :ramdisk, String, "Ramdisk ID (EBS only)"
  option :k, :kernel, String, "Kernel ID (EBS only)"
  option :s, :snapshot, String, "Snapshot ID (EBS only)"
  option :a, :arch, String, "Architecture. One of: i386, x86_64 (EBS only)"
  option :d, :description, String, "A description of the image (EBS only)"
  action :R, :register, "Register an image"
  action :D, :destroy, "Deregister an image (does not remove image files from S3)"
  argv :ami
  command :images => Rudy::CLI::AWS::EC2::Images
  command_alias :images, :image
  command_alias :images, :im
  
  about "Amazon EC2 Instances"
  usage "rudy-ec2 instances"
  usage "rudy-ec2 instances [-g group-name] [instance-ID]"
  usage "rudy-ec2 instances -C -m ami-235fba4a -s m1.small -k keypair-name"
  usage "rudy-ec2 instances -C -a 255.255.255.255 -k keypair-name"
  usage "rudy-ec2 instances -R instance-ID"
  usage "rudy-ec2 instances -D instance-ID"
  usage "rudy-ec2 instances -R -g group-name"
  usage "rudy-ec2 instances -D -g group-name"
  option :g, :group, String, "The security group name"
  option :m, :ami, String, "The machine image ID (ami)"
  option :s, :size, String, "The instance size (default: m1.small)"
  option :k, :keypair, String, "The SSH keypair to use for launch"
  option :a, :address, String, "The IP address to associate to the new instance"
  option :n, :newaddress, "Create and assign a new elastic IP"
  option :p, :private, "Do not give the instance a public IP address"
  action :C, :create, "Create a machine instance"
  action :R, :restart, "Restart a machine instance"
  action :D, :destroy, "Destroy a machine instance"
  argv :instid
  command :instances => Rudy::CLI::AWS::EC2::Instances
  command_alias :instances, :instance
  command_alias :instances, :in
  command_alias :instances, :i
  
  about "Amazon EC2 EC2::Keypairs"
  usage "rudy-ec2 keypairs"
  usage "rudy-ec2 keypairs -C name"
  usage "rudy-ec2 keypairs -D name"
  action :D, :destroy, "Unregister keypair from EC2 (this is permanent!)"
  action :C, :create, "Create and register a keypair with EC2"
  argv :name
  command :keypairs => Rudy::CLI::AWS::EC2::Keypairs
  command_alias :keypairs, :keypair
  command_alias :keypairs, :k
  
  about "Amazon EC2 Snapshots"
  usage "rudy-ec2 snapshots"
  usage "rudy-ec2 snapshots -C -v volume-id"
  usage "rudy-ec2 snapshots -D snapshot-id"
  option :v, :volume, String, "Volume ID"
  action :D, :destroy, "Destroy a snapshot (this is permanent!)"
  action :C, :create, "Create a snapshot"
  argv :snapid
  command :snapshots => Rudy::CLI::AWS::EC2::Snapshots
  command_alias :snapshots, :snapshot
  command_alias :snapshots, :s
  
  about "Open an SSH connection"
  usage "rudy-ec2 ssh"
  usage "rudy-ec2 -u root -k path/2/key ssh"
  usage "rudy-ec2 -u root -k path/2/key ssh uname -a"
  usage "rudy-ec2 ssh -g group-name"
  usage "rudy-ec2 ssh -i instance-id"
  option :print, "Only print the SSH command, don't connect"
  option :g, :group, String, "A security group name"
  option :i, :instid, String, "An instance ID"
  argv :cmd
  command :ssh => Rudy::CLI::AWS::EC2::Candy 
  command_alias :ssh, :connect
  
  about "Amazon EC2 status"
  command :status => Rudy::CLI::AWS::EC2::Candy
  
  about "Amazon EC2 Volumes"
  usage "rudy-ec2 volumes"
  usage "rudy-ec2 volumes -C -s size [-d device-path]"
  usage "rudy-ec2 volumes -A -i instance-id volume-id"
  usage "rudy-ec2 volumes -N volume-id"
  usage "rudy-ec2 volumes -D volume-id"
  option :i, :instance, String, "Instance ID"
  option :s, :size, String, "Size (in GB)"
  option :t, :snapshot, String, "Snapshot ID (snap)"
  option :d, :device, String, "Device path (default: /dev/sdh)"
  action :D, :destroy, "Destroy a volume (this is permanent!)"
  action :C, :create, "Create a volume"
  action :A, :attach, "Attach a volume to a running instance"
  action :N, :detach, "Detach a volume from an instance"
  argv :volid
  command :volumes => Rudy::CLI::AWS::EC2::Volumes
  command_alias :volumes, :volume
  command_alias :volumes, :v
  
  about "Availability Zones"
  usage "rudy-ec2 zones"
  argv :name
  command :zones => Rudy::CLI::AWS::EC2::Zones
  command_alias :zones, :zone
  command_alias :zones, :z
  
  about "Display existing environment objects"  
  option :l, :all, "Include all regions"
  command :info => Rudy::CLI::AWS::EC2::Info
  
end

begin
  Drydock.run!(ARGV, STDIN) if Drydock.run? && !Drydock.has_run?
rescue Drydock::ArgError, Drydock::OptError => ex
  STDERR.puts ex.message
  STDERR.puts ex.usage
rescue Drydock::InvalidArgument => ex
  STDERR.puts ex.message  
rescue Rudy::Error => ex
  STDERR.puts ex.message
  STDERR.puts ex.backtrace if Drydock.debug?
rescue => ex
  STDERR.puts "ERROR (#{ex.class.to_s}): #{ex.message}"
  STDERR.puts ex.backtrace if Drydock.debug?
rescue Interrupt
  puts "#{$/}Exiting... "
  exit 1
end


