Skip to content

Commit

Permalink
Merge pull request #31 from mittwald/feature/backup-commands
Browse files Browse the repository at this point in the history
Add commands for backup management
  • Loading branch information
martin-helmich authored Aug 1, 2023
2 parents f4f58c8 + 8f04298 commit 3ec4cb1
Show file tree
Hide file tree
Showing 24 changed files with 778 additions and 285 deletions.
172 changes: 131 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,11 @@ USAGE
* [`mw org membership list`](#mw-org-membership-list)
* [`mw org membership list-own`](#mw-org-membership-list-own)
* [`mw org membership revoke MEMBERSHIP-ID`](#mw-org-membership-revoke-membership-id)
* [`mw project backup get PROJECTBACKUPID`](#mw-project-backup-get-projectbackupid)
* [`mw project backup create`](#mw-project-backup-create)
* [`mw project backup delete BACKUP-ID`](#mw-project-backup-delete-backup-id)
* [`mw project backup download BACKUP-ID`](#mw-project-backup-download-backup-id)
* [`mw project backup get BACKUP-ID`](#mw-project-backup-get-backup-id)
* [`mw project backup list`](#mw-project-backup-list)
* [`mw project backupschedule get PROJECTBACKUPSCHEDULEID`](#mw-project-backupschedule-get-projectbackupscheduleid)
* [`mw project backupschedule list`](#mw-project-backupschedule-list)
* [`mw project create`](#mw-project-create)
* [`mw project cronjob execution get CRONJOB-ID EXECUTION-ID`](#mw-project-cronjob-execution-get-cronjob-id-execution-id)
Expand Down Expand Up @@ -2593,23 +2595,122 @@ FLAG DESCRIPTIONS
scripts), you can use this flag to easily get the IDs of created resources for further processing.
```

## `mw project backup get PROJECTBACKUPID`
## `mw project backup create`

Get a ProjectBackup.
Create a new backup of a project

```
USAGE
$ mw project backup get PROJECTBACKUPID [-o json|yaml | | ]
$ mw project backup create --expires <value> [-q] [-p <value>] [--description <value>] [-w] [--wait-timeout <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.
-w, --wait Wait for the resource to be ready.
--description=<value> a description for the backup.
--expires=<value> (required) An interval after which the backup expires (examples: 30m, 30d, 1y).
--wait-timeout=<value> [default: 600] The number of seconds to wait for the resource to be ready.
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.
```

## `mw project backup delete BACKUP-ID`

Delete a backup

```
USAGE
$ mw project backup delete BACKUP-ID [-q] [-f]
ARGUMENTS
BACKUP-ID The ID of the Backup to show.
FLAGS
-f, --force Do not ask for confirmation
-q, --quiet suppress process output and only display a machine-readable summary.
DESCRIPTION
Delete a backup
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 project backup download BACKUP-ID`

Download a backup to your local disk

```
USAGE
$ mw project backup download BACKUP-ID [-q] [--format tar|zip] [--password <value> | --generate-password |
--prompt-password] [--resume --output <value>]
ARGUMENTS
PROJECTBACKUPID ID of the ProjectBackup to retrieve.
BACKUP-ID the ID of the Backup to download.
FLAGS
-q, --quiet suppress process output and only display a machine-readable summary.
--format=<option> [default: tar] the file format to download the backup in.
<options: tar|zip>
--generate-password generate a random password to encrypt the backup with.
--output=<value> the file to write the backup to; if omitted, the filename will be determined by the server.
--password=<value> the password to encrypt the backup with.
--prompt-password prompt for a password to encrypt the backup with.
--resume resume a previously interrupted download.
DESCRIPTION
Download a backup to your local disk
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.
--generate-password generate a random password to encrypt the backup with.
CAUTION: this is not stored anywhere.
--password=<value> the password to encrypt the backup with.
CAUTION #1: this is not stored anywhere.
CAUTION #2: it is dangerous to use this option, as the password might be stored in your shell history.
--prompt-password prompt for a password to encrypt the backup with.
CAUTION: this is not stored anywhere.
```

## `mw project backup get BACKUP-ID`

show details of a backup.

```
USAGE
$ mw project backup get BACKUP-ID [-o json|yaml | | ]
ARGUMENTS
BACKUP-ID The ID of the Backup to show.
FLAGS
-o, --output=<option> output in a more machine friendly format
<options: json|yaml>
DESCRIPTION
Get a ProjectBackup.
show details of a backup.
```

## `mw project backup list`
Expand Down Expand Up @@ -2644,48 +2745,36 @@ FLAG DESCRIPTIONS
to persistently set a default project for all commands that accept this flag.
```

## `mw project backupschedule get PROJECTBACKUPSCHEDULEID`
## `mw project backupschedule list`

Get a ProjectBackupSchedule.
List backup schedules belonging to a given project.

```
USAGE
$ mw project backupschedule get PROJECTBACKUPSCHEDULEID [-o json|yaml | | ]
ARGUMENTS
PROJECTBACKUPSCHEDULEID ID of the ProjectBackupSchedule to retrieve.
$ mw project backupschedule list [--columns <value> | -x] [--sort <value>] [--filter <value>] [--output csv|json|yaml | |
[--csv | --no-truncate]] [--no-header | ] [-p <value>]
FLAGS
-o, --output=<option> output in a more machine friendly format
<options: json|yaml>
-p, --project-id=<value> ID or short ID of a project; this flag is optional if a default project is set in the
context
-x, --extended show extra columns
--columns=<value> only show provided columns (comma-separated)
--csv output is csv format [alias: --output=csv]
--filter=<value> filter property by partial string matching, ex: name=foo
--no-header hide table header from output
--no-truncate do not truncate output to fit screen
--output=<option> output in a more machine friendly format
<options: csv|json|yaml>
--sort=<value> property to sort by (prepend '-' for descending)
DESCRIPTION
Get a ProjectBackupSchedule.
```

## `mw project backupschedule list`

List BackupSchedules belonging to a given Project.
List backup schedules belonging to a given project.
```
USAGE
$ mw project backupschedule list --project-id <value> [--columns <value> | -x] [--sort <value>] [--filter <value>] [--output
csv|json|yaml | | [--csv | --no-truncate]] [--no-header | ]
FLAGS
-x, --extended show extra columns
--columns=<value> only show provided columns (comma-separated)
--csv output is csv format [alias: --output=csv]
--filter=<value> filter property by partial string matching, ex: name=foo
--no-header hide table header from output
--no-truncate do not truncate output to fit screen
--output=<option> output in a more machine friendly format
<options: csv|json|yaml>
--project-id=<value> (required) ID of the Project to list BackupSchedules for.
--sort=<value> property to sort by (prepend '-' for descending)
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
DESCRIPTION
List BackupSchedules belonging to a given Project.
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.
```

## `mw project create`
Expand All @@ -2694,14 +2783,15 @@ Get the details of a project

```
USAGE
$ mw project create -d <value> [-s <value>] [-q] [-w] [--update-context]
$ mw project create -d <value> [-s <value>] [-q] [-w] [--wait-timeout <value>] [--update-context]
FLAGS
-d, --description=<value> (required) A description for the project.
-q, --quiet suppress process output and only display a machine-readable summary.
-s, --server-id=<value> ID or short ID of a server; this flag is optional if a default server is set in the context
-w, --wait Wait for the project to be ready.
-w, --wait Wait for the resource to be ready.
--update-context Update the CLI context to use the newly created project
--wait-timeout=<value> [default: 600] The number of seconds to wait for the resource to be ready.
DESCRIPTION
Get the details of a project
Expand Down
31 changes: 9 additions & 22 deletions src/commands/org/invite.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import {
} from "../../rendering/process/process_flags.js";
import { Flags } from "@oclif/core";
import { MittwaldAPIV2 } from "@mittwald/api-client";
import MembershipCustomerRoles = MittwaldAPIV2.Components.Schemas.MembershipCustomerRoles;
import { ReactNode } from "react";
import parseDuration from "parse-duration";
import { assertStatus } from "@mittwald/api-client-commons";
import { Success } from "../../rendering/react/components/Success.js";
import { Value } from "../../rendering/react/components/Value.js";
import {
expirationDateFromFlagsOptional,
expireFlags,
} from "../../lib/expires.js";
import MembershipCustomerRoles = MittwaldAPIV2.Components.Schemas.MembershipCustomerRoles;

const inviteFlags = {
email: Flags.string({
Expand All @@ -26,10 +29,7 @@ const inviteFlags = {
message: Flags.string({
description: "A message to include in the invitation email.",
}),
expires: Flags.string({
description:
"An interval after which the invitation expires (examples: 30m, 30d, 1y).",
}),
...expireFlags("invitation"),
};

export class Invite extends ExecRenderBaseCommand<
Expand All @@ -39,21 +39,6 @@ export class Invite extends ExecRenderBaseCommand<
static description = "Invite a user to an organization.";
static flags = { ...orgFlags, ...processFlags, ...inviteFlags };

protected getExpirationDate(): Date | undefined {
if (!this.flags.expires) {
return undefined;
}

const d = new Date();
const i = parseDuration(this.flags.expires);

if (!i) {
throw new Error("could not parse duration: " + this.flags.expires);
}

return new Date(d.getTime() + i);
}

protected async exec(): Promise<{ inviteId: string }> {
const process = makeProcessRenderer(
this.flags,
Expand All @@ -73,7 +58,9 @@ export class Invite extends ExecRenderBaseCommand<
mailAddress: this.flags.email,
role: this.flags.role as MembershipCustomerRoles,
message: this.flags.message,
membershipExpiresAt: this.getExpirationDate()?.toJSON(),
membershipExpiresAt: expirationDateFromFlagsOptional(
this.flags,
)?.toJSON(),
},
});

Expand Down
90 changes: 90 additions & 0 deletions src/commands/project/backup/create.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { ExecRenderBaseCommand } from "../../../rendering/react/ExecRenderBaseCommand.js";
import {
makeProcessRenderer,
processFlags,
} from "../../../rendering/process/process_flags.js";
import { projectFlags, withProjectId } from "../../../lib/project/flags.js";
import React, { ReactNode } from "react";
import { Flags } from "@oclif/core";
import {
expirationDateFromFlags,
expireFlagsRequired,
} from "../../../lib/expires.js";
import { assertStatus } from "@mittwald/api-client-commons";
import { Success } from "../../../rendering/react/components/Success.js";
import { waitFlags, waitUntil } from "../../../lib/wait.js";
import { Text } from "ink";

type CreateResult = {
backupId: string;
};

export class Create extends ExecRenderBaseCommand<typeof Create, CreateResult> {
static summary = "Create a new backup of a project";
static flags = {
...processFlags,
...projectFlags,
description: Flags.string({
description: "a description for the backup.",
}),
...expireFlagsRequired("backup"),
...waitFlags,
};

protected async exec(): Promise<CreateResult> {
const p = makeProcessRenderer(this.flags, "Creating backup");
const projectId = await withProjectId(
this.apiClient,
this.flags,
this.args,
this.config,
);
const { description } = this.flags;
const expirationTime = expirationDateFromFlags(this.flags);

const backup = await p.runStep("creating backup", async () => {
const r = await this.apiClient.backup.createProjectBackup({
pathParameters: { projectId },
data: {
description,
expirationTime: expirationTime.toJSON(),
},
});

assertStatus(r, 201);

return r.data;
});

if (this.flags.wait) {
const stepWaiting = p.addStep(
<Text>waiting for backup to be complete</Text>,
);

await waitUntil(async () => {
const backupResponse = await this.apiClient.backup.getProjectBackup({
pathParameters: { projectBackupId: backup.id },
});

if (
backupResponse.status === 200 &&
backupResponse.data.status === "Completed"
) {
return true;
}
}, this.flags["wait-timeout"]);

stepWaiting.complete();
}

p.complete(<Success>Backup successfully created.</Success>);

return { backupId: backup.id };
}

protected render(executionResult: CreateResult): ReactNode {
if (this.flags.quiet) {
return executionResult.backupId;
}
}
}
Loading

0 comments on commit 3ec4cb1

Please sign in to comment.