Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backup schedule operations #701

Merged
merged 19 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f037e9e
implement create, delete and update commands for backup schedule.
niristius Aug 14, 2024
e47afcc
update readme
niristius Aug 14, 2024
fb49dab
clean up backup schedule operations and flag-names
niristius Aug 15, 2024
5dffa96
Merge branch 'master' into backup-schedule-operations
martin-helmich Aug 22, 2024
6d028ab
chore: re-generate README
martin-helmich Aug 22, 2024
ba1b32b
clean up types, flags and descriptions
niristius Aug 26, 2024
9257705
chore: re-generate README
niristius Aug 26, 2024
0ea8ec7
add returns where reasonable
niristius Aug 27, 2024
c52aa23
change mysql user id to arg for update and delete and centralize flags
niristius Aug 28, 2024
2d34eda
chore: re-generate README
niristius Aug 28, 2024
8595b71
set useful summaries and descriptions for backup schedule flags
niristius Aug 28, 2024
72d95fc
Merge remote-tracking branch 'origin/backup-schedule-operations' into…
niristius Aug 28, 2024
0a84f87
chore: re-generate README
niristius Aug 28, 2024
144a438
Update src/commands/backup/schedule/delete.tsx
martin-helmich Aug 28, 2024
916af28
make ttl description more precise and change update baseclass to Update
niristius Aug 30, 2024
24fbe60
Merge remote-tracking branch 'origin/master' into backup-schedule-ope…
martin-helmich Sep 3, 2024
c8d2ffe
chore: re-generate README
martin-helmich Sep 3, 2024
e6dd240
assertSuccess instead of manually assertStatus
niristius Sep 3, 2024
b119577
Merge remote-tracking branch 'origin/backup-schedule-operations' into…
niristius Sep 3, 2024
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
111 changes: 111 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,10 @@ USAGE
* [`mw backup download BACKUP-ID`](#mw-backup-download-backup-id)
* [`mw backup get BACKUP-ID`](#mw-backup-get-backup-id)
* [`mw backup list`](#mw-backup-list)
* [`mw backup schedule create`](#mw-backup-schedule-create)
* [`mw backup schedule delete BACKUP-SCHEDULE-ID`](#mw-backup-schedule-delete-backup-schedule-id)
* [`mw backup schedule list`](#mw-backup-schedule-list)
* [`mw backup schedule update BACKUP-SCHEDULE-ID`](#mw-backup-schedule-update-backup-schedule-id)
* [`mw context get`](#mw-context-get)
* [`mw context reset`](#mw-context-reset)
* [`mw context set`](#mw-context-set)
Expand Down Expand Up @@ -2256,6 +2259,74 @@ FLAG DESCRIPTIONS
to persistently set a default project for all commands that accept this flag.
```

## `mw backup schedule create`

Create a new backup schedule

```
USAGE
$ mw backup schedule create --schedule <value> --ttl <value> [-p <value>] [-q] [--description <value>]

FLAGS
-p, --project-id=<value> ID or short ID of a project; this flag is optional if a default project is set in the
context
-q, --quiet suppress process output and only display a machine-readable summary.
--description=<value> Set the description for the backup schedule.
--schedule=<value> (required) Set the interval at which the backup should be scheduled.
--ttl=<value> (required) Define the backup retention period in days for backups created.

FLAG DESCRIPTIONS
-p, --project-id=<value>

ID or short ID of a project; this flag is optional if a default project is set in the context

May contain a short ID or a full ID of a project; you can also use the "mw context set --project-id=<VALUE>" command
to persistently set a default project for all commands that accept this flag.

-q, --quiet suppress process output and only display a machine-readable summary.

This flag controls if you want to see the process output or only a summary. When using mw non-interactively (e.g. in
scripts), you can use this flag to easily get the IDs of created resources for further processing.

--description=<value> Set the description for the backup schedule.

Set the description for the given backup schedule to be displayed in mStudio and with the list command.

--schedule=<value> Set the interval at which the backup should be scheduled.

Must be specified as a cron schedule expression. Cannot be scheduled more often than once per hour. Defines the
interval at which the backup creation will be executed.

--ttl=<value> Define the backup retention period in days for backups created.

Must be specified as a natural number between 7 and 400, representing the number of days the backup will be kept.
```

## `mw backup schedule delete BACKUP-SCHEDULE-ID`

Delete a backup schedule

```
USAGE
$ mw backup schedule delete BACKUP-SCHEDULE-ID [-q] [-f]

ARGUMENTS
BACKUP-SCHEDULE-ID ID of schedule to delete

FLAGS
-f, --force Do not ask for confirmation
-q, --quiet suppress process output and only display a machine-readable summary.

DESCRIPTION
Delete a backup schedule

FLAG DESCRIPTIONS
-q, --quiet suppress process output and only display a machine-readable summary.

This flag controls if you want to see the process output or only a summary. When using mw non-interactively (e.g. in
scripts), you can use this flag to easily get the IDs of created resources for further processing.
```

## `mw backup schedule list`

List backup schedules belonging to a given project.
Expand Down Expand Up @@ -2292,6 +2363,46 @@ FLAG DESCRIPTIONS
to persistently set a default project for all commands that accept this flag.
```

## `mw backup schedule update BACKUP-SCHEDULE-ID`

Update an existing backup schedule

```
USAGE
$ mw backup schedule update BACKUP-SCHEDULE-ID [-q] [--description <value>] [--schedule <value>] [--ttl <value>]

ARGUMENTS
BACKUP-SCHEDULE-ID Define the backup schedule that is to be updated

FLAGS
-q, --quiet suppress process output and only display a machine-readable summary.
--description=<value> Set the description for the backup schedule.
--schedule=<value> Set the interval at which the backup should be scheduled.
--ttl=<value> Define the backup retention period in days for backups created.

DESCRIPTION
Update an existing backup schedule

FLAG DESCRIPTIONS
-q, --quiet suppress process output and only display a machine-readable summary.

This flag controls if you want to see the process output or only a summary. When using mw non-interactively (e.g. in
scripts), you can use this flag to easily get the IDs of created resources for further processing.

--description=<value> Set the description for the backup schedule.

Set the description for the given backup schedule to be displayed in mStudio and with the list command.

--schedule=<value> Set the interval at which the backup should be scheduled.

Must be specified as a cron schedule expression. Cannot be scheduled more often than once per hour. Defines the
interval at which the backup creation will be executed.

--ttl=<value> Define the backup retention period in days for backups created.

Must be specified as a natural number between 7 and 400, representing the number of days the backup will be kept.
```

## `mw context get`

Print an overview of currently set context parameters
Expand Down
94 changes: 94 additions & 0 deletions src/commands/backup/schedule/create.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { ExecRenderBaseCommand } from "../../../lib/basecommands/ExecRenderBaseCommand.js";
import {
makeProcessRenderer,
processFlags,
} from "../../../rendering/process/process_flags.js";
import { ReactNode } from "react";
import { assertStatus } from "@mittwald/api-client-commons";
import { Success } from "../../../rendering/react/components/Success.js";
import { Value } from "../../../rendering/react/components/Value.js";

import { projectFlags } from "../../../lib/resources/project/flags.js";
import type { MittwaldAPIV2Client } from "@mittwald/api-client";
import { backupScheduleFlagDefinitions } from "../../../lib/resources/backup/schedule/flags.js";

type Result = {
projectBackupScheduleId: string;
};
type BackupScheduleCreationData = Parameters<
MittwaldAPIV2Client["backup"]["createProjectBackupSchedule"]
>[0]["data"];

export class Create extends ExecRenderBaseCommand<typeof Create, Result> {
static summary = "Create a new backup schedule";
static flags = {
...projectFlags,
...processFlags,
description: backupScheduleFlagDefinitions.description(),
schedule: backupScheduleFlagDefinitions.schedule({ required: true }),
ttl: backupScheduleFlagDefinitions.ttl({ required: true }),
};

protected async exec(): Promise<Result> {
const process = makeProcessRenderer(
this.flags,
"Creating a new backup schedule",
);
const projectId = await this.withProjectId(Create);
const { description, schedule, ttl } = this.flags;

const backupScheduleCreationPayload: BackupScheduleCreationData = {
schedule,
ttl,
};

if (description) {
backupScheduleCreationPayload.description = description;
}

const { id: projectBackupScheduleId } = await process.runStep(
"creating backup schedule",
async () => {
const r = await this.apiClient.backup.createProjectBackupSchedule({
projectId,
data: backupScheduleCreationPayload,
});
assertStatus(r, 201);
return r.data;
},
);

const projectBackupSchedule = await process.runStep(
"checking newly created backup schedule",
async () => {
const r = await this.apiClient.backup.getProjectBackupSchedule({
projectBackupScheduleId,
});
assertStatus(r, 200);
return r.data;
},
);

if (description) {
await process.complete(
<Success>
The backup schedule "
<Value>{projectBackupSchedule.description}</Value>" was successfully
created.
</Success>,
);
} else {
await process.complete(
<Success>The backup schedule was successfully created.</Success>,
);
}

return { projectBackupScheduleId };
}

protected render({ projectBackupScheduleId }: Result): ReactNode {
if (this.flags.quiet) {
return projectBackupScheduleId;
}
}
}
44 changes: 44 additions & 0 deletions src/commands/backup/schedule/delete.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { DeleteBaseCommand } from "../../../lib/basecommands/DeleteBaseCommand.js";
import { assertStatus } from "@mittwald/api-client-commons";
import { Args } from "@oclif/core";
import {
makeProcessRenderer,
processFlags,
} from "../../../rendering/process/process_flags.js";

export class Delete extends DeleteBaseCommand<typeof Delete> {
static description = "Delete a backup schedule";
static resourceName = "backupSchedule";
static args = {
"backup-schedule-id": Args.string({
description: "ID of schedule to delete",
required: true,
}),
};
static flags = {
...processFlags,
};

protected async deleteResource(): Promise<void> {
const process = makeProcessRenderer(this.flags, "Updating backup schedule");
martin-helmich marked this conversation as resolved.
Show resolved Hide resolved
const projectBackupScheduleId = this.args["backup-schedule-id"];

const currentBackupSchedule =
await this.apiClient.backup.getProjectBackupSchedule({
projectBackupScheduleId,
});

if (currentBackupSchedule.data.isSystemBackup) {
await process.error(
"The system backup created through this schedule is reserved to restore your project in an emergency. " +
"It can not be deleted.",
);
}

const response = await this.apiClient.backup.deleteProjectBackupSchedule({
projectBackupScheduleId,
});

assertStatus(response, 204);
niristius marked this conversation as resolved.
Show resolved Hide resolved
}
}
80 changes: 80 additions & 0 deletions src/commands/backup/schedule/update.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { ExecRenderBaseCommand } from "../../../lib/basecommands/ExecRenderBaseCommand.js";
import { Args } from "@oclif/core";
import { ReactNode } from "react";
import {
makeProcessRenderer,
processFlags,
} from "../../../rendering/process/process_flags.js";
import { Success } from "../../../rendering/react/components/Success.js";
import assertSuccess from "../../../lib/apiutil/assert_success.js";
import type { MittwaldAPIV2Client } from "@mittwald/api-client";
import { backupScheduleFlagDefinitions } from "../../../lib/resources/backup/schedule/flags.js";

type UpdateResult = void;
type backupScheduleUpdatePayload = Parameters<
MittwaldAPIV2Client["backup"]["updateProjectBackupSchedule"]
>[0]["data"];

export default class Create extends ExecRenderBaseCommand<
typeof Create,
niristius marked this conversation as resolved.
Show resolved Hide resolved
UpdateResult
> {
static description = "Update an existing backup schedule";
static args = {
"backup-schedule-id": Args.string({
description: "Define the backup schedule that is to be updated",
required: true,
}),
};
static flags = {
...processFlags,
description: backupScheduleFlagDefinitions.description(),
schedule: backupScheduleFlagDefinitions.schedule(),
ttl: backupScheduleFlagDefinitions.ttl(),
};

protected async exec(): Promise<void> {
const process = makeProcessRenderer(this.flags, "Updating backup schedule");
const projectBackupScheduleId = this.args["backup-schedule-id"];
const { description, schedule, ttl } = this.flags;

const backupScheduleUpdatePayload: backupScheduleUpdatePayload = {};

if (description) {
backupScheduleUpdatePayload.description = description;
}

if (schedule) {
backupScheduleUpdatePayload.schedule = schedule;
}

if (ttl) {
backupScheduleUpdatePayload.ttl = ttl;
}

if (Object.keys(backupScheduleUpdatePayload).length == 0) {
await process.complete(
<Success>Nothing to change. Have a good day!</Success>,
);
return;
} else {
await process.runStep("Updating backup schedule", async () => {
const response =
await this.apiClient.backup.updateProjectBackupSchedule({
projectBackupScheduleId,
data: backupScheduleUpdatePayload,
});
assertSuccess(response);
});

await process.complete(
<Success>Your backup schedule has successfully been updated.</Success>,
);
return;
}
}

protected render(): ReactNode {
return true;
}
}
21 changes: 21 additions & 0 deletions src/lib/resources/backup/schedule/flags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Flags } from "@oclif/core";

export const backupScheduleFlagDefinitions = {
description: Flags.custom<string>({
summary: "Set the description for the backup schedule.",
description:
"Set the description for the given backup schedule to be displayed in mStudio and with the list command.",
}),
schedule: Flags.custom<string>({
summary: "Set the interval at which the backup should be scheduled.",
description:
"Must be specified as a cron schedule expression. " +
"Cannot be scheduled more often than once per hour. " +
"Defines the interval at which the backup creation will be executed.",
}),
ttl: Flags.custom<string>({
summary: "Define the backup retention period in days for backups created.",
description:
"Must be specified as a natural number between 7 and 400, representing the number of days the backup will be kept.",
}),
niristius marked this conversation as resolved.
Show resolved Hide resolved
};