Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions app/client/packages/rts/src/ctl/backup/BackupState.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
import { getTimeStampInISO } from "./index";

export class BackupState {
readonly args: string[];
readonly initAt: string = getTimeStampInISO();
readonly args: readonly string[];
readonly initAt: string = new Date().toISOString().replace(/:/g, "-");
readonly errors: string[] = [];

backupRootPath: string = "";
archivePath: string = "";

encryptionPassword: string = "";
isEncryptionEnabled: boolean = false;

constructor(args: string[]) {
this.args = args;
this.args = Object.freeze([...args]);

// We seal `this` so that no link in the chain can "add" new properties to the state. This is intentional. If any
// link wants to save data in the `BackupState`, which shouldn't even be needed in most cases, it should do so by
// explicitly declaring a property in this class. No surprises.
Object.seal(this);
}

isEncryptionEnabled() {
return !!this.encryptionPassword;
}
}
50 changes: 24 additions & 26 deletions app/client/packages/rts/src/ctl/backup/backup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,25 @@ import * as backup from ".";
import * as Constants from "../constants";
import * as utils from "../utils";
import readlineSync from "readline-sync";
import {
checkAvailableBackupSpace,
encryptBackupArchive,
executeCopyCMD,
executeMongoDumpCMD,
getAvailableBackupSpaceInBytes,
getEncryptionPasswordFromUser,
getGitRoot,
removeSensitiveEnvData,
} from "./links";

jest.mock("../utils", () => ({
...jest.requireActual("../utils"),
execCommand: jest.fn().mockImplementation(async (a) => a.join(" ")),
}));

describe("Backup Tests", () => {
test("Timestamp string in ISO format", () => {
console.log(backup.getTimeStampInISO());
expect(backup.getTimeStampInISO()).toMatch(
/(\d{4})-(\d{2})-(\d{2})T(\d{2})-(\d{2})-(\d{2})\.(\d{3})Z/,
);
});

test("Available Space in /appsmith-stacks volume in Bytes", async () => {
const res = expect(await backup.getAvailableBackupSpaceInBytes("/"));
const res = expect(await getAvailableBackupSpaceInBytes("/"));

res.toBeGreaterThan(1024 * 1024);
});
Expand All @@ -32,14 +35,12 @@ describe("Backup Tests", () => {
it("Should throw Error when the available size is below MIN_REQUIRED_DISK_SPACE_IN_BYTES", () => {
const size = Constants.MIN_REQUIRED_DISK_SPACE_IN_BYTES - 1;

expect(() => backup.checkAvailableBackupSpace(size)).toThrow();
expect(() => checkAvailableBackupSpace(size)).toThrow();
});

it("Should not should throw Error when the available size is >= MIN_REQUIRED_DISK_SPACE_IN_BYTES", () => {
expect(() => {
backup.checkAvailableBackupSpace(
Constants.MIN_REQUIRED_DISK_SPACE_IN_BYTES,
);
checkAvailableBackupSpace(Constants.MIN_REQUIRED_DISK_SPACE_IN_BYTES);
}).not.toThrow(
"Not enough space available at /appsmith-stacks. Please ensure availability of at least 5GB to backup successfully.",
);
Expand All @@ -59,29 +60,29 @@ describe("Backup Tests", () => {
const appsmithMongoURI = "mongodb://username:password@host/appsmith";
const cmd =
"mongodump --uri=mongodb://username:password@host/appsmith --archive=/dest/mongodb-data.gz --gzip";
const res = await backup.executeMongoDumpCMD(dest, appsmithMongoURI);
const res = await executeMongoDumpCMD(dest, appsmithMongoURI);

expect(res).toBe(cmd);
console.log(res);
});

test("Test get gitRoot path when APPSMITH_GIT_ROOT is '' ", () => {
expect(backup.getGitRoot("")).toBe("/appsmith-stacks/git-storage");
expect(getGitRoot("")).toBe("/appsmith-stacks/git-storage");
});

test("Test get gitRoot path when APPSMITH_GIT_ROOT is null ", () => {
expect(backup.getGitRoot()).toBe("/appsmith-stacks/git-storage");
expect(getGitRoot()).toBe("/appsmith-stacks/git-storage");
});

test("Test get gitRoot path when APPSMITH_GIT_ROOT is defined ", () => {
expect(backup.getGitRoot("/my/git/storage")).toBe("/my/git/storage");
expect(getGitRoot("/my/git/storage")).toBe("/my/git/storage");
});

test("Test ln command generation", async () => {
const gitRoot = "/appsmith-stacks/git-storage";
const dest = "/destdir";
const cmd = "ln -s /appsmith-stacks/git-storage /destdir/git-storage";
const res = await backup.executeCopyCMD(gitRoot, dest);
const res = await executeCopyCMD(gitRoot, dest);

expect(res).toBe(cmd);
console.log(res);
Expand All @@ -102,7 +103,7 @@ describe("Backup Tests", () => {

test("If MONGODB and Encryption env values are being removed", () => {
expect(
backup.removeSensitiveEnvData(`APPSMITH_REDIS_URL=redis://127.0.0.1:6379\nAPPSMITH_DB_URL=mongodb://appsmith:pass@localhost:27017/appsmith\nAPPSMITH_MONGODB_USER=appsmith\nAPPSMITH_MONGODB_PASSWORD=pass\nAPPSMITH_INSTANCE_NAME=Appsmith\n
removeSensitiveEnvData(`APPSMITH_REDIS_URL=redis://127.0.0.1:6379\nAPPSMITH_DB_URL=mongodb://appsmith:pass@localhost:27017/appsmith\nAPPSMITH_MONGODB_USER=appsmith\nAPPSMITH_MONGODB_PASSWORD=pass\nAPPSMITH_INSTANCE_NAME=Appsmith\n
`),
).toMatch(
`APPSMITH_REDIS_URL=redis://127.0.0.1:6379\nAPPSMITH_INSTANCE_NAME=Appsmith\n`,
Expand All @@ -111,7 +112,7 @@ describe("Backup Tests", () => {

test("If MONGODB and Encryption env values are being removed", () => {
expect(
backup.removeSensitiveEnvData(`APPSMITH_REDIS_URL=redis://127.0.0.1:6379\nAPPSMITH_ENCRYPTION_PASSWORD=dummy-pass\nAPPSMITH_ENCRYPTION_SALT=dummy-salt\nAPPSMITH_DB_URL=mongodb://appsmith:pass@localhost:27017/appsmith\nAPPSMITH_MONGODB_USER=appsmith\nAPPSMITH_MONGODB_PASSWORD=pass\nAPPSMITH_INSTANCE_NAME=Appsmith\n
removeSensitiveEnvData(`APPSMITH_REDIS_URL=redis://127.0.0.1:6379\nAPPSMITH_ENCRYPTION_PASSWORD=dummy-pass\nAPPSMITH_ENCRYPTION_SALT=dummy-salt\nAPPSMITH_DB_URL=mongodb://appsmith:pass@localhost:27017/appsmith\nAPPSMITH_MONGODB_USER=appsmith\nAPPSMITH_MONGODB_PASSWORD=pass\nAPPSMITH_INSTANCE_NAME=Appsmith\n
`),
).toMatch(
`APPSMITH_REDIS_URL=redis://127.0.0.1:6379\nAPPSMITH_INSTANCE_NAME=Appsmith\n`,
Expand Down Expand Up @@ -199,7 +200,7 @@ describe("Backup Tests", () => {
const password = "password#4321";

readlineSync.question = jest.fn().mockImplementation(() => password);
const password_res = backup.getEncryptionPasswordFromUser();
const password_res = getEncryptionPasswordFromUser();

expect(password_res).toEqual(password);
});
Expand All @@ -215,13 +216,13 @@ describe("Backup Tests", () => {
return password;
});

expect(() => backup.getEncryptionPasswordFromUser()).toThrow();
expect(() => getEncryptionPasswordFromUser()).toThrow();
});

test("Get encrypted archive path", async () => {
const archivePath = "/rootDir/appsmith-backup-0000-00-0T00-00-00.00Z";
const encryptionPassword = "password#4321";
const encArchivePath = await backup.encryptBackupArchive(
const encArchivePath = await encryptBackupArchive(
archivePath,
encryptionPassword,
);
Expand All @@ -234,10 +235,7 @@ describe("Backup Tests", () => {
test("Test backup encryption function", async () => {
const archivePath = "/rootDir/appsmith-backup-0000-00-0T00-00-00.00Z";
const encryptionPassword = "password#123";
const res = await backup.encryptBackupArchive(
archivePath,
encryptionPassword,
);
const res = await encryptBackupArchive(archivePath, encryptionPassword);

console.log(res);
expect(res).toEqual("/rootDir/appsmith-backup-0000-00-0T00-00-00.00Z.enc");
Expand Down
Loading