Class: Backup::Storage::GoogleDrive
- Inherits:
-
Base
- Object
- Base
- Backup::Storage::GoogleDrive
- Includes:
- Storage::Cycler
- Defined in:
- lib/storage/googledrive.rb
Defined Under Namespace
Classes: Error
Instance Attribute Summary collapse
-
#gdrive_exe ⇒ Object
Path to gdrive executable.
-
#refresh_token ⇒ Object
Use the gdrive executable to obtain a refresh token.
Instance Method Summary collapse
- #find_id_from_path(path = remote_path, create = true) ⇒ Object
- #gdrive_delete(id, recursive = true) ⇒ Object
- #gdrive_list(query) ⇒ Object
- #gdrive_mkdir(name, parent = nil) ⇒ Object
- #gdrive_upload(src, parent = nil) ⇒ Object
- #get_folder_id(name, parent = nil) ⇒ Object
-
#initialize(model, storage_id = nil) ⇒ GoogleDrive
constructor
Creates a new instance of the storage object.
-
#remove!(package) ⇒ Object
# Called by the Cycler.
-
#transfer! ⇒ Object
Transfer each of the package files to Dropbox in chunks of
chunk_size.
Constructor Details
#initialize(model, storage_id = nil) ⇒ GoogleDrive
Creates a new instance of the storage object
23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/storage/googledrive.rb', line 23 def initialize(model, storage_id = nil) super @path ||= 'backups' path.sub!(/^\//, '') required = %w{ refresh_token } raise Error, "Configuration Error: a refresh_token is required" if refresh_token.nil? raise Error, "Configuration Error: gdrive executable is required." if gdrive_exe.nil? end |
Instance Attribute Details
#gdrive_exe ⇒ Object
Path to gdrive executable
15 16 17 |
# File 'lib/storage/googledrive.rb', line 15 def gdrive_exe @gdrive_exe end |
#refresh_token ⇒ Object
Use the gdrive executable to obtain a refresh token. Add that token to your backup model. The gdrive exe will handle refresing the access tokens
19 20 21 |
# File 'lib/storage/googledrive.rb', line 19 def refresh_token @refresh_token end |
Instance Method Details
#find_id_from_path(path = remote_path, create = true) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/storage/googledrive.rb', line 65 def find_id_from_path(path = remote_path, create = true) parent = nil path.split('/').each do |path_part| id = get_folder_id(path_part, parent) if id.to_s.empty? && create id = gdrive_mkdir(path_part, parent) end parent = id end return parent end |
#gdrive_delete(id, recursive = true) ⇒ Object
138 139 140 141 142 143 144 145 146 |
# File 'lib/storage/googledrive.rb', line 138 def gdrive_delete(id, recursive = true) cmd = "gdrive --refresh-token '#{refresh_token}' delete #{'-r' if recursive} '#{id}'" output = `#{cmd}` if output.downcase.include? "error" raise Error, "Could not delete object with id: #{id}. See gdrive output: #{output}" else Logger.info output end end |
#gdrive_list(query) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/storage/googledrive.rb', line 83 def gdrive_list(query) unless query.empty? cmd = "gdrive --refresh-token '#{refresh_token}' list --no-header -q \"#{query}\"" output = `#{cmd}` if output.downcase.include? "error" raise Error, "Could not list or find the object with query string '#{query}'. gdrive output: #{output}" elsif output.empty? return nil else begin return /^([^ ]*).*/.match(output)[1] # will return an empty string on no match rescue => err return nil end end else raise Error, "A search query is required to list/find a file or folder" end end |
#gdrive_mkdir(name, parent = nil) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/storage/googledrive.rb', line 103 def gdrive_mkdir(name, parent = nil) unless name.empty? parent = parent ? parent : 'root' cmd = "gdrive --refresh-token '#{refresh_token}' mkdir -p '#{parent}' '#{name}'" output = `#{cmd}` if output.downcase.include? "error" raise Error, "Could not create the directory '#{name}' with parent '#{parent}'. gdrive output: #{output}" else id = /^Directory (.*?) created/.match(output)[1] raise Error, "Could not determine ID of newly created folder. See gdrive output: #{output}" if id.to_s.empty? Logger.info "Created folder #{name} successfully with id '#{id}'" return id end else raise Error, "Name parameter is required to make a directory" end end |
#gdrive_upload(src, parent = nil) ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/storage/googledrive.rb', line 121 def gdrive_upload(src, parent = nil) parent = parent ? parent : 'root' cmd = "gdrive --refresh-token '#{refresh_token}' upload -p '#{parent}' '#{src}'" output = `#{cmd}` if ( ["error", "failed"].any? {|s| output.downcase.include? s } ) raise Error, "Could not upload file. See gdrive output: #{output}" else begin id = /.*Uploaded (.*?) .*/.match(output)[1] raise Error, "empty id" if id.to_s.empty? Logger.info "Uploaded #{src} into parent folder '#{parent}' successfully. Google Drive file_id: #{ id }" rescue => err raise Error.wrap(err, "Could not determine ID of newly created folder. See gdrive output: #{output}") end end end |
#get_folder_id(name, parent = nil) ⇒ Object
78 79 80 81 |
# File 'lib/storage/googledrive.rb', line 78 def get_folder_id(name, parent = nil) parent = parent ? parent : 'root' gdrive_list("name = '#{name}' and '#{parent}' in parents") end |
#remove!(package) ⇒ Object
# Called by the Cycler. # Any error raised will be logged as a warning.
55 56 57 58 59 60 61 62 63 |
# File 'lib/storage/googledrive.rb', line 55 def remove!(package) Logger.info "Removing backup package dated #{ package.time }..." id = find_id_from_path(remote_path_for(package), false) if id.to_s.empty? raise Error, "Backup packge #{ package.time } not found in Google Drive" else gdrive_delete(id) end end |
#transfer! ⇒ Object
Transfer each of the package files to Dropbox in chunks of chunk_size. Each chunk will be retried chunk_retries times, pausing retry_waitsec between retries, if errors occur.
42 43 44 45 46 47 48 49 50 51 |
# File 'lib/storage/googledrive.rb', line 42 def transfer! package.filenames.each do |filename| src = File.join(Config.tmp_path, filename) dest = File.join(remote_path, filename) Logger.info "Storing '#{ dest }'..." parent_id = find_id_from_path(remote_path) gdrive_upload(src, parent_id) end end |