Commits

Pior Bastida  committed 6ba3387

added ec2ssh command

  • Participants
  • Parent commits c7c31dd

Comments (0)

Files changed (2)

File scripts/ec2ssh

+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2012 Ludia Inc.
+# This software is licensed as described in the file LICENSE, which
+# you should have received as part of this distribution.
+# Author: Pior Bastida <pbastida@socialludia.com>
+
+import os
+import subprocess
+import argparse
+
+import argh
+from argh.exceptions import CommandError
+
+from awstools import ec2helper
+
+HELP_INSTANCE = "Instance or list of instances"
+HELP_COMMAND = "Command to run on the instances"
+HELP_LIST = "List instances by name"
+HELP_CONFIRM = "Always confirm"
+HELP_VERBOSE = "Verbose mode"
+HELP_ONE = "Run on the first instance found only"
+HELP_YES = "Always answer yes"
+
+epilog = """The 'instance' argument can be one or multiple specifiers
+separated by commas.
+
+valid specifiers:
+    Private IP:             12.34.567.89
+    Instance ID:            i-1a2b3c4d5e
+    Tag Name (or altName):  tt-api-stage
+    Wildcard on tag Name:   tt-api-*"""
+
+
+@argh.arg('instance', default=None, nargs='?', help=HELP_INSTANCE)
+@argh.arg('command', default=None, nargs='*', help=HELP_COMMAND)
+@argh.arg('-l', '--list', default=False, help=HELP_LIST)
+@argh.arg('-c', '--confirm', default=False, help=HELP_CONFIRM)
+@argh.arg('-v', '--verbose', default=False, help=HELP_VERBOSE)
+@argh.arg('-y', '--yes', default=False, help=HELP_YES)
+@argh.arg('-1', '--one', default=False, help=HELP_ONE)
+@argh.wrap_errors(ValueError)
+def connect(args):
+    """SSH to multiple EC2 instances by name, instance-id or private ip"""
+
+    if args.list:
+        instances = ec2helper.get_instances()
+        names = sorted([ec2helper.get_name(i) for i in instances])
+        yield '\n'.join(names)
+
+    elif args.instance is None:
+        raise CommandError("No instances specified.")
+
+    else:
+        if args.confirm and args.yes:
+            raise CommandError("Option confirm and yes are not compatible")
+
+        try:
+            specifiers = args.instance.lower().strip().split(',')
+            instances = ec2helper.filter_instances(
+                specifiers,
+                ec2helper.get_instances(),
+                )
+            if len(instances) == 0:
+                raise CommandError("No instances found.")
+        except KeyboardInterrupt:
+            raise CommandError("Killed while accessing AWS api.")
+
+        if args.one:
+            instances = instances[0:1]
+
+        if len(instances) > 1 or args.confirm:
+            args.verbose = True
+        if len(instances) > 1 and not args.yes:
+            args.confirm = True
+
+        if args.verbose and args.command:
+            yield '----- Command: %s' % ' '.join(args.command)
+        if args.verbose:
+            names = sorted([ec2helper.get_name(i) for i in instances])
+            yield '----- Instances(%s): %s' % (len(names), ",".join(names))
+
+        if args.confirm:
+            if not argh.confirm('Confirm', default=True):
+                raise CommandError("Aborted")
+
+        if len(instances) == 1:
+            host = instances[0].public_dns_name
+            try:
+                os.execvp('ssh', ['ec2ssh', host] + args.command)
+            except OSError as e:
+                raise Exception("Failed to call the ssh command: %s" % e)
+        else:
+
+            for instance in instances:
+                if args.verbose:
+                    yield "----- %s: %s  %s" % (
+                        instance.id,
+                        instance.public_dns_name,
+                        instance.private_ip_address,
+                        )
+
+                host = instances[0].public_dns_name
+                subprocess.call(['ssh', host] + args.command)
+
+        if args.verbose:
+            yield '----- DONE'
+
+
+def main():
+    parser = argh.ArghParser(epilog=epilog,
+                        formatter_class=argparse.RawDescriptionHelpFormatter)
+    parser.set_default_command(connect)
+    parser.dispatch()
+
+if __name__ == '__main__':
+    main()
 packages =
     awstools
     awstools.tests
-scripts = scripts/cfn
+scripts = 
+    scripts/cfn
+    scripts/ec2ssh
 
 [nosetests]
 where = awstools