aws-ssh 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/bin/aws-ssh +162 -0
  3. metadata +5 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 528f3fee7a959f32e7e5cda371d4e35fe98fe403
4
- data.tar.gz: d5d3faf114cd04448bd45ea259d4b1a9e69b8428
3
+ metadata.gz: 78ca737b88d4a338e7f18dfab077b2fe7948d1ba
4
+ data.tar.gz: 3b14eb94c34a986a0afe5412e5167681ad599b93
5
5
  SHA512:
6
- metadata.gz: 037d03e913644404aad34e487c3709d1a62c1b068efe018583c653066dfa7f96f3a1b1b390e6f9ceff0a2651bede193185fa95e5a9b5d2dc9f2c6e346e5c901b
7
- data.tar.gz: 3560dd269f9687cd9f17a56cdd47b04d34031531887b948b527b537d4f419ab3d4d6a4f8c98aa9a8e53d04646b4b0c927356b530801f5700b6a0b10ba63a2c40
6
+ metadata.gz: 7643046e0babf3bd28ee73ebc595148929dd14524aa02992c4b1e91c05f385d31b65521c43470181af647cb0082689eb8aada2567fe21f580a364064dcfbd78b
7
+ data.tar.gz: fe55c550ecda8d8dfdd1577a06b1ca7a97becce04299218d6d332f95bf1708d4f251b02a2b5c686d4e6a1da3c0913ad01236672e885a58c824d9da719922d83a
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'slop'
4
+ require 'aws-sdk'
5
+ require 'yaml'
6
+
7
+ module AWSSH
8
+ class Runner
9
+ DEFAULT_OPTIONS = {
10
+ 'user' => ENV['user'],
11
+ 'format' => 'ssh',
12
+ 'verbose' => false
13
+ }
14
+
15
+ attr_accessor :host_regex
16
+
17
+ def run
18
+ self.host_regex = cli.args.first
19
+ exit_error! 'AWS Region not set' unless cli[:region]
20
+ exit_error! 'AWS Profile not set' unless cli[:profile]
21
+
22
+ shout "Hostname: #{host_regex}"
23
+ shout "Options: #{cli.to_h.inspect}"
24
+ shout "Defaults: #{defaults.inspect}"
25
+
26
+ Aws.config.merge!(profile: cli[:profile], region: cli[:region])
27
+
28
+ if cli['show-only']
29
+ print_output
30
+ else
31
+ ssh!
32
+ end
33
+ end
34
+
35
+ def cli
36
+ @cli ||= Slop.parse do |o|
37
+ o.banner = <<-USAGE
38
+ awssh - a tool that makes easy to ssh into AWS EC2 servers
39
+
40
+ Usage: awssh [hostname regex]
41
+
42
+ Examples:
43
+ $ awssh prod.*app2
44
+ ... will SSH into the instance and you will see:
45
+ user@prod-rails-app4~$
46
+
47
+ $ awssh --show-only --stack qa -u worker
48
+ ... will show all instances registered in QA stack of Opsworks
49
+ ssh worker@10.20.30.40 => MyApp QA - qa-rails-app
50
+ ssh worker@10.20.30.41 => MyApp QA - qa-sidekiq
51
+
52
+ # All hosts in one-line (suitable for CSSH):
53
+ worker@10.20.30.40 worker@10.20.30.41
54
+ USAGE
55
+
56
+ o.separator "Options:"
57
+ o.string '-s', '--stack', 'stack name regex. E.g: `-s prod` will match "Production" stack name'
58
+ o.string '-p', '--profile', 'AWS config profile name. Default: profile set in .awssh file', default: defaults['profile']
59
+ o.string '-r', '--region', 'region. E.g: us-east-1. Default: region set in .awssh file', default: defaults['region']
60
+ o.string '-u', '--user', 'SSH username to use. Default: user set in .awssh file or current machine user', default: defaults['user']
61
+ o.bool '-so', '--show-only', 'Only show the matched hosts instead of ssh. Default: false', default: false
62
+ o.bool '-cs', '--csensitive', 'Uses case-sensitive for regex matching. Default: false', default: false
63
+ o.bool '-v', '--verbose', 'Verbose mode. Default: false', default: false
64
+ o.on '--help', 'Shows help' do
65
+ puts o
66
+ exit
67
+ end
68
+ end
69
+ end
70
+
71
+ def ssh!
72
+ if instances.size > 1
73
+ print_output
74
+ exit_error! "\nMultiple hostnames matched. Please be more specific in hostnames regex or use the last output line to use CSSH.\n"
75
+ end
76
+ exec "ssh #{connection_string(instances.first)}"
77
+ end
78
+
79
+ def print_output
80
+ instances.each do |i|
81
+ puts "ssh #{connection_string(i)} \t => #{i.name}"
82
+ end
83
+ puts "\n# All hosts in one-line (suitable for CSSH):"
84
+ puts instances.map { |i| connection_string(i) }.join(' ')
85
+ end
86
+
87
+ def connection_string(instance)
88
+ "#{cli[:user]}@#{instance.ip}"
89
+ end
90
+
91
+ def defaults
92
+ @defaults ||= begin
93
+ defaults = File.exist?('.awssh') ? YAML.load_file('.awssh') : {}
94
+ DEFAULT_OPTIONS.merge(defaults)
95
+ end
96
+ end
97
+
98
+ def instances
99
+ @instances ||= AWSEC2.new.instances(host_regex, cli[:stack], cli[:csensitive]).select do |i|
100
+ shout "Instance #{i.name} is not part of an Opsworks Stack" unless i.stack_name
101
+ shout "Instance #{i.name} not running. Current state: #{i.state}" unless i.running?
102
+ i.running?
103
+ end
104
+ end
105
+
106
+ def exit_error!(msg)
107
+ $stderr.puts msg
108
+ exit(1)
109
+ end
110
+
111
+ def shout(msg)
112
+ puts "[DEBUG] #{msg}" if cli.verbose?
113
+ end
114
+ end
115
+
116
+ EC2Instance = Struct.new(:name, :hostname, :stack_name, :state, :ip) do
117
+ def initialize(instance)
118
+ name = extract_tag(instance, 'Name')
119
+ hostname = extract_tag(instance, 'opsworks:instance')
120
+ stack_name = extract_tag(instance, 'opsworks:stack')
121
+
122
+ super(name, hostname, stack_name, instance.state.name, instance.public_ip_address)
123
+ end
124
+
125
+ def running?
126
+ state == 'running'
127
+ end
128
+
129
+ def extract_tag(instance, tag)
130
+ tag = instance.tags.find { |t| t.key == tag }
131
+ tag ? tag.value : nil
132
+ end
133
+ end
134
+
135
+ class AWSEC2
136
+ def instances(host_regex, stack_regex, case_sensitive)
137
+ ec2.describe_instances.reservations.map(&:instances).flatten.map do |instance_data|
138
+ instance = EC2Instance.new(instance_data)
139
+ if stack_regex
140
+ next unless word_match?(instance.stack_name, stack_regex, case_sensitive)
141
+ end
142
+ if host_regex
143
+ next unless word_match?(instance.hostname, host_regex, case_sensitive)
144
+ next unless word_match?(instance.name, host_regex, case_sensitive)
145
+ end
146
+
147
+ instance
148
+ end.compact.sort_by(&:name)
149
+ end
150
+
151
+ def ec2
152
+ @ec2 ||= Aws::EC2::Client.new
153
+ end
154
+
155
+ def word_match?(value, regex_str, case_sensitive)
156
+ regex = case_sensitive ? /#{regex_str}/ : /#{regex_str}/i
157
+ !!(value =~ regex)
158
+ end
159
+ end
160
+ end
161
+
162
+ AWSSH::Runner.new.run
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws-ssh
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rafael Sales
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-17 00:00:00.000000000 Z
11
+ date: 2015-08-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: slop
@@ -43,11 +43,13 @@ email:
43
43
  - rafaelcds@gmail.com
44
44
  executables:
45
45
  - awssh
46
+ - aws-ssh
46
47
  extensions: []
47
48
  extra_rdoc_files: []
48
49
  files:
50
+ - bin/aws-ssh
49
51
  - bin/awssh
50
- homepage: https://github.com/buzzstarter/awssh
52
+ homepage: https://github.com/buzzstarter/aws-ssh
51
53
  licenses:
52
54
  - MIT
53
55
  metadata: {}