bakman 0.0.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,26 @@
1
+ # This classe require date to manipulate backup date and compare age between backups
2
+ require 'date'
3
+
4
+
5
+ # This class represent one backup of "something"
6
+ class Backup
7
+
8
+ # One backup refers to the #filepath that contains that backup.
9
+ # That file has to be represented by #{name_of_something}_#{date}
10
+ # The #date has to be represented this way : %Y%m%dT%H%M
11
+ attr_reader :filepath, :date
12
+ attr_accessor :to_keep
13
+
14
+ # create one instance of Backup with the #filepath
15
+ def initialize(filepath)
16
+ @filepath = filepath
17
+ @date = Date.strptime(filepath[/\d{8}T\d{4}/],'%Y%m%dT%H%M')
18
+ @to_keep = false
19
+ end
20
+
21
+ # delete that backup (you could need that if the backup is too old)
22
+ def delete!
23
+ puts "#{filepath} deleted."
24
+ File.delete(filepath)
25
+ end
26
+ end
@@ -0,0 +1,127 @@
1
+ # This classe require date to manipulate backup date and compare age between backups
2
+ require 'date'
3
+
4
+ # This class handles a collection of #Backup for the same object "something".
5
+ # This is useful to manipulate backups as a whole
6
+ class BackupList < Array
7
+
8
+ # The object you want to manage the backups has
9
+ # * a #name
10
+ # * the backups are saved in a #folder
11
+ attr_reader :name, :folder, :lenght
12
+
13
+ # This is populating the array with #Backup objects
14
+ # It is sorted at the end for later manipulation on a date sorted array.
15
+ def create(folder,name)
16
+ @name = name
17
+ @folder = folder
18
+ @lenght = 0
19
+ list = Dir.glob("#{folder}/#{name}*")
20
+ list.each do |path|
21
+ self << Backup.new(path)
22
+ @lenght += 1
23
+ end
24
+ self.sort_by! {|bck| bck.date}
25
+ end
26
+
27
+ # A short method to print the list of backups
28
+ def list
29
+ puts "The list of backups for #{self.name}"
30
+ self.each do |bck|
31
+ puts bck.filepath
32
+ end
33
+ end
34
+
35
+ # A method to determine if a backup has to be kept or not.
36
+ # We go thru the array in the reverse order. It allows to test the more recent entries first and keep them first.
37
+ # To be kept, a backup needs :
38
+ # * to have his ( #Backup.date ) between #down_date and #up_date
39
+ # * to be more recent
40
+ # * to not be already kept
41
+ # It returns nb_kept for post analyses
42
+ def keep_backup(nb_to_keep,down_date, up_date)
43
+ range = down_date..up_date
44
+ nb_kept = 0
45
+ self.reverse_each do |bck|
46
+ if range === bck.date
47
+ if nb_kept < nb_to_keep
48
+ if bck.to_keep != true
49
+ puts "#{bck.filepath} will be kept!"
50
+ bck.to_keep = true
51
+ nb_kept += 1
52
+ end
53
+ end
54
+ end
55
+ end
56
+ return nb_kept
57
+ end
58
+
59
+ # A useful method to rotate the files
60
+ # * #nb_to_keep is the number of backups to keep betwwen the two #down_date and #up_date
61
+ # (number above #number_to_keep will be deleted)
62
+ def rotate(nb_to_keep, down_date, up_date)
63
+ nb_kept = keep_backup(nb_to_keep,down_date, up_date)
64
+
65
+ if nb_kept == nb_to_keep
66
+ puts "There is enough backups for this time period."
67
+ else
68
+ puts "Not enough backups between #{down_date} and #{up_date}."
69
+ if up_date == Date.today
70
+ puts "Instead of #{nb_to_keep} backup(s), you will have #{nb_kept} backup(s)"
71
+ else
72
+ puts "We will look for a closer period to find backups if possible."
73
+ self.reverse.rotate(nb_to_keep - nb_kept, up_date, Date.today)
74
+ end
75
+ end
76
+ end
77
+
78
+ # a redefinition of the reverse method from the parent class array
79
+ def reverse
80
+ reversed = BackupList.new
81
+ self.reverse_each do |bck|
82
+ reversed << bck
83
+ end
84
+ return reversed
85
+ end
86
+
87
+
88
+ # A quick method to clean backups files, the one that are not to be kept ( Backup.to_keep == false )
89
+ def clean_bck!
90
+ self.each do |bck|
91
+ if bck.to_keep == false
92
+ bck.delete!
93
+ end
94
+ end
95
+ end
96
+
97
+ # A method to do an automatic GrandFather Father Son rotation of the backups
98
+ # Here a month is 30 days
99
+ # * #nb_g is the number of GrandFather backups to keep (Monthly)
100
+ # * #nb_f is the number of Father backups to keep (weekly)
101
+ # * #nb_s is the number of son backups to keep (daily)
102
+ #/!\ It checks until the prev year but not before.
103
+ def rotate_gfs!(nb_g, nb_f, nb_s)
104
+
105
+ puts "Rotate GrandFather"
106
+ self.rotate(nb_g,Date.today.prev_year, Date.today.prev_day(30))
107
+
108
+ puts "Rotate Father"
109
+ self.rotate(nb_f,Date.today.prev_day(29), Date.today.prev_day(7))
110
+
111
+ puts "Rotate Son"
112
+ self.rotate(nb_s,Date.today.prev_day(6),Date.today)
113
+
114
+ puts "Remove unecessary backups"
115
+ self.clean_bck!
116
+
117
+ end
118
+
119
+ # A method to rsync the backup folder with a remote host describe by #host
120
+ # #host should be username@machine
121
+ # the ssh_keys have to be exchanged before using this (if not, it will failed)
122
+ # /!\ the folder has to exist on the remote host.
123
+ def rsync!(host, remote_folder)
124
+ puts "rsync #{folder}/#{name}* #{host}:#{remote_folder}"
125
+ `rsync #{folder}/#{name}* #{host}:#{remote_folder}`
126
+ end
127
+ end
data/lib/bakman.rb CHANGED
@@ -1,103 +1,2 @@
1
- # This set of classes require date to manipulate backup date and compare age between backups
2
- require 'date'
3
-
4
- # This class represent one backup of "something"
5
- class Backup
6
-
7
- # One backup refers to the #filepath that contains that backup.
8
- # That file has to be represented by #{name_of_something}_#{date}
9
- # The #date has to be represented this way : %Y%m%dT%H%M
10
- attr_reader :filepath, :date
11
-
12
- # create one instance of Backup with the #filepath
13
- def initialize(filepath)
14
- @filepath = filepath
15
- @date = Date.strptime(filepath[/\d{8}T\d{4}/],'%Y%m%dT%H%M')
16
- end
17
-
18
- # delete that backup (you could need that if the backup is too old)
19
- def delete!
20
- puts "#{filepath} deleted."
21
- File.delete(filepath)
22
- end
23
- end
24
-
25
-
26
- # This class handles a collection of #Backup for the same object "something".
27
- # This is useful to manipulate backups as a whole
28
- class BackupList < Array
29
-
30
- # The object you want to manage the backups has
31
- # * a #name
32
- # * the backups are saved in a #folder
33
- attr_reader :name, :folder
34
-
35
- # This is populating the array with #Backup objects
36
- # It is sorted at the end for later manipulation on a date sorted array.
37
- def initialize(folder,name)
38
- @name = name
39
- @folder = folder
40
- list = Dir.glob("#{folder}/#{name}*")
41
- list.each do |path|
42
- self << Backup.new(path)
43
- end
44
- self.sort_by! {|bck| bck.date}
45
- end
46
-
47
- # A short method to print the list of backups
48
- def list
49
- puts "The list of backups for #{self.name}"
50
- self.each do |bck|
51
- puts bck.filepath
52
- end
53
- end
54
-
55
- # A useful method to rotate the files
56
- # * #nb_to_keep is the number of backups to keep betwwen the two #down_date and #up_date
57
- # (number above #number_to_keep will be deleted)
58
- def rotate!(nb_to_keep, down_date, up_date)
59
- range = down_date..up_date
60
- list = []
61
- self.each do |bck|
62
- list << bck if range === bck.date
63
- end
64
-
65
- if list.length == 0
66
- puts "No backup between #{down_date} and #{up_date}."
67
- elsif list.length <= nb_to_keep
68
- puts "There is no need to delete backups."
69
- else
70
- nb_to_delete = list.length - nb_to_keep
71
- puts "#{nb_to_keep} backup(s) will be kept and #{nb_to_delete} backup(s) will be deleted."
72
- list.pop(nb_to_keep)
73
- list.each {|bck| bck.delete!}
74
- end
75
- end
76
-
77
- # A method to do an automatic GrandFather Father Son rotation of the backups
78
- # Here a month is 30 days
79
- # * #nb_g is the number of GrandFather backups to keep (Monthly)
80
- # * #nb_f is the number of Father backups to keep (weekly)
81
- # * #nb_s is the number of son backups to keep (daily)
82
- #/!\ It checks until the prev year but not before.
83
- def rotate_gfs!(nb_g, nb_f, nb_s)
84
-
85
- puts "Rotate GrandFather"
86
- self.rotate!(nb_g,Date.today.prev_year, Date.today.prev_day(30))
87
-
88
- puts "Rotate Father"
89
- self.rotate!(nb_f,Date.today.prev_day(29), Date.today.prev_day(7))
90
-
91
- puts "Rotate Son"
92
- self.rotate!(nb_s,Date.today.prev_day(6),Date.today)
93
-
94
- end
95
- # A method to rsync the backup folder with a remote host describe by #host
96
- # #host should be username@machine
97
- # the ssh_keys have to be exchanged before using this (if not, it will failed)
98
- # /!\ the folder has to exist on the remote host.
99
- def rsync!(host, remote_folder)
100
- puts "rsync #{folder}/#{name}* #{host}:#{remote_folder}"
101
- `rsync #{folder}/#{name}* #{host}:#{remote_folder}`
102
- end
103
- end
1
+ require 'bakman/backup.rb'
2
+ require 'bakman/backuplist.rb'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bakman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -19,6 +19,8 @@ extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
21
  - lib/bakman.rb
22
+ - lib/bakman/backup.rb
23
+ - lib/bakman/backuplist.rb
22
24
  homepage: http://rubygems.org/gems/bakman
23
25
  licenses: []
24
26
  post_install_message: