datacenter 0.3.1 → 0.4.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -1
- data/Rakefile +2 -1
- data/lib/datacenter.rb +2 -1
- data/lib/datacenter/shell/command_error.rb +18 -0
- data/lib/datacenter/shell/local.rb +101 -0
- data/lib/datacenter/shell/remote.rb +80 -0
- data/lib/datacenter/version.rb +1 -1
- data/spec/shell_spec.rb +32 -11
- metadata +5 -3
- data/lib/datacenter/shell.rb +0 -83
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2098304fc0285b30cbe84d111c637bc2f9ed0ca9
|
4
|
+
data.tar.gz: 81dbb70a0d7e4a17dd5f1028ebccb97da5627e02
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d72ca3f494c43436f9eda558deb0f24e0bd163e03581c51ff477db681d7347d4cd62a71681ca6ffd7154d3babb4a00d9ea59878678611d7f8db5330ebefd9350
|
7
|
+
data.tar.gz: eabe4a509235bfb64d5dee6f2cfeeb36bac9ead2d6eeec759b11db7cedd60817f37a660c9ae509497fc0568b3ee7712b48f4b64f60efed690655c902548c2db5
|
data/.travis.yml
CHANGED
@@ -4,8 +4,10 @@ rvm:
|
|
4
4
|
- 2.0
|
5
5
|
- 2.1
|
6
6
|
- 2.2
|
7
|
+
- 2.3.0
|
7
8
|
- jruby
|
8
9
|
before_install:
|
10
|
+
- gem install bundler
|
9
11
|
- sudo apt-get -y install openssh-server
|
10
12
|
- ssh-keygen -q -t rsa -N "" -f ~/.ssh/id_rsa
|
11
|
-
- cp $HOME/.ssh/id_rsa.pub $HOME/.ssh/authorized_keys
|
13
|
+
- cp $HOME/.ssh/id_rsa.pub $HOME/.ssh/authorized_keys
|
data/Rakefile
CHANGED
@@ -5,6 +5,7 @@ Rake::TestTask.new(:spec) do |t|
|
|
5
5
|
t.libs << 'spec'
|
6
6
|
t.pattern = 'spec/**/*_spec.rb'
|
7
7
|
t.verbose = false
|
8
|
+
t.warning = false
|
8
9
|
end
|
9
10
|
|
10
11
|
desc 'Console'
|
@@ -15,4 +16,4 @@ task :console do
|
|
15
16
|
Pry.start
|
16
17
|
end
|
17
18
|
|
18
|
-
task default: :spec
|
19
|
+
task default: :spec
|
data/lib/datacenter.rb
CHANGED
@@ -2,6 +2,7 @@ require 'net/ssh'
|
|
2
2
|
require 'open3'
|
3
3
|
require 'class_config'
|
4
4
|
require 'logger'
|
5
|
+
require 'delegate'
|
5
6
|
|
6
7
|
module Datacenter
|
7
8
|
extend ClassConfig
|
@@ -9,4 +10,4 @@ module Datacenter
|
|
9
10
|
attr_config :process_cache_expiration, 2
|
10
11
|
end
|
11
12
|
|
12
|
-
Dir.glob(File.expand_path('datacenter
|
13
|
+
Dir.glob(File.expand_path('datacenter/**/*.rb', File.dirname(__FILE__))).sort.each { |f| require f }
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Datacenter
|
2
|
+
module Shell
|
3
|
+
class CommandError < StandardError
|
4
|
+
|
5
|
+
attr_reader :command, :error
|
6
|
+
|
7
|
+
def initialize(command, error)
|
8
|
+
@command = command
|
9
|
+
@error = error
|
10
|
+
end
|
11
|
+
|
12
|
+
def message
|
13
|
+
"#{command}\n#{error}"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module Datacenter
|
2
|
+
module Shell
|
3
|
+
class Local
|
4
|
+
|
5
|
+
class SafeIO < SimpleDelegator
|
6
|
+
def initialize(io)
|
7
|
+
@io = io
|
8
|
+
super StringIO.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def write(message)
|
12
|
+
super message
|
13
|
+
@io.write message
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@mutex = Mutex.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def run(command, options={})
|
23
|
+
Datacenter.logger.debug(self.class) { command }
|
24
|
+
|
25
|
+
opts = {
|
26
|
+
chdir: options[:chdir] || Dir.pwd,
|
27
|
+
out: options[:out] || StringIO.new,
|
28
|
+
err: options[:err] || StringIO.new
|
29
|
+
}
|
30
|
+
|
31
|
+
if RUBY_ENGINE == 'jruby'
|
32
|
+
run_system command, opts
|
33
|
+
else
|
34
|
+
run_open3 command, opts
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.open(*args)
|
39
|
+
shell = new *args
|
40
|
+
yield shell
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def run_open3(command, options)
|
46
|
+
status = nil
|
47
|
+
result = nil
|
48
|
+
error = nil
|
49
|
+
|
50
|
+
begin
|
51
|
+
Open3.popen3("#{command}", chdir: options[:chdir]) do |stdin, stdout, stderr, wait_thr|
|
52
|
+
status = wait_thr.value
|
53
|
+
result = stdout.read
|
54
|
+
error = stderr.read
|
55
|
+
|
56
|
+
options[:out] << result
|
57
|
+
options[:err] << error
|
58
|
+
end
|
59
|
+
rescue => ex
|
60
|
+
raise CommandError.new(command, ex.message)
|
61
|
+
end
|
62
|
+
|
63
|
+
raise CommandError.new(command, error) unless status.success?
|
64
|
+
|
65
|
+
result
|
66
|
+
end
|
67
|
+
|
68
|
+
def run_system(command, options)
|
69
|
+
@mutex.synchronize do
|
70
|
+
begin
|
71
|
+
stdout = $stdout
|
72
|
+
stderr = $stderr
|
73
|
+
|
74
|
+
$stdout = SafeIO.new options[:out]
|
75
|
+
$stderr = SafeIO.new options[:err]
|
76
|
+
|
77
|
+
Dir.chdir(options[:chdir]) { system "#{command}" }
|
78
|
+
|
79
|
+
status = $?
|
80
|
+
|
81
|
+
$stdout.rewind
|
82
|
+
$stderr.rewind
|
83
|
+
|
84
|
+
result = $stdout.read.force_encoding('UTF-8')
|
85
|
+
error = $stderr.read.force_encoding('UTF-8')
|
86
|
+
|
87
|
+
raise CommandError.new(command, error) unless status.success?
|
88
|
+
|
89
|
+
result
|
90
|
+
|
91
|
+
ensure
|
92
|
+
$stdout = stdout
|
93
|
+
$stderr = stderr
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Datacenter
|
2
|
+
module Shell
|
3
|
+
class Remote
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
@args = args
|
7
|
+
end
|
8
|
+
|
9
|
+
def open
|
10
|
+
@session ||= Net::SSH.start *args
|
11
|
+
end
|
12
|
+
|
13
|
+
def close
|
14
|
+
if session && !session.closed?
|
15
|
+
session.close
|
16
|
+
@session = nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def run(command, options={})
|
21
|
+
if session
|
22
|
+
run! command, options
|
23
|
+
else
|
24
|
+
self.class.open(*args) { |shell| shell.run command, options }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.open(*args)
|
29
|
+
shell = new *args
|
30
|
+
shell.open
|
31
|
+
yield shell
|
32
|
+
ensure
|
33
|
+
shell.close
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
attr_reader :args, :session
|
39
|
+
|
40
|
+
def run!(command, options={})
|
41
|
+
Datacenter.logger.debug(self.class) { command }
|
42
|
+
|
43
|
+
result = ''
|
44
|
+
error = ''
|
45
|
+
|
46
|
+
out = options[:out] || StringIO.new
|
47
|
+
err = options[:err] || StringIO.new
|
48
|
+
|
49
|
+
exit_code = nil
|
50
|
+
|
51
|
+
session.open_channel do |channel|
|
52
|
+
channel.exec(command) do |ch, success|
|
53
|
+
abort "FAILED: couldn't execute command (ssh.channel.exec)" unless success
|
54
|
+
|
55
|
+
channel.on_data do |ch, data|
|
56
|
+
out << data
|
57
|
+
result << data
|
58
|
+
end
|
59
|
+
|
60
|
+
channel.on_extended_data do |ch, type, data|
|
61
|
+
err << data
|
62
|
+
error << data
|
63
|
+
end
|
64
|
+
|
65
|
+
channel.on_request('exit-status') do |ch, data|
|
66
|
+
exit_code = data.read_long
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
session.loop
|
72
|
+
|
73
|
+
raise CommandError.new(command, error) unless exit_code == 0
|
74
|
+
|
75
|
+
result
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/datacenter/version.rb
CHANGED
data/spec/shell_spec.rb
CHANGED
@@ -3,21 +3,48 @@ require 'minitest_helper'
|
|
3
3
|
describe Datacenter::Shell do
|
4
4
|
|
5
5
|
module SharedExpamples
|
6
|
+
|
7
|
+
let(:shell) { shell_class.new *shell_args }
|
8
|
+
|
6
9
|
it 'Success' do
|
7
10
|
filename = File.join '/tmp', Time.now.to_i.to_s
|
8
11
|
shell.run "echo \"test file\" > #{filename}"
|
9
|
-
shell.run("cat #{filename}").must_equal
|
12
|
+
shell.run("cat #{filename}").must_equal "test file\n"
|
10
13
|
end
|
11
14
|
|
12
15
|
it 'Error' do
|
13
16
|
filename = '/invalid_dir/invalid_file'
|
14
|
-
shell.run
|
17
|
+
error = Proc.new { shell.run "cat #{filename}" }.must_raise Datacenter::Shell::CommandError
|
18
|
+
error.message.must_include "cat: #{filename}: No such file or directory"
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'Block' do
|
22
|
+
shell_class.open(*shell_args) do |shell|
|
23
|
+
shell.run('ls /').must_equal `ls /`
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'Redirect stdout' do
|
28
|
+
out = StringIO.new
|
29
|
+
shell.run 'ls /', out: out
|
30
|
+
out.rewind
|
31
|
+
out.read.must_equal `ls /`
|
15
32
|
end
|
33
|
+
|
34
|
+
it 'Redirect stderr' do
|
35
|
+
err = StringIO.new
|
36
|
+
filename = '/invalid_dir/invalid_file'
|
37
|
+
Proc.new { shell.run "cat #{filename}", err: err }.must_raise Datacenter::Shell::CommandError
|
38
|
+
err.rewind
|
39
|
+
err.read.must_include "cat: #{filename}: No such file or directory"
|
40
|
+
end
|
41
|
+
|
16
42
|
end
|
17
43
|
|
18
44
|
describe 'Local' do
|
19
45
|
|
20
|
-
let(:
|
46
|
+
let(:shell_args) { [] }
|
47
|
+
let(:shell_class) { Datacenter::Shell::Local }
|
21
48
|
|
22
49
|
include SharedExpamples
|
23
50
|
|
@@ -25,17 +52,11 @@ describe Datacenter::Shell do
|
|
25
52
|
|
26
53
|
describe 'Remote' do
|
27
54
|
|
28
|
-
let(:
|
29
|
-
let(:
|
55
|
+
let(:shell_args) { ['localhost', `whoami`.strip] }
|
56
|
+
let(:shell_class) { Datacenter::Shell::Remote }
|
30
57
|
|
31
58
|
include SharedExpamples
|
32
59
|
|
33
|
-
it 'Block' do
|
34
|
-
Datacenter::Shell::Remote.open(*connection_args) do |shell|
|
35
|
-
shell.run('ls /').must_equal `ls /`.strip
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
60
|
end
|
40
61
|
|
41
62
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: datacenter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gabriel Naiman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-ssh
|
@@ -144,7 +144,9 @@ files:
|
|
144
144
|
- lib/datacenter/machine.rb
|
145
145
|
- lib/datacenter/os.rb
|
146
146
|
- lib/datacenter/process.rb
|
147
|
-
- lib/datacenter/shell.rb
|
147
|
+
- lib/datacenter/shell/command_error.rb
|
148
|
+
- lib/datacenter/shell/local.rb
|
149
|
+
- lib/datacenter/shell/remote.rb
|
148
150
|
- lib/datacenter/version.rb
|
149
151
|
- spec/cache_spec.rb
|
150
152
|
- spec/commands.yml
|
data/lib/datacenter/shell.rb
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
module Datacenter
|
2
|
-
module Shell
|
3
|
-
|
4
|
-
class Local
|
5
|
-
|
6
|
-
def initialize
|
7
|
-
@mutex = Mutex.new
|
8
|
-
end
|
9
|
-
|
10
|
-
def run(command)
|
11
|
-
Datacenter.logger.debug(self.class) { command }
|
12
|
-
if RUBY_ENGINE == 'jruby'
|
13
|
-
run_system command
|
14
|
-
else
|
15
|
-
run_open3 command
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def run_open3(command)
|
22
|
-
i,o,e,t = Open3.popen3 command
|
23
|
-
(o.readlines.join + e.readlines.join).strip
|
24
|
-
end
|
25
|
-
|
26
|
-
def run_system(command)
|
27
|
-
@mutex.synchronize do
|
28
|
-
begin
|
29
|
-
$stdout = StringIO.new
|
30
|
-
$stderr = StringIO.new
|
31
|
-
|
32
|
-
system command
|
33
|
-
|
34
|
-
[$stdout, $stderr].map do |io|
|
35
|
-
io.rewind
|
36
|
-
io.readlines.join.force_encoding('UTF-8')
|
37
|
-
end.join.strip
|
38
|
-
|
39
|
-
ensure
|
40
|
-
$stdout = STDOUT
|
41
|
-
$stderr = STDERR
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
class Remote
|
48
|
-
attr_reader :options
|
49
|
-
|
50
|
-
def initialize(*args)
|
51
|
-
@options = args
|
52
|
-
end
|
53
|
-
|
54
|
-
def run(command)
|
55
|
-
Datacenter.logger.debug(self.class) { command }
|
56
|
-
if @session
|
57
|
-
@session.exec!(command).strip
|
58
|
-
else
|
59
|
-
Net::SSH.start(*options) { |ssh| ssh.exec! command }.to_s.strip
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def open
|
64
|
-
@session ||= Net::SSH.start *options
|
65
|
-
end
|
66
|
-
|
67
|
-
def close
|
68
|
-
if @session
|
69
|
-
@session.close
|
70
|
-
@session = nil
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def self.open(*args, &block)
|
75
|
-
shell = new *args
|
76
|
-
shell.open
|
77
|
-
block.call shell
|
78
|
-
shell.close
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
end
|
83
|
-
end
|