anywhere 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|