diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ac2f535 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*~ +build/ +dist/ diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..2209fd4 --- /dev/null +++ b/Readme.md @@ -0,0 +1,13 @@ +This is `ec2-ssh`, a command line tool to simplify SSH connections to AWS EC2 machines. + +See the original (blog post from Instagram)[http://instagram-engineering.tumblr.com/post/11399488246/simplifying-ec2-ssh-connections] + +# What changed in this fork? + +- add an option to supply to default ssh username +- bash and zsh completion +- add script-readable output to `ec2-host` + +# How to use shell completions? + +Document me..... diff --git a/bin/ec2-host b/bin/ec2-host index f1637b0..e6e84c1 100755 --- a/bin/ec2-host +++ b/bin/ec2-host @@ -19,14 +19,15 @@ Try `ec2-ssh --help' for more information.""" def full_usage(): - print >>stderr, """Usage: ec2-host [-k KEY] [-s SECRET] [-r REGION] [-t TAG] [NAME] + print >>stderr, """Usage: ec2-host [-k KEY] [-s SECRET] [-r REGION] [-t TAG] [-S sep] [NAME] Prints server host name. --help display this help and exit -k, --aws-key KEY Amazon EC2 Key, defaults to ENV[AWS_ACCESS_KEY_ID] -s, --aws-secret SECRET Amazon EC2 Secret, defaults to ENV[AWS_SECRET_ACCESS_KEY] -r, --region REGION Amazon EC2 Region, defaults to us-east-1 or ENV[AWS_EC2_REGION] - -t, --tag TAG Tag name for searching, defaults to 'Name'""" + -t, --tag TAG Tag name for searching, defaults to 'Name' + -S, --separator SEP Separator to use between hostname and dns""" def ec2_active_instances(label_tag, filters): @@ -48,8 +49,8 @@ def ec2_active_instances(label_tag, filters): def main(argv): try: - opts, args = getopt.getopt(argv, "hLk:s:r:t:", - ["help", "aws-key=", "aws-secret=", "region=", "tag="]) + opts, args = getopt.getopt(argv, "hLk:s:r:t:S:", + ["help", "aws-key=", "aws-secret=", "region=", "tag=", "separator="]) except getopt.GetoptError, err: print >>sys.stderr, err short_usage() @@ -59,6 +60,7 @@ def main(argv): aws_secret = os.environ.get("AWS_SECRET_ACCESS_KEY") region = os.environ.get("AWS_EC2_REGION") tag = "Name" + separator="\t" for opt, arg in opts: if opt in ("-h", "--help"): @@ -72,6 +74,8 @@ def main(argv): region = arg elif opt in ("-t", "--tag"): tag = arg + elif opt in ("-S", "--separator"): + separator = arg if not aws_key or not aws_secret: if not aws_key: @@ -115,7 +119,7 @@ def main(argv): return elif numinstances == 0 or numinstances > 1: for pair in sorted(instances, key=lambda p: p[0]): - print "%s\t%s" % pair + print "%s%s%s" % (pair[0], separator, pair[1]) sys.exit(0) return diff --git a/bin/ec2-ssh b/bin/ec2-ssh index 3afd98b..a126f15 100755 --- a/bin/ec2-ssh +++ b/bin/ec2-ssh @@ -15,6 +15,9 @@ For a list of instances, run ec2-host without any paramteres -s, SECRET Amazon EC2 Secret, defaults to \$AWS_SECRET_ACCESS_KEY -r, REGION Amazon EC2 Region, defaults to us-east-1 -t, TAG Tag name for searching, defaults to 'Name' + -U, USER Set default user to 'USER' (default 'ubuntu') + -S Disable SSH security (host key checks) + -R Become root via 'sudo -i' after login EOF } @@ -23,13 +26,17 @@ test $# -eq 0 && { usage; exit; } # Process options cmd="ec2-host" -while getopts ":hk:s:r:t:" opt; do +default_user="ubuntu" +while getopts ":hk:s:r:t:U:SR" opt; do case $opt in h ) usage; exit 1;; k ) cmd="$cmd -k $OPTARG";; s ) cmd="$cmd -s $OPTARG";; r ) cmd="$cmd -r $OPTARG";; t ) cmd="$cmd -t $OPTARG";; + U ) default_user="$OPTARG";; + S ) ssh_opts="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=false";; + R ) cmd_extra="&& sudo -i";; \? ) usage; exit 1 esac done @@ -43,7 +50,7 @@ user="${hostparts[0]}" if [ -z "$inst" ]; then inst="$1" - user="ubuntu" + user="$default_user" fi # support tag:value format for identifying instances @@ -59,12 +66,13 @@ else fi # get host from ec2-host command -host=$(eval "$cmd $inst") +host=$(eval "$cmd '$inst'") # pass all other parameters (${@:2}) to ssh allowing # things like: ec2-ssh nginx uptime -cmd="echo \\\". ~/.bashrc && PS1='\[\e]0;$inst: \w\\\a\]\[\\\033[01;32m\]$inst\[\\\033[00m\]:\[\\\033[01;34m\]\w\[\\\033[00m\]\\\$ '\\\" > ~/.ec2sshrc; /bin/bash --rcfile .ec2sshrc -i" + +cmd="echo \\\". ~/.bashrc && PS1='\[\e]0;$inst: \w\\\a\]\[\\\033[01;32m\]$inst\[\\\033[00m\]:\[\\\033[01;34m\]\w\[\\\033[00m\]\\\$ '${cmd_extra}\\\" > ~/.ec2sshrc; /bin/bash --rcfile .ec2sshrc -i" if test "${@:2}"; then cmd="${@:2}" fi -test -n "$host" && echo "Connecting to $host." && exec sh -c "ssh -t $user@$host \"$cmd\"" +test -n "$host" && echo "Connecting to $host." && exec sh -c "ssh $ssh_opts -t $user@$host \"$cmd\"" diff --git a/completion.bash b/completion.bash new file mode 100644 index 0000000..991f76b --- /dev/null +++ b/completion.bash @@ -0,0 +1,24 @@ +_ec2_ssh() { + local cur opts IFS + declare -a hosts + + COMPREPLY=() + cur="${COMP_WORDS[$COMP_CWORD]}" + + opts="-k -s -r -t" + if [ "${cur}" == "-" ]; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + + IFS=$'\n' + if [ "$cur" != "" ]; then + hosts=( $(ec2-host --separator ';' | cut -f1 -d';' | grep $cur) ) + else + hosts=( $(ec2-host --separator ';' | cut -f1 -d';') ) + fi + COMPREPLY=( $(printf '%q\n' "${hosts[@]}") ) + return 0 +} + +complete -F _ec2_ssh ec2-ssh diff --git a/completion.zsh b/completion.zsh new file mode 100644 index 0000000..4eaff5d --- /dev/null +++ b/completion.zsh @@ -0,0 +1,26 @@ +#compdef ec2-ssh + +_ec2_ssh() { + local state IFS + typeset -A opt_args + + _arguments -s -S \ + "-k+[KEY]" \ + "-s+[SECRET]" \ + "-t+[TAG]" \ + "-r+[REGION]" \ + "*: :->hosts" + + case $state in + hosts) + IFS=$'\n' + hosts=( $(ec2-host --separator ';' | cut -f1 -d';') ) + compadd "$@" "${hosts[@]}" + ;; + *) + # nothing for now + ;; + esac +} + +_ec2_ssh "$@"