rbfs 0.0.10 → 0.0.14
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 +4 -22
- data/Rakefile +3 -1
- data/lib/rbfs/args.rb +6 -0
- data/lib/rbfs/command.rb +26 -18
- data/lib/rbfs/rsync.rb +18 -5
- data/lib/rbfs/version.rb +1 -1
- data/rbfs.gemspec +2 -0
- data/spec/rbfs/command_spec.rb +92 -0
- data/spec/rbfs/rsync_spec.rb +1 -1
- metadata +32 -14
- data/lib/rbfs/host.rb +0 -23
- data/lib/rbfs/host_parser.rb +0 -20
- data/spec/rbfs/host_parser_spec.rb +0 -30
- data/spec/rbfs/host_spec.rb +0 -38
data/README.md
CHANGED
@@ -1,29 +1,11 @@
|
|
1
1
|
# Rbfs
|
2
2
|
|
3
|
-
|
3
|
+
[](https://travis-ci.org/jbussdieker/ruby-rbfs)
|
4
|
+
[](https://codeclimate.com/github/jbussdieker/ruby-rbfs)
|
5
|
+
[](http://badge.fury.io/rb/rbfs)
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
Add this line to your application's Gemfile:
|
8
|
-
|
9
|
-
gem 'rbfs'
|
10
|
-
|
11
|
-
And then execute:
|
12
|
-
|
13
|
-
$ bundle
|
14
|
-
|
15
|
-
Or install it yourself as:
|
16
|
-
|
17
|
-
$ gem install rbfs
|
7
|
+
Ruby File Sync
|
18
8
|
|
19
9
|
## Usage
|
20
10
|
|
21
11
|
TODO: Write usage instructions here
|
22
|
-
|
23
|
-
## Contributing
|
24
|
-
|
25
|
-
1. Fork it
|
26
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
-
5. Create new Pull Request
|
data/Rakefile
CHANGED
data/lib/rbfs/args.rb
CHANGED
@@ -16,6 +16,12 @@ module Rbfs
|
|
16
16
|
opts.on("-r", "--root ROOT", "Root path to sync") do |v|
|
17
17
|
options[:root] = v
|
18
18
|
end
|
19
|
+
opts.on("-e", "--remote-root ROOT", "Remote root path to sync") do |v|
|
20
|
+
options[:remote_root] = v
|
21
|
+
end
|
22
|
+
opts.on("--shell SHELL", "Remote shell to use") do |v|
|
23
|
+
options[:shell] = v
|
24
|
+
end
|
19
25
|
opts.on("-s", "--subpath PATH", "Subpath of root to sync") do |v|
|
20
26
|
options[:subpath] = v
|
21
27
|
end
|
data/lib/rbfs/command.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
+
require 'hosts_file'
|
1
2
|
require 'rbfs/args'
|
2
3
|
require 'rbfs/config'
|
3
|
-
require "rbfs/host_parser"
|
4
4
|
require "rbfs/rsync"
|
5
5
|
require "rbfs/futures"
|
6
6
|
require "rbfs/logger"
|
@@ -9,10 +9,15 @@ module Rbfs
|
|
9
9
|
class Command
|
10
10
|
attr_accessor :config
|
11
11
|
|
12
|
-
def initialize
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
def initialize(config = nil)
|
13
|
+
if config
|
14
|
+
@config = config
|
15
|
+
else
|
16
|
+
@config = parse_config unless config
|
17
|
+
end
|
18
|
+
@config[:logger] = Logger.new(@config)
|
19
|
+
logger.critical "No hosts file specified" unless @config[:hosts]
|
20
|
+
logger.critical "Root path not specified" unless @config[:root]
|
16
21
|
end
|
17
22
|
|
18
23
|
def parse_config
|
@@ -24,7 +29,9 @@ module Rbfs
|
|
24
29
|
else
|
25
30
|
config = cmdline_args
|
26
31
|
end
|
27
|
-
config[:
|
32
|
+
unless config[:remote_root]
|
33
|
+
config[:remote_root] = config[:root]
|
34
|
+
end
|
28
35
|
config
|
29
36
|
end
|
30
37
|
|
@@ -34,25 +41,26 @@ module Rbfs
|
|
34
41
|
|
35
42
|
def sync
|
36
43
|
success = true
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
logger.info "#{host}: #{result[:exitcode].to_i}"
|
43
|
-
end
|
44
|
-
result[:output].split("\n").each do |line|
|
45
|
-
logger.puts " | #{line}"
|
44
|
+
|
45
|
+
sync_hosts.each do |host, result|
|
46
|
+
logger.info "#{host.name}: #{result.error}"
|
47
|
+
result.changes.each do |change|
|
48
|
+
logger.puts " | #{change.filename} (#{change.summary})"
|
46
49
|
end
|
47
|
-
success = false
|
50
|
+
success = false unless result.success?
|
48
51
|
end
|
52
|
+
|
49
53
|
success
|
50
54
|
end
|
51
55
|
|
52
56
|
def sync_hosts
|
53
|
-
|
57
|
+
if config[:subpath]
|
58
|
+
config[:root] = File.join(config[:root], config[:subpath])
|
59
|
+
config[:remote_root] = File.join(config[:remote_root], config[:subpath])
|
60
|
+
end
|
61
|
+
|
54
62
|
logger.info "Syncing #{config[:root]}..."
|
55
|
-
hosts =
|
63
|
+
hosts = HostsFile.load(config[:hosts])
|
56
64
|
hosts.collect do |host|
|
57
65
|
[host, sync_host(host)]
|
58
66
|
end
|
data/lib/rbfs/rsync.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'rsync'
|
2
|
+
|
1
3
|
module Rbfs
|
2
4
|
class Rsync
|
3
5
|
def initialize(config = {}, host = nil)
|
@@ -10,24 +12,35 @@ module Rbfs
|
|
10
12
|
end
|
11
13
|
|
12
14
|
def remote_url
|
13
|
-
"#{@host.ip}:#{@config[:
|
15
|
+
"#{@host.ip}:#{@config[:remote_root]}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def local_root
|
19
|
+
if File.directory?(@config[:root])
|
20
|
+
@config[:root] + "/"
|
21
|
+
else
|
22
|
+
@config[:root]
|
23
|
+
end
|
14
24
|
end
|
15
25
|
|
16
26
|
def mkdir
|
17
|
-
args = [@host.ip, "mkdir", "-p", @config[:
|
27
|
+
args = [@host.ip, "mkdir", "-p", @config[:remote_root]]
|
18
28
|
command("ssh", args)
|
19
29
|
end
|
20
30
|
|
21
31
|
def rsync
|
22
|
-
args = ["-
|
32
|
+
args = ["-a", "--delete"]
|
33
|
+
args << "-e #{@config[:shell]}" if @config[:shell]
|
23
34
|
args << "-v" if @config[:verbose]
|
24
35
|
args << "-n" if @config[:dry]
|
25
36
|
args << "--timeout=#{@config[:timeout]}" if @config[:timeout]
|
26
|
-
|
37
|
+
::Rsync.run(local_root, remote_url, args)
|
27
38
|
end
|
28
39
|
|
29
40
|
def sync
|
30
|
-
|
41
|
+
if File.directory?(@config[:root])
|
42
|
+
mkdir
|
43
|
+
end
|
31
44
|
rsync
|
32
45
|
end
|
33
46
|
|
data/lib/rbfs/version.rb
CHANGED
data/rbfs.gemspec
CHANGED
@@ -17,6 +17,8 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
+
spec.add_dependency "rsync", "~> 0.0"
|
21
|
+
spec.add_dependency "hosts_file", "~> 0.0"
|
20
22
|
spec.add_development_dependency "bundler", "~> 1.3"
|
21
23
|
spec.add_development_dependency "rake"
|
22
24
|
spec.add_development_dependency "rspec"
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'rbfs/command'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
describe Rbfs::Command do
|
5
|
+
def make_test_dir(&block)
|
6
|
+
Dir.mktmpdir do |dir|
|
7
|
+
@tmpdir = dir
|
8
|
+
File.open(File.join(@tmpdir, "hosts"), 'w') {|f| f.write("127.0.0.1 testhost")}
|
9
|
+
Dir.mkdir(File.join(@tmpdir, "local"))
|
10
|
+
Dir.mkdir(File.join(@tmpdir, "remote"))
|
11
|
+
yield
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def build_simple_test_dir
|
16
|
+
File.open(File.join(@tmpdir, "local", "sample.txt"), 'w') do |f|
|
17
|
+
f.write("hello world!")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def build_multipath_test_dir
|
22
|
+
Dir.mkdir(File.join(@tmpdir, "local", "somepath"))
|
23
|
+
File.open(File.join(@tmpdir, "local", "somepath", "sample.txt"), 'w') do |f|
|
24
|
+
f.write("hello world!")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_deeppath_test_dir
|
29
|
+
Dir.mkdir(File.join(@tmpdir, "local", "somepath"))
|
30
|
+
Dir.mkdir(File.join(@tmpdir, "local", "somepath", "someotherpath"))
|
31
|
+
File.open(File.join(@tmpdir, "local", "somepath", "someotherpath", "sample.txt"), 'w') do |f|
|
32
|
+
f.write("hello world!")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_tree(subpath)
|
37
|
+
`cd #{@tmpdir}/#{subpath}; tree`
|
38
|
+
end
|
39
|
+
|
40
|
+
context "simple", :local => true do
|
41
|
+
around(:each) do |example|
|
42
|
+
make_test_dir do
|
43
|
+
example.run
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should do simple file sync" do
|
48
|
+
build_simple_test_dir
|
49
|
+
Rbfs::Command.new(
|
50
|
+
:hosts => File.join(@tmpdir, "hosts"),
|
51
|
+
:root => File.join(@tmpdir, "local") + "/sample.txt",
|
52
|
+
:shell => '"ssh -o StrictHostKeyChecking=no"',
|
53
|
+
:remote_root => File.join(@tmpdir, "remote") + "/sample.txt"
|
54
|
+
).sync
|
55
|
+
get_tree("local").should eql(get_tree("remote"))
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should do simple path sync" do
|
59
|
+
build_simple_test_dir
|
60
|
+
Rbfs::Command.new(
|
61
|
+
:hosts => File.join(@tmpdir, "hosts"),
|
62
|
+
:root => File.join(@tmpdir, "local"),
|
63
|
+
:shell => '"ssh -o StrictHostKeyChecking=no"',
|
64
|
+
:remote_root => File.join(@tmpdir, "remote")
|
65
|
+
).sync
|
66
|
+
get_tree("local").should eql(get_tree("remote"))
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should do multi path sync" do
|
70
|
+
build_multipath_test_dir
|
71
|
+
Rbfs::Command.new(
|
72
|
+
:hosts => File.join(@tmpdir, "hosts"),
|
73
|
+
:root => File.join(@tmpdir, "local"),
|
74
|
+
:shell => '"ssh -o StrictHostKeyChecking=no"',
|
75
|
+
:remote_root => File.join(@tmpdir, "remote")
|
76
|
+
).sync
|
77
|
+
get_tree("local").should eql(get_tree("remote"))
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should do sub path sync" do
|
81
|
+
build_deeppath_test_dir
|
82
|
+
Rbfs::Command.new(
|
83
|
+
:hosts => File.join(@tmpdir, "hosts"),
|
84
|
+
:root => File.join(@tmpdir, "local"),
|
85
|
+
:subpath => "somepath/someotherpath/",
|
86
|
+
:shell => '"ssh -o StrictHostKeyChecking=no"',
|
87
|
+
:remote_root => File.join(@tmpdir, "remote")
|
88
|
+
).sync
|
89
|
+
get_tree("local").should eql(get_tree("remote"))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/spec/rbfs/rsync_spec.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbfs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.14
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,33 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-24 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rsync
|
16
|
+
requirement: &10282820 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *10282820
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hosts_file
|
27
|
+
requirement: &10281820 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0.0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *10281820
|
14
36
|
- !ruby/object:Gem::Dependency
|
15
37
|
name: bundler
|
16
|
-
requirement: &
|
38
|
+
requirement: &10280700 !ruby/object:Gem::Requirement
|
17
39
|
none: false
|
18
40
|
requirements:
|
19
41
|
- - ~>
|
@@ -21,10 +43,10 @@ dependencies:
|
|
21
43
|
version: '1.3'
|
22
44
|
type: :development
|
23
45
|
prerelease: false
|
24
|
-
version_requirements: *
|
46
|
+
version_requirements: *10280700
|
25
47
|
- !ruby/object:Gem::Dependency
|
26
48
|
name: rake
|
27
|
-
requirement: &
|
49
|
+
requirement: &10279760 !ruby/object:Gem::Requirement
|
28
50
|
none: false
|
29
51
|
requirements:
|
30
52
|
- - ! '>='
|
@@ -32,10 +54,10 @@ dependencies:
|
|
32
54
|
version: '0'
|
33
55
|
type: :development
|
34
56
|
prerelease: false
|
35
|
-
version_requirements: *
|
57
|
+
version_requirements: *10279760
|
36
58
|
- !ruby/object:Gem::Dependency
|
37
59
|
name: rspec
|
38
|
-
requirement: &
|
60
|
+
requirement: &10278940 !ruby/object:Gem::Requirement
|
39
61
|
none: false
|
40
62
|
requirements:
|
41
63
|
- - ! '>='
|
@@ -43,7 +65,7 @@ dependencies:
|
|
43
65
|
version: '0'
|
44
66
|
type: :development
|
45
67
|
prerelease: false
|
46
|
-
version_requirements: *
|
68
|
+
version_requirements: *10278940
|
47
69
|
description: Ruby File Sync
|
48
70
|
email:
|
49
71
|
- jbussdieker@gmail.com
|
@@ -63,15 +85,12 @@ files:
|
|
63
85
|
- lib/rbfs/command.rb
|
64
86
|
- lib/rbfs/config.rb
|
65
87
|
- lib/rbfs/futures.rb
|
66
|
-
- lib/rbfs/host.rb
|
67
|
-
- lib/rbfs/host_parser.rb
|
68
88
|
- lib/rbfs/logger.rb
|
69
89
|
- lib/rbfs/rsync.rb
|
70
90
|
- lib/rbfs/version.rb
|
71
91
|
- rbfs.gemspec
|
92
|
+
- spec/rbfs/command_spec.rb
|
72
93
|
- spec/rbfs/futures_spec.rb
|
73
|
-
- spec/rbfs/host_parser_spec.rb
|
74
|
-
- spec/rbfs/host_spec.rb
|
75
94
|
- spec/rbfs/rsync_spec.rb
|
76
95
|
homepage: ''
|
77
96
|
licenses: []
|
@@ -98,8 +117,7 @@ signing_key:
|
|
98
117
|
specification_version: 3
|
99
118
|
summary: Ruby File Sync
|
100
119
|
test_files:
|
120
|
+
- spec/rbfs/command_spec.rb
|
101
121
|
- spec/rbfs/futures_spec.rb
|
102
|
-
- spec/rbfs/host_parser_spec.rb
|
103
|
-
- spec/rbfs/host_spec.rb
|
104
122
|
- spec/rbfs/rsync_spec.rb
|
105
123
|
has_rdoc:
|
data/lib/rbfs/host.rb
DELETED
data/lib/rbfs/host_parser.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
require "rbfs/host"
|
2
|
-
|
3
|
-
module Rbfs
|
4
|
-
class HostParser
|
5
|
-
include Enumerable
|
6
|
-
|
7
|
-
def initialize(file)
|
8
|
-
@file = file
|
9
|
-
end
|
10
|
-
|
11
|
-
def each(&block)
|
12
|
-
lines = @file.read.split("\n")
|
13
|
-
lines.reject! {|line| line.strip.start_with? "#" }
|
14
|
-
lines.reject! {|line| line.strip.empty? }
|
15
|
-
lines.each do |line|
|
16
|
-
yield(Host.new(line))
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'rbfs/host_parser'
|
2
|
-
require 'stringio'
|
3
|
-
|
4
|
-
describe Rbfs::HostParser do
|
5
|
-
def test_case(string, size)
|
6
|
-
io = StringIO.new(string)
|
7
|
-
hp = Rbfs::HostParser.new(io)
|
8
|
-
hp.collect {|v|v}.length.should eql(size)
|
9
|
-
end
|
10
|
-
|
11
|
-
it "should handle a file with only comments" do
|
12
|
-
test_case("# TEST", 0)
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should handle a file with one host" do
|
16
|
-
test_case("1.1.1.1 HOSTNAME", 1)
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should handle a basic file" do
|
20
|
-
test_case("# TEST\n1.1.1.1 HOSTNAME", 1)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should handle empty lines" do
|
24
|
-
test_case("\n\n# TEST\n1.1.1.1 HOSTNAME\n\n", 1)
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should handle multiple lines" do
|
28
|
-
test_case("1.1.1.1 HOSTNAME\n1.1.1.1 HOSTNAME\n1.1.1.1 HOSTNAME", 3)
|
29
|
-
end
|
30
|
-
end
|
data/spec/rbfs/host_spec.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'rbfs/host'
|
2
|
-
|
3
|
-
describe Rbfs::Host do
|
4
|
-
def test_example(line, ip, name=nil, alias_name=nil)
|
5
|
-
host = Rbfs::Host.new(line)
|
6
|
-
host.ip.should eql(ip)
|
7
|
-
host.name.should eql(name)
|
8
|
-
host.alias.should eql(alias_name)
|
9
|
-
end
|
10
|
-
|
11
|
-
it "should handle minimal syntax" do
|
12
|
-
test_example("1.1.1.1", "1.1.1.1")
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should handle basic syntax" do
|
16
|
-
test_example("1.1.1.1 HOSTNAME", "1.1.1.1", "HOSTNAME")
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should handle advanced syntax" do
|
20
|
-
test_example("1.1.1.1 HOSTNAME HOST", "1.1.1.1", "HOSTNAME", "HOST")
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should support tab separation" do
|
24
|
-
test_example("1.1.1.1\tHOSTNAME", "1.1.1.1", "HOSTNAME")
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should tolerate lots of tab separation" do
|
28
|
-
test_example("1.1.1.1\t\t\t\t\t\t\tHOSTNAME", "1.1.1.1", "HOSTNAME")
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should tolerate lots of spaces" do
|
32
|
-
test_example("1.1.1.1 HOSTNAME", "1.1.1.1", "HOSTNAME")
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should tolerate lots of aliases" do
|
36
|
-
test_example("1.1.1.1 HOSTNAME HOSTA HOSTB HOSTC HOSTD", "1.1.1.1", "HOSTNAME", "HOSTA")
|
37
|
-
end
|
38
|
-
end
|