backups: remove noop backend

the noop backend is migrated into 0 sites config.

when the updater code sees that there is no site to backup, it will
just fail. user has to manually update with skipBackup flag.
This commit is contained in:
Girish Ramakrishnan
2025-09-22 16:33:51 +02:00
parent 807094c829
commit 305441ea28
18 changed files with 17 additions and 246 deletions
+2
View File
@@ -2964,3 +2964,5 @@
* backups: store integrity information and perform validation
* reverse proxy: remove OCSP support. this is being deprecated in favor of CRLs
* sqlite: fix issue where dump was also logged when backing up
* backups: remove noop backend
-5
View File
@@ -281,7 +281,6 @@
"failed": "Følgende brugere blev ikke importeret:",
"sendInviteCheckbox": "Send en e-mail med invitation til importerede brugere"
},
"newUserAction": "Ny bruger",
"users": {
"user": "Bruger",
"groups": "Grupper",
@@ -302,7 +301,6 @@
},
"groups": {
"title": "Grupper",
"newGroupAction": "Ny gruppe",
"name": "Navn",
"users": "Brugere",
"externalLdapTooltip": "Fra ekstern LDAP-mappe"
@@ -578,7 +576,6 @@
"cifsSealSupport": "Brug kryptering af segl. Kræver mindst SMB v3",
"title": "Konfigurere backuplagring",
"provider": "Udbyder af lagerplads",
"noopNote": "Denne indstilling ødelægger Cloudrons backup- og gendannelsesfunktionalitet og bør kun bruges til testformål. Sørg for, at serveren er sikkerhedskopieret fuldstændigt ved hjælp af alternative midler.",
"mountPoint": "Monteringspunkt",
"mountPointDescription": "Mountpunktet skal oprettes manuelt. Se <a href=\"{{ providerDocsLink }}\" target=\"_blank\">docs</a>.",
"localDirectory": "Lokal backup-mappe",
@@ -1051,7 +1048,6 @@
"ovhAppSecret": "Application Secret"
},
"title": "Domæner og certs",
"addDomain": "Tilføj domæne",
"domain": "Domæne",
"provider": "Udbyder",
"tooltipEdit": "Rediger domæne",
@@ -1836,7 +1832,6 @@
"title": "Fjern virkelig {{ volume }} ?",
"removeAction": "Fjern"
},
"addVolumeAction": "Tilfoj Volume",
"hostPath": "Target",
"name": "Navn",
"openFileManagerActionTooltip": "Åbn FileManager",
-5
View File
@@ -256,7 +256,6 @@
"externalLdapTooltip": "Aus externem LDAP Verzeichnis",
"users": "User",
"name": "Name",
"newGroupAction": "Neue Gruppe",
"title": "Gruppen",
"emptyPlaceholder": "Noch keine Gruppen"
},
@@ -278,7 +277,6 @@
"mailmanagerTooltip": "Dieser User kann Benutzer und Postfächer verwalten.",
"setGhostTooltip": "Als anderer User ausgeben"
},
"newUserAction": "Neuer User",
"role": {
"owner": "Superadmin",
"admin": "Administrationsrolle",
@@ -798,7 +796,6 @@
"cancelAction": "Abbrechen"
},
"domain": "Domäne",
"addDomain": "Domäne hinzufügen",
"provider": "Anbieter",
"tooltipEdit": "Domäne bearbeiten",
"tooltipRemove": "Domäne entfernen",
@@ -909,7 +906,6 @@
"localDirectory": "Lokales Backup-Verzeichnis",
"mountPointDescription": "Der Mount-Point muss manuell gesetzt werden. Weitere Informationen in der <a href=\"{{ providerDocsLink }}\" target=\"_blank\">Anleitung</a>.",
"mountPoint": "Mount-Point",
"noopNote": "Diese Option unterbricht die Sicherungs- und Wiederherstellungsfunktionalität von Cloudron und sollte nur zu Testzwecken verwendet werden. Der Server muss in dieser Betriebsart vollständig mit alternativen Mitteln gesichert werden.",
"provider": "Speicher-Anbieter",
"title": "Backup-Speicher konfigurieren",
"encryptionPasswordRepeat": "Password wiederholen",
@@ -1965,7 +1961,6 @@
"openFileManagerActionTooltip": "File-Manager öffnen",
"name": "Name",
"hostPath": "Ziel",
"addVolumeAction": "Datenträger hinzufügen",
"title": "Datenträger",
"mountType": "Einhängepunkttyp",
"updateVolumeDialog": {
-6
View File
@@ -194,7 +194,6 @@
}
},
"users": {
"newUserAction": "New User",
"users": {
"user": "User",
"groups": "Groups",
@@ -215,7 +214,6 @@
},
"groups": {
"title": "Groups",
"newGroupAction": "New Group",
"name": "Name",
"users": "Users",
"externalLdapTooltip": "From external LDAP directory",
@@ -601,7 +599,6 @@
"configureBackupStorage": {
"title": "Configure Backup Storage",
"provider": "Storage provider",
"noopNote": "This option breaks the backup and restore functionality of Cloudron and should only be used for testing. Please make sure the server is completely backed up using alternate means.",
"mountPoint": "Mount point",
"mountPointDescription": "The mount point has to be set up manually. See <a href=\"{{ providerDocsLink }}\" target=\"_blank\">docs</a>.",
"localDirectory": "Local backup directory",
@@ -1056,7 +1053,6 @@
},
"domains": {
"title": "Domains & Certs",
"addDomain": "Add Domain",
"domain": "Domain",
"provider": "Provider",
"tooltipEdit": "Edit Domain",
@@ -1980,7 +1976,6 @@
},
"volumes": {
"title": "Volumes",
"addVolumeAction": "Add Volume",
"hostPath": "Target",
"name": "Name",
"openFileManagerActionTooltip": "File Manager",
@@ -2067,7 +2062,6 @@
},
"clients": {
"title": "OpenID Clients",
"newClient": "New Client",
"empty": "No OpenID Clients"
}
},
-5
View File
@@ -237,7 +237,6 @@
"externalLdapTooltip": "Desde un directorio LDAP externo",
"users": "Usuarios",
"name": "Nombre",
"newGroupAction": "Nuevo Grupo",
"title": "Grupos",
"emptyPlaceholder": "No hay grupos aún"
},
@@ -259,7 +258,6 @@
"invitationTooltip": "Invitar Usuario",
"mailmanagerTooltip": "Este usuario puede administrar usuarios y buzones de correo"
},
"newUserAction": "Nuevo Usuario",
"transferOwnershipDialog": {
"description": "Esto hará que el usuario seleccionado sea el propietario y administrador de este Cloudron y eliminará los derechos de administrador del propietario actual.",
"title": "¿Realmente quieres transferir la propiedad?",
@@ -475,7 +473,6 @@
"localDirectory": "Directorio local para copias de seguridad",
"mountPointDescription": "El punto de montaje debe configurarse manualmente. Consulta esta <a href=\"{{ providerDocsLink }}\" target=\"_blank\"> documentación </a>.",
"mountPoint": "Punto de montaje",
"noopNote": "Esta opción rompe la funcionalidad de copia de seguridad y restauración de Cloudron y solo debe usarse para realizar pruebas. Asegúrese de que se haya realizado una copia de seguridad completa del servidor utilizando medios alternativos.",
"provider": "Proveedor de almacenamiento",
"title": "Configurar el almacenamiento de la Copia de Seguridad",
"password": "Contraseña",
@@ -1031,7 +1028,6 @@
"tooltipEdit": "Editar Dominio",
"provider": "Proveedor",
"domain": "Dominio",
"addDomain": "Añadir Dominio",
"syncDns": {
"showLogsAction": "Mostrar Registros",
"title": "Sincronizar DNS",
@@ -1535,7 +1531,6 @@
"openFileManagerActionTooltip": "Abrir Gestor de Archivos",
"name": "Nombre",
"hostPath": "Objetivo",
"addVolumeAction": "Añade un Volumen",
"title": "Volúmenes",
"description": "Los volúmenes son sistemas de archivos locales o remotos. Se pueden usar como el almacenamiento de datos principal de una aplicación o como una ubicación de almacenamiento compartida entre aplicaciones.",
"localDirectory": "Directorio Local",
-5
View File
@@ -113,12 +113,10 @@
"invitationTooltip": "Envoyer une invitation à l'utilisateur",
"mailmanagerTooltip": "Cet utilisateur peut gérer les utilisateurs et les boîtes mail"
},
"newUserAction": "Nouvel utilisateur",
"groups": {
"name": "Nom",
"title": "Groupes",
"users": "Utilisateurs",
"newGroupAction": "Nouveau groupe",
"externalLdapTooltip": "Depuis un annuaire LDAP externe"
},
"settings": {
@@ -468,7 +466,6 @@
"uploadConcurrencyDescription": "Nombre de fichiers pouvant être envoyés simultanément au cours d'une sauvegarde",
"downloadConcurrencyDescription": "Nombre de fichiers pouvant être reçus simultanément au cours d'une restauration",
"copyConcurrencyDescription": "Nombre de fichiers à distance pouvant être copiés au cours d'une sauvegarde",
"noopNote": "Cette option neutralise les fonctionnalités de sauvegarde et de restauration de Cloudron et ne doit être utilisée qu'à des fins de test. Veuillez vous assurer qu'une sauvegarde complète du système a été effectuée par d'autres moyens.",
"prefix": "Préfixe",
"region": "Région",
"s3AccessKeyId": "ID de clé d'accès",
@@ -1287,7 +1284,6 @@
"openFileManagerActionTooltip": "Ouvrir le gestionnaire de fichiers",
"removeVolumeActionTooltip": "Supprimer le volume",
"hostPath": "Point de montage",
"addVolumeAction": "Ajouter un volume",
"title": "Volumes",
"localDirectory": "Répertoire local",
"tooltipEdit": "Modifier le Volume",
@@ -1591,7 +1587,6 @@
"tooltipEdit": "Modifier le domaine",
"provider": "Fournisseur",
"domain": "Domaine",
"addDomain": "Ajouter un domaine",
"title": "Domaines et Certificats",
"domainWellKnown": {
"title": "Emplacements Well-Known de {{ domain }}"
-5
View File
@@ -73,7 +73,6 @@
"openFileManagerActionTooltip": "Apri il File Manager",
"name": "Nome",
"hostPath": "Percorso Host",
"addVolumeAction": "Aggiungi Volume",
"title": "Volumi"
},
"lang": {
@@ -676,7 +675,6 @@
"localDirectory": "Directory di backup locale",
"mountPointDescription": "Il punto di montaggio deve essere impostato manualmente. Consulta i <a href=\"{{ providerDocsLink }}\" target=\"_blank\"> documenti </a>.",
"mountPoint": "Punto di montaggio",
"noopNote": "Questa opzione interrompe la funzionalità di backup e ripristino di Cloudron e deve essere utilizzata solo per i test. Assicurati di aver eseguito il backup completo del server utilizzando metodi alternativi.",
"provider": "Provider archiviazione",
"title": "Configura archiviazione backup",
"uploadPartSizeDescription": "Dimensioni del singolo file nel caricamento multiplo. Fino a 3 parti vengono caricate in parallelo e richiedono maggiore memoria.",
@@ -951,7 +949,6 @@
"externalLdapTooltip": "Dalla directory LDAP esterna",
"users": "Utenti",
"name": "Nome",
"newGroupAction": "Nuovo Gruppo",
"title": "Gruppi"
},
"users": {
@@ -969,7 +966,6 @@
"user": "Utente",
"transferOwnershipTooltip": "Trasferisci Proprietà"
},
"newUserAction": "Nuovo Utente",
"transferOwnershipDialog": {
"transferAction": "Trasferisci la proprietà",
"description": "L'utente selezionato e l'amministratore di questo Cloudron acquisiranno i permessi di ammministrazione, mentre l'attuale proprietario li perderà.",
@@ -1410,7 +1406,6 @@
"tooltipEdit": "Modifica Dominio",
"provider": "Provider",
"domain": "Dominio",
"addDomain": "Aggiungi dominio",
"title": "Domini e Certificati"
},
"eventlog": {
-6
View File
@@ -194,7 +194,6 @@
}
},
"users": {
"newUserAction": "Nieuwe gebruiker",
"users": {
"user": "Gebruiker",
"groups": "Groepen",
@@ -218,7 +217,6 @@
"name": "Naam",
"users": "Gebruikers",
"externalLdapTooltip": "Van extern LDAP adresboek",
"newGroupAction": "Nieuwe groep",
"emptyPlaceholder": "Geen groepen beschikbaar"
},
"settings": {
@@ -623,7 +621,6 @@
"copyConcurrencyDescription": "Aantal externe bestandskopieën, die parallel bij het maken van een back-up gebruikt worden.",
"copyConcurrencyDigitalOceanNote": "Het limiet van DigitalOcean Spaces ligt op 20.",
"encryptionPasswordPlaceholder": "Wachtwoord wat gebruikt is om backups te versleutelen",
"noopNote": "Deze optie onderbreekt de backup en herstel functionaliteit van Cloudron en dient alleen gebruikt te worden voor testen. Zorg ervoor dat van deze server op een andere wijze een backup wordt gemaakt.",
"s3AccessKeyId": "Toegangssleutel id",
"s3SecretAccessKey": "Geheime toegangssleutel",
"formatChangeNote": "Voorgaande backups, die een ander opslagformaat gebruikten, dienen handmatig verwijderd te worden.",
@@ -894,7 +891,6 @@
"customNameservers": "Domein maakt gebruik van aangepaste (eigen) nameservers"
},
"title": "Domeinen & Certificaten",
"addDomain": "Domein toevoegen",
"domain": "Domein",
"provider": "Aanbieder",
"tooltipEdit": "Bewerk domein",
@@ -1944,7 +1940,6 @@
"removeVolumeActionTooltip": "Verwijder Volume",
"openFileManagerActionTooltip": "Bestandsbeheer",
"name": "Naam",
"addVolumeAction": "Volume toevoegen",
"title": "Volumes",
"mountType": "Koppeltype",
"updateVolumeDialog": {
@@ -2067,7 +2062,6 @@
},
"clients": {
"title": "OpenID Clients",
"newClient": "Nieuwe Client",
"empty": "Geen OpenID Clients"
}
},
-4
View File
@@ -351,7 +351,6 @@
"groups": {
"emptyPlaceholder": "Não há grupos disponíveis",
"title": "Grupos",
"newGroupAction": "Novo Grupo",
"name": "Nome",
"users": "Utilizadores",
"externalLdapTooltip": "Da diretoria LDAP externa"
@@ -491,7 +490,6 @@
"active": "Utilizadores Ativos",
"inactive": "Utilizadores Inativos"
},
"newUserAction": "Novo Utilizador",
"settings": {
"title": "Definições do Utilizador",
"subscriptionRequiredAction": "Configurar Subscrição Agora",
@@ -1009,7 +1007,6 @@
"description": "Para adicionar mais domínios, por favor, configure um plano pago.",
"setupAction": "Configurar Subscrição"
},
"addDomain": "Adicionar Domínio",
"domain": "Domínio",
"provider": "Provedor",
"tooltipEdit": "Editar Domínio",
@@ -1262,7 +1259,6 @@
"name": "Nome",
"openFileManagerActionTooltip": "Gestor de Ficheiros",
"title": "Volumes",
"addVolumeAction": "Adicionar Volume",
"removeVolumeActionTooltip": "Remover Volume",
"removeVolumeDialog": {
"title": "Deseja remover {{ volume }} ?",
-6
View File
@@ -212,10 +212,8 @@
"setGhostTooltip": "Обезличить",
"mailmanagerTooltip": "Этот пользователь может управлять другими пользователями и почтовыми ящиками"
},
"newUserAction": "Новый пользователь",
"groups": {
"title": "Группы",
"newGroupAction": "Новая группа",
"name": "Имя",
"users": "Пользователи",
"externalLdapTooltip": "Из внешнего LDAP каталога",
@@ -959,7 +957,6 @@
"title": "Настроить расписание и хранение резервных копий"
},
"configureBackupStorage": {
"noopNote": "Этот параметр полностью отключает функцию резервного копирования и восстановления. Используйте её только в тестовых целях. Предварительно убедитесь, что Вы настроили альтернативные способы резервного копирования на Вашем сервере.",
"formatChangeNote": "Резервные копии, хранящиеся в старом хранилище, должны быть удалены вручную.",
"encryptionPassword": "Пароль шифрования",
"title": "Настроить хранилище резервных копий",
@@ -1516,7 +1513,6 @@
"inwxPassword": "Пароль",
"customNameservers": "Домен использует пользовательские серверы имён"
},
"addDomain": "Добавить домен",
"removeDialog": {
"title": "Действительно удалить {{ domain }}?",
"description": "Данное действие удалит домен <code>{{ domain }}</code>.",
@@ -1920,7 +1916,6 @@
}
},
"volumes": {
"addVolumeAction": "Добавить том",
"name": "Имя",
"openFileManagerActionTooltip": "Файловый менеджер",
"removeVolumeActionTooltip": "Удалить том",
@@ -2067,7 +2062,6 @@
},
"clients": {
"title": "Клиенты OpenID",
"newClient": "Новый клиент",
"empty": "Клиенты OpenID не добавлены"
}
},
-5
View File
@@ -286,11 +286,9 @@
"externalLdapTooltip": "Từ thư mục LDAP ngoài",
"users": "Người dùng",
"name": "Tên",
"newGroupAction": "Nhóm mới",
"title": "Nhóm",
"emptyPlaceholder": "Chưa có nhóm nào cả"
},
"newUserAction": "Người dùng mới",
"editGroupDialog": {
"title": "Chỉnh sửa nhóm {{ name }}",
"externalLdapWarning": "Nhóm này được đồng bộ từ thư mục LDAP ngoài."
@@ -573,7 +571,6 @@
"mountPointDescription": "Điểm mount cần được cài đặt thủ công. Xem <a href=\"{{ providerDocsLink }}\" target=\"_blank\">hướng dẫn</a>.",
"title": "Cấu hình nơi lưu trữ bản sao lưu",
"mountPoint": "Điểm mount",
"noopNote": "Lựa chọn này sẽ làm hỏng tính năng sao lưu và khôi phục của Cloudron và chỉ nên dùng khi test hệ thống. Xin đảm bảo rằng server được sao lưu toàn bộ bằng những phương tiện khác.",
"format": "Định dạng lưu trữ",
"encryptedFilenames": "Tên tập tin đã mã hoá",
"chown": "Hệ thống tập tin bên ngoài có hỗ trợ chown",
@@ -1506,7 +1503,6 @@
"tooltipEdit": "Chỉnh tên miền",
"provider": "Nhà cung cấp",
"domain": "Tên miền",
"addDomain": "Thêm tên miền",
"syncDns": {
"title": "Đồng bộ DNS",
"description": "Lựa chọn này sẽ cấp lại các bản ghi DNS cho app và email cho tất cả tên miền.",
@@ -1916,7 +1912,6 @@
"removeVolumeActionTooltip": "Xoá volume",
"openFileManagerActionTooltip": "Mở Quản lý tập tin",
"hostPath": "Điểm đến",
"addVolumeAction": "Thêm volume",
"updateVolumeDialog": {
"title": "Cập nhật Volume {{ volume }}"
},
@@ -208,7 +208,6 @@
"s3SecretAccessKey": "Secret access key",
"gcsServiceKey": "Service Account Key",
"format": "存储格式",
"noopNote": "这个选项会停用 Cloudron 的备份和恢复功能,仅应该被用于测试。请确保这台服务器已经使用其它方式备份。",
"formatChangeNote": "使用旧存储格式的备份需要被手动删除。",
"encryptionPassword": "加密密码(可选)",
"advancedSettings": "高级设置…",
@@ -389,7 +388,6 @@
"searchPlaceholder": "使用应用名称如 Github, Dropbox, Slack, Trello, ... 来搜索替代品"
},
"users": {
"newUserAction": "新用户",
"users": {
"user": "用户",
"groups": "用户组",
@@ -410,7 +408,6 @@
},
"groups": {
"title": "用户组",
"newGroupAction": "新用户组",
"name": "名称",
"users": "用户",
"externalLdapTooltip": "使用外部 LDAP 目录"
@@ -893,7 +890,6 @@
},
"domains": {
"title": "域名和证书",
"addDomain": "添加域名",
"domain": "域名",
"provider": "提供商",
"tooltipEdit": "编辑域名",
@@ -1589,7 +1585,6 @@
"addAction": "添加",
"title": "添加磁盘卷"
},
"addVolumeAction": "添加卷",
"name": "名称",
"hostPath": "主机路径",
"removeVolumeDialog": {
@@ -26,10 +26,7 @@ const props = defineProps({
const systemModel = SystemModel.create();
const provisionModel = ProvisionModel.create();
const storageProviders = STORAGE_PROVIDERS.concat([
{ name: 'No-op (Only for testing)', value: 'noop' }
]);
const storageProviders = Array.from(STORAGE_PROVIDERS);
const blockDevices = ref([]);
const disk = ref('');
const gcsKeyFileName = ref('');
@@ -120,9 +117,6 @@ onMounted(async () => {
<SingleSelect id="providerInput" v-model="provider" :options="storageProviders" option-key="value" option-label="name" />
</FormGroup>
<!-- Noop -->
<div class="warning-label" v-show="provider === 'noop'">{{ $t('backups.configureBackupStorage.noopNote') }}</div>
<!-- mountpoint -->
<FormGroup v-if="provider === 'mountpoint'">
<label for="mountPointInput">{{ $t('backups.configureBackupStorage.mountPoint') }}</label>
@@ -206,7 +200,7 @@ onMounted(async () => {
<TextInput id="bucketInput" v-model="providerConfig.bucket" required />
</FormGroup>
<FormGroup v-if="(provider !== 'filesystem' && provider !== 'noop') && !importOnly">
<FormGroup v-if="provider !== 'filesystem' && !importOnly">
<label for="prefixInput">{{ $t('backups.configureBackupStorage.prefix') }}</label>
<TextInput id="prefixInput" v-model="providerConfig.prefix" placeholder="Prefix for backup file names" />
</FormGroup>
@@ -265,7 +259,7 @@ onMounted(async () => {
<div class="error-label" v-show="gcsFileParseError">{{ gcsFileParseError }}</div>
</FormGroup>
<FormGroup v-if="provider !== 'noop'">
<FormGroup>
<label for="formatInput">{{ $t('backups.configureBackupStorage.format') }} <sup><a href="https://docs.cloudron.io/backups/#backup-formats" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
<SingleSelect id="formatInput" v-model="format" :options="BACKUP_FORMATS" option-label="name" option-key="value" required />
<div class="warning-label" v-show="format === 'rsync' && (s3like(provider) || provider === 'gcs') && !importOnly">{{ $t('backups.configureBackupStorage.s3LikeNote') }} <sup><a href="https://docs.cloudron.io/backups/#amazon-s3" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></div>
@@ -6,6 +6,10 @@ const child_process = require('node:child_process'),
path = require('node:path'),
paths = require('../src/paths.js');
async function deleteOldSettings(db) {
await db.runSql('DELETE FROM settings WHERE name=? OR name=? OR name=?', [ 'backup_storage', 'backup_limits', 'backup_policy' ]);
}
exports.up = async function (db) {
const cmd = 'CREATE TABLE IF NOT EXISTS backupSites(' +
'id VARCHAR(128) NOT NULL UNIQUE,' +
@@ -31,7 +35,7 @@ exports.up = async function (db) {
const domainCountResults = await db.runSql('SELECT COUNT(*) AS total FROM domains');
if (domainCountResults[0].total === 0) {
console.log('This cloudron is not activated. Deleting the default backup config from 20171205124434-settings-default-backupConfig.js'); // will be added at provision time
await db.runSql('DELETE FROM settings WHERE name=? OR name=? OR name=?', [ 'backup_storage', 'backup_limits', 'backup_policy']);
await deleteOldSettings(db);
return;
}
@@ -53,8 +57,10 @@ exports.up = async function (db) {
// provider is top level
provider = tmp.provider;
if (provider === 'noop') return await deleteOldSettings(db); // noop is migrated as 0 sites. user has to manually update with skipBackup
// the s3 and filesystem backend use the _provider internal property
if (provider !== 'gcs' && provider !== 'noop') tmp._provider = tmp.provider;
if (provider !== 'gcs') tmp._provider = tmp.provider;
delete tmp.provider;
// backupFolder is now backupDir
@@ -96,7 +102,7 @@ exports.up = async function (db) {
await db.runSql('START TRANSACTION');
await db.runSql('INSERT INTO backupSites (id, name, provider, configJson, limitsJson, integrityKeyPairJson, retentionJson, schedule, encryptionJson, format, main) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
[ id, name, provider, JSON.stringify(config), JSON.stringify(limits), JSON.stringify(integrityKeyPair), JSON.stringify(retention), schedule, JSON.stringify(encryption), format, main ]);
await db.runSql('DELETE FROM settings WHERE name=? OR name=? OR name=?', [ 'backup_storage', 'backup_limits', 'backup_policy' ]);
await deleteOldSettings(db);
await db.runSql('COMMIT');
};
+1 -4
View File
@@ -19,12 +19,9 @@ function api(format) {
throw new BoxError(BoxError.INTERNAL_ERROR, `Undefined format ${format}`);
}
function validateFormat(provider, format) {
assert.strictEqual(typeof provider, 'string');
function validateFormat(format) {
assert.strictEqual(typeof format, 'string');
if (provider === 'noop') return null;
if (format === 'tgz' || format == 'rsync') return null;
return new BoxError(BoxError.BAD_FIELD, 'Invalid backup format');
+2 -3
View File
@@ -93,7 +93,6 @@ function storageApi(backupSite) {
case 'upcloud-objectstorage': return require('./storage/s3.js');
case 'contabo-objectstorage': return require('./storage/s3.js');
case 'hetzner-objectstorage': return require('./storage/s3.js');
case 'noop': return require('./storage/noop.js');
default: throw new BoxError(BoxError.BAD_FIELD, `Unknown provider: ${backupSite.provider}`);
}
}
@@ -517,7 +516,7 @@ async function add(data, auditSource) {
encryptedFilenames = data.encryptedFilenames || false,
encryptionPasswordHint = data.encryptionPasswordHint || null;
const formatError = backupFormats.validateFormat(provider, format);
const formatError = backupFormats.validateFormat(format);
if (formatError) throw formatError;
const nameError = validateName(name);
@@ -581,7 +580,7 @@ async function createPseudo(data) {
const encryptionPassword = data.encryptionPassword ?? null,
encryptedFilenames = !!data.encryptedFilenames;
const formatError = backupFormats.validateFormat(provider, format);
const formatError = backupFormats.validateFormat(format);
if (formatError) throw formatError;
let encryption = null;
-135
View File
@@ -1,135 +0,0 @@
'use strict';
exports = module.exports = {
getAvailableSize,
getStatus,
upload,
exists,
download,
copy,
listDir,
remove,
removeDir,
setup,
teardown,
cleanup,
verifyConfig,
removePrivateFields,
injectPrivateFields
};
const assert = require('node:assert'),
BoxError = require('../boxerror.js'),
debug = require('debug')('box:storage/noop'),
fs = require('node:fs');
async function getAvailableSize(apiConfig) {
assert.strictEqual(typeof apiConfig, 'object');
return Number.POSITIVE_INFINITY;
}
async function getStatus(apiConfig) {
assert.strictEqual(typeof apiConfig, 'object');
return { state: 'active' };
}
async function upload(apiConfig, remotePath) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof remotePath, 'string');
debug(`upload: ${remotePath}`);
const uploadStream = fs.createWriteStream('/dev/null');
return {
stream: uploadStream,
async finish() {}
};
}
async function exists(apiConfig, remotePath) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof remotePath, 'string');
debug(`exists: ${remotePath}`);
return false;
}
async function download(apiConfig, remotePath) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof remotePath, 'string');
debug('download: %s', remotePath);
throw new BoxError(BoxError.NOT_IMPLEMENTED, 'Cannot download from noop backend');
}
async function listDir(apiConfig, remotePath, batchSize, marker) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof remotePath, 'string');
assert.strictEqual(typeof batchSize, 'number');
assert(typeof marker !== 'undefined');
return { entries: [], marker: null };
}
async function copy(apiConfig, fromRemotePath, toRemotePath, progressCallback) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof fromRemotePath, 'string');
assert.strictEqual(typeof toRemotePath, 'string');
assert.strictEqual(typeof progressCallback, 'function');
debug(`copy: ${fromRemotePath} -> ${toRemotePath}`);
}
async function remove(apiConfig, filename) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof filename, 'string');
debug(`remove: ${filename}`);
}
async function removeDir(apiConfig, remotePathPrefix, progressCallback) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof remotePathPrefix, 'string');
assert.strictEqual(typeof progressCallback, 'function');
debug(`removeDir: ${remotePathPrefix}`);
}
async function cleanup(apiConfig, progressCallback) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof progressCallback, 'function');
}
async function verifyConfig({ id, provider, config }) {
assert.strictEqual(typeof id, 'string');
assert.strictEqual(typeof provider, 'string');
assert.strictEqual(typeof config, 'object');
return {};
}
async function setup(apiConfig) {
assert.strictEqual(typeof apiConfig, 'object');
}
async function teardown(apiConfig) {
assert.strictEqual(typeof apiConfig, 'object');
}
function removePrivateFields(apiConfig) {
return apiConfig;
}
// eslint-disable-next-line no-unused-vars
function injectPrivateFields(newConfig, currentConfig) {
}
-35
View File
@@ -15,7 +15,6 @@ const backupSites = require('../backupsites.js'),
filesystem = require('../storage/filesystem.js'),
fs = require('node:fs'),
gcs = require('../storage/gcs.js'),
noop = require('../storage/noop.js'),
os = require('node:os'),
path = require('node:path'),
s3 = require('../storage/s3.js'),
@@ -150,40 +149,6 @@ describe('Storage', function () {
});
});
describe('noop', function () {
const gBackupConfig = {
provider: 'noop',
format: 'tgz'
};
it('upload works', async function () {
await noop.upload(gBackupConfig, 'file', {});
});
it('can download file', async function () {
const [error] = await safe(noop.download(gBackupConfig, 'file'));
expect(error).to.be.an(Error);
});
it('list dir contents of source dir', async function () {
const result = await noop.listDir(gBackupConfig, 'sourceDir', 1000, null /* marker */);
expect(result.marker).to.be(null);
expect(result.entries).to.eql([]);
});
it('can copy', async function () {
await noop.copy(gBackupConfig, 'sourceFile', 'destFile', () => {});
});
it('can remove file', async function () {
await noop.remove(gBackupConfig, 'sourceFile');
});
it('can remove empty dir', async function () {
await noop.remove(gBackupConfig, 'sourceDir');
});
});
describe('s3', function () {
const basePath = path.join(os.tmpdir(), 's3-backup-test-buckets');
const backupConfig = {