backup_jenkins 0.0.5 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -5
- data/README.md +15 -14
- data/backup_jenkins.gemspec +1 -4
- data/lib/backup_jenkins/aws.rb +51 -16
- data/lib/backup_jenkins/backup.rb +28 -0
- data/lib/backup_jenkins/cli.rb +173 -8
- data/lib/backup_jenkins/config.rb +9 -5
- data/lib/backup_jenkins/formatter.rb +37 -0
- data/lib/backup_jenkins/version.rb +1 -1
- data/lib/backup_jenkins.rb +9 -6
- data/spec/lib/backup_jenkins/aws_spec.rb +20 -45
- data/spec/lib/backup_jenkins/backup_spec.rb +13 -0
- data/spec/lib/backup_jenkins/cli_spec.rb +18 -3
- data/spec/lib/backup_jenkins/config_spec.rb +2 -2
- data/spec/lib/backup_jenkins/formatter_spec.rb +61 -0
- metadata +8 -5
data/Gemfile
CHANGED
@@ -5,19 +5,18 @@ gemspec
|
|
5
5
|
|
6
6
|
group :development do
|
7
7
|
gem "guard"
|
8
|
-
gem "guard-rspec"
|
9
8
|
gem "guard-bundler"
|
10
|
-
gem "
|
11
|
-
gem "rb-fsevent", :require => false
|
9
|
+
gem "guard-rspec"
|
12
10
|
gem "rb-fchange", :require => false
|
11
|
+
gem "rb-fsevent", :require => false
|
12
|
+
gem "rb-inotify", :require => false
|
13
13
|
gem "terminal-notifier-guard"
|
14
14
|
end
|
15
15
|
|
16
16
|
group :test do
|
17
|
+
gem "ci_reporter"
|
17
18
|
gem "rake"
|
18
19
|
gem "rspec"
|
19
|
-
gem "ci_reporter"
|
20
20
|
gem "simplecov"
|
21
21
|
gem "simplecov-rcov"
|
22
|
-
gem "flog"
|
23
22
|
end
|
data/README.md
CHANGED
@@ -1,27 +1,28 @@
|
|
1
1
|
# BackupJenkins
|
2
|
-
[![Build Status](https://secure.travis-ci.org/jcmuller/
|
3
|
-
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/jcmuller/
|
4
|
-
[![Dependency Status](https://gemnasium.com/jcmuller/
|
2
|
+
[![Build Status](https://secure.travis-ci.org/jcmuller/backup_jenkins.png)](http://travis-ci.org/jcmuller/backup_jenkins)
|
3
|
+
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/jcmuller/backup_jenkins)
|
4
|
+
[![Dependency Status](https://gemnasium.com/jcmuller/backup_jenkins.png)](https://gemnasium.com/jcmuller/backup_jenkins)
|
5
5
|
|
6
|
-
|
6
|
+
This gem provides `backup_jenkins`, which provided with a correctly configured `config.yml`
|
7
|
+
located on `~/.config/backup_jenkins/` will backup your job configurations, next build number,
|
8
|
+
global configuration and plugins up to your Amazon AWS S3 account.
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
Add this line to your application's Gemfile:
|
11
|
-
|
12
|
-
gem 'backup_jenkins'
|
10
|
+
### Prerequisites
|
13
11
|
|
14
|
-
|
12
|
+
* Amazon AWS S3 account (you need to provide the user and secret keys)
|
13
|
+
* Jenkins installation
|
14
|
+
* Backup volume with lots of space
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
Or install it yourself as:
|
16
|
+
## Installation
|
19
17
|
|
20
18
|
$ gem install backup_jenkins
|
21
19
|
|
22
20
|
## Usage
|
23
21
|
|
24
|
-
|
22
|
+
$ backup_jenkins
|
23
|
+
|
24
|
+
The first time you run `backup_jenkins`, it shows you a sample configuration file which you
|
25
|
+
should copy into the appropriate location and fill in with your information.
|
25
26
|
|
26
27
|
## Contributing
|
27
28
|
|
data/backup_jenkins.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.email = ["jcmuller@gmail.com"]
|
7
7
|
gem.description = %{Simple Jenkins config and plugin backup to S3}
|
8
8
|
gem.summary = %q{This gem allows you to get a backup instance of jenkins up and running pretty quickly}
|
9
|
-
gem.homepage = "http://github.com/jcmuller/
|
9
|
+
gem.homepage = "http://github.com/jcmuller/backup_jenkins"
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
12
12
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -16,8 +16,5 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.version = BackupJenkins::VERSION
|
17
17
|
|
18
18
|
gem.add_dependency("aws-sdk")
|
19
|
-
|
20
19
|
gem.add_development_dependency("rake")
|
21
|
-
#gem.add_development_dependency("pry-debugger")
|
22
|
-
#gem.add_development_dependency("pry-stack_explorer")
|
23
20
|
end
|
data/lib/backup_jenkins/aws.rb
CHANGED
@@ -2,28 +2,49 @@ module BackupJenkins
|
|
2
2
|
class AWS
|
3
3
|
class UploadFileError < StandardError; end
|
4
4
|
|
5
|
+
include BackupJenkins::Formatter
|
6
|
+
|
5
7
|
def initialize(config = Config.new)
|
6
8
|
@config = config
|
7
9
|
setup_aws
|
8
10
|
end
|
9
11
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
@files.sort!{ |a, b| a.key <=> b.key }
|
14
|
-
end
|
15
|
-
|
16
|
-
def backup_files
|
17
|
-
s3_files.with_prefix(config.base_file_name)
|
12
|
+
def list_backup_files
|
13
|
+
file_hashes = backup_files_for_all_hosts.map{ |f| s3_object_to_hash(f) }
|
14
|
+
format_backup_file_data(file_hashes)
|
18
15
|
end
|
19
16
|
|
20
17
|
def remove_old_files
|
21
18
|
puts "Looking for old files..." if config.verbose
|
22
|
-
populate_files
|
23
19
|
do_remove_old_files
|
24
20
|
puts "Done." if config.verbose
|
25
21
|
end
|
26
22
|
|
23
|
+
def upload_file(filename, file)
|
24
|
+
puts "About to upload #{filename}..." if config.verbose
|
25
|
+
new_file = s3_files.create(filename, file)
|
26
|
+
puts "Done" if config.verbose
|
27
|
+
raise UploadFileError unless new_file.class == ::AWS::S3::S3Object
|
28
|
+
end
|
29
|
+
|
30
|
+
def download_file(filename)
|
31
|
+
remote_file = bucket.objects[filename]
|
32
|
+
|
33
|
+
File.open(filename, 'w') do |file|
|
34
|
+
count = 0
|
35
|
+
remote_file.read do |chunk|
|
36
|
+
file.write(chunk)
|
37
|
+
print "." if count % 512 == 0
|
38
|
+
count += 1
|
39
|
+
end
|
40
|
+
puts "."
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
attr_reader :config, :bucket
|
47
|
+
|
27
48
|
def do_remove_old_files
|
28
49
|
files_to_remove.each do |file|
|
29
50
|
puts "Removing #{file.key}..." if config.verbose
|
@@ -36,16 +57,17 @@ module BackupJenkins
|
|
36
57
|
files - files.last(config.backup["backups_to_keep"])
|
37
58
|
end
|
38
59
|
|
39
|
-
def
|
40
|
-
|
41
|
-
new_file = s3_files.create(filename, file)
|
42
|
-
puts "Done" if config.verbose
|
43
|
-
raise UploadFileError unless new_file.class == ::AWS::S3::S3Object
|
60
|
+
def files
|
61
|
+
@files ||= backup_files_for_this_host.sort{ |a, b| a.key <=> b.key }
|
44
62
|
end
|
45
63
|
|
46
|
-
|
64
|
+
def backup_files_for_this_host
|
65
|
+
s3_files.with_prefix(config.base_file_name)
|
66
|
+
end
|
47
67
|
|
48
|
-
|
68
|
+
def backup_files_for_all_hosts
|
69
|
+
s3_files.with_prefix(config.backup["file_name_base"])
|
70
|
+
end
|
49
71
|
|
50
72
|
def setup_aws
|
51
73
|
s3 = initialize_s3_object
|
@@ -61,6 +83,19 @@ module BackupJenkins
|
|
61
83
|
)
|
62
84
|
end
|
63
85
|
|
86
|
+
# Returns a structure like:
|
87
|
+
# [
|
88
|
+
# { :key => "jenkins_berman_20121107_1721.tar.bz2", :content_length => 88762813 },
|
89
|
+
# { :key => "jenkins_berman_20121107_1745.tar.bz2", :content_length => 88762572 }
|
90
|
+
# ]
|
91
|
+
def s3_object_to_hash(s3_object)
|
92
|
+
{}.tap do |hash|
|
93
|
+
[:key, :content_length, :metadata].each do |key|
|
94
|
+
hash[key] = s3_object.send(key)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
64
99
|
def s3_files
|
65
100
|
bucket.objects
|
66
101
|
end
|
@@ -2,6 +2,8 @@ require 'fileutils'
|
|
2
2
|
|
3
3
|
module BackupJenkins
|
4
4
|
class Backup
|
5
|
+
include BackupJenkins::Formatter
|
6
|
+
|
5
7
|
def initialize(config = Config.new)
|
6
8
|
@config = config
|
7
9
|
end
|
@@ -16,6 +18,10 @@ module BackupJenkins
|
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
21
|
+
def list_local_files
|
22
|
+
format_backup_file_data(backup_files)
|
23
|
+
end
|
24
|
+
|
19
25
|
def create_dir_and_copy_impl(file_name)
|
20
26
|
raise "file '#{file_name}' does not exist" unless FileTest.file?(file_name)
|
21
27
|
|
@@ -37,6 +43,19 @@ module BackupJenkins
|
|
37
43
|
|
38
44
|
create_tarball
|
39
45
|
remove_temporary_files
|
46
|
+
rescue Interrupt
|
47
|
+
puts "Cleaning up..."
|
48
|
+
clean_up
|
49
|
+
end
|
50
|
+
|
51
|
+
def clean_up
|
52
|
+
puts "Removing #{backup_directory}"
|
53
|
+
remove_temporary_files
|
54
|
+
|
55
|
+
puts "Removing #{tarball_filename}"
|
56
|
+
FileUtils.rm_rf(tarball_filename)
|
57
|
+
rescue Errno::ENOENT
|
58
|
+
puts e
|
40
59
|
end
|
41
60
|
|
42
61
|
def copy_files
|
@@ -86,5 +105,14 @@ module BackupJenkins
|
|
86
105
|
def timestamp
|
87
106
|
Time.now.strftime(config.backup["timestamp"])
|
88
107
|
end
|
108
|
+
|
109
|
+
def backup_files
|
110
|
+
Dir["#{config.backup["dir_base"]}/#{config.base_file_name}_*tar.bz2"].map do |file|
|
111
|
+
{
|
112
|
+
:key => file.gsub(%r{#{config.backup["dir_base"]}/}, ''),
|
113
|
+
:content_length => File.size(file)
|
114
|
+
}
|
115
|
+
end
|
116
|
+
end
|
89
117
|
end
|
90
118
|
end
|
data/lib/backup_jenkins/cli.rb
CHANGED
@@ -2,18 +2,183 @@ module BackupJenkins
|
|
2
2
|
class CLI
|
3
3
|
class << self
|
4
4
|
def run
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
cli = self.new
|
6
|
+
cli.parse_options
|
7
|
+
cli.run
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse_options
|
12
|
+
options.each do |opt, arg|
|
13
|
+
case opt
|
14
|
+
when '--config'
|
15
|
+
override_config_file_with(arg)
|
16
|
+
when '--download'
|
17
|
+
download_file(arg)
|
18
|
+
when '--help'
|
19
|
+
show_help
|
20
|
+
when '--license'
|
21
|
+
show_license
|
22
|
+
when '--list'
|
23
|
+
list_remote_backups
|
24
|
+
when '--list-local'
|
25
|
+
list_local_backups
|
26
|
+
when '--only-local'
|
27
|
+
@only_local = true
|
28
|
+
when '--verbose'
|
29
|
+
override_config_file_with_option("verbose" => true)
|
30
|
+
when '--version'
|
31
|
+
show_version
|
32
|
+
end
|
33
|
+
end
|
34
|
+
rescue GetoptLong::MissingArgument
|
35
|
+
# GetoptLong Already outputs the error.
|
36
|
+
puts "\n"
|
37
|
+
show_help
|
38
|
+
end
|
39
|
+
|
40
|
+
def options_possible
|
41
|
+
[
|
42
|
+
[
|
43
|
+
'--config', '-c', GetoptLong::REQUIRED_ARGUMENT,
|
44
|
+
'Override config file location. Path to this file is required.'
|
45
|
+
],
|
46
|
+
[
|
47
|
+
'--download', '-d', GetoptLong::REQUIRED_ARGUMENT,
|
48
|
+
'Download a backup file to current directory. File name is required.'
|
49
|
+
],
|
50
|
+
['--help', '-h', GetoptLong::NO_ARGUMENT, 'Print this message.'],
|
51
|
+
['--license', '-L', GetoptLong::NO_ARGUMENT, 'Print license.'],
|
52
|
+
['--list', '-l', GetoptLong::NO_ARGUMENT, 'List backups available on S3.'],
|
53
|
+
['--list-local', '-o', GetoptLong::NO_ARGUMENT, 'List local backups available.'],
|
54
|
+
['--only-local', '-O', GetoptLong::NO_ARGUMENT, 'Only create local backup file.'],
|
55
|
+
['--verbose', '-v', GetoptLong::NO_ARGUMENT, 'Be verbose. This overrides config file.'],
|
56
|
+
['--version', '-V', GetoptLong::NO_ARGUMENT, 'Print version number and exit,']
|
57
|
+
]
|
58
|
+
end
|
59
|
+
|
60
|
+
def run
|
61
|
+
backup.do_backup
|
62
|
+
|
63
|
+
full_filename = backup.tarball_filename
|
64
|
+
filename = File.basename(full_filename)
|
65
|
+
|
66
|
+
aws.upload_file(filename, File.open(full_filename)) unless @only_local
|
67
|
+
aws.remove_old_files # Clean up!
|
68
|
+
rescue Interrupt
|
69
|
+
backup.clean_up
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def config
|
75
|
+
@config ||= BackupJenkins::Config.new
|
76
|
+
end
|
77
|
+
|
78
|
+
def aws
|
79
|
+
@aws ||= BackupJenkins::AWS.new(config)
|
80
|
+
end
|
81
|
+
|
82
|
+
def backup
|
83
|
+
@backup ||= BackupJenkins::Backup.new(config)
|
84
|
+
end
|
85
|
+
|
86
|
+
def options
|
87
|
+
@options ||= GetoptLong.new(*options_possible.map{ |o| o.first(3) })
|
88
|
+
end
|
89
|
+
|
90
|
+
# Entry points
|
91
|
+
|
92
|
+
def show_help
|
93
|
+
STDOUT.puts help_info
|
94
|
+
exit
|
95
|
+
end
|
96
|
+
|
97
|
+
def show_version
|
98
|
+
STDOUT.puts version_info
|
99
|
+
exit
|
100
|
+
end
|
101
|
+
|
102
|
+
def show_license
|
103
|
+
STDOUT.puts license_info
|
104
|
+
exit
|
105
|
+
end
|
106
|
+
|
107
|
+
def list_remote_backups
|
108
|
+
STDOUT.puts aws.list_backup_files
|
109
|
+
exit
|
110
|
+
end
|
111
|
+
|
112
|
+
def list_local_backups
|
113
|
+
STDOUT.puts backup.list_local_files
|
114
|
+
exit
|
115
|
+
end
|
116
|
+
|
117
|
+
def download_file(filename)
|
118
|
+
aws.download_file(filename)
|
119
|
+
exit
|
120
|
+
end
|
121
|
+
|
122
|
+
def override_config_file_with(config_file_name)
|
123
|
+
raise "File not found or not readable" unless File.readable?(config_file_name)
|
124
|
+
@config = BackupJenkins::Config.new(config_file_name)
|
125
|
+
end
|
126
|
+
|
127
|
+
def override_config_file_with_option(options = {})
|
128
|
+
config.override(options)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Data
|
132
|
+
|
133
|
+
def license_info
|
134
|
+
"#{File.read(license_file_path)}\n\n"
|
135
|
+
end
|
136
|
+
|
137
|
+
def license_file_path
|
138
|
+
File.expand_path("../../..//LICENSE", __FILE__)
|
139
|
+
end
|
8
140
|
|
9
|
-
|
141
|
+
def version_info
|
142
|
+
<<-EOV
|
143
|
+
backup_jenkins (#{BackupJenkins::VERSION})
|
144
|
+
https://github.com/jcmuller/backup_jenkins
|
145
|
+
(c) 2012 Juan C. Muller
|
146
|
+
Work on this has been proudly backed by ChallengePost, Inc.
|
147
|
+
EOV
|
148
|
+
end
|
10
149
|
|
11
|
-
|
12
|
-
|
150
|
+
def help_info
|
151
|
+
<<-EOH
|
152
|
+
Usage: #{File.basename($0)} [options]
|
153
|
+
[#{options_possible.map{ |o| short_hand_option(o)}.join('], [')}]
|
154
|
+
|
155
|
+
Options:
|
156
|
+
#{option_details}
|
157
|
+
|
158
|
+
#{version_info}
|
159
|
+
EOH
|
160
|
+
end
|
13
161
|
|
14
|
-
|
15
|
-
|
162
|
+
def short_hand_option(option)
|
163
|
+
if option[2] == GetoptLong::REQUIRED_ARGUMENT
|
164
|
+
[option[0], option[1]].join('|') << " argument"
|
165
|
+
else
|
166
|
+
[option[0], option[1]].join('|')
|
16
167
|
end
|
17
168
|
end
|
169
|
+
|
170
|
+
def option_details
|
171
|
+
<<-EOO
|
172
|
+
#{options_possible.map{ |o| expand_option(o) }.join("\n")}
|
173
|
+
EOO
|
174
|
+
end
|
175
|
+
|
176
|
+
def longest_width
|
177
|
+
@max_width ||= options_possible.map{ |o| o[0] }.max{ |a, b| a.length <=> b.length }.length
|
178
|
+
end
|
179
|
+
|
180
|
+
def expand_option(option)
|
181
|
+
sprintf(" %-#{longest_width + 6}s %s", option.first(2).join(', '), option[3])
|
182
|
+
end
|
18
183
|
end
|
19
184
|
end
|
@@ -2,8 +2,8 @@ module BackupJenkins
|
|
2
2
|
class Config
|
3
3
|
attr_reader :s3
|
4
4
|
|
5
|
-
def initialize
|
6
|
-
@config = config_file
|
5
|
+
def initialize(path = default_config_file_path)
|
6
|
+
@config = config_file(path)
|
7
7
|
end
|
8
8
|
|
9
9
|
def method_missing(meth, *args, &block)
|
@@ -23,20 +23,24 @@ module BackupJenkins
|
|
23
23
|
%x{hostname -s}.chomp
|
24
24
|
end
|
25
25
|
|
26
|
+
def override(options = {})
|
27
|
+
@config.merge!(options)
|
28
|
+
end
|
29
|
+
|
26
30
|
private
|
27
31
|
|
28
32
|
attr_reader :config
|
29
33
|
|
30
|
-
def config_file
|
34
|
+
def config_file(config_file_path)
|
31
35
|
YAML.load_file(config_file_path)
|
32
36
|
rescue Errno::ENOENT
|
33
|
-
STDERR.puts "Please create a config file in #{
|
37
|
+
STDERR.puts "Please create a config file in #{default_config_file_path}"
|
34
38
|
STDERR.puts "\nIt should look like:\n\n#{config_file_example}"
|
35
39
|
|
36
40
|
exit 1
|
37
41
|
end
|
38
42
|
|
39
|
-
def
|
43
|
+
def default_config_file_path
|
40
44
|
"#{ENV['HOME']}/.config/backup_jenkins/config.yml"
|
41
45
|
end
|
42
46
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module BackupJenkins
|
2
|
+
module Formatter
|
3
|
+
|
4
|
+
# Assumes that filenames are ordered already
|
5
|
+
# Requires a structure like:
|
6
|
+
# [
|
7
|
+
# { :key => "jenkins_berman_20121107_1721.tar.bz2", :content_length => 88762813 },
|
8
|
+
# { :key => "jenkins_berman_20121107_1745.tar.bz2", :content_length => 88762572 }
|
9
|
+
# ]
|
10
|
+
def format_backup_file_data(file_hashes)
|
11
|
+
by_host = {}
|
12
|
+
file_hashes.each do |file_hash|
|
13
|
+
(date, host, key) = extract_data_from_filename(file_hash[:key])
|
14
|
+
by_host[host] ||= []
|
15
|
+
by_host[host].push([date, key, file_hash[:content_length] / 2.0**20])
|
16
|
+
end
|
17
|
+
|
18
|
+
"".tap do |output|
|
19
|
+
by_host.each do |host, data|
|
20
|
+
output << host.capitalize << ":" << $/
|
21
|
+
data.each do |datum|
|
22
|
+
output << sprintf(" - %s key: %s (%0.2f MB)#{$/}", *datum)
|
23
|
+
end
|
24
|
+
output << $/
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def extract_data_from_filename(filename)
|
30
|
+
sans_base = filename.gsub(/#{config.backup["file_name_base"]}_/, '').gsub(/\.tar\.bz2/, '')
|
31
|
+
(hostname, date, time) = sans_base.split("_")
|
32
|
+
formatted_date = Time.parse(date << time).strftime("%Y/%m/%d %H:%M")
|
33
|
+
[formatted_date, hostname, filename]
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
data/lib/backup_jenkins.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'yaml'
|
3
2
|
require 'aws'
|
3
|
+
require 'getoptlong'
|
4
|
+
require 'time'
|
5
|
+
require 'yaml'
|
4
6
|
|
5
7
|
module BackupJenkins
|
6
|
-
autoload :AWS,
|
7
|
-
autoload :Backup,
|
8
|
-
autoload :CLI,
|
9
|
-
autoload :Config,
|
10
|
-
autoload :
|
8
|
+
autoload :AWS, 'backup_jenkins/aws'
|
9
|
+
autoload :Backup, 'backup_jenkins/backup'
|
10
|
+
autoload :CLI, 'backup_jenkins/cli'
|
11
|
+
autoload :Config, 'backup_jenkins/config'
|
12
|
+
autoload :Formatter, 'backup_jenkins/formatter'
|
13
|
+
autoload :VERSION, 'backup_jenkins/version'
|
11
14
|
end
|
@@ -8,7 +8,7 @@ describe BackupJenkins::AWS do
|
|
8
8
|
BackupJenkins::Config.stub(:new).and_return(config)
|
9
9
|
|
10
10
|
config.stub(:aws).and_return({ "access_key" => "some_key", "secret" => "some_secret" })
|
11
|
-
config.stub(:backup).and_return({ "backups_to_keep" => 2 })
|
11
|
+
config.stub(:backup).and_return({ "backups_to_keep" => 2, "file_name_base" => "jenkins" })
|
12
12
|
|
13
13
|
::AWS::S3.stub(:new).and_return(s3_mocks)
|
14
14
|
end
|
@@ -28,26 +28,36 @@ describe BackupJenkins::AWS do
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
describe "#
|
32
|
-
it "should get the objects from
|
31
|
+
describe "#files" do
|
32
|
+
it "should get the objects from backup_files_for_this_host and sort them" do
|
33
33
|
a = mock(:key => 1)
|
34
34
|
b = mock(:key => 2)
|
35
35
|
c = mock(:key => 3)
|
36
36
|
|
37
|
-
subject.should_receive(:
|
38
|
-
subject.
|
37
|
+
subject.should_receive(:backup_files_for_this_host).and_return([b, c, a])
|
38
|
+
subject.send(:files).should == [a, b, c]
|
39
39
|
subject.instance_variable_get(:"@files").should == [a, b, c]
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
describe "#
|
43
|
+
describe "#backup_files_for_this_host" do
|
44
44
|
it "should return the right files" do
|
45
45
|
config.should_receive(:base_file_name).and_return("base_file_name")
|
46
46
|
objects = mock
|
47
47
|
objects.should_receive(:with_prefix).with("base_file_name").and_return([1, 2, 3])
|
48
48
|
subject.should_receive(:s3_files).and_return(objects)
|
49
49
|
|
50
|
-
subject.
|
50
|
+
subject.send(:backup_files_for_this_host).should == [1, 2, 3]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#list_backup_files" do
|
55
|
+
it "should call the right methods" do
|
56
|
+
subject.should_receive(:s3_object_to_hash).twice.and_return(:blah)
|
57
|
+
subject.should_receive(:backup_files_for_all_hosts).and_return([mock, mock])
|
58
|
+
subject.should_receive(:format_backup_file_data).with([:blah, :blah])
|
59
|
+
|
60
|
+
subject.list_backup_files
|
51
61
|
end
|
52
62
|
end
|
53
63
|
|
@@ -56,22 +66,10 @@ describe BackupJenkins::AWS do
|
|
56
66
|
config.stub(:verbose).and_return(false)
|
57
67
|
end
|
58
68
|
|
59
|
-
it "should
|
60
|
-
subject.should_receive(:populate_files)
|
69
|
+
it "should call do_remove_old_files" do
|
61
70
|
subject.should_receive(:do_remove_old_files)
|
62
71
|
subject.remove_old_files
|
63
72
|
end
|
64
|
-
|
65
|
-
it "should print stuff if verbose", :pending => 'failing on JRuby' 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
73
|
end
|
76
74
|
|
77
75
|
describe "#do_remove_old_files" do
|
@@ -85,24 +83,14 @@ describe BackupJenkins::AWS do
|
|
85
83
|
file_2.should_receive(:delete)
|
86
84
|
|
87
85
|
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", :pending => 'failing on JRuby' 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
|
86
|
+
subject.send(:do_remove_old_files)
|
99
87
|
end
|
100
88
|
end
|
101
89
|
|
102
90
|
describe "#files_to_remove" do
|
103
91
|
it "should get the last n files (where n is total number - keep)" do
|
104
92
|
subject.stub(:files).and_return(%w(a b c d e f g))
|
105
|
-
subject.files_to_remove.should == ["a", "b", "c", "d", "e"]
|
93
|
+
subject.send(:files_to_remove).should == ["a", "b", "c", "d", "e"]
|
106
94
|
end
|
107
95
|
end
|
108
96
|
|
@@ -118,19 +106,6 @@ describe BackupJenkins::AWS do
|
|
118
106
|
subject.upload_file("filename", "file")
|
119
107
|
end
|
120
108
|
|
121
|
-
it "should print stuff in verbose", :pending => 'failing on JRuby' 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
109
|
it "should raise exception if no s3 object is created" do
|
135
110
|
config.stub(:verbose).and_return(false)
|
136
111
|
|
@@ -61,6 +61,19 @@ describe BackupJenkins::Backup do
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
+
describe "#list_local_files" do
|
65
|
+
before do
|
66
|
+
config.stub(:backup).and_return("dir_base" => "base")
|
67
|
+
config.stub(:base_file_name).and_return("base_file_name")
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should call the right methods" do
|
71
|
+
subject.should_receive(:backup_files)
|
72
|
+
subject.should_receive(:format_backup_file_data)
|
73
|
+
subject.list_local_files
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
64
77
|
describe "#create_dir_and_copy_impl" do
|
65
78
|
before do
|
66
79
|
FileTest.stub(:file?).and_return(true)
|
@@ -19,11 +19,13 @@ describe BackupJenkins::CLI do
|
|
19
19
|
aws.stub(:remove_old_files)
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
BackupJenkins::CLI.run
|
22
|
+
describe ".run" do
|
23
|
+
after { BackupJenkins::CLI.run }
|
24
|
+
it { BackupJenkins::CLI.any_instance.should_receive(:run) }
|
24
25
|
end
|
25
26
|
|
26
|
-
describe "
|
27
|
+
describe "#run" do
|
28
|
+
after { subject.run }
|
27
29
|
it { BackupJenkins::AWS.should_receive(:new).with(config) }
|
28
30
|
it { BackupJenkins::Backup.should_receive(:new).with(config) }
|
29
31
|
it { BackupJenkins::Config.should_receive(:new) }
|
@@ -32,4 +34,17 @@ describe BackupJenkins::CLI do
|
|
32
34
|
it { aws.should_receive(:upload_file).with("tarball_filename", :IO) }
|
33
35
|
it { aws.should_receive(:remove_old_files) }
|
34
36
|
end
|
37
|
+
|
38
|
+
describe "#longest_width" do
|
39
|
+
before { subject.stub(:options_possible).and_return([%w(1234), %w(1234567890), %w(123)]) }
|
40
|
+
it { subject.send(:longest_width).should == 10 }
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#expand_option" do
|
44
|
+
it {
|
45
|
+
subject.send(:expand_option, ['--this-option', '-t', 0, 'This is my explanation']).should(
|
46
|
+
eq " --this-option, -t This is my explanation"
|
47
|
+
)
|
48
|
+
}
|
49
|
+
end
|
35
50
|
end
|
@@ -39,7 +39,7 @@ describe BackupJenkins::Config do
|
|
39
39
|
end
|
40
40
|
|
41
41
|
it "should print some helpful text if config file doesn't exist" do
|
42
|
-
subject.should_receive(:
|
42
|
+
subject.should_receive(:default_config_file_path).and_return("config")
|
43
43
|
|
44
44
|
YAML.should_receive(:load_file).and_raise(Errno::ENOENT)
|
45
45
|
File.should_receive(:read).and_return("sample")
|
@@ -47,7 +47,7 @@ describe BackupJenkins::Config do
|
|
47
47
|
STDERR.should_receive(:puts).with("Please create a config file in config")
|
48
48
|
STDERR.should_receive(:puts).with("\nIt should look like:\n\nsample")
|
49
49
|
|
50
|
-
expect{ subject.send(:config_file) }.to raise_error SystemExit
|
50
|
+
expect{ subject.send(:config_file, nil) }.to raise_error SystemExit
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class SpecFormatterIncluder
|
4
|
+
include BackupJenkins::Formatter
|
5
|
+
|
6
|
+
attr_reader :config
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@config = BackupJenkins::Config.new
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe BackupJenkins::Formatter do
|
14
|
+
subject { SpecFormatterIncluder.new }
|
15
|
+
|
16
|
+
describe "#format_backup_file_data" do
|
17
|
+
let(:files) {
|
18
|
+
[
|
19
|
+
{ :key => "jenkins_berman_20121107_1721.tar.bz2", :content_length => 88762813 },
|
20
|
+
{ :key => "jenkins_berman_20121107_1745.tar.bz2", :content_length => 88762572 },
|
21
|
+
{ :key => "jenkins_berman_20121107_1923.tar.bz2", :content_length => 88761816 },
|
22
|
+
{ :key => "jenkins_berman_20121107_2038.tar.bz2", :content_length => 88752599 },
|
23
|
+
{ :key => "jenkins_cronus_20121107_2033.tar.bz2", :content_length => 17139234 },
|
24
|
+
{ :key => "jenkins_perseo_20121107_0035.tar.bz2", :content_length => 52683965 },
|
25
|
+
{ :key => "jenkins_perseo_20121107_0135.tar.bz2", :content_length => 52684962 }
|
26
|
+
]
|
27
|
+
}
|
28
|
+
|
29
|
+
it "should format things nicely" do
|
30
|
+
output = subject.send(:format_backup_file_data, files)
|
31
|
+
output.should == <<-EOO
|
32
|
+
Berman:
|
33
|
+
- 2012/11/07 17:21 key: jenkins_berman_20121107_1721.tar.bz2 (84.65 MB)
|
34
|
+
- 2012/11/07 17:45 key: jenkins_berman_20121107_1745.tar.bz2 (84.65 MB)
|
35
|
+
- 2012/11/07 19:23 key: jenkins_berman_20121107_1923.tar.bz2 (84.65 MB)
|
36
|
+
- 2012/11/07 20:38 key: jenkins_berman_20121107_2038.tar.bz2 (84.64 MB)
|
37
|
+
|
38
|
+
Cronus:
|
39
|
+
- 2012/11/07 20:33 key: jenkins_cronus_20121107_2033.tar.bz2 (16.35 MB)
|
40
|
+
|
41
|
+
Perseo:
|
42
|
+
- 2012/11/07 00:35 key: jenkins_perseo_20121107_0035.tar.bz2 (50.24 MB)
|
43
|
+
- 2012/11/07 01:35 key: jenkins_perseo_20121107_0135.tar.bz2 (50.24 MB)
|
44
|
+
|
45
|
+
EOO
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#extract_data_from_filename" do
|
50
|
+
it "should obtain important info from filename" do
|
51
|
+
filename = "jenkins_berman_20121107_1721.tar.bz2"
|
52
|
+
|
53
|
+
result = subject.send(:extract_data_from_filename, filename)
|
54
|
+
result.should == [
|
55
|
+
'2012/11/07 17:21',
|
56
|
+
'berman',
|
57
|
+
'jenkins_berman_20121107_1721.tar.bz2'
|
58
|
+
]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
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.7
|
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: 2012-11-
|
12
|
+
date: 2012-11-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: aws-sdk
|
@@ -67,13 +67,15 @@ files:
|
|
67
67
|
- lib/backup_jenkins/backup.rb
|
68
68
|
- lib/backup_jenkins/cli.rb
|
69
69
|
- lib/backup_jenkins/config.rb
|
70
|
+
- lib/backup_jenkins/formatter.rb
|
70
71
|
- lib/backup_jenkins/version.rb
|
71
72
|
- spec/lib/backup_jenkins/aws_spec.rb
|
72
73
|
- spec/lib/backup_jenkins/backup_spec.rb
|
73
74
|
- spec/lib/backup_jenkins/cli_spec.rb
|
74
75
|
- spec/lib/backup_jenkins/config_spec.rb
|
76
|
+
- spec/lib/backup_jenkins/formatter_spec.rb
|
75
77
|
- spec/spec_helper.rb
|
76
|
-
homepage: http://github.com/jcmuller/
|
78
|
+
homepage: http://github.com/jcmuller/backup_jenkins
|
77
79
|
licenses: []
|
78
80
|
post_install_message:
|
79
81
|
rdoc_options: []
|
@@ -87,7 +89,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
87
89
|
version: '0'
|
88
90
|
segments:
|
89
91
|
- 0
|
90
|
-
hash:
|
92
|
+
hash: -3794041082511016081
|
91
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
94
|
none: false
|
93
95
|
requirements:
|
@@ -96,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
98
|
version: '0'
|
97
99
|
segments:
|
98
100
|
- 0
|
99
|
-
hash:
|
101
|
+
hash: -3794041082511016081
|
100
102
|
requirements: []
|
101
103
|
rubyforge_project:
|
102
104
|
rubygems_version: 1.8.24
|
@@ -109,3 +111,4 @@ test_files:
|
|
109
111
|
- spec/lib/backup_jenkins/backup_spec.rb
|
110
112
|
- spec/lib/backup_jenkins/cli_spec.rb
|
111
113
|
- spec/lib/backup_jenkins/config_spec.rb
|
114
|
+
- spec/lib/backup_jenkins/formatter_spec.rb
|