understudy 0.0.2 → 0.0.3
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 +7 -0
- data/.gitignore +3 -0
- data/.travis.yml +1 -2
- data/Gemfile +12 -0
- data/README.md +7 -2
- data/bin/understudy +111 -10
- data/lib/understudy.rb +2 -1
- data/lib/understudy/stage.rb +17 -0
- data/lib/understudy/version.rb +1 -1
- data/spec/lib/stage_spec.rb +18 -0
- data/spec/spec_helper.rb +2 -0
- data/understudy.gemspec +0 -5
- metadata +14 -87
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1385e86aea71e2bc87313d6a9231cb960bf315a9
|
4
|
+
data.tar.gz: a3d1b983680dd55592377ab154eed2e3b9ea6ae7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d1adf79bd8bf14c29a38b268c9532183d3230e41e71732abeb24a0c411980ccb2f70941435058d75c2f58d595633070e3a75710e93564c63be4da76bdde0d47c
|
7
|
+
data.tar.gz: f680c7e1e4a4c122494c0bdfcc402d3563becce8fae7cec7201f9cca1c3469314a43ae8027c0d2614cef89233d2e53769d9aeecb7f347b9b476648e189fdb9fe
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -2,3 +2,15 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in understudy.gemspec
|
4
4
|
gemspec
|
5
|
+
|
6
|
+
group :development, :test do
|
7
|
+
gem "rspec", "~> 2"
|
8
|
+
gem "rake"
|
9
|
+
gem "coveralls"
|
10
|
+
gem "fakefs"
|
11
|
+
end
|
12
|
+
|
13
|
+
group :development do
|
14
|
+
gem "bundler", "~> 1.3"
|
15
|
+
gem 'guard-rspec', :require => false
|
16
|
+
end
|
data/README.md
CHANGED
@@ -6,20 +6,25 @@
|
|
6
6
|
[](https://codeclimate.com/github/ketiko/understudy)
|
7
7
|
[](https://coveralls.io/r/ketiko/understudy?branch=master)
|
8
8
|
|
9
|
-
|
10
9
|
Automated system backups via rdiff-backup
|
11
10
|
|
12
11
|
* [Source Code](http://github.com/ketiko/understudy)
|
13
12
|
* [API documentation](http://rubydoc.info/github/ketiko/understudy/master)
|
14
13
|
* [Rubygem](http://rubygems.org/gems/understudy)
|
15
14
|
|
15
|
+
Understudy fills in for you when you need them the most, when you lose your data. It knows every line and is ready to step in whenever you need it.
|
16
|
+
|
17
|
+
Understudy automates entire system backups using rdiff-backup internally. It's based on automated rdiff-backup configurations I've found myself setting up over and over.
|
18
|
+
I wanted to simplify some of the rdiff-backup process by enabling some defaults based on the path. I also wanted to be able easily backup an entire machine without worrying about
|
19
|
+
multiple rdiff-backup scripts.
|
20
|
+
|
16
21
|
## Installation
|
17
22
|
|
18
23
|
$ gem install understudy
|
19
24
|
|
20
25
|
## Usage
|
21
26
|
|
22
|
-
$ understudy
|
27
|
+
$ understudy --help
|
23
28
|
|
24
29
|
## License
|
25
30
|
|
data/bin/understudy
CHANGED
@@ -1,19 +1,120 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
ENV['TMPDIR']='/tmp/backup/'
|
4
|
+
require 'optparse'
|
5
|
+
require 'ostruct'
|
6
|
+
require 'fileutils'
|
7
|
+
require 'rdiff_simple'
|
6
8
|
|
7
|
-
|
9
|
+
options = OpenStruct.new
|
10
|
+
@verbose = false
|
8
11
|
|
9
|
-
|
10
|
-
class CLI < Thor
|
11
|
-
include Thor::Actions
|
12
|
+
usage = "Usage: understudy [options] job-name"
|
12
13
|
|
13
|
-
|
14
|
+
OptionParser.new do |opts|
|
15
|
+
opts.banner = usage
|
16
|
+
opts.on '-v', '--verbose', 'Output extra information' do |v|
|
17
|
+
@verbose = v
|
18
|
+
end
|
19
|
+
opts.on '-f', '--first-time', 'Force first-time run' do |f|
|
20
|
+
options.first = f
|
21
|
+
end
|
22
|
+
end.parse!
|
23
|
+
|
24
|
+
def error msg
|
25
|
+
STDERR.puts "ERROR: #{msg}"
|
26
|
+
exit 255
|
27
|
+
end
|
28
|
+
|
29
|
+
error usage if ARGV.length != 1
|
30
|
+
|
31
|
+
job_name = ARGV.shift
|
32
|
+
|
33
|
+
config_file = "/etc/understudy/#{job_name}.conf"
|
34
|
+
|
35
|
+
error "Cannot find '#{config_file}'" unless File.exist? config_file
|
36
|
+
|
37
|
+
DATA_DIR = "/var/lib/understudy/#{job_name}"
|
38
|
+
|
39
|
+
FileUtils.mkdir_p DATA_DIR
|
40
|
+
|
41
|
+
lockfile = File.open( "#{DATA_DIR}/LOCK", File::RDWR|File::CREAT, 0644 )
|
42
|
+
unless lockfile.flock File::LOCK_EX|File::LOCK_NB
|
43
|
+
error "Job #{job_name} is already running"
|
44
|
+
end
|
45
|
+
lockfile.puts $$
|
46
|
+
lockfile.flush
|
47
|
+
|
48
|
+
config = OpenStruct.new
|
49
|
+
|
50
|
+
# Any options that aren't our options go to rdiff-backup
|
51
|
+
OUR_OPTIONS = %w{source dest command}
|
52
|
+
|
53
|
+
rdiff_args = []
|
54
|
+
|
55
|
+
File.read( config_file ).split( /\n/ ).each do |line|
|
56
|
+
line.sub! /#.*$/, ''
|
57
|
+
line.sub! /^\s+/, ''
|
58
|
+
line.sub! /\s+$/, ''
|
59
|
+
next if line.empty?
|
14
60
|
|
15
|
-
|
61
|
+
line =~ /^([-\w]+)(\s+=\s+(.*))?$/ or raise "Strange line in config: #{line}"
|
62
|
+
key = $1
|
63
|
+
val = $3
|
64
|
+
if OUR_OPTIONS.member? key
|
65
|
+
config.send "#{key}=".to_sym, val
|
66
|
+
else
|
67
|
+
rdiff_args.push "--#{key}" + ( val ? "=#{val}" : "" )
|
16
68
|
end
|
17
69
|
end
|
18
70
|
|
19
|
-
|
71
|
+
error "Missing 'dest' config option" unless config.dest
|
72
|
+
error "Missing 'source' config option" unless config.source
|
73
|
+
|
74
|
+
rdiff_data = "#{config.dest}/rdiff-backup-data"
|
75
|
+
exists = File.directory? rdiff_data
|
76
|
+
if exists && options.first
|
77
|
+
error "Cannot force first time, destination '#{config.dest}' already exists"
|
78
|
+
elsif !exists && !options.first
|
79
|
+
error "Destination '#{config.dest}' does not appear to exist, try again with --first-time"
|
80
|
+
end
|
81
|
+
|
82
|
+
def info message
|
83
|
+
return unless @verbose
|
84
|
+
end
|
85
|
+
|
86
|
+
def run command
|
87
|
+
friendly = nil
|
88
|
+
if command.is_a? Array
|
89
|
+
friendly = command.map { |i| i =~ /[^-=\/\.\w]/ ? "'#{i}'" : i }.join ' '
|
90
|
+
info "Running: #{friendly}"
|
91
|
+
RdiffSimple.execute( *command ) or error "Could not run #{friendly}"
|
92
|
+
else
|
93
|
+
friendly = command
|
94
|
+
info "Running: #{friendly}"
|
95
|
+
RdiffSimple.execute( command ) or error "Could not run #{command}"
|
96
|
+
end
|
97
|
+
if $? != 0
|
98
|
+
error "Could not run #{friendly}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
ENV['PATH'] += ":/etc/understudy"
|
103
|
+
run config.command if config.command
|
104
|
+
|
105
|
+
command = ["nice"]
|
106
|
+
command << "rdiff-backup"
|
107
|
+
|
108
|
+
command << "--terminal-verbosity=5" if @verbose
|
109
|
+
#command << "--print-statistics"
|
110
|
+
|
111
|
+
command += rdiff_args
|
112
|
+
|
113
|
+
command << config.source
|
114
|
+
command << config.dest
|
115
|
+
|
116
|
+
run command
|
117
|
+
|
118
|
+
info "Backup successful"
|
119
|
+
|
120
|
+
exit 0
|
data/lib/understudy.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Understudy
|
2
|
+
module Stage
|
3
|
+
DEFAULT_DIRECTORY = '/etc/understudy/'
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def setup(directory = nil)
|
7
|
+
config_dir = directory ||= DEFAULT_DIRECTORY
|
8
|
+
|
9
|
+
hostname = `hostname`
|
10
|
+
config_file = File.join(config_dir, "#{hostname.chomp}.config")
|
11
|
+
|
12
|
+
FileUtils.mkdir_p(config_dir) unless File.exists?(config_dir)
|
13
|
+
FileUtils.touch(config_file)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/understudy/version.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Understudy::Stage do
|
4
|
+
describe "#setup" do
|
5
|
+
before(:each) do
|
6
|
+
Understudy::Stage.setup
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should create the default configuration directory" do
|
10
|
+
File.exists?(Understudy::Stage::DEFAULT_DIRECTORY).should be_true
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should a configuration file for the machine" do
|
14
|
+
File.exists?(File.join(Understudy::Stage::DEFAULT_DIRECTORY, "#{`hostname`.chomp}.config")).should be_true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'bundler/setup'
|
3
|
+
require 'fakefs/spec_helpers'
|
3
4
|
|
4
5
|
if RUBY_VERSION > "1.9"
|
5
6
|
if ENV['TRAVIS']
|
@@ -16,5 +17,6 @@ require 'understudy'
|
|
16
17
|
RSpec.configure do |config|
|
17
18
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
18
19
|
config.run_all_when_everything_filtered = true
|
20
|
+
config.include FakeFS::SpecHelpers
|
19
21
|
end
|
20
22
|
|
data/understudy.gemspec
CHANGED
@@ -21,11 +21,6 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.extra_rdoc_files = [ "LICENSE.txt", "README.md" ]
|
22
22
|
spec.rdoc_options = [ "--charset=UTF-8" ]
|
23
23
|
|
24
|
-
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
-
spec.add_development_dependency "rspec", "~> 2"
|
26
|
-
spec.add_development_dependency "rake"
|
27
|
-
spec.add_development_dependency "coveralls"
|
28
|
-
|
29
24
|
spec.add_dependency "thor"
|
30
25
|
spec.add_dependency "rdiff-simple"
|
31
26
|
end
|
metadata
CHANGED
@@ -1,110 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: understudy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.3
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Ryan Hansen
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-07-14 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: bundler
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '1.3'
|
22
|
-
type: :development
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '1.3'
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: rspec
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - ~>
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: '2'
|
38
|
-
type: :development
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: '2'
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name: rake
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
|
-
requirements:
|
51
|
-
- - ! '>='
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0'
|
54
|
-
type: :development
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
|
-
requirements:
|
59
|
-
- - ! '>='
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: coveralls
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
|
-
requirements:
|
67
|
-
- - ! '>='
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '0'
|
70
|
-
type: :development
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ! '>='
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: '0'
|
78
13
|
- !ruby/object:Gem::Dependency
|
79
14
|
name: thor
|
80
15
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
16
|
requirements:
|
83
|
-
- -
|
17
|
+
- - '>='
|
84
18
|
- !ruby/object:Gem::Version
|
85
19
|
version: '0'
|
86
20
|
type: :runtime
|
87
21
|
prerelease: false
|
88
22
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
23
|
requirements:
|
91
|
-
- -
|
24
|
+
- - '>='
|
92
25
|
- !ruby/object:Gem::Version
|
93
26
|
version: '0'
|
94
27
|
- !ruby/object:Gem::Dependency
|
95
28
|
name: rdiff-simple
|
96
29
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
30
|
requirements:
|
99
|
-
- -
|
31
|
+
- - '>='
|
100
32
|
- !ruby/object:Gem::Version
|
101
33
|
version: '0'
|
102
34
|
type: :runtime
|
103
35
|
prerelease: false
|
104
36
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
37
|
requirements:
|
107
|
-
- -
|
38
|
+
- - '>='
|
108
39
|
- !ruby/object:Gem::Version
|
109
40
|
version: '0'
|
110
41
|
description: Automated system backups via rdiff-backup
|
@@ -127,42 +58,38 @@ files:
|
|
127
58
|
- Rakefile
|
128
59
|
- bin/understudy
|
129
60
|
- lib/understudy.rb
|
61
|
+
- lib/understudy/stage.rb
|
130
62
|
- lib/understudy/version.rb
|
63
|
+
- spec/lib/stage_spec.rb
|
131
64
|
- spec/spec_helper.rb
|
132
65
|
- spec/understudy_spec.rb
|
133
66
|
- understudy.gemspec
|
134
67
|
homepage: http://github.com/ketiko/understudy
|
135
68
|
licenses:
|
136
69
|
- MIT
|
70
|
+
metadata: {}
|
137
71
|
post_install_message:
|
138
72
|
rdoc_options:
|
139
73
|
- --charset=UTF-8
|
140
74
|
require_paths:
|
141
75
|
- lib
|
142
76
|
required_ruby_version: !ruby/object:Gem::Requirement
|
143
|
-
none: false
|
144
77
|
requirements:
|
145
|
-
- -
|
78
|
+
- - '>='
|
146
79
|
- !ruby/object:Gem::Version
|
147
80
|
version: '0'
|
148
|
-
segments:
|
149
|
-
- 0
|
150
|
-
hash: 4466193392918768577
|
151
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
|
-
none: false
|
153
82
|
requirements:
|
154
|
-
- -
|
83
|
+
- - '>='
|
155
84
|
- !ruby/object:Gem::Version
|
156
85
|
version: '0'
|
157
|
-
segments:
|
158
|
-
- 0
|
159
|
-
hash: 4466193392918768577
|
160
86
|
requirements: []
|
161
87
|
rubyforge_project:
|
162
|
-
rubygems_version:
|
88
|
+
rubygems_version: 2.0.2
|
163
89
|
signing_key:
|
164
|
-
specification_version:
|
90
|
+
specification_version: 4
|
165
91
|
summary: Automated system backups via rdiff-backup
|
166
92
|
test_files:
|
93
|
+
- spec/lib/stage_spec.rb
|
167
94
|
- spec/spec_helper.rb
|
168
95
|
- spec/understudy_spec.rb
|