closh 0.0.1.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c2ccd50d3128e79f0170e486c6c41960224e9a76
4
+ data.tar.gz: b9e91861f3fc669bc8cf2dc1ca6d8c1bc45b51fd
5
+ SHA512:
6
+ metadata.gz: 334acd5b103683388a71123a76c0e75c4f1d3ef9123a19a6d5afc9169b77a7b9a8f93d65fbb8707bb0349deb2a81e2501126ea88773e0d6c579d72b0c52b116b
7
+ data.tar.gz: f767a8e1e8279cefccfc8c63e02b83510d3e6b9d397b6e4e38958789accadc440ad584dd60d3b07c063b3e8c5cdfde53c0e2f2c4c3c573d6d7215ab52151768c
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Vincent Ollivier
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,99 @@
1
+ Cloud Shell
2
+ ===========
3
+
4
+ A shell running in the cloud
5
+
6
+
7
+ Installation
8
+ ------------
9
+
10
+ $ gem install closh
11
+
12
+ Alternatively you can build the gem from its repository:
13
+
14
+ $ git clone git://github.com/vinc/closh.git
15
+ $ cd closh
16
+ $ gem build closh.gemspec
17
+ $ gem install closh-0.0.1.gem
18
+
19
+
20
+ Usage
21
+ -----
22
+
23
+ Run a command in the cloud:
24
+
25
+ $ closh -x "cut -d . -f 1 /proc/uptime"
26
+ 23
27
+
28
+ More verbose:
29
+
30
+ $ closh -vx "cut -d . -f 1 /proc/uptime"
31
+ debug: uploading SSH public key to AWS ...
32
+ debug: creating server on AWS ...
33
+ debug: connecting to 'ubuntu@158.116.77.89' ...
34
+ debug: executing command 'cut -d . -f 1 /proc/uptime' ...
35
+ 23
36
+ debug: destroying server ...
37
+
38
+ Pipe to stdin:
39
+
40
+ $ echo "cut -d . -f 1 /proc/uptime" | closh -x "bash -s"
41
+
42
+ Run a script remotely:
43
+
44
+ $ closh -x "bash -s" < example.sh
45
+
46
+ Skip the `-x` flag to keep a session alive for long running scripts.
47
+
48
+ Use `-l` to list sessions and `-r` to resume one:
49
+
50
+ $ closh -r 158.116.77.89 "tail -f screenlog.0"
51
+
52
+ More options:
53
+
54
+ $ closh -h
55
+ Usage: closh <command>
56
+
57
+ Cloud Shell v0.0.1
58
+ Options:
59
+ -n, --dry-run Create fake server and run locally
60
+ -c, --config=<s> Config file (default: ~/.closh.yaml)
61
+ -k, --key=<s> SSH public key (default: ~/.ssh/id_rsa.pub)
62
+ -r, --resume=<s> Resume session
63
+ -x, --kill Kill session at the end
64
+ -l, --list List sessions
65
+ -v, --verbose Use verbose mode
66
+ -h, --help Show this message
67
+ -V, --version Print version and exit
68
+
69
+
70
+ Configure
71
+ ---------
72
+
73
+ Cloud Shell is based on [Fog](http://fog.io/) under the hood to create compute
74
+ servers.
75
+
76
+ The configuration is stored in a YAML file (`~/.closh.yaml`). It is divided in
77
+ two parts: compute and server. The former being fed to `Fog::Compute.new` and
78
+ the latter to `Fog::Compute::*::Server.new`.
79
+
80
+ ```yaml
81
+ ---
82
+
83
+ compute:
84
+ provider: AWS
85
+ aws_access_key_id: <%= ENV["AWS_ACCESS_KEY_ID"] %>
86
+ aws_secret_access_key: <%= ENV["AWS_SECRET_ACCESS_KEY"] %>
87
+ region: us-west-2
88
+
89
+ server:
90
+ image_id: ami-70728c08 # ubuntu 17.04 amd64 hvm:ebs-ssd
91
+ flavor_id: t2.micro
92
+ username: ubuntu
93
+ ```
94
+
95
+
96
+ License
97
+ -------
98
+
99
+ Copyright (C) 2017 Vincent Ollivier. Released under MIT.
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "closh"
4
+
5
+ CloudShell::CLI.run
@@ -0,0 +1,6 @@
1
+ require "closh/session"
2
+ require "closh/cli"
3
+ require "closh/version"
4
+
5
+ module CloudShell
6
+ end
@@ -0,0 +1,63 @@
1
+ require "active_support/core_ext/object/blank"
2
+ require "active_support/hash_with_indifferent_access"
3
+ require "erb"
4
+ require "trollop"
5
+ require "yaml"
6
+
7
+ module CloudShell
8
+ module CLI
9
+ def self.run
10
+ opts = self.parse_opts(ARGV)
11
+
12
+ config_path = File.expand_path(opts[:config])
13
+ config = YAML.load(ERB.new(File.read(config_path)).result).deep_symbolize_keys
14
+
15
+ shell = CloudShell::Session.new(config, opts)
16
+
17
+ if opts[:list]
18
+ shell.list_servers
19
+ exit
20
+ end
21
+
22
+ if opts[:resume]
23
+ shell.find_server(opts[:resume])
24
+ else
25
+ key_path = File.expand_path(opts[:key])
26
+ key_body = File.read(key_path)
27
+ shell.upload_ssh_key(key_body)
28
+
29
+ shell.create_server
30
+ end
31
+
32
+ begin
33
+ command = ARGV.join(" ").presence || "$SHELL"
34
+ shell.exec(command) do |channel|
35
+ unless STDIN.tty?
36
+ channel.send_data(STDIN.read)
37
+ channel.eof!
38
+ end
39
+ end
40
+ ensure
41
+ shell.destroy_server if opts[:kill]
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def self.parse_opts(args)
48
+ Trollop::options(ARGV) do
49
+ version "Cloud Shell v#{CloudShell::VERSION}"
50
+ usage "<command>"
51
+ opt :dry_run, "Create fake server and run locally", short: "n"
52
+ opt :config, "Config file", type: :string, default: "~/.closh.yaml"
53
+ opt :key, "SSH public key", type: :string, default: "~/.ssh/id_rsa.pub"
54
+ opt :resume, "Resume session", type: :string
55
+ opt :kill, "Kill session at the end", short: "x"
56
+ opt :list, "List sessions"
57
+ opt :verbose, "Use verbose mode"
58
+ opt :help, "Show this message"
59
+ opt :version, "Print version and exit", short: "V"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,95 @@
1
+ require "fog"
2
+ require "net/ssh"
3
+ require "rainbow"
4
+
5
+ module CloudShell
6
+ class Session
7
+ def initialize(config, options)
8
+ @config = config
9
+ @provider = config[:compute][:provider]
10
+ @key_name = config[:compute][:key_name] || "closh"
11
+
12
+ @options = options
13
+ Fog.mock! if options[:dry_run]
14
+
15
+ @compute = Fog::Compute.new(config[:compute])
16
+ end
17
+
18
+ def upload_ssh_key(key)
19
+ if @compute.key_pairs.get(@key_name).nil?
20
+ debug("uploading SSH public key to #{@provider} ...")
21
+ @compute.import_key_pair(@key_name, key)
22
+ end
23
+ end
24
+
25
+ def list_servers
26
+ debug("listing servers on #{@provider} ...")
27
+ @compute.servers.each do |server|
28
+ puts server.public_ip_address if server.public_ip_address
29
+ end
30
+ end
31
+
32
+ def find_server(address)
33
+ debug("finding server on #{@provider} ...")
34
+ config = @config[:server]
35
+ @username = config[:username] || "root"
36
+ @compute.servers.each do |server|
37
+ return @server = server if server.public_ip_address == address
38
+ end
39
+ error("could not find server on #{@provider}")
40
+ exit 1
41
+ end
42
+
43
+ def create_server
44
+ debug("creating server on #{@provider} ...")
45
+ config = @config[:server].merge({ key_name: @key_name })
46
+ @username = config[:username] || "root"
47
+ @server = @compute.servers.create(config)
48
+ @server.wait_for { ready? }
49
+ end
50
+
51
+ def destroy_server
52
+ debug("destroying server ...")
53
+ @server.destroy
54
+ end
55
+
56
+ def exec(command, &block)
57
+ debug("connecting to '#{@username}@#{@server.public_ip_address}' ...")
58
+ if @options[:dry_run]
59
+ debug("executing command '#{command}' ...")
60
+ system(command)
61
+ else
62
+ Net::SSH.start(@server.public_ip_address, @username) do |ssh|
63
+ ssh.open_channel do |channel|
64
+ debug("executing command `#{command}` ...")
65
+ channel.exec(command) do |_, success|
66
+ channel.on_data do |_, data|
67
+ print data
68
+ end
69
+
70
+ if block_given?
71
+ block.call(channel)
72
+ end
73
+ end
74
+ end
75
+ ssh.loop
76
+ end
77
+ end
78
+ rescue Errno::ECONNREFUSED
79
+ n = 10
80
+ error("connection refused, retrying in #{n} seconds")
81
+ sleep n
82
+ retry
83
+ end
84
+
85
+ private
86
+
87
+ def debug(text)
88
+ puts Rainbow("debug: ").cyan + text if @options[:verbose]
89
+ end
90
+
91
+ def error(text)
92
+ puts Rainbow("error: ").yellow + text if @options[:verbose]
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,3 @@
1
+ module CloudShell
2
+ VERSION = "0.0.1.alpha.1".freeze
3
+ end
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: closh
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.alpha.1
5
+ platform: ruby
6
+ authors:
7
+ - Vincent Ollivier
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-10-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.1'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 5.1.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '5.1'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 5.1.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: fog
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.42'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.42.0
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.42'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.42.0
53
+ - !ruby/object:Gem::Dependency
54
+ name: net-ssh
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '4.1'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 4.1.0
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '4.1'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 4.1.0
73
+ - !ruby/object:Gem::Dependency
74
+ name: rainbow
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '2.2'
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 2.2.0
83
+ type: :runtime
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.2'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 2.2.0
93
+ - !ruby/object:Gem::Dependency
94
+ name: trollop
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '2.1'
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 2.1.0
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '2.1'
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 2.1.0
113
+ - !ruby/object:Gem::Dependency
114
+ name: rspec
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: '3.6'
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: 3.6.0
123
+ type: :development
124
+ prerelease: false
125
+ version_requirements: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '3.6'
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: 3.6.0
133
+ description: Closh automatically bootstrap servers in the cloud to run shell commands
134
+ email: v@vinc.cc
135
+ executables:
136
+ - closh
137
+ extensions: []
138
+ extra_rdoc_files: []
139
+ files:
140
+ - LICENSE
141
+ - README.md
142
+ - bin/closh
143
+ - lib/closh.rb
144
+ - lib/closh/cli.rb
145
+ - lib/closh/session.rb
146
+ - lib/closh/version.rb
147
+ homepage: https://github.com/vinc/closh
148
+ licenses:
149
+ - MIT
150
+ metadata: {}
151
+ post_install_message:
152
+ rdoc_options: []
153
+ require_paths:
154
+ - lib
155
+ required_ruby_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ required_rubygems_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">"
163
+ - !ruby/object:Gem::Version
164
+ version: 1.3.1
165
+ requirements: []
166
+ rubyforge_project:
167
+ rubygems_version: 2.6.11
168
+ signing_key:
169
+ specification_version: 4
170
+ summary: A shell running in the cloud
171
+ test_files: []