Skip to content

Commit 7d6c44e

Browse files
committed
First commit
0 parents  commit 7d6c44e

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed

ec2ssh

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
#!/usr/bin/env perl
2+
3+
use strict;
4+
use warnings;
5+
use Getopt::Long qw/:config pass_through/;
6+
use Pod::Usage;
7+
use JSON;
8+
9+
sub describe_instances {
10+
# Query using the AWS command line interface for a list of ec2 instances
11+
# matching an $instance_name where $instance_name=tag:value and the 'tag:'
12+
# portion is optional defaulting to 'Name'
13+
my ($instance_name, $profile, $region, $filters, $debug)= @_;
14+
my ($tag_name, $tag_value)
15+
= $instance_name =~ /:/
16+
? split /:/, $instance_name
17+
: ('Name', $instance_name);
18+
19+
my $cmd=
20+
"aws ec2 describe-instances --output json --color off --no-paginate";
21+
$cmd.= " --filters Name=tag:$tag_name,Values=$tag_value" if $tag_value;
22+
$cmd.= " --profile $profile" if $profile;
23+
$cmd.= " --region $region" if $region;
24+
$cmd.= " --filters $filters" if $filters;
25+
print STDERR "Describing Instances\n\$ $cmd\n" if $debug;
26+
27+
my @instances;
28+
my $reservations= `$cmd`;
29+
die "External command failed: $cmd" if $?;
30+
my $reservations_ref = from_json($reservations);
31+
foreach my $reservation (@{$reservations_ref->{Reservations}}) {
32+
foreach my $instance (@{$reservation->{Instances}}) {
33+
my $public_dns= $instance->{PublicDnsName} || 'None';
34+
my $private_dns= $instance->{PrivateDnsName} || 'None';
35+
my $name = 'None';
36+
foreach my $tag (@{$instance->{Tags}}) {
37+
$name= $tag->{Value} if $tag->{Key} eq 'Name';
38+
}
39+
push @instances, join "\t", ($name, $public_dns, $private_dns);
40+
}
41+
}
42+
return @instances;
43+
}
44+
45+
my $help = 0;
46+
my $valid_options = 0;
47+
my $debug = 0;
48+
my $list = 0;
49+
my $profile = '';
50+
my $region = '';
51+
my $filters = '';
52+
my $private = 0;
53+
$valid_options= GetOptions(
54+
'help|?' => \$help,
55+
'debug|d' => \$debug,
56+
'list' => \$list,
57+
'profile=s' => \$profile,
58+
'region=s' => \$region,
59+
'filters=s' => \$filters,
60+
'private' => \$private,
61+
);
62+
63+
# Parse instance-name
64+
my $instance_parts= $ARGV[0] || '';
65+
my ($user, $instance_name);
66+
if ($instance_parts =~ m/\@/) {
67+
($user, $instance_name)= split /\@/, $instance_parts;
68+
}
69+
else {
70+
$instance_name= $instance_parts;
71+
}
72+
pod2usage(
73+
-verbose => 2,
74+
-noperldoc => 1
75+
) if $help || !$valid_options;
76+
77+
# Retrieve a list of instances matching instance-name
78+
my @instances=
79+
describe_instances($instance_name, $profile, $region, $filters, $debug);
80+
my $instance_count = scalar @instances;
81+
if($list or $instance_count != 1) {
82+
# Display matching instances
83+
print join("\n", @instances), "\n";
84+
}
85+
else {
86+
# Open an ssh connection to matching instance
87+
my ($tag_name, $public_dns, $private_dns) = split /\t/, $instances[0];
88+
# Connect using the public_dns, if it doesn't exist or if the user set the
89+
# private flag then use the private_dns
90+
my $hostname
91+
= $public_dns ne 'None' && !$private ? $public_dns
92+
: $private_dns ne 'None' ? $private_dns
93+
: undef;
94+
if($hostname) {
95+
$hostname = "$user\@$hostname" if $user;
96+
my $ssh_args = join " ", grep { $_ ne $instance_parts } @ARGV;
97+
print STDERR "Connecting to $hostname [$tag_name]\n";
98+
print STDERR "\$ ssh $hostname $ssh_args\n" if $debug;
99+
exec("ssh $hostname $ssh_args");
100+
}
101+
else {
102+
print STDERR "Matching instance ($tag_name) has no public or private DNS name\n";
103+
}
104+
}
105+
106+
1;
107+
108+
=head1 NAME
109+
110+
ec2ssh - SSH to Amazon EC2 instances via tag name
111+
112+
=head1 SYNOPSIS
113+
114+
ec2ssh [OPTIONS] instance-name [SSH-OPTIONS]
115+
116+
Options:
117+
-? --help Display this help and exits.
118+
-d --debug Turn on debug logging.
119+
--list Return a list of matching instances.
120+
--profile Use a specific profile from your aws credential file.
121+
--region The region to use, overrides config/env settings.
122+
--filters A list of filters used to match properties for instances. For a complete reference to the available filter keys for this operation, see the Amazon EC2 API reference.
123+
--private Force ssh to connect using the private dns name.
124+
125+
SSH-Options
126+
127+
All ssh options are supported provided they are passed in *AFTER* the instance-name.
128+
129+
Examples:
130+
# SSH to EC2 instance whose name is bowker-imageweb
131+
ec2ssh bowker-imageweb
132+
133+
# SSH to ec2 instance using an identity file
134+
ec2ssh bowker-imageweb -i /path/to/identity-file
135+
136+
# SSH to ec2 instance as a specific 'user'
137+
ec2ssh user@bowker-imageweb
138+
139+
# List all ec2 instances associated with the default profile
140+
ec2ssh --list
141+
142+
# List all ec2 instances that start with the tag name 'bowker'
143+
ec2ssh --list bowker*
144+
145+
# SSH to ec2 instance named bowker-imageweb in a different region
146+
ec2ssh --region us-west-2 bowker-imageweb
147+
148+
# SSH to ec2 instance and execute command 'whoami'
149+
ec2ssh bowker-imageweb whoami
150+
151+
# SSH to ec2 instance that is part of a specific profile (non-default)
152+
ec2ssh --profile pqis bowker-imageweb
153+
154+
# SSH to ec2 instance using it's private DNS name
155+
ec2ssh --private bowker-imageweb
156+
157+
=head1 DESCRIPTION
158+
159+
Open an ssh connection to an EC2 instance where <instance-name> equals
160+
tag:value. The 'tag:' portion of <instance-name> is optional, and defaults to
161+
'Name'. A list of instances will be returned when using the --list parameter
162+
or if more then one matching instance is found.
163+
164+
All ssh options are supported as long as they are passed in *AFTER* the
165+
<instance-name>.
166+
167+
Please note, this command wraps the AWS Command Line Interface tool which must
168+
be installed and configured (http://aws.amazon.com/cli/) prior to it's use.
169+
Please follow these instructions to install the AWS CLI:
170+
171+
# Install AWS CLI
172+
$ sudo pip install awscli
173+
174+
# Configure AWS CLI 'default' profile
175+
$ aws configure
176+
177+
# Additional profiles can be configured as follows
178+
$ aws configure --profile <profile-name>
179+
180+
=head1 AUTHOR
181+
182+
Peter Williams
183+
184+
=head1 LICENSE
185+
186+
This library is free software; you may redistribute it and/or modify it under
187+
the same terms as Perl itself.
188+
189+
=cut

0 commit comments

Comments
 (0)