yore 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest.txt CHANGED
@@ -14,9 +14,6 @@ README.rdoc
14
14
  script/console
15
15
  script/destroy
16
16
  script/generate
17
- spec/rewind_spec.rb
18
- spec/spec.opts
19
- spec/spec_helper.rb
20
- spec/test_job_a.xml
21
- spec/yore_spec.rb
22
- tasks/rspec.rake
17
+ test/test_job_a.xml
18
+ test/test_job_b.xml
19
+ test/yore_test.rb
data/README.rdoc CHANGED
@@ -1,32 +1,43 @@
1
1
  = yore
2
2
 
3
- * FIX (url)
3
+ * RubyForge Project : http://rubyforge.org/projects/buzzware
4
+ * Author : http://www.buzzware.com.au
4
5
 
5
6
  == DESCRIPTION:
6
7
 
7
- FIX (describe your package)
8
+ yore (as in "days of yore") is hands-off scheduled backup utility designed for web servers.
9
+ It does backups of files and databases (MySQL only at present) to Amazon S3.
8
10
 
9
11
  == FEATURES/PROBLEMS:
10
12
 
11
- * FIX (list of features or problems)
13
+ * Compressed, encrypted, single file backups of folders and mysql databases
14
+ * Designed to be called regularly
15
+ * Backups are uploaded to Amazon S3
16
+ * will later remove old files that don't match the configurable scheme for backup history
12
17
 
13
18
  == SYNOPSIS:
14
19
 
15
- FIX (code sample of usage)
20
+ yore backup yore_config.xml
16
21
 
17
22
  == REQUIREMENTS:
18
23
 
19
- * FIX (list of requirements)
24
+ * s3sync (http://rubyforge.org/projects/s3sync/)
25
+ * RequirePaths (http://rubyforge.org/projects/blackwhitelogin)
26
+ * cmdparse (http://cmdparse.rubyforge.org)
27
+ * shairontoledo-popen4 (http://github.com/shairontoledo/popen4)
28
+ * tar, bzip2, openssl, mysql
29
+ * tested on MacOS and Linux
20
30
 
21
31
  == INSTALL:
22
32
 
23
- * FIX (sudo gem install, anything else)
33
+ sudo gem sources -a http://gems.github.com
34
+ sudo gem install yore
24
35
 
25
36
  == LICENSE:
26
37
 
27
38
  (The MIT License)
28
39
 
29
- Copyright (c) 2009 FIXME full name
40
+ Copyright (c) 2009 Gary McGhee, Buzzware Solutions
30
41
 
31
42
  Permission is hereby granted, free of charge, to any person obtaining
32
43
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -1,12 +1,11 @@
1
1
  require 'rubygems'
2
2
  require 'rake/rdoctask'
3
3
  require 'rake/testtask'
4
- require 'spec/rake/spectask'
5
4
  %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
6
5
  require File.dirname(__FILE__) + '/lib/yore.orig'
7
6
 
8
7
  # built following http://newgem.rubyforge.org/
9
- # using RSpec option
8
+ # using RSpec option (later converted to shoulda)
10
9
  # and had to add processor_ids from dr nic :
11
10
  # http://groups.google.com/group/new-gem-generator/browse_thread/thread/648f70da782e607a/928ea0fe8319d886?lnk=raot
12
11
 
@@ -20,7 +19,8 @@ $hoe = Hoe.new('yore', Yore::VERSION) do |p|
20
19
  p.extra_deps = [
21
20
  ['RequirePaths','>= 1.0.1'],
22
21
  ['cmdparse', '>= 2.0.2'],
23
- ['s3sync', '>= 1.2.5']
22
+ ['s3sync', '>= 1.2.5'],
23
+ ['shairontoledo-popen4', '>= 0.1.2']
24
24
  ]
25
25
  p.extra_dev_deps = [
26
26
  ['newgem', ">= #{::Newgem::VERSION}"]
@@ -51,7 +51,7 @@ Dir['tasks/**/*.rake'].each { |t| load t }
51
51
  # t.test_files = FileList['test/**/*.rb']
52
52
  # end
53
53
 
54
- Spec::Rake::SpecTask.new do |t|
55
- t.spec_files = FileList['spec/**/*.rb']
56
- end
54
+ #Spec::Rake::SpecTask.new do |t|
55
+ # t.spec_files = FileList['spec/**/*.rb']
56
+ #end
57
57
 
data/lib/yore.orig.rb CHANGED
@@ -2,5 +2,5 @@ $:.unshift(File.dirname(__FILE__)) unless
2
2
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
3
 
4
4
  module Yore
5
- VERSION = '0.0.1'
5
+ VERSION = '0.0.2'
6
6
  end
@@ -2,6 +2,9 @@ require 'rubygems'
2
2
  gem 'RequirePaths'; require 'require_paths'
3
3
  require_paths '.','..'
4
4
 
5
+ gem 'Platform'; require 'platform'
6
+ gem 'shairontoledo-popen4'; require 'popen4'
7
+
5
8
  require 'fileutils'
6
9
  require 'net/smtp'
7
10
 
@@ -13,6 +16,66 @@ require 'ihl_ruby/extend_base_classes'
13
16
  THIS_FILE = __FILE__
14
17
  THIS_DIR = File.dirname(THIS_FILE)
15
18
 
19
+ module POpen4
20
+
21
+ class ExecuteError < StandardError
22
+
23
+ attr_reader :result #,:stderr,:stdout,:exitcode,:pid
24
+
25
+ def initialize(aArg)
26
+ if aArg.is_a? Hash
27
+ super(aArg[:stdout] || '')
28
+ @result = aArg
29
+ # @stderr = aArg[:stderr]
30
+ # @stdout = aArg[:stdout]
31
+ # @exitcode = aArg[:exitcode]
32
+ # @pid = aArg[:pid]
33
+ else
34
+ super(aArg)
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ # Usage :
41
+ # result = POpen4::shell('somebinary') do |r| # block gives opportunity to adjust result, and avoid exception raised from non-zero exit codes
42
+ # if r[:exitcode]==254 # eg. say this binary returns 254 to mean something special but not an error
43
+ # r[:stdout] = 'some correct output'
44
+ # r[:stderr] = ''
45
+ # r[:exitcode] = 0
46
+ # end
47
+ # end
48
+ #
49
+ # OR
50
+ #
51
+ # result = POpen4::shell('somebinary');
52
+ # puts result[:stdout]
53
+ def self.shell(aCommand,aWorkingDir=nil,aTimeout=nil)
54
+ raise ExecuteError.new('aWorkingDir doesnt exist') unless !aWorkingDir || File.exists?(aWorkingDir)
55
+ orig_wd = Dir.getwd
56
+ result = {:command => aCommand, :dir => (aWorkingDir || orig_wd)}
57
+ status = nil
58
+ begin
59
+ Dir.chdir(aWorkingDir) if aWorkingDir
60
+ Timeout.timeout(aTimeout,ExecuteError) do # nil aTimeout will not time out
61
+ status = POpen4::popen4(aCommand) do |stdout, stderr, stdin, pid|
62
+ result[:stdout] = stdout.read
63
+ result[:stderr] = stderr.read
64
+ result[:pid] = pid
65
+ end
66
+ end
67
+ ensure
68
+ Dir.chdir(orig_wd)
69
+ end
70
+ result[:exitcode] = (status && status.exitstatus) || 1
71
+ yield(result) if block_given?
72
+ raise ExecuteError.new(result) if result[:exitcode] != 0
73
+ return result
74
+ end
75
+
76
+ end
77
+
78
+
16
79
  module YoreCore
17
80
 
18
81
  class KeepDaily
@@ -163,8 +226,8 @@ module YoreCore
163
226
  :keep_daily => 14,
164
227
  :keep_weekly => 12,
165
228
  :keep_monthly => 12,
166
- :crypto_iv => "3A63775C1E3F291B0925578165EB917E",
167
- :crypto_key => "07692FC8656F04AE5518B80D38681E038A3C12050DF6CC97CEEC33D800D5E2FE",
229
+ :crypto_iv => "3A63775C1E3F291B0925578165EB917E", # apparently a string of up to 32 random hex digits
230
+ :crypto_key => "07692FC8656F04AE5518B80D38681E038A3C12050DF6CC97CEEC33D800D5E2FE", # apparently a string of up to 64 random hex digits
168
231
  :first_hour => 4,
169
232
  :prefix => 'backup',
170
233
  :log_level => 'DEBUG',
@@ -190,7 +253,7 @@ module YoreCore
190
253
  attr_reader :basepath
191
254
 
192
255
  def initialize(aConfig=nil)
193
- DEFAULT_CONFIG[:email_report] = true # fixes some bug where this was nil
256
+ DEFAULT_CONFIG[:email_report] = false # fixes some bug where this was nil
194
257
  configure(aConfig || DEFAULT_CONFIG)
195
258
  end
196
259
 
@@ -242,10 +305,11 @@ module YoreCore
242
305
  #@filelist =
243
306
  end
244
307
 
245
- def shell(aCommandline)
246
- reporter.debug aCommandline
247
- reporter.debug response = `#{aCommandline}`
248
- response
308
+ def shell(aCommandline,&aBlock)
309
+ reporter.debug "To shell: " + aCommandline
310
+ result = block_given? ? POpen4::shell(aCommandline,nil,nil,&aBlock) : POpen4::shell(aCommandline)
311
+ reporter.debug "From shell: '#{result[:stdout]}'"
312
+ return result[:stdout]
249
313
  end
250
314
 
251
315
  def get_log
@@ -303,8 +367,14 @@ module YoreCore
303
367
  shell "openssl enc -d -aes-256-cbc -K #{config[:crypto_key]} -iv #{config[:crypto_iv]} -in #{aFileIn} -out #{aFileOut}"
304
368
  end
305
369
 
370
+ def ensure_bucket(aBucket=nil)
371
+ aBucket ||= config[:bucket]
372
+ shell "s3cmd createbucket #{aBucket}"
373
+ end
374
+
306
375
  # uploads the given file to the current bucket as its basename
307
376
  def upload(aFile)
377
+ ensure_bucket()
308
378
  shell "s3cmd put #{config[:bucket]}:#{File.basename(aFile)} #{aFile}"
309
379
  end
310
380
 
@@ -323,7 +393,7 @@ module YoreCore
323
393
  # :first_hour
324
394
  # :
325
395
  def encode_file_name(aTimeNow=Time.now)
326
- "#{config[:prefix]}-#{backup_date(aTimeNow).date_numeric}.rew"
396
+ "#{config[:prefix]}-#{backup_date(aTimeNow).date_numeric}.yor"
327
397
  end
328
398
 
329
399
  # return date based on filename
@@ -337,6 +407,7 @@ module YoreCore
337
407
  #end
338
408
 
339
409
  def backup_process(aSourceFiles,aTimeNow=Time.now,aTempDir=nil)
410
+ #require 'ruby-debug'; debugger
340
411
  aTempDir ||= MiscUtils.make_temp_dir('yore_')
341
412
  temp_file = File.expand_path('backup.tar',aTempDir)
342
413
  collect(aSourceFiles,temp_file)
@@ -411,12 +482,14 @@ module YoreCore
411
482
  xmlRoot = XmlUtils.get_file_root(job)
412
483
 
413
484
  filelist = []
485
+ sourceFound = false
414
486
 
415
487
  REXML::XPath.each(xmlRoot, '/Yore/Sources/Source') do |xmlSource|
416
- case xmlSource['Type']
488
+ case xmlSource.attributes['Type']
417
489
  when 'File' then
418
490
  REXML::XPath.each(xmlSource, 'IncludePath') do |xmlPath|
419
- filelist += MiscUtils::recursive_file_list(File.expand_path(xmlPath.text,config[:basepath]))
491
+ filelist += MiscUtils::recursive_file_list(MiscUtils::path_combine(config[:basepath],xmlPath.text))
492
+ sourceFound = true
420
493
  end
421
494
  when 'MySql' then
422
495
  #<Source Type="MySql" >
@@ -431,11 +504,14 @@ module YoreCore
431
504
  raise Error.new("Invalid or missing parameter")
432
505
  end
433
506
  db_to_file(args,file)
434
- filelist += file
507
+ filelist += file
508
+ sourceFound = true
435
509
  end
436
510
  end
437
511
  end
438
512
 
513
+ raise Error.new("Backup source found but file list empty") if sourceFound && filelist.empty?
514
+
439
515
  filelist.uniq!
440
516
  filelist.sort!
441
517
 
File without changes
@@ -0,0 +1,41 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Yore>
3
+ <SimpleItems>
4
+ <Item Name="keep_daily">14</Item>
5
+ <Item Name="keep_weekly">12</Item>
6
+ <Item Name="keep_monthly">12</Item>
7
+ <Item Name="crypto_iv">56FD29B5CE3F291B0925577435EBEE7E</Item>
8
+ <Item Name="crypto_key">07692FC3456A345055B45A37560A85390A3565A0436E035E35636A603A5A2FE</Item>
9
+ <Item Name="bucket">yoretest</Item>
10
+ <Item Name="first_hour">4</Item>
11
+ <Item Name="prefix">yoretest</Item>
12
+ <Item Name="log_level">DEBUG</Item>
13
+ <Item Name="email_report">false</Item>
14
+
15
+ <Item Name="mail_host">mail.authsmtp.com</Item>
16
+ <Item Name="mail_port">25</Item>
17
+ <Item Name="mail_helodomain">finwa.org.au</Item>
18
+ <Item Name="mail_user">ac37391</Item>
19
+ <Item Name="mail_password">mbju7wwzv</Item>
20
+ <Item Name="mail_from">noreply@buzzware.com.au</Item>
21
+ <Item Name="mail_from_alias">FINWA Web Server</Item>
22
+ <Item Name="mail_to">familyincnet@gmail.com</Item>
23
+ <Item Name="mail_to_alias">FINWA</Item>
24
+ <Item Name="mail_auth">login</Item>
25
+
26
+ <Item Name="mysqldump">/usr/local/mysql/bin/mysqldump</Item>
27
+
28
+ </SimpleItems>
29
+ <Sources>
30
+ <Source Type="File">
31
+ <IncludePath>/tmp/yoretest</IncludePath>
32
+ <!-- <ExcludePath></ExcludePath> -->
33
+ </Source>
34
+ <!--<Source Type="MySql" > -->
35
+ <!-- <Database Name="joomla_db" Host="localhost" User="root" Password="prot123ection">-->
36
+ <!-- <ToFile>/Users/gary/temp/test.sql</ToFile> -->
37
+ <!-- </Database> -->
38
+ <!--</Source> -->
39
+ </Sources>
40
+ </Yore>
41
+
@@ -1,18 +1,10 @@
1
1
  require 'rubygems'
2
- require File.dirname(__FILE__) + '/spec_helper.rb'
3
-
4
2
  gem 'RequirePaths'; require 'require_paths'
5
3
  require_paths '../lib','../../..'
6
4
 
5
+ require 'test/unit'
6
+ gem 'Shoulda'; require 'shoulda'
7
7
 
8
- ## Time to add your specs!
9
- # http://rspec.info/
10
- #describe "Place your specs here" do
11
- #
12
- # it "find this spec in spec directory" do
13
- # violated "Be sure to write your specs"
14
- # end
15
- #end
16
8
 
17
9
  require 'ihl_ruby/misc_utils'
18
10
 
@@ -25,14 +17,15 @@ def ensure_clean_bucket(aName)
25
17
  `s3cmd deleteall #{aName}`
26
18
  end
27
19
 
28
- describe YoreCore::Yore do
29
- before(:each) do
20
+ class YoreTest < Test::Unit::TestCase
21
+
22
+ def setup
30
23
  @yore = YoreCore::Yore.new
31
24
  end
32
25
 
33
- it "should collect a list of files into a single file with a .contents file" do
26
+ should "collect a list of files into a single file with a .contents file" do
34
27
  # create a temp dir
35
- temp_dir = MiscUtils::make_temp_dir('yore_spec')
28
+ temp_dir = MiscUtils::make_temp_dir('yore_test')
36
29
  # create source and dest subfolders
37
30
  source_dir = File.expand_path('source',temp_dir)
38
31
  dest_dir = File.expand_path('dest',temp_dir)
@@ -55,14 +48,14 @@ describe YoreCore::Yore do
55
48
  i = 0
56
49
  filelist_out.each_line {|line|
57
50
  next if line==".contents\n"
58
- i.should < filelist.length
59
- line.chomp("\n").should == MiscUtils.path_debase(filelist[i],source_dir) # .bite('/')
51
+ assert i < filelist.length
52
+ assert_equal line.chomp("\n"), MiscUtils.path_debase(filelist[i],source_dir) # .bite('/')
60
53
  i += 1
61
54
  }
62
55
  # could also check .contents file against actual contents
63
56
  end
64
57
 
65
- it "should encrypt and unencrypt a file with a standard iv but a supplied key" do
58
+ should "encrypt and unencrypt a file with a standard iv but a supplied key" do
66
59
  orig_content = 'abcdef123456'
67
60
  temp_file1 = MiscUtils.make_temp_file(nil,nil,orig_content)
68
61
  temp_file2 = temp_file1+'.enc'
@@ -72,23 +65,23 @@ describe YoreCore::Yore do
72
65
  @yore.unpack(temp_file2,temp_file3)
73
66
 
74
67
  file3_content = MiscUtils.string_from_file(temp_file3)
75
- file3_content.should == orig_content
68
+ assert_equal file3_content, orig_content
76
69
  end
77
70
 
78
- it "should create a backup filename combining a prefix, date, day and standard extension, and be able to decode the filename back to a date" do
71
+ should "create a backup filename combining a prefix, date, day and standard extension, and be able to decode the filename back to a date" do
79
72
  @yore.configure({
80
- :prefix => 'spec',
73
+ :prefix => 'test',
81
74
  :first_hour => 4
82
75
  })
83
76
  now = Time.local(2009, 1, 1, 0, 0, 0, 0)
84
- exp_filename = "spec-20081231.rew"
77
+ exp_filename = "test-20081231.yor"
85
78
  calc_filename = @yore.encode_file_name(now)
86
- calc_filename.should == exp_filename
87
- @yore.decode_file_name(calc_filename).should == Time.local(2008, 12, 31)
79
+ assert_equal calc_filename, exp_filename
80
+ assert_equal Time.local(2008, 12, 31), @yore.decode_file_name(calc_filename)
88
81
  end
89
82
 
90
- it "should upload and download files intact" do
91
- bucket = 'yore_spec'
83
+ should "upload and download files intact" do
84
+ bucket = 'yore_test'
92
85
  ensure_clean_bucket(bucket)
93
86
  @yore.configure({
94
87
  :bucket => bucket
@@ -101,19 +94,19 @@ describe YoreCore::Yore do
101
94
  File.rename(temp_file, orig_file)
102
95
  puts @yore.download(temp_file)
103
96
  down_file_content = MiscUtils.string_from_file(temp_file)
104
- down_file_content.should == content
97
+ assert_equal content, down_file_content
105
98
  end
106
99
 
107
- it "should backup and restore multiple directories of file" do
100
+ should "backup and restore multiple directories of file" do
108
101
  # create a temp dir
109
- temp_dir = MiscUtils::make_temp_dir('yore_spec')
102
+ temp_dir = MiscUtils::make_temp_dir('yore_test')
110
103
  # create source and dest subfolders
111
104
  source_dir = File.expand_path('source',temp_dir)
112
105
  source1 = File.join(source_dir,'source1')
113
106
  source2 = File.join(source_dir,'source2')
114
107
  dest_dir = File.expand_path('dest',temp_dir)
115
- bucket = 'yore_spec'
116
-
108
+ bucket = 'yore_test'
109
+
117
110
  FileUtils.mkdir_p([source1,source2,dest_dir])
118
111
  # create some dirs and files in source
119
112
  ['a','a/1','b','c'].each {|p| FileUtils.mkdir_p(File.expand_path(p,source1))}
@@ -137,7 +130,7 @@ job_template = <<EOF
137
130
  <Item Name="bucket">${BUCKET}</Item>
138
131
  </SimpleItems>
139
132
  <Sources>
140
- <Source>
133
+ <Source Type="File">
141
134
  <IncludePath>${SOURCE1}</IncludePath>
142
135
  <IncludePath>${SOURCE2}</IncludePath>
143
136
  </Source>
@@ -158,8 +151,13 @@ EOF
158
151
  })
159
152
 
160
153
  # call yore script with ruby from the command line, then download result and check contents
161
- puts cmd = "ruby #{File.expand_path('../bin/yore.rb',THIS_DIR)} backup #{job_file}"
162
- puts result = `#{cmd}`
154
+ begin
155
+ result = @yore.shell("ruby #{File.expand_path('../../bin/yore',THIS_DIR)} backup #{job_file}")
156
+ rescue ::StandardError => e
157
+ flunk e.inspect
158
+ end
159
+
160
+ puts result
163
161
 
164
162
  retrieved_fname = File.expand_path(@yore.encode_file_name(), dest_dir)
165
163
  collection_fname = MiscUtils::temp_file
@@ -171,9 +169,9 @@ EOF
171
169
 
172
170
  # check contains filelist files ignoring .contents
173
171
  cmd = "tar --list --file=#{collection_fname}"
174
- filelist_out = `#{cmd}`
172
+ filelist_out = @yore.shell(cmd)
175
173
  filelist_out = filelist_out.split("\n").sort
176
- filelist_out.should == filelist
174
+ assert_equal filelist, filelist_out
177
175
  # i = 0
178
176
  # filelist_out.each {|line|
179
177
  # next if line==".contents\n"
@@ -184,16 +182,15 @@ EOF
184
182
  # could also check .contents file against actual contents
185
183
  end
186
184
 
187
- it "should assign proper boolean values" do
188
- class Blah
189
- SOMECONSTANT = {:a => 'AAA', :b => true, :c => false}
190
- end
191
-
192
- puts Blah::SOMECONSTANT.inspect
193
- end
194
-
185
+ should "handle test_file_b" do
186
+ aController = YoreCore::Yore.new # main program object
187
+ job = File.expand_path('../../test/test_job_b.xml',THIS_DIR)
188
+ xmlRoot = XmlUtils.get_file_root(job)
189
+ aController.configure(xmlRoot,nil,{:basepath => File.dirname(File.expand_path(job))})
190
+ aController.backup(job)
191
+ end
195
192
 
196
- it "should provide configurable criteria for keeping old files"
193
+ should "provide configurable criteria for keeping old files"
197
194
 
198
- it "should clean a folder full of files, removing files that don't match configurable criteria for keeping old files"
195
+ should "clean a folder full of files, removing files that don't match configurable criteria for keeping old files"
199
196
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gary McGhee
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-25 00:00:00 +09:00
12
+ date: 2009-02-04 00:00:00 +09:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -42,6 +42,16 @@ dependencies:
42
42
  - !ruby/object:Gem::Version
43
43
  version: 1.2.5
44
44
  version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: shairontoledo-popen4
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 0.1.2
54
+ version:
45
55
  - !ruby/object:Gem::Dependency
46
56
  name: newgem
47
57
  type: :development
@@ -62,7 +72,7 @@ dependencies:
62
72
  - !ruby/object:Gem::Version
63
73
  version: 1.8.0
64
74
  version:
65
- description: FIX (describe your package)
75
+ description: yore (as in "days of yore") is hands-off scheduled backup utility designed for web servers. It does backups of files and databases (MySQL only at present) to Amazon S3.
66
76
  email:
67
77
  - contact@buzz@ware@com@au
68
78
  executables:
@@ -91,14 +101,11 @@ files:
91
101
  - script/console
92
102
  - script/destroy
93
103
  - script/generate
94
- - spec/rewind_spec.rb
95
- - spec/spec.opts
96
- - spec/spec_helper.rb
97
- - spec/test_job_a.xml
98
- - spec/yore_spec.rb
99
- - tasks/rspec.rake
104
+ - test/test_job_a.xml
105
+ - test/test_job_b.xml
106
+ - test/yore_test.rb
100
107
  has_rdoc: true
101
- homepage: FIX (url)
108
+ homepage: "RubyForge Project : http://rubyforge.org/projects/buzzware"
102
109
  post_install_message:
103
110
  rdoc_options:
104
111
  - --main
@@ -123,6 +130,6 @@ rubyforge_project: buzzware
123
130
  rubygems_version: 1.3.1
124
131
  signing_key:
125
132
  specification_version: 2
126
- summary: FIX (describe your package)
133
+ summary: yore (as in "days of yore") is hands-off scheduled backup utility designed for web servers
127
134
  test_files: []
128
135
 
data/spec/rewind_spec.rb DELETED
@@ -1,187 +0,0 @@
1
- require 'rubygems'
2
- gem 'RequirePaths'; require 'require_paths'
3
- require_paths '../../..'
4
-
5
- require 'ihl_ruby/misc_utils'
6
-
7
- require 'fileutils'
8
-
9
- require 'yore_core'
10
-
11
- def ensure_clean_bucket(aName)
12
- `s3cmd createbucket #{aName}`
13
- `s3cmd deleteall #{aName}`
14
- end
15
-
16
- describe YoreCore::Yore do
17
- before(:each) do
18
- @yore = YoreCore::Yore.new
19
- end
20
-
21
- it "should collect a list of files into a single file with a .contents file" do
22
- # create a temp dir
23
- temp_dir = MiscUtils::make_temp_dir('yore_spec')
24
- # create source and dest subfolders
25
- source_dir = File.expand_path('source',temp_dir)
26
- dest_dir = File.expand_path('dest',temp_dir)
27
- FileUtils.mkdir_p([source_dir,dest_dir])
28
- # create some dirs and files in source
29
- ['a','a/1','b','c'].each {|p| FileUtils.mkdir_p(File.expand_path(p,source_dir))}
30
- %w(a/blah.txt a/1/blahblah.txt b/apples.txt c/carrots.txt).each do |f|
31
- MiscUtils::make_temp_file(f,source_dir)
32
- end
33
- # collect into dest file
34
- # get recursive file list, without carrots
35
- filelist = MiscUtils::recursive_file_list(source_dir) {|p| not p =~ /carrots.txt/}
36
- dest_file = File.join(dest_dir,'destfile.bzb')
37
-
38
- @yore.collect(filelist,dest_file)
39
-
40
- # check contains filelist files ignoring .contents
41
- cmd = "tar --list --file=#{dest_file}"
42
- filelist_out = `#{cmd}`
43
- i = 0
44
- filelist_out.each_line {|line|
45
- next if line==".contents\n"
46
- i.should < filelist.length
47
- line.chomp("\n").should == MiscUtils.path_debase(filelist[i],source_dir) # .bite('/')
48
- i += 1
49
- }
50
- # could also check .contents file against actual contents
51
- end
52
-
53
- it "should encrypt and unencrypt a file with a standard iv but a supplied key" do
54
- orig_content = 'abcdef123456'
55
- temp_file1 = MiscUtils.make_temp_file(nil,nil,orig_content)
56
- temp_file2 = temp_file1+'.enc'
57
- temp_file3 = temp_file1+'.dec'
58
-
59
- @yore.pack(temp_file1,temp_file2)
60
- @yore.unpack(temp_file2,temp_file3)
61
-
62
- file3_content = MiscUtils.string_from_file(temp_file3)
63
- file3_content.should == orig_content
64
- end
65
-
66
- it "should create a backup filename combining a prefix, date, day and standard extension, and be able to decode the filename back to a date" do
67
- @yore.configure({
68
- :prefix => 'spec',
69
- :first_hour => 4
70
- })
71
- now = Time.local(2009, 1, 1, 0, 0, 0, 0)
72
- exp_filename = "spec-20081231.rew"
73
- calc_filename = @yore.encode_file_name(now)
74
- calc_filename.should == exp_filename
75
- @yore.decode_file_name(calc_filename).should == Time.local(2008, 12, 31)
76
- end
77
-
78
- it "should upload and download files intact" do
79
- bucket = 'yore_spec'
80
- ensure_clean_bucket(bucket)
81
- @yore.configure({
82
- :bucket => bucket
83
- })
84
- content = 'this is my test content'
85
- temp_dir = MiscUtils.make_temp_dir()
86
- temp_file = MiscUtils.make_temp_file(nil, temp_dir, content)
87
- puts @yore.upload(temp_file)
88
- orig_file = temp_file+'.orig'
89
- File.rename(temp_file, orig_file)
90
- puts @yore.download(temp_file)
91
- down_file_content = MiscUtils.string_from_file(temp_file)
92
- down_file_content.should == content
93
- end
94
-
95
- it "should backup and restore multiple directories of file" do
96
- # create a temp dir
97
- temp_dir = MiscUtils::make_temp_dir('yore_spec')
98
- # create source and dest subfolders
99
- source_dir = File.expand_path('source',temp_dir)
100
- source1 = File.join(source_dir,'source1')
101
- source2 = File.join(source_dir,'source2')
102
- dest_dir = File.expand_path('dest',temp_dir)
103
- bucket = 'yore_spec'
104
-
105
- FileUtils.mkdir_p([source1,source2,dest_dir])
106
- # create some dirs and files in source
107
- ['a','a/1','b','c'].each {|p| FileUtils.mkdir_p(File.expand_path(p,source1))}
108
- %w(a/blah.txt a/1/blahblah.txt b/apples.txt c/carrots.txt).each do |f|
109
- MiscUtils::make_temp_file(f,source1)
110
- end
111
- ['w','x/1','y/2','z'].each {|p| FileUtils.mkdir_p(File.expand_path(p,source2))}
112
- %w(w/zonk.txt x/1/eggs.txt y/2/bloop.txt z/zax.txt).each do |f|
113
- MiscUtils::make_temp_file(f,source2)
114
- end
115
-
116
- # create job file
117
- job_template = <<EOF
118
- <?xml version="1.0" encoding="UTF-8"?>
119
- <Yore>
120
- <SimpleItems>
121
- <Item Name="crypto_iv">3A63775C1E3F291B0925578165EB917E</Item>
122
- <Item Name="crypto_key">07692FC8656F04AE5518B80D38681E038A3C12050DF6CC97CEEC33D800D5E2FE</Item>
123
- <Item Name="prefix">backup</Item>
124
- <Item Name="log_level">DEBUG</Item>
125
- <Item Name="bucket">${BUCKET}</Item>
126
- </SimpleItems>
127
- <Sources>
128
- <Source>
129
- <IncludePath>${SOURCE1}</IncludePath>
130
- <IncludePath>${SOURCE2}</IncludePath>
131
- </Source>
132
- </Sources>
133
- </Yore>
134
- EOF
135
-
136
- job_content = StringUtils::render_template(job_template,{
137
- 'SOURCE1' => source1,
138
- 'SOURCE2' => source2,
139
- 'BUCKET' => bucket
140
- })
141
- MiscUtils::string_to_file(job_content,job_file = MiscUtils::temp_file)
142
-
143
- ensure_clean_bucket(bucket)
144
- @yore.configure({
145
- :bucket => bucket
146
- })
147
-
148
- # call yore script with ruby from the command line, then download result and check contents
149
- puts cmd = "#{File.expand_path('../lib/yore',THIS_DIR)} backup #{job_file}"
150
- puts result = `#{cmd}`
151
-
152
- retrieved_fname = File.expand_path(@yore.encode_file_name(), dest_dir)
153
- collection_fname = MiscUtils::temp_file
154
-
155
- puts @yore.download(retrieved_fname)
156
- puts @yore.unpack(retrieved_fname,collection_fname)
157
-
158
- filelist = MiscUtils::recursive_file_list(source_dir,false)
159
-
160
- # check contains filelist files ignoring .contents
161
- cmd = "tar --list --file=#{collection_fname}"
162
- filelist_out = `#{cmd}`
163
- filelist_out = filelist_out.split("\n").sort
164
- filelist_out.should == filelist
165
- # i = 0
166
- # filelist_out.each {|line|
167
- # next if line==".contents\n"
168
- # i.should < filelist.length
169
- # line.chomp("\n").should == MiscUtils.path_debase(filelist[i],source_dir) # .bite('/')
170
- # i += 1
171
- # }
172
- # could also check .contents file against actual contents
173
- end
174
-
175
- it "should assign proper boolean values" do
176
- class Blah
177
- SOMECONSTANT = {:a => 'AAA', :b => true, :c => false}
178
- end
179
-
180
- puts Blah::SOMECONSTANT.inspect
181
- end
182
-
183
- it "should provide configurable criteria for keeping old files"
184
-
185
- it "should clean a folder full of files, removing files that don't match configurable criteria for keeping old files"
186
- end
187
-
data/spec/spec.opts DELETED
@@ -1 +0,0 @@
1
- --colour
data/spec/spec_helper.rb DELETED
@@ -1,10 +0,0 @@
1
- begin
2
- require 'spec'
3
- rescue LoadError
4
- require 'rubygems'
5
- gem 'rspec'
6
- require 'spec'
7
- end
8
-
9
- $:.unshift(File.dirname(__FILE__) + '/../lib')
10
- require 'yore'
data/tasks/rspec.rake DELETED
@@ -1,21 +0,0 @@
1
- begin
2
- require 'spec'
3
- rescue LoadError
4
- require 'rubygems'
5
- require 'spec'
6
- end
7
- begin
8
- require 'spec/rake/spectask'
9
- rescue LoadError
10
- puts <<-EOS
11
- To use rspec for testing you must install rspec gem:
12
- gem install rspec
13
- EOS
14
- exit(0)
15
- end
16
-
17
- desc "Run the specs under spec/models"
18
- Spec::Rake::SpecTask.new do |t|
19
- t.spec_opts = ['--options', "spec/spec.opts"]
20
- t.spec_files = FileList['spec/**/*_spec.rb']
21
- end