Class: Backup::Adapters::Base

Inherits:
Object
  • Object
show all
Includes:
CommandHelper
Defined in:
lib/backup/adapters/base.rb

Direct Known Subclasses

Archive, Custom, MongoDB, MySQL, PostgreSQL, SQLite

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from CommandHelper

#log, #run

Constructor Details

#initialize(trigger, procedure) ⇒ Base

Initializes the Backup Process

This will first load in any prefixed settings from the Backup::Adapters::Base Then it will add it’s own settings.

First it will call the ‘perform’ method. This method is concerned with the backup, and must be implemented by derived classes! Then it will optionally encrypt the backed up file Then it will store it to the specified storage location Then it will record the data to the database Once this is all done, all the temporary files will be removed

Wrapped inside of begin/ensure/end block to ensure the deletion of any files in the tmp directory



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/backup/adapters/base.rb', line 37

def initialize(trigger, procedure)
  self.trigger                     = trigger
  self.procedure                   = procedure
  self.timestamp                   = Time.now.strftime("%Y%m%d%H%M%S")
  self.tmp_path                    = File.join(BACKUP_PATH.gsub(' ', '\ '), 'tmp', 'backup', trigger)
  self.encrypt_with_password       = procedure.attributes['encrypt_with_password']
  self.encrypt_with_gpg_public_key = procedure.attributes['encrypt_with_gpg_public_key']
  self.keep_backups                = procedure.attributes['keep_backups']

  self.performed_file   = "#{timestamp}.#{trigger.gsub(' ', '-')}#{performed_file_extension}"
  self.compressed_file  = "#{performed_file}.gz"
  self.final_file       = compressed_file

  begin
    create_tmp_folder
    load_settings # if respond_to?(:load_settings)
    handle_before_backup
    perform
    encrypt
    store
    handle_after_backup
    record
    notify
  ensure
    remove_tmp_files
  end
end

Instance Attribute Details

#compressed_fileObject

IMPORTANT final_file must have the value of the final filename result so if a file gets compressed, then the file could look like this:

myfile.gz

and if a file afterwards gets encrypted, the file will look like:

myfile.gz.enc (with a password)
myfile.gz.gpg (with a gpg public key)

It is important that, whatever the final filename of the file will be, that :final_file will contain it.



22
23
24
# File 'lib/backup/adapters/base.rb', line 22

def compressed_file
  @compressed_file
end

#encrypt_with_gpg_public_keyObject

Returns the value of attribute encrypt_with_gpg_public_key.



9
10
11
# File 'lib/backup/adapters/base.rb', line 9

def encrypt_with_gpg_public_key
  @encrypt_with_gpg_public_key
end

#encrypt_with_passwordObject

Returns the value of attribute encrypt_with_password.



9
10
11
# File 'lib/backup/adapters/base.rb', line 9

def encrypt_with_password
  @encrypt_with_password
end

#encrypted_fileObject

IMPORTANT final_file must have the value of the final filename result so if a file gets compressed, then the file could look like this:

myfile.gz

and if a file afterwards gets encrypted, the file will look like:

myfile.gz.enc (with a password)
myfile.gz.gpg (with a gpg public key)

It is important that, whatever the final filename of the file will be, that :final_file will contain it.



22
23
24
# File 'lib/backup/adapters/base.rb', line 22

def encrypted_file
  @encrypted_file
end

#final_fileObject

IMPORTANT final_file must have the value of the final filename result so if a file gets compressed, then the file could look like this:

myfile.gz

and if a file afterwards gets encrypted, the file will look like:

myfile.gz.enc (with a password)
myfile.gz.gpg (with a gpg public key)

It is important that, whatever the final filename of the file will be, that :final_file will contain it.



22
23
24
# File 'lib/backup/adapters/base.rb', line 22

def final_file
  @final_file
end

#keep_backupsObject

Returns the value of attribute keep_backups.



9
10
11
# File 'lib/backup/adapters/base.rb', line 9

def keep_backups
  @keep_backups
end

#optionsObject

Returns the value of attribute options.



9
10
11
# File 'lib/backup/adapters/base.rb', line 9

def options
  @options
end

#performed_fileObject

IMPORTANT final_file must have the value of the final filename result so if a file gets compressed, then the file could look like this:

myfile.gz

and if a file afterwards gets encrypted, the file will look like:

myfile.gz.enc (with a password)
myfile.gz.gpg (with a gpg public key)

It is important that, whatever the final filename of the file will be, that :final_file will contain it.



22
23
24
# File 'lib/backup/adapters/base.rb', line 22

def performed_file
  @performed_file
end

#procedureObject

Returns the value of attribute procedure.



9
10
11
# File 'lib/backup/adapters/base.rb', line 9

def procedure
  @procedure
end

#timestampObject

Returns the value of attribute timestamp.



9
10
11
# File 'lib/backup/adapters/base.rb', line 9

def timestamp
  @timestamp
end

#tmp_pathObject

Returns the value of attribute tmp_path.



9
10
11
# File 'lib/backup/adapters/base.rb', line 9

def tmp_path
  @tmp_path
end

#triggerObject

Returns the value of attribute trigger.



9
10
11
# File 'lib/backup/adapters/base.rb', line 9

def trigger
  @trigger
end

Instance Method Details

#create_tmp_folderObject

Creates the temporary folder for the specified adapter



66
67
68
69
70
# File 'lib/backup/adapters/base.rb', line 66

def create_tmp_folder
  #need to create with universal privlages as some backup tasks might create this path under sudo
  run "mkdir -m 0777 -p #{tmp_path.sub(/\/[^\/]+$/, '')}"  #this is the parent to the tmp_path
  run "mkdir -m 0777 -p #{tmp_path}"                       #the temp path dir
end

#encryptObject

Encrypts the archive file



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/backup/adapters/base.rb', line 101

def encrypt
  if encrypt_with_gpg_public_key.is_a?(String) && encrypt_with_password.is_a?(String)
    puts "both 'encrypt_with_gpg_public_key' and 'encrypt_with_password' are set.  Please choose one or the other.  Exiting."
    exit 1
  end
  
  if encrypt_with_gpg_public_key.is_a?(String)
    if `which gpg` == ''
      puts "Encrypting with a GPG public key requires that gpg be in your public path.  gpg was not found.  Exiting"
      exit 1
    end
    log system_messages[:encrypting_w_key]
    self.encrypted_file   = "#{self.final_file}.gpg"

    # tmp_file = Tempfile.new('backup.pub'){ |tmp_file| tmp_file << encrypt_with_gpg_public_key }
    tmp_file = Tempfile.new('backup.pub')
    tmp_file << encrypt_with_gpg_public_key
    tmp_file.close       
    # that will either say the key was added OR that it wasn't needed, but either way we need to parse for the uid
    # which will be wrapped in '<' and '>' like <[email protected]>
    encryptionKeyId = `gpg --import #{tmp_file.path} 2>&1`.match(/<(.+)>/)[1] 
    run "gpg -e --trust-model always -o #{File.join(tmp_path, encrypted_file)} -r '#{encryptionKeyId}' #{File.join(tmp_path, compressed_file)}"
  elsif encrypt_with_password.is_a?(String)
    log system_messages[:encrypting_w_pass]
    self.encrypted_file   = "#{self.final_file}.enc"
    run "openssl enc -des-cbc -in #{File.join(tmp_path, compressed_file)} -out #{File.join(tmp_path, encrypted_file)} -k #{encrypt_with_password}"
  end
  self.final_file = encrypted_file if encrypted_file
end

#handle_after_backupObject



93
94
95
96
97
98
# File 'lib/backup/adapters/base.rb', line 93

def handle_after_backup
  return unless self.procedure.after_backup_block
  log system_messages[:after_backup_hook]
  #run it through this instance so the block is run as a part of this adapter...which means it has access to all sorts of sutff
  self.instance_eval &self.procedure.after_backup_block
end

#handle_before_backupObject



86
87
88
89
90
91
# File 'lib/backup/adapters/base.rb', line 86

def handle_before_backup
  return unless self.procedure.before_backup_block
  log system_messages[:before_backup_hook]
  #run it through this instance so the block is run as a part of this adapter...which means it has access to all sorts of sutff
  self.instance_eval &self.procedure.before_backup_block
end

#load_settingsObject

TODO make methods in derived classes public? respond_to cannot identify private methods



73
74
# File 'lib/backup/adapters/base.rb', line 73

def load_settings
end

#notifyObject

Delivers a notification by email regarding the successfully stored backup



144
145
146
147
148
# File 'lib/backup/adapters/base.rb', line 144

def notify
  if Backup::Mail::Base.setup?
    Backup::Mail::Base.notify!(self)
  end
end

#recordObject

Records data on every individual file to the database



137
138
139
140
141
# File 'lib/backup/adapters/base.rb', line 137

def record
  record = procedure.initialize_record
  record.load_adapter(self)
  record.save
end

#remove_tmp_filesObject

Removes the files inside the temporary folder



82
83
84
# File 'lib/backup/adapters/base.rb', line 82

def remove_tmp_files
  run "rm -r #{File.join(tmp_path)}" if File.exists?(tmp_path) #just in case there isn't one because the process was skipped
end

#skip_backup(msg) ⇒ Object



76
77
78
79
# File 'lib/backup/adapters/base.rb', line 76

def skip_backup(msg)
  log "Terminating backup early because: #{msg}"
  exit 1
end

#storeObject

Initializes the storing process



132
133
134
# File 'lib/backup/adapters/base.rb', line 132

def store
  procedure.initialize_storage(self)
end

#system_messagesObject



150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/backup/adapters/base.rb', line 150

def system_messages
  { :compressing        => "Compressing backup..",
    :archiving          => "Archiving backup..",
    :encrypting_w_pass  => "Encrypting backup with password..",
    :encrypting_w_key   => "Encrypting backup with gpg public key..",
    :mysqldump          => "Creating MySQL dump..",
    :mongo_dump         => "Creating MongoDB dump..",
    :mongo_copy         => "Creating MongoDB disk level copy..",
    :before_backup_hook => "Running before backup hook..",
    :after_backup_hook  => "Running after backup hook..",
    :pgdump             => "Creating PostgreSQL dump..",
    :sqlite             => "Copying and compressing SQLite database..",
    :commands           => "Executing commands.." }
end