backup_jenkins 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +9 -0
- data/Guardfile +8 -0
- data/config/{config-sample.yml → config-example.yml} +0 -0
- data/lib/backup_jenkins/aws.rb +17 -6
- data/lib/backup_jenkins/backup.rb +8 -14
- data/lib/backup_jenkins/config.rb +21 -1
- data/lib/backup_jenkins/version.rb +1 -1
- data/spec/lib/backup_jenkins/aws_spec.rb +146 -0
- data/spec/lib/backup_jenkins/backup_spec.rb +212 -0
- data/spec/lib/backup_jenkins/cli_spec.rb +31 -0
- data/spec/lib/backup_jenkins/config_spec.rb +42 -10
- data/spec/spec_helper.rb +3 -0
- metadata +39 -12
data/Gemfile
CHANGED
@@ -3,6 +3,15 @@ source :rubygems
|
|
3
3
|
# Specify your gem's dependencies in backup_jenkins.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
+
group :development do
|
7
|
+
gem "guard"
|
8
|
+
gem "guard-rspec"
|
9
|
+
gem "rb-inotify", require: false
|
10
|
+
gem "rb-fsevent", require: false
|
11
|
+
gem "rb-fchange", require: false
|
12
|
+
gem "terminal-notifier-guard"
|
13
|
+
end
|
14
|
+
|
6
15
|
group :test do
|
7
16
|
gem "rake"
|
8
17
|
gem "rspec"
|
data/Guardfile
ADDED
File without changes
|
data/lib/backup_jenkins/aws.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module BackupJenkins
|
2
2
|
class AWS
|
3
|
+
class UploadFileError < StandardError; end
|
4
|
+
|
3
5
|
def initialize(config = Config.new)
|
4
6
|
@config = config
|
5
7
|
setup_aws
|
@@ -7,22 +9,27 @@ module BackupJenkins
|
|
7
9
|
|
8
10
|
def populate_files
|
9
11
|
@files = []
|
10
|
-
|
12
|
+
backup_files.each{ |o| files << o }
|
11
13
|
@files.sort!{ |a, b| a.key <=> b.key }
|
12
14
|
end
|
13
15
|
|
16
|
+
def backup_files
|
17
|
+
s3_files.with_prefix(config.base_file_name)
|
18
|
+
end
|
19
|
+
|
14
20
|
# TODO change this to use a time decay algorithm
|
15
21
|
def remove_old_files
|
16
22
|
puts "Looking for old files..." if config.verbose
|
17
|
-
|
18
23
|
populate_files
|
24
|
+
do_remove_old_files
|
25
|
+
puts "Done." if config.verbose
|
26
|
+
end
|
19
27
|
|
28
|
+
def do_remove_old_files
|
20
29
|
files_to_remove.each do |file|
|
21
30
|
puts "Removing #{file.key}..." if config.verbose
|
22
31
|
file.delete
|
23
32
|
end
|
24
|
-
|
25
|
-
puts "Done." if config.verbose
|
26
33
|
end
|
27
34
|
|
28
35
|
def files_to_remove
|
@@ -31,9 +38,9 @@ module BackupJenkins
|
|
31
38
|
|
32
39
|
def upload_file(filename, file)
|
33
40
|
puts "About to upload #{filename}..." if config.verbose
|
34
|
-
new_file =
|
41
|
+
new_file = s3_files.create(filename, file)
|
35
42
|
puts "Done" if config.verbose
|
36
|
-
raise
|
43
|
+
raise UploadFileError unless new_file.class == ::AWS::S3::S3Object
|
37
44
|
end
|
38
45
|
|
39
46
|
private
|
@@ -50,5 +57,9 @@ module BackupJenkins
|
|
50
57
|
raise "Couldn't create bucket!" unless @bucket.exists?
|
51
58
|
end
|
52
59
|
|
60
|
+
def s3_files
|
61
|
+
bucket.objects
|
62
|
+
end
|
63
|
+
|
53
64
|
end
|
54
65
|
end
|
@@ -7,15 +7,7 @@ module BackupJenkins
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def backup_directory
|
10
|
-
@backup_directory ||= "#{config.backup["dir_base"]}/#{base_file_name}_#{timestamp}"
|
11
|
-
end
|
12
|
-
|
13
|
-
def base_file_name
|
14
|
-
"#{config.backup["file_name_base"]}_#{hostname}"
|
15
|
-
end
|
16
|
-
|
17
|
-
def hostname
|
18
|
-
%x{hostname -s}.chomp
|
10
|
+
@backup_directory ||= "#{config.backup["dir_base"]}/#{config.base_file_name}_#{timestamp}"
|
19
11
|
end
|
20
12
|
|
21
13
|
def create_dir_and_copy(file_names)
|
@@ -28,12 +20,14 @@ module BackupJenkins
|
|
28
20
|
raise "file '#{file_name}' does not exist" unless FileTest.file?(file_name)
|
29
21
|
|
30
22
|
new_file_name = new_file_path(file_name)
|
31
|
-
|
23
|
+
new_file_dir = File.dirname(new_file_name)
|
24
|
+
|
25
|
+
FileUtils.mkdir_p(new_file_dir, verbose: config.verbose)
|
32
26
|
FileUtils.cp(file_name, new_file_name, verbose: config.verbose)
|
33
27
|
end
|
34
28
|
|
35
29
|
def new_file_path(file_name)
|
36
|
-
"#{backup_directory}/#{file_name.gsub(%r{#{config.jenkins["home"]}}, "")}"
|
30
|
+
"#{backup_directory}/#{file_name.gsub(%r{#{config.jenkins["home"]}}, "")}".gsub(%r{//}, '/')
|
37
31
|
end
|
38
32
|
|
39
33
|
def do_backup
|
@@ -80,9 +74,9 @@ module BackupJenkins
|
|
80
74
|
end
|
81
75
|
|
82
76
|
def tar_options
|
83
|
-
|
84
|
-
|
85
|
-
|
77
|
+
%w(j c f).tap do |options|
|
78
|
+
options.unshift('v') if config.verbose
|
79
|
+
end.join('')
|
86
80
|
end
|
87
81
|
|
88
82
|
private
|
@@ -3,7 +3,7 @@ module BackupJenkins
|
|
3
3
|
attr_reader :s3
|
4
4
|
|
5
5
|
def initialize
|
6
|
-
@config =
|
6
|
+
@config = config_file
|
7
7
|
end
|
8
8
|
|
9
9
|
def method_missing(meth, *args, &block)
|
@@ -15,9 +15,29 @@ module BackupJenkins
|
|
15
15
|
config.has_key?(meth.to_s) || super
|
16
16
|
end
|
17
17
|
|
18
|
+
def base_file_name
|
19
|
+
"#{backup["file_name_base"]}_#{hostname}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def hostname
|
23
|
+
%x{hostname -s}.chomp
|
24
|
+
end
|
25
|
+
|
18
26
|
private
|
19
27
|
|
20
28
|
attr_reader :config
|
21
29
|
|
30
|
+
def config_file
|
31
|
+
YAML.load_file(config_file_path)
|
32
|
+
rescue Errno::ENOENT
|
33
|
+
STDERR.puts "Please create a config file in #{config_file_path}"
|
34
|
+
STDERR.puts "\nIt should look like:\n\n#{File.read('config/config-example.yml')}"
|
35
|
+
|
36
|
+
exit 1
|
37
|
+
end
|
38
|
+
|
39
|
+
def config_file_path
|
40
|
+
"#{ENV['HOME']}/.config/backup_jenkins/config.yml"
|
41
|
+
end
|
22
42
|
end
|
23
43
|
end
|
@@ -1,4 +1,150 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe BackupJenkins::AWS do
|
4
|
+
let(:config) { stub }
|
5
|
+
let(:s3_mocks) { stub(buckets: stub(:[] => stub(exists?: true), create: true)) }
|
6
|
+
|
7
|
+
before do
|
8
|
+
BackupJenkins::Config.stub(:new).and_return(config)
|
9
|
+
|
10
|
+
config.stub(:aws).and_return({ "access_key" => "some_key", "secret" => "some_secret" })
|
11
|
+
config.stub(:backup).and_return({ "backups_to_keep" => 2 })
|
12
|
+
|
13
|
+
::AWS::S3.stub(:new).and_return(s3_mocks)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#setup_aws" do
|
17
|
+
after do
|
18
|
+
subject
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should instantiate an S3 object" do
|
22
|
+
::AWS::S3.should_receive(:new).and_return(s3_mocks)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "shuld create bucket" do
|
26
|
+
s3_mocks.buckets.should_receive(:[]).and_return(mock(exists?: false))
|
27
|
+
s3_mocks.buckets.should_receive(:create).and_return(mock(exists?: true))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#populate_files" do
|
32
|
+
it "should get the objects from backup_files and sort them" do
|
33
|
+
a = mock(key: 1)
|
34
|
+
b = mock(key: 2)
|
35
|
+
c = mock(key: 3)
|
36
|
+
|
37
|
+
subject.should_receive(:backup_files).and_return([b, c, a])
|
38
|
+
subject.populate_files.should == [a, b, c]
|
39
|
+
subject.instance_variable_get(:"@files").should == [a, b, c]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#backup_files" do
|
44
|
+
it "should return the right files" do
|
45
|
+
config.should_receive(:base_file_name).and_return("base_file_name")
|
46
|
+
objects = mock
|
47
|
+
objects.should_receive(:with_prefix).with("base_file_name").and_return([1, 2, 3])
|
48
|
+
subject.should_receive(:s3_files).and_return(objects)
|
49
|
+
|
50
|
+
subject.backup_files.should == [1, 2, 3]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#remove_old_files" do
|
55
|
+
before do
|
56
|
+
config.stub(:verbose).and_return(false)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should populate_files" do
|
60
|
+
subject.should_receive(:populate_files)
|
61
|
+
subject.should_receive(:do_remove_old_files)
|
62
|
+
subject.remove_old_files
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should print stuff if verbose" do
|
66
|
+
config.should_receive(:verbose).twice.and_return(true)
|
67
|
+
subject.stub(:populate_files)
|
68
|
+
subject.stub(:do_remove_old_files)
|
69
|
+
|
70
|
+
STDOUT.should_receive(:puts).with("Looking for old files...")
|
71
|
+
STDOUT.should_receive(:puts).with("Done.")
|
72
|
+
|
73
|
+
subject.remove_old_files
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#do_remove_old_files" do
|
78
|
+
it "should iterate over files_to_remove and call delete on each one" do
|
79
|
+
config.stub(:verbose).and_return(false)
|
80
|
+
|
81
|
+
file_1 = mock
|
82
|
+
file_2 = mock
|
83
|
+
|
84
|
+
file_1.should_receive(:delete)
|
85
|
+
file_2.should_receive(:delete)
|
86
|
+
|
87
|
+
subject.should_receive(:files_to_remove).and_return([file_1, file_2])
|
88
|
+
subject.do_remove_old_files
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should output that's removing a file if verbose" do
|
92
|
+
file_1 = mock(key: "filename", delete: true)
|
93
|
+
|
94
|
+
config.should_receive(:verbose).and_return(true)
|
95
|
+
subject.should_receive(:files_to_remove).and_return([file_1])
|
96
|
+
STDOUT.should_receive(:puts).with("Removing filename...")
|
97
|
+
|
98
|
+
subject.do_remove_old_files
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "#files_to_remove" do
|
103
|
+
it "should get the last n files (where n is total number - keep)" do
|
104
|
+
subject.stub(:files).and_return(%w(a b c d e f g))
|
105
|
+
subject.files_to_remove.should == ["a", "b", "c", "d", "e"]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "#upload_file" do
|
110
|
+
it "should create a file" do
|
111
|
+
config.stub(:verbose).and_return(false)
|
112
|
+
objects = mock
|
113
|
+
objects.should_receive(:create).with("filename", "file").and_return(
|
114
|
+
mock(class: AWS::S3::S3Object)
|
115
|
+
)
|
116
|
+
subject.should_receive(:s3_files).and_return(objects)
|
117
|
+
|
118
|
+
subject.upload_file("filename", "file")
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should print stuff in verbose" do
|
122
|
+
config.should_receive(:verbose).twice.and_return(true)
|
123
|
+
|
124
|
+
objects = mock
|
125
|
+
objects.stub(:create).with("filename", "file").and_return(mock(class: AWS::S3::S3Object))
|
126
|
+
subject.stub(:s3_files).and_return(objects)
|
127
|
+
|
128
|
+
STDOUT.should_receive(:puts).with("About to upload filename...")
|
129
|
+
STDOUT.should_receive(:puts).with("Done")
|
130
|
+
|
131
|
+
subject.upload_file("filename", "file")
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should raise exception if no s3 object is created" do
|
135
|
+
config.stub(:verbose).and_return(false)
|
136
|
+
|
137
|
+
objects = mock
|
138
|
+
objects.stub(:create).with("filename", "file").and_return(mock)
|
139
|
+
subject.stub(:s3_files).and_return(objects)
|
140
|
+
|
141
|
+
expect{ subject.upload_file("filename", "file")}.to raise_error \
|
142
|
+
::BackupJenkins::AWS::UploadFileError
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "#s3_files" do
|
147
|
+
after { subject.send(:s3_files) }
|
148
|
+
it { subject.should_receive(:bucket).and_return(mock(objects: mock)) }
|
149
|
+
end
|
4
150
|
end
|
@@ -1,4 +1,216 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe BackupJenkins::Backup do
|
4
|
+
let(:config) { mock }
|
5
|
+
|
6
|
+
before do
|
7
|
+
BackupJenkins::Config.stub(:new).and_return(config)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "should assign @config" do
|
12
|
+
subject.instance_variable_get(:"@config").should == config
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#backup_directory" do
|
17
|
+
let(:backup) { { "dir_base" => "/path/to/some/dir_base" } }
|
18
|
+
|
19
|
+
it "should return the dir base + the base file name + time stamp" do
|
20
|
+
config.should_receive(:backup).and_return(backup)
|
21
|
+
config.should_receive(:base_file_name).and_return("filename")
|
22
|
+
subject.should_receive(:timestamp).and_return("timestamp")
|
23
|
+
|
24
|
+
subject.backup_directory.should == "/path/to/some/dir_base/filename_timestamp"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should get data only once" do
|
28
|
+
config.should_receive(:backup).once.and_return(backup)
|
29
|
+
config.should_receive(:base_file_name).once.and_return("filename")
|
30
|
+
subject.should_receive(:timestamp).once.and_return("timestamp")
|
31
|
+
|
32
|
+
subject.backup_directory
|
33
|
+
subject.backup_directory
|
34
|
+
subject.backup_directory
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#copy_files" do
|
39
|
+
before do
|
40
|
+
subject.stub(:plugin_files).and_return("plugin_files")
|
41
|
+
subject.stub(:user_content_files).and_return("user_content_files")
|
42
|
+
subject.stub(:jobs_files).and_return("jobs_files")
|
43
|
+
|
44
|
+
subject.stub(:create_dir_and_copy)
|
45
|
+
end
|
46
|
+
|
47
|
+
after { subject.copy_files }
|
48
|
+
|
49
|
+
it { subject.should_receive(:create_dir_and_copy).with("plugin_files") }
|
50
|
+
it { subject.should_receive(:create_dir_and_copy).with("user_content_files") }
|
51
|
+
it { subject.should_receive(:create_dir_and_copy).with("jobs_files") }
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#create_dir_and_copy" do
|
55
|
+
it "should iterate over filenames and call create_dir_and_copy_impl with them" do
|
56
|
+
subject.should_receive(:create_dir_and_copy_impl).with("a")
|
57
|
+
subject.should_receive(:create_dir_and_copy_impl).with("b")
|
58
|
+
subject.should_receive(:create_dir_and_copy_impl).with("c")
|
59
|
+
|
60
|
+
subject.create_dir_and_copy(%w(a b c))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#create_dir_and_copy_impl" do
|
65
|
+
before do
|
66
|
+
FileTest.stub(:file?).and_return(true)
|
67
|
+
FileUtils.stub(:mkdir_p)
|
68
|
+
FileUtils.stub(:cp)
|
69
|
+
config.stub(:verbose).and_return(false)
|
70
|
+
subject.stub(:new_file_path).and_return("/this/is/a/new/path/to_file")
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should get the new file path of the file" do
|
74
|
+
subject.should_receive(:new_file_path)
|
75
|
+
subject.create_dir_and_copy_impl("filename")
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should create directory new_directory" do
|
79
|
+
FileUtils.should_receive(:mkdir_p).with("/this/is/a/new/path", verbose: false)
|
80
|
+
subject.create_dir_and_copy_impl("filename")
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should copy old file to new file" do
|
84
|
+
FileUtils.should_receive(:cp).with("filename", "/this/is/a/new/path/to_file", verbose: false)
|
85
|
+
subject.create_dir_and_copy_impl("filename")
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should raise error if file to copy from doesn't exist" do
|
89
|
+
FileTest.should_receive(:file?).and_return(false)
|
90
|
+
expect{ subject.create_dir_and_copy_impl("filename") }.to raise_error
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#create_tarball" do
|
95
|
+
before do
|
96
|
+
Dir.stub(:chdir)
|
97
|
+
FileTest.stub(:file?).and_return(true)
|
98
|
+
|
99
|
+
config.stub(:verbose).and_return(false)
|
100
|
+
|
101
|
+
subject.stub(:`)
|
102
|
+
subject.stub(:backup_directory).and_return("directory")
|
103
|
+
subject.stub(:tar_options).and_return("options")
|
104
|
+
end
|
105
|
+
|
106
|
+
context do
|
107
|
+
after { subject.create_tarball }
|
108
|
+
it { Dir.should_receive(:chdir).with("directory") }
|
109
|
+
it { subject.should_receive(:`).with("tar options directory.tar.bz2 .") }
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should raise error if file doesn't exist" do
|
113
|
+
FileTest.should_receive(:file?).and_return(false)
|
114
|
+
expect{ subject.create_tarball }.to raise_error
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "#do_backup" do
|
119
|
+
before do
|
120
|
+
FileTest.stub(:directory?).and_return(false)
|
121
|
+
subject.stub(:backup_directory).and_return("backup_directory")
|
122
|
+
subject.stub(:copy_files)
|
123
|
+
subject.stub(:create_tarball)
|
124
|
+
subject.stub(:remove_temporary_files)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should raise error if backup directory exists already" do
|
128
|
+
FileTest.should_receive(:directory?).and_return(true)
|
129
|
+
expect{ subject.do_backup }.to raise_error
|
130
|
+
end
|
131
|
+
|
132
|
+
context do
|
133
|
+
after { subject.do_backup }
|
134
|
+
|
135
|
+
it { subject.should_receive(:copy_files) }
|
136
|
+
it { subject.should_receive(:create_tarball) }
|
137
|
+
it { subject.should_receive(:remove_temporary_files) }
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe "#jobs_files" do
|
142
|
+
before { config.stub(:jenkins).and_return({ "home" => "home" }) }
|
143
|
+
|
144
|
+
it "should return the config.xml and nextBuildNumber files in job directories" do
|
145
|
+
subject.should_receive(:`).
|
146
|
+
with("find home -maxdepth 3 -name config.xml -or -name nextBuildNumber").
|
147
|
+
and_return("file1\nfile2\nfile3")
|
148
|
+
subject.jobs_files.should == %w(file1 file2 file3)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "#new_file_path" do
|
153
|
+
it "should return backup_directory/something" do
|
154
|
+
subject.should_receive(:backup_directory).and_return("backup_directory")
|
155
|
+
config.should_receive(:jenkins).and_return({ "home" => "some_nice_house"})
|
156
|
+
|
157
|
+
subject.new_file_path("some_nice_house/and/then/a/room").should == "backup_directory/and/then/a/room"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "#plugin_files" do
|
162
|
+
before { config.stub(:jenkins).and_return({ "home" => "home" }) }
|
163
|
+
|
164
|
+
it "returns a collection of directories including all the files that have .jpi" do
|
165
|
+
Dir.should_receive(:[]).with("home/plugins/*.jpi").and_return(["jpi"])
|
166
|
+
Dir.should_receive(:[]).with("home/plugins/*.jpi.pinned").and_return(["pinned"])
|
167
|
+
Dir.should_receive(:[]).with("home/plugins/*.jpi.disabled").and_return(["disabled"])
|
168
|
+
|
169
|
+
subject.plugin_files.should == %w(jpi pinned disabled)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "#remove_temporary_files" do
|
174
|
+
before do
|
175
|
+
subject.should_receive(:backup_directory).and_return("backup_directory")
|
176
|
+
config.stub(:verbose).and_return(false)
|
177
|
+
end
|
178
|
+
|
179
|
+
after { subject.remove_temporary_files }
|
180
|
+
it { FileUtils.should_receive(:rm_rf).with("backup_directory", verbose: false) }
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "#tar_options" do
|
184
|
+
it "should be jcf" do
|
185
|
+
config.should_receive(:verbose).and_return(false)
|
186
|
+
subject.tar_options == "jcf"
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should be vjcf" do
|
190
|
+
config.should_receive(:verbose).and_return(true)
|
191
|
+
subject.tar_options == "vjcf"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
describe "#tarball_filename" do
|
196
|
+
before { subject.should_receive(:backup_directory).and_return("backup_directory") }
|
197
|
+
it { subject.tarball_filename.should == "backup_directory.tar.bz2"}
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "#timestamp" do
|
201
|
+
it "should return the current time with the desired timestamp from the config" do
|
202
|
+
config.stub(:backup).and_return("timestamp" => "%Y%m%d_%H%M")
|
203
|
+
Time.stub(:now).and_return(Time.parse("2013/01/01 12:34PM"))
|
204
|
+
subject.send(:timestamp).should == "20130101_1234"
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
describe "#user_content_files" do
|
209
|
+
before { config.stub(:jenkins).and_return({ "home" => "home" }) }
|
210
|
+
|
211
|
+
it "should return files inside the userContent directory" do
|
212
|
+
Dir.should_receive(:[]).with("home/userContent/*").and_return(["my_file"])
|
213
|
+
subject.user_content_files.should == %w(my_file)
|
214
|
+
end
|
215
|
+
end
|
4
216
|
end
|
@@ -1,4 +1,35 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe BackupJenkins::CLI do
|
4
|
+
let(:aws) { stub }
|
5
|
+
let(:backup) { stub }
|
6
|
+
let(:config) { stub }
|
7
|
+
|
8
|
+
before do
|
9
|
+
BackupJenkins::AWS.stub(:new).and_return(aws)
|
10
|
+
BackupJenkins::Backup.stub(:new).and_return(backup)
|
11
|
+
BackupJenkins::Config.stub(:new).and_return(config)
|
12
|
+
|
13
|
+
File.stub(:open).and_return(:IO)
|
14
|
+
|
15
|
+
backup.stub(:do_backup)
|
16
|
+
backup.stub(:tarball_filename).and_return("tarball_filename")
|
17
|
+
|
18
|
+
aws.stub(:upload_file)
|
19
|
+
aws.stub(:remove_old_files)
|
20
|
+
end
|
21
|
+
|
22
|
+
after do
|
23
|
+
BackupJenkins::CLI.run
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ".run" do
|
27
|
+
it { BackupJenkins::AWS.should_receive(:new).with(config) }
|
28
|
+
it { BackupJenkins::Backup.should_receive(:new).with(config) }
|
29
|
+
it { BackupJenkins::Config.should_receive(:new) }
|
30
|
+
it { backup.should_receive(:do_backup) }
|
31
|
+
it { backup.should_receive(:tarball_filename).and_return("tarball_filename") }
|
32
|
+
it { aws.should_receive(:upload_file).with("tarball_filename", :IO) }
|
33
|
+
it { aws.should_receive(:remove_old_files) }
|
34
|
+
end
|
4
35
|
end
|
@@ -3,19 +3,51 @@ require 'tempfile'
|
|
3
3
|
|
4
4
|
describe BackupJenkins::Config do
|
5
5
|
before do
|
6
|
-
|
7
|
-
"aws" => {
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
config = {
|
7
|
+
"aws" => { "access_key" => "some_key", "secret" => "some_secret" },
|
8
|
+
"backup" => { "file_name_base" => "jenkins" }
|
9
|
+
}
|
10
|
+
|
11
|
+
YAML.stub(:load_file).and_return(config)
|
12
12
|
end
|
13
13
|
|
14
|
-
it
|
15
|
-
|
14
|
+
it { expect{ subject.foo }.to raise_error NoMethodError }
|
15
|
+
it { should be_respond_to(:aws) }
|
16
|
+
it { should_not be_respond_to(:foo) }
|
17
|
+
it { subject.aws["access_key"].should == "some_key" }
|
18
|
+
it { subject.aws["secret"].should == "some_secret" }
|
19
|
+
|
20
|
+
describe "#base_file_name" do
|
21
|
+
before { subject.stub(:hostname).and_return("hostname") }
|
22
|
+
it { subject.base_file_name.should == "jenkins_hostname" }
|
16
23
|
end
|
17
24
|
|
18
|
-
|
19
|
-
subject.
|
25
|
+
describe "#hostname" do
|
26
|
+
after { subject.hostname.should == 'hostname' }
|
27
|
+
it { subject.should_receive(:`).with("hostname -s").and_return("hostname\n") }
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#config_file" do
|
31
|
+
it "should load file" do
|
32
|
+
YAML.should_receive(:load_file).and_return("configuration")
|
33
|
+
subject.instance_variable_get(:"@config").should == "configuration"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should exit with non 0 on error" do
|
37
|
+
YAML.should_receive(:load_file).and_raise(Errno::ENOENT)
|
38
|
+
expect{ subject }.to raise_error SystemExit
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should print some helpful text if config file doesn't exist" do
|
42
|
+
subject.should_receive(:config_file_path).twice.and_return("config")
|
43
|
+
|
44
|
+
YAML.should_receive(:load_file).and_raise(Errno::ENOENT)
|
45
|
+
File.should_receive(:read).and_return("sample")
|
46
|
+
|
47
|
+
STDERR.should_receive(:puts).with("Please create a config file in config")
|
48
|
+
STDERR.should_receive(:puts).with("\nIt should look like:\n\nsample")
|
49
|
+
|
50
|
+
expect{ subject.send(:config_file) }.to raise_error SystemExit
|
51
|
+
end
|
20
52
|
end
|
21
53
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: backup_jenkins
|
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:
|
@@ -13,7 +13,7 @@ date: 2012-11-07 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: aws-sdk
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: rake
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: '0'
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: pry-debugger
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ! '>='
|
@@ -43,10 +53,15 @@ dependencies:
|
|
43
53
|
version: '0'
|
44
54
|
type: :development
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: pry-stack_explorer
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ! '>='
|
@@ -54,7 +69,12 @@ dependencies:
|
|
54
69
|
version: '0'
|
55
70
|
type: :development
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
58
78
|
description: Simple Jenkins config and plugin backup to S3
|
59
79
|
email:
|
60
80
|
- jcmuller@gmail.com
|
@@ -67,12 +87,13 @@ files:
|
|
67
87
|
- .rspec
|
68
88
|
- .travis.yml
|
69
89
|
- Gemfile
|
90
|
+
- Guardfile
|
70
91
|
- LICENSE
|
71
92
|
- README.md
|
72
93
|
- Rakefile
|
73
94
|
- backup_jenkins.gemspec
|
74
95
|
- bin/backup_jenkins
|
75
|
-
- config/config-
|
96
|
+
- config/config-example.yml
|
76
97
|
- lib/backup_jenkins.rb
|
77
98
|
- lib/backup_jenkins/aws.rb
|
78
99
|
- lib/backup_jenkins/backup.rb
|
@@ -96,21 +117,27 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
117
|
- - ! '>='
|
97
118
|
- !ruby/object:Gem::Version
|
98
119
|
version: '0'
|
120
|
+
segments:
|
121
|
+
- 0
|
122
|
+
hash: 2193945610003715727
|
99
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
124
|
none: false
|
101
125
|
requirements:
|
102
126
|
- - ! '>='
|
103
127
|
- !ruby/object:Gem::Version
|
104
128
|
version: '0'
|
129
|
+
segments:
|
130
|
+
- 0
|
131
|
+
hash: 2193945610003715727
|
105
132
|
requirements: []
|
106
133
|
rubyforge_project:
|
107
|
-
rubygems_version: 1.8.
|
134
|
+
rubygems_version: 1.8.24
|
108
135
|
signing_key:
|
109
136
|
specification_version: 3
|
110
137
|
summary: This gem allows you to get a backup instance of jenkins up and running pretty
|
111
138
|
quickly
|
112
139
|
test_files:
|
140
|
+
- spec/lib/backup_jenkins/aws_spec.rb
|
113
141
|
- spec/lib/backup_jenkins/backup_spec.rb
|
114
142
|
- spec/lib/backup_jenkins/cli_spec.rb
|
115
143
|
- spec/lib/backup_jenkins/config_spec.rb
|
116
|
-
- spec/lib/backup_jenkins/aws_spec.rb
|