anywhere 0.0.1 → 0.0.2
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.
- data/README.md +5 -0
- data/Rakefile +6 -0
- data/anywhere.gemspec +1 -1
- data/lib/anywhere/base.rb +31 -5
- data/lib/anywhere/local.rb +7 -3
- data/lib/anywhere/logger.rb +32 -11
- data/lib/anywhere/ssh.rb +6 -2
- data/lib/anywhere/version.rb +1 -1
- data/spec/integration/ssh_integration_spec.rb +46 -9
- data/spec/lib/anywhere/local_spec.rb +17 -3
- data/spec/lib/anywhere/logger_spec.rb +33 -0
- metadata +3 -3
data/README.md
CHANGED
@@ -34,6 +34,11 @@ Or install it yourself as:
|
|
34
34
|
=> [<run_time=0.06875, cmd=<uptime>, stdout=<1 lines, 72 chars>, stderr=<empty>, exit_status=0>,
|
35
35
|
<run_time=0.067885, cmd=<uptime>, stdout=<1 lines, 72 chars>, stderr=<empty>, exit_status=0>]
|
36
36
|
|
37
|
+
## Running the specs
|
38
|
+
|
39
|
+
For the ssh integration rest you need to have some host (could be your local vagrant) you can access as root. This host must be
|
40
|
+
set in the `SSH_TEST_HOST` instance variable.
|
41
|
+
|
37
42
|
## Contributing
|
38
43
|
|
39
44
|
1. Fork it
|
data/Rakefile
CHANGED
data/anywhere.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency "net-ssh"
|
22
|
-
spec.add_dependency "
|
22
|
+
spec.add_dependency "rainbow"
|
23
23
|
spec.add_dependency "pry"
|
24
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
25
25
|
spec.add_development_dependency "rake"
|
data/lib/anywhere/base.rb
CHANGED
@@ -13,12 +13,38 @@ module Anywhere
|
|
13
13
|
whoami == "root"
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
|
16
|
+
def capture(path, compressed = false)
|
17
|
+
io = StringIO.new
|
18
|
+
cmd = "cat #{path}"
|
19
|
+
cmd << " | gzip " if compressed
|
20
|
+
execute(cmd, nil, io)
|
21
|
+
io.rewind
|
22
|
+
out = io.read
|
23
|
+
if compressed
|
24
|
+
# not sure why this is not working with the uncompress method
|
25
|
+
out, s = Open3.capture2("cat - | gunzip", stdin_data: out)
|
26
|
+
out
|
27
|
+
else
|
28
|
+
out
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def uncompress(string)
|
33
|
+
require "zlib"
|
34
|
+
require "base64"
|
35
|
+
zstream = Zlib::Inflate.new
|
36
|
+
buf = zstream.inflate(string)
|
37
|
+
zstream.finish
|
38
|
+
zstream.close
|
39
|
+
buf
|
40
|
+
end
|
41
|
+
|
42
|
+
def execute(cmd, stdin = nil, stdout = nil)
|
43
|
+
do_execute(cmd, stdin, stdout) do |stream, data|
|
18
44
|
data.split("\n").each do |line|
|
19
45
|
if stream == :stderr
|
20
46
|
logger.error line
|
21
|
-
|
47
|
+
elsif !stdout
|
22
48
|
logger.debug line
|
23
49
|
end
|
24
50
|
end
|
@@ -77,7 +103,7 @@ module Anywhere
|
|
77
103
|
end
|
78
104
|
end
|
79
105
|
logger.info "writing #{content.length} bytes to #{path} (md5: #{md5})"
|
80
|
-
tmp_path = "/
|
106
|
+
tmp_path = "/tmp/anywhere/files.#{md5}"
|
81
107
|
execute("#{sudo_cmd} mkdir -p #{File.dirname(tmp_path)}")
|
82
108
|
execute("#{sudo_cmd} chown #{whoami} #{File.dirname(tmp_path)}")
|
83
109
|
logger.debug "writing to #{tmp_path}"
|
@@ -94,7 +120,7 @@ module Anywhere
|
|
94
120
|
logger.debug "moving #{tmp_path} to #{path}"
|
95
121
|
if file_exists?(path)
|
96
122
|
logger.debug "diff #{path} #{tmp_path}"
|
97
|
-
execute("diff #{tmp_path} #{path}").stdout.split("\n").each do |line|
|
123
|
+
execute("diff #{tmp_path} #{path}; /bin/true").stdout.split("\n").each do |line|
|
98
124
|
logger.debug line
|
99
125
|
end
|
100
126
|
end
|
data/lib/anywhere/local.rb
CHANGED
@@ -5,7 +5,7 @@ require "anywhere/base"
|
|
5
5
|
|
6
6
|
module Anywhere
|
7
7
|
class Local < Base
|
8
|
-
def do_execute(cmd, stdin_data = nil)
|
8
|
+
def do_execute(cmd, stdin_data = nil, stdout_io = nil)
|
9
9
|
require "open3"
|
10
10
|
result = Result.new(cmd)
|
11
11
|
result.started!
|
@@ -19,10 +19,14 @@ module Anywhere
|
|
19
19
|
stream.each do |line|
|
20
20
|
if stream == stdout
|
21
21
|
result.add_stdout(line.strip)
|
22
|
-
|
22
|
+
if stdout_io
|
23
|
+
stdout_io << line
|
24
|
+
else
|
25
|
+
logger.debug(line)
|
26
|
+
end
|
23
27
|
elsif stream == stderr
|
24
28
|
result.add_stderr(line.strip)
|
25
|
-
logger.error(line)
|
29
|
+
logger.error(line)
|
26
30
|
end
|
27
31
|
end
|
28
32
|
end
|
data/lib/anywhere/logger.rb
CHANGED
@@ -1,9 +1,27 @@
|
|
1
|
-
require "
|
1
|
+
require "rainbow"
|
2
2
|
require "time"
|
3
|
+
require "logger"
|
3
4
|
|
4
5
|
module Anywhere
|
5
6
|
class Logger
|
7
|
+
LEVELS = {
|
8
|
+
DEBUG: 0,
|
9
|
+
INFO: 1,
|
10
|
+
WARN: 2,
|
11
|
+
ERROR: 3,
|
12
|
+
FATAL: 4,
|
13
|
+
UNKNOWN: 5
|
14
|
+
}
|
15
|
+
|
16
|
+
COLORS = {
|
17
|
+
0 => "#6d6d6d", # 109, 109, 109
|
18
|
+
1 => "#227000", # 34, 112
|
19
|
+
2 => "#f79700", # 247, 151
|
20
|
+
3 => "#f00000", # 240, 0
|
21
|
+
}
|
22
|
+
|
6
23
|
attr_accessor :prefix
|
24
|
+
attr_writer :log_level
|
7
25
|
|
8
26
|
class << self
|
9
27
|
def mutex
|
@@ -11,6 +29,10 @@ module Anywhere
|
|
11
29
|
end
|
12
30
|
end
|
13
31
|
|
32
|
+
def log_level
|
33
|
+
@log_level ||= ::Logger::INFO
|
34
|
+
end
|
35
|
+
|
14
36
|
def initialize(attributes = {})
|
15
37
|
@attributes = attributes
|
16
38
|
end
|
@@ -23,16 +45,15 @@ module Anywhere
|
|
23
45
|
@attributes[:stream] ||= STDOUT
|
24
46
|
end
|
25
47
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
print_with_prefix "DEBUG".blue + " #{message}"
|
48
|
+
LEVELS.each do |name, l|
|
49
|
+
define_method(name.downcase) do |message|
|
50
|
+
return if log_level > l
|
51
|
+
prefix = "%05s" % [name.to_s]
|
52
|
+
if color = COLORS[l]
|
53
|
+
prefix = prefix.color(color)
|
54
|
+
end
|
55
|
+
print_with_prefix "%s %s" % [prefix, message]
|
56
|
+
end
|
36
57
|
end
|
37
58
|
|
38
59
|
def print_with_prefix(message)
|
data/lib/anywhere/ssh.rb
CHANGED
@@ -14,7 +14,7 @@ module Anywhere
|
|
14
14
|
@attributes = attributes.merge(paranoid: false)
|
15
15
|
end
|
16
16
|
|
17
|
-
def do_execute(cmd, stdin = nil)
|
17
|
+
def do_execute(cmd, stdin = nil, stdout = nil)
|
18
18
|
result = Result.new(cmd)
|
19
19
|
result.started!
|
20
20
|
ssh.open_channel do |ch|
|
@@ -22,7 +22,11 @@ module Anywhere
|
|
22
22
|
raise "could not execute command" unless success
|
23
23
|
ch.on_data do |ch, data|
|
24
24
|
result.add_stdout data
|
25
|
-
|
25
|
+
if stdout
|
26
|
+
stdout << data
|
27
|
+
elsif block_given?
|
28
|
+
yield(:stdout, data)
|
29
|
+
end
|
26
30
|
end
|
27
31
|
|
28
32
|
ch.on_extended_data do |ch, type, data|
|
data/lib/anywhere/version.rb
CHANGED
@@ -16,8 +16,9 @@ describe "SSH integration spec" do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
before :all do
|
19
|
-
@user = "
|
20
|
-
host = "
|
19
|
+
@user = "root"
|
20
|
+
host = ENV["SSH_TEST_HOST"]
|
21
|
+
raise %(ENV["SSH_TEST_HOST"] must be set) if host.nil?
|
21
22
|
port = 22
|
22
23
|
|
23
24
|
@runner = Anywhere::SSH.new(host, @user, port: port)
|
@@ -32,27 +33,45 @@ describe "SSH integration spec" do
|
|
32
33
|
end
|
33
34
|
|
34
35
|
describe "#home_dir" do
|
35
|
-
it { runner.home_dir.should eq("/
|
36
|
+
it { runner.home_dir.should eq("/root") }
|
36
37
|
end
|
37
38
|
|
38
39
|
describe "#extract_tar" do
|
39
40
|
let(:path) { FIXTURES_PATH.join("arch.tgz") }
|
40
41
|
|
41
42
|
it "extracts the provided path" do
|
42
|
-
runner.extract_tar(path, "/tmp/
|
43
|
-
runner.execute("ls /tmp/
|
44
|
-
runner.execute("cat /tmp/
|
43
|
+
runner.extract_tar(path, "/tmp/anywhere/tar")
|
44
|
+
runner.execute("ls /tmp/anywhere/tar").stdout.split("\n").should eq(["a.txt", "b.txt"])
|
45
|
+
runner.execute("cat /tmp/anywhere/tar/a.txt").stdout.should eq("this is a\n")
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
48
49
|
describe "#mkdir_p" do
|
49
50
|
before :each do
|
50
|
-
@runner.execute("rm -Rf /tmp/
|
51
|
+
@runner.execute("rm -Rf /tmp/anywhere")
|
51
52
|
end
|
52
53
|
|
53
54
|
it "should create a new directory" do
|
54
|
-
@runner.mkdir_p("mkdir -p /tmp/
|
55
|
-
@runner.execute("file /tmp/
|
55
|
+
@runner.mkdir_p("mkdir -p /tmp/anywhere/test")
|
56
|
+
@runner.execute("file /tmp/anywhere/test").stdout.should include("/tmp/anywhere/test: directory")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "#capture" do
|
61
|
+
subject(:str) do
|
62
|
+
runner.capture("/etc/passwd")
|
63
|
+
end
|
64
|
+
|
65
|
+
it { should be_kind_of(String) }
|
66
|
+
it { should start_with("root") }
|
67
|
+
|
68
|
+
describe "compressed" do
|
69
|
+
subject(:str) do
|
70
|
+
runner.capture("/etc/passwd", compressed = true)
|
71
|
+
end
|
72
|
+
|
73
|
+
it { should be_kind_of(String) }
|
74
|
+
it { should start_with("root") }
|
56
75
|
end
|
57
76
|
end
|
58
77
|
|
@@ -63,6 +82,18 @@ describe "SSH integration spec" do
|
|
63
82
|
it { subject.stdout.should include("load average") }
|
64
83
|
it { subject.stderr.length.should eq(0) }
|
65
84
|
|
85
|
+
describe "capturing" do
|
86
|
+
subject(:str) do
|
87
|
+
io = StringIO.new
|
88
|
+
runner.execute("cat /etc/passwd", nil, io)
|
89
|
+
io.rewind
|
90
|
+
io.read
|
91
|
+
end
|
92
|
+
|
93
|
+
it { str.should be_kind_of(String) }
|
94
|
+
it { str.length.should_not eq(0) }
|
95
|
+
end
|
96
|
+
|
66
97
|
describe "with unknwon command" do
|
67
98
|
subject(:error) do
|
68
99
|
begin
|
@@ -105,6 +136,12 @@ describe "SSH integration spec" do
|
|
105
136
|
subject { runner.write_file(@path, "hello world") }
|
106
137
|
it { should be_success }
|
107
138
|
it { runner.execute("cat #{@path}").stdout.should eq("hello world") }
|
139
|
+
|
140
|
+
it "should overwrite files" do
|
141
|
+
runner.write_file(@path, "hello world")
|
142
|
+
runner.write_file(@path, "hello world2")
|
143
|
+
runner.capture(@path).should eq("hello world2")
|
144
|
+
end
|
108
145
|
end
|
109
146
|
|
110
147
|
describe "write big files" do
|
@@ -2,11 +2,12 @@ require "spec_helper"
|
|
2
2
|
require "anywhere/local"
|
3
3
|
|
4
4
|
describe "Anywhere::Local" do
|
5
|
-
|
6
|
-
Anywhere.
|
5
|
+
subject(:local) do
|
6
|
+
local = Anywhere::Local.new
|
7
|
+
local.logger.stub(:stream) { StringIO.new }
|
8
|
+
local
|
7
9
|
end
|
8
10
|
|
9
|
-
subject(:local) { Anywhere::Local.new }
|
10
11
|
it { should_not be_nil }
|
11
12
|
|
12
13
|
describe "whoami" do
|
@@ -21,6 +22,19 @@ describe "Anywhere::Local" do
|
|
21
22
|
it { subject.exit_status.should eq(0) }
|
22
23
|
it { subject.stdout.should be_kind_of(String) }
|
23
24
|
|
25
|
+
describe "#capture" do
|
26
|
+
subject(:str) do
|
27
|
+
io = StringIO.new
|
28
|
+
local.logger.unstub(:stream) { StringIO.new }
|
29
|
+
local.execute("cat anywhere.gemspec", nil, io)
|
30
|
+
io.rewind
|
31
|
+
io.read
|
32
|
+
end
|
33
|
+
|
34
|
+
it { str.should be_kind_of(String) }
|
35
|
+
it { str.length.should_not eq(0) }
|
36
|
+
end
|
37
|
+
|
24
38
|
describe "with command raising an error" do
|
25
39
|
subject(:error) do
|
26
40
|
caught_err = nil
|
@@ -6,11 +6,44 @@ describe "Anywhere::Logger" do
|
|
6
6
|
it { should_not be_nil }
|
7
7
|
it { subject.prefix.should be_nil }
|
8
8
|
|
9
|
+
it "sets the default log level to INFO" do
|
10
|
+
logger.log_level.should eq(Logger::INFO)
|
11
|
+
end
|
12
|
+
|
9
13
|
describe "setting the prefix" do
|
10
14
|
it "changes the prefix" do
|
11
15
|
subject.prefix = "test"
|
12
16
|
subject.prefix.should eq("test")
|
13
17
|
end
|
14
18
|
end
|
19
|
+
|
20
|
+
describe "log levels" do
|
21
|
+
let(:stringio) { StringIO.new }
|
22
|
+
let(:log_level) { Logger::DEBUG }
|
23
|
+
|
24
|
+
subject(:lines) do
|
25
|
+
logger.log_level = log_level
|
26
|
+
logger.stub(:stream) { stringio }
|
27
|
+
logger.info "log info"
|
28
|
+
logger.debug "log debug"
|
29
|
+
stringio.rewind
|
30
|
+
stringio.read.split("\n")
|
31
|
+
end
|
32
|
+
|
33
|
+
it { should be_kind_of(Array) }
|
34
|
+
it { subject.count.should eq(2) }
|
35
|
+
it { subject.at(0).should include("INFO") }
|
36
|
+
it { subject.at(1).should include("DEBUG") }
|
37
|
+
|
38
|
+
describe "with log level being info" do
|
39
|
+
let(:log_level) { Logger::INFO }
|
40
|
+
|
41
|
+
it { subject.count.should eq(1) }
|
42
|
+
it { subject.at(0).should include("INFO") }
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "" do
|
46
|
+
end
|
47
|
+
end
|
15
48
|
end
|
16
49
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: anywhere
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-06-
|
12
|
+
date: 2013-06-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: net-ssh
|
@@ -28,7 +28,7 @@ dependencies:
|
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
|
-
name:
|
31
|
+
name: rainbow
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
none: false
|
34
34
|
requirements:
|