mirror of
https://codeberg.org/vlw/cloud-backup.git
synced 2025-09-14 10:03:40 +02:00
wip(22w9a): sql param fix
This commit is contained in:
parent
247e6732bf
commit
29ef6ff8dd
8 changed files with 46 additions and 38 deletions
|
@ -1,7 +1,9 @@
|
||||||
|
# Path to the local folder to back up
|
||||||
SOURCE_FOLDER=
|
SOURCE_FOLDER=
|
||||||
|
# Name of the remote bucket (destination)
|
||||||
TARGET_BUCKET=
|
TARGET_BUCKET=
|
||||||
|
|
||||||
# Cloud provider "gcs, aws, azure"
|
# Cloud provider (gcs, s3, azure)
|
||||||
SERVICE_NAME=
|
SERVICE_NAME=
|
||||||
# Path to service account key file
|
# Path to service account key file
|
||||||
SERVICE_KEY=
|
SERVICE_KEY=
|
|
@ -32,7 +32,7 @@ class Backup(FileSystem):
|
||||||
|
|
||||||
self.has_change = True
|
self.has_change = True
|
||||||
|
|
||||||
print(f"Uploading: '{item[0]}' ... ", end="")
|
print(f"⧖ | Uploading: '{item[0]}'", end="\r")
|
||||||
|
|
||||||
blob = item
|
blob = item
|
||||||
# Upload as zip archive
|
# Upload as zip archive
|
||||||
|
@ -41,13 +41,15 @@ class Backup(FileSystem):
|
||||||
|
|
||||||
# Upload to cloud
|
# Upload to cloud
|
||||||
if self.cloud.upload(blob):
|
if self.cloud.upload(blob):
|
||||||
|
print(f"✓ | Upload sucessful: '{item[0]}'")
|
||||||
# Update local database
|
# Update local database
|
||||||
if self.db.set_item(item):
|
if not self.db.set_item(item):
|
||||||
print("OK")
|
print("🛈 | Failed to update database")
|
||||||
else:
|
else:
|
||||||
print("OK, but failed to update database")
|
print(f"✕ | Upload failed: '{item[0]}'")
|
||||||
else:
|
if self.cloud.error:
|
||||||
print("FAILED")
|
print("🛈 | " + str(self.cloud.error))
|
||||||
|
|
||||||
|
|
||||||
# Remove temp zip
|
# Remove temp zip
|
||||||
if self.compress:
|
if self.compress:
|
||||||
|
@ -61,4 +63,4 @@ class Backup(FileSystem):
|
||||||
self.backup_item(item)
|
self.backup_item(item)
|
||||||
|
|
||||||
if not self.has_change:
|
if not self.has_change:
|
||||||
print("Up to date. No changes found")
|
print("✓ | Up to date. No changes found")
|
|
@ -8,6 +8,8 @@ class Storage:
|
||||||
self._service = None
|
self._service = None
|
||||||
self.service = os.getenv("SERVICE_NAME")
|
self.service = os.getenv("SERVICE_NAME")
|
||||||
|
|
||||||
|
self.error = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def service(self):
|
def service(self):
|
||||||
return self._service
|
return self._service
|
||||||
|
@ -27,4 +29,7 @@ class Storage:
|
||||||
return values
|
return values
|
||||||
|
|
||||||
def upload(self, *argv):
|
def upload(self, *argv):
|
||||||
return self.service.upload(*argv)
|
upload = self.service.upload(*argv)
|
||||||
|
self.error = self.service.error
|
||||||
|
|
||||||
|
return upload
|
||||||
|
|
|
@ -11,10 +11,21 @@ class StorageClient:
|
||||||
client = storage.Client()
|
client = storage.Client()
|
||||||
self.bucket = client.bucket(self.get_bucket())
|
self.bucket = client.bucket(self.get_bucket())
|
||||||
|
|
||||||
|
self._error = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def error(self):
|
||||||
|
return self._error
|
||||||
|
|
||||||
|
@error.setter
|
||||||
|
def error(self, state):
|
||||||
|
self._error = state
|
||||||
|
|
||||||
def get_bucket(self):
|
def get_bucket(self):
|
||||||
return os.getenv("TARGET_BUCKET")
|
return os.getenv("TARGET_BUCKET")
|
||||||
|
|
||||||
def upload(self, path: str) -> bool:
|
def upload(self, path: str) -> bool:
|
||||||
|
self.error = None
|
||||||
name = get_file(path)
|
name = get_file(path)
|
||||||
blob = self.bucket.blob(name)
|
blob = self.bucket.blob(name)
|
||||||
|
|
||||||
|
@ -22,5 +33,7 @@ class StorageClient:
|
||||||
with open(path, "rb") as f:
|
with open(path, "rb") as f:
|
||||||
blob.upload_from_file(f)
|
blob.upload_from_file(f)
|
||||||
return True
|
return True
|
||||||
except:
|
except Exception as e:
|
||||||
|
if e.response.status_code == 403:
|
||||||
|
self.error = "Account lacks 'storage.objects.create' permissions on this bucket "
|
||||||
return False
|
return False
|
|
@ -27,15 +27,15 @@ class Database(SQLite):
|
||||||
|
|
||||||
# Check if item exists in the database
|
# Check if item exists in the database
|
||||||
def item_exists(self, item: Union[list, tuple]) -> bool:
|
def item_exists(self, item: Union[list, tuple]) -> bool:
|
||||||
sql = f"SELECT anchor FROM manifest WHERE anchor = '{item[0]}'"
|
sql = "SELECT anchor FROM manifest WHERE anchor = ?"
|
||||||
res = self.query(sql)
|
res = self.query(sql, (item[0]))
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
# Check if item should be backed up by comparing mtime and checksum
|
# Check if item should be backed up by comparing mtime and checksum
|
||||||
def check_item(self, item: Union[list, tuple]) -> bool:
|
def check_item(self, item: Union[list, tuple]) -> bool:
|
||||||
sql = f"SELECT {self.columns} FROM manifest WHERE anchor = '{item[0]}'"
|
sql = f"SELECT {self.columns} FROM manifest WHERE anchor = ?"
|
||||||
db_item = self.query(sql)
|
db_item = self.query(sql, (item[0]))
|
||||||
|
|
||||||
# New item or item changed, so back it up
|
# New item or item changed, so back it up
|
||||||
if not db_item or (item != db_item[0]):
|
if not db_item or (item != db_item[0]):
|
||||||
|
@ -44,10 +44,10 @@ class Database(SQLite):
|
||||||
|
|
||||||
# Insert or update item in database
|
# Insert or update item in database
|
||||||
def set_item(self, item: Union[list, tuple]) -> bool:
|
def set_item(self, item: Union[list, tuple]) -> bool:
|
||||||
sql = f"UPDATE manifest SET anchor = '{item[0]}', chksum = {item[1]} WHERE anchor = '{item[0]}'"
|
sql = "UPDATE manifest SET anchor = ?, chksum = ? WHERE anchor = ?"
|
||||||
|
|
||||||
if not self.item_exists(item):
|
if not self.item_exists(item):
|
||||||
sql = f"INSERT INTO manifest ({self.columns}) VALUES ('{item[0]}', {item[1]})"
|
sql = f"INSERT INTO manifest ({self.columns}) VALUES (?, ?)"
|
||||||
self.query(sql)
|
self.query(sql, (item[0], item[1], item[0]))
|
||||||
|
|
||||||
return True
|
return True
|
|
@ -1,16 +0,0 @@
|
||||||
from .sqlite import SQLite
|
|
||||||
|
|
||||||
class Flags(SQLite):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
self._columns = ["k", "v"]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def columns(self):
|
|
||||||
return ",".join(self._columns)
|
|
||||||
|
|
||||||
@columns.setter
|
|
||||||
def columns(self, columns: list):
|
|
||||||
self._columns = columns
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
import sqlite3 as sqlite
|
import sqlite3 as sqlite
|
||||||
|
from typing import Iterable
|
||||||
|
|
||||||
dbname = "._cloudbackup.db"
|
dbname = "._cloudbackup.db"
|
||||||
|
|
||||||
|
@ -23,8 +24,8 @@ class SQLite():
|
||||||
return " ".join([s.strip() for s in sql.splitlines()])
|
return " ".join([s.strip() for s in sql.splitlines()])
|
||||||
|
|
||||||
# Run SQL query
|
# Run SQL query
|
||||||
def query(self, sql: str):
|
def query(self, sql: str, params: Iterable = ()):
|
||||||
query = self.cursor.execute(sql)
|
query = self.cursor.execute(sql, params)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
result = query.fetchall()
|
result = query.fetchall()
|
||||||
|
@ -61,8 +62,8 @@ class SQLite():
|
||||||
if envar:
|
if envar:
|
||||||
return envar
|
return envar
|
||||||
|
|
||||||
sql = f"SELECT v FROM flags WHERE k = '{key}'"
|
sql = "SELECT v FROM flags WHERE k = ?"
|
||||||
res = self.query(sql)
|
res = self.query(sql, [key])
|
||||||
|
|
||||||
if not res:
|
if not res:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -26,7 +26,8 @@ class FileSystem:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def zip(item) -> str:
|
def zip(item) -> str:
|
||||||
dest = f"{tempfile.gettempdir()}/{str(item[1])}"
|
name = FileSystem.chksum(item[0])
|
||||||
|
dest = f"{tempfile.gettempdir()}/{name}"
|
||||||
|
|
||||||
# Make a temp zip file of single file or folder
|
# Make a temp zip file of single file or folder
|
||||||
if file_exists(item[0]):
|
if file_exists(item[0]):
|
||||||
|
|
Loading…
Add table
Reference in a new issue