@mittwald/cli 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/dist/commands/app/dependency/list.d.ts +1 -0
  2. package/dist/commands/app/dependency/versions.d.ts +1 -0
  3. package/dist/commands/app/get.js +1 -2
  4. package/dist/commands/app/list-upgrade-candidates.d.ts +1 -0
  5. package/dist/commands/app/list.d.ts +1 -0
  6. package/dist/commands/backup/delete.d.ts +1 -0
  7. package/dist/commands/backup/get.js +1 -2
  8. package/dist/commands/backup/list.d.ts +1 -0
  9. package/dist/commands/backup/schedule/list.d.ts +1 -0
  10. package/dist/commands/container/delete.d.ts +1 -0
  11. package/dist/commands/container/list.d.ts +1 -0
  12. package/dist/commands/container/logs.d.ts +1 -0
  13. package/dist/commands/container/run.d.ts +0 -16
  14. package/dist/commands/container/run.js +4 -61
  15. package/dist/commands/container/update.d.ts +36 -0
  16. package/dist/commands/container/update.js +174 -0
  17. package/dist/commands/conversation/categories.d.ts +1 -0
  18. package/dist/commands/conversation/create.d.ts +1 -0
  19. package/dist/commands/conversation/list.d.ts +1 -0
  20. package/dist/commands/conversation/reply.d.ts +1 -0
  21. package/dist/commands/cronjob/delete.d.ts +1 -0
  22. package/dist/commands/cronjob/execution/get.d.ts +1 -1
  23. package/dist/commands/cronjob/execution/list.d.ts +1 -0
  24. package/dist/commands/cronjob/execution/logs.d.ts +1 -0
  25. package/dist/commands/cronjob/get.js +1 -2
  26. package/dist/commands/cronjob/list.d.ts +1 -0
  27. package/dist/commands/database/list.d.ts +1 -0
  28. package/dist/commands/database/mysql/charsets.d.ts +1 -0
  29. package/dist/commands/database/mysql/delete.d.ts +1 -0
  30. package/dist/commands/database/mysql/get.d.ts +1 -1
  31. package/dist/commands/database/mysql/list.d.ts +1 -0
  32. package/dist/commands/database/mysql/user/delete.d.ts +1 -0
  33. package/dist/commands/database/mysql/user/get.d.ts +1 -1
  34. package/dist/commands/database/mysql/user/list.d.ts +1 -0
  35. package/dist/commands/database/mysql/versions.d.ts +1 -0
  36. package/dist/commands/database/redis/get.d.ts +1 -1
  37. package/dist/commands/database/redis/list.d.ts +1 -0
  38. package/dist/commands/database/redis/versions.d.ts +1 -0
  39. package/dist/commands/domain/dnszone/get.js +1 -2
  40. package/dist/commands/domain/dnszone/list.d.ts +1 -0
  41. package/dist/commands/domain/get.js +1 -2
  42. package/dist/commands/domain/list.d.ts +1 -0
  43. package/dist/commands/domain/virtualhost/delete.d.ts +1 -0
  44. package/dist/commands/domain/virtualhost/get.js +1 -2
  45. package/dist/commands/domain/virtualhost/list.d.ts +1 -0
  46. package/dist/commands/extension/list-installed.d.ts +1 -0
  47. package/dist/commands/extension/list.d.ts +1 -0
  48. package/dist/commands/mail/address/create.d.ts +2 -1
  49. package/dist/commands/mail/address/create.js +2 -1
  50. package/dist/commands/mail/address/delete.d.ts +1 -0
  51. package/dist/commands/mail/address/get.d.ts +1 -1
  52. package/dist/commands/mail/address/list.d.ts +1 -0
  53. package/dist/commands/mail/deliverybox/delete.d.ts +1 -0
  54. package/dist/commands/mail/deliverybox/get.d.ts +1 -1
  55. package/dist/commands/mail/deliverybox/list.d.ts +1 -0
  56. package/dist/commands/org/delete.d.ts +1 -0
  57. package/dist/commands/org/get.js +1 -2
  58. package/dist/commands/org/invite/list-own.d.ts +1 -0
  59. package/dist/commands/org/invite/list.d.ts +1 -0
  60. package/dist/commands/org/list.d.ts +1 -0
  61. package/dist/commands/org/membership/list-own.d.ts +4 -0
  62. package/dist/commands/org/membership/list.d.ts +4 -0
  63. package/dist/commands/project/delete.d.ts +1 -0
  64. package/dist/commands/project/filesystem/usage.js +1 -2
  65. package/dist/commands/project/get.js +1 -2
  66. package/dist/commands/project/invite/get.d.ts +1 -1
  67. package/dist/commands/project/invite/list-own.d.ts +1 -0
  68. package/dist/commands/project/invite/list.d.ts +1 -0
  69. package/dist/commands/project/list.d.ts +1 -0
  70. package/dist/commands/project/membership/get-own.d.ts +1 -0
  71. package/dist/commands/project/membership/get.d.ts +1 -1
  72. package/dist/commands/project/membership/list-own.d.ts +1 -0
  73. package/dist/commands/project/membership/list.d.ts +1 -0
  74. package/dist/commands/registry/delete.d.ts +1 -0
  75. package/dist/commands/registry/list.d.ts +1 -0
  76. package/dist/commands/server/get.d.ts +1 -1
  77. package/dist/commands/server/list.d.ts +1 -0
  78. package/dist/commands/sftp-user/delete.d.ts +1 -0
  79. package/dist/commands/sftp-user/list.d.ts +1 -0
  80. package/dist/commands/ssh-user/delete.d.ts +1 -0
  81. package/dist/commands/ssh-user/list.d.ts +1 -0
  82. package/dist/commands/stack/delete.d.ts +1 -0
  83. package/dist/commands/stack/deploy.js +1 -8
  84. package/dist/commands/stack/list.d.ts +1 -0
  85. package/dist/commands/stack/ps.d.ts +1 -0
  86. package/dist/commands/stack/ps.js +1 -1
  87. package/dist/commands/user/api-token/get.d.ts +1 -1
  88. package/dist/commands/user/api-token/list.d.ts +1 -0
  89. package/dist/commands/user/api-token/revoke.d.ts +1 -0
  90. package/dist/commands/user/get.d.ts +1 -1
  91. package/dist/commands/user/session/get.d.ts +1 -1
  92. package/dist/commands/user/session/list.d.ts +1 -0
  93. package/dist/commands/user/ssh-key/delete.d.ts +1 -0
  94. package/dist/commands/user/ssh-key/get.d.ts +1 -1
  95. package/dist/commands/user/ssh-key/list.d.ts +1 -0
  96. package/dist/lib/basecommands/BaseCommand.d.ts +7 -5
  97. package/dist/lib/basecommands/BaseCommand.js +25 -8
  98. package/dist/lib/basecommands/CommandFlags.d.ts +3 -3
  99. package/dist/lib/basecommands/CoreBaseCommand.d.ts +12 -0
  100. package/dist/lib/basecommands/CoreBaseCommand.js +16 -0
  101. package/dist/lib/basecommands/DeleteBaseCommand.d.ts +1 -0
  102. package/dist/lib/basecommands/DeleteBaseCommand.js +1 -0
  103. package/dist/lib/basecommands/ExecRenderBaseCommand.d.ts +3 -0
  104. package/dist/lib/basecommands/ExecRenderBaseCommand.js +3 -0
  105. package/dist/lib/basecommands/ExtendedBaseCommand.d.ts +3 -0
  106. package/dist/lib/basecommands/ExtendedBaseCommand.js +3 -0
  107. package/dist/lib/basecommands/GetBaseCommand.d.ts +1 -1
  108. package/dist/lib/basecommands/GetBaseCommand.js +1 -0
  109. package/dist/lib/basecommands/ListBaseCommand.d.ts +1 -0
  110. package/dist/lib/basecommands/ListBaseCommand.js +1 -0
  111. package/dist/lib/basecommands/UnauthenticatedBaseCommand.d.ts +10 -0
  112. package/dist/lib/basecommands/UnauthenticatedBaseCommand.js +16 -0
  113. package/dist/lib/resources/container/containerconfig.d.ts +43 -0
  114. package/dist/lib/resources/container/containerconfig.js +82 -0
  115. package/dist/lib/resources/stack/enrich.d.ts +2 -2
  116. package/dist/lib/resources/stack/enrich.js +1 -31
  117. package/package.json +8 -8
@@ -14,6 +14,7 @@ export declare class List extends ListBaseCommand<typeof List, ResponseItem, Res
14
14
  "no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
15
  "no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
16
  "csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
17
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
18
  };
18
19
  protected sorter: SorterFunction<ResponseItem>;
19
20
  getData(): Promise<Response>;
@@ -16,6 +16,7 @@ export declare class Versions extends ListBaseCommand<typeof Versions, ResponseI
16
16
  "no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
17
  "no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
18
  "csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
19
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
20
  };
20
21
  sorter: SorterFunction<ResponseItem>;
21
22
  getData(): Promise<Response>;
@@ -1,13 +1,12 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { RenderBaseCommand } from "../../lib/basecommands/RenderBaseCommand.js";
3
3
  import { RenderJson } from "../../rendering/react/json/RenderJson.js";
4
- import { GetBaseCommand } from "../../lib/basecommands/GetBaseCommand.js";
5
4
  import { AppInstallationDetails } from "../../rendering/react/components/AppInstallation/AppInstallationDetails.js";
6
5
  import { useApp, useAppInstallation } from "../../lib/resources/app/hooks.js";
7
6
  import { appInstallationArgs } from "../../lib/resources/app/flags.js";
8
7
  export default class Get extends RenderBaseCommand {
9
8
  static description = "Get details about an app installation";
10
- static flags = { ...GetBaseCommand.baseFlags };
9
+ static flags = { ...RenderBaseCommand.buildFlags() };
11
10
  static args = { ...appInstallationArgs };
12
11
  render() {
13
12
  const appInstallationId = this.useAppInstallationId(Get);
@@ -16,6 +16,7 @@ export default class List extends ListBaseCommand<typeof List, ResponseItem, Res
16
16
  "no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
17
  "no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
18
  "csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
19
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
20
  };
20
21
  protected getData(): Promise<Response>;
21
22
  protected mapData(data: ResponseItem[]): Promise<ResponseItem[]>;
@@ -22,6 +22,7 @@ export default class List extends ListBaseCommand<typeof List, ResponseItem, Res
22
22
  "no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
23
23
  "no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
24
24
  "csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
25
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
25
26
  };
26
27
  protected getData(): Promise<Response>;
27
28
  protected mapData(data: SuccessfulResponse<Response, 200>["data"]): Promise<ExtendedResponseItem[]>;
@@ -5,6 +5,7 @@ export declare class Delete extends DeleteBaseCommand<typeof Delete> {
5
5
  static flags: {
6
6
  force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
7
  quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
9
  };
9
10
  static args: {
10
11
  "backup-id": import("@oclif/core/interfaces").Arg<string>;
@@ -3,7 +3,6 @@ import { RenderBaseCommand } from "../../lib/basecommands/RenderBaseCommand.js";
3
3
  import { useProjectBackup } from "../../lib/resources/projectbackup/hooks.js";
4
4
  import { ProjectBackupDetails } from "../../rendering/react/components/ProjectBackup/ProjectBackupDetails.js";
5
5
  import { RenderJson } from "../../rendering/react/json/RenderJson.js";
6
- import { GetBaseCommand } from "../../lib/basecommands/GetBaseCommand.js";
7
6
  import { Box } from "ink";
8
7
  import { backupArgs, withBackupId } from "../../lib/resources/backup/flags.js";
9
8
  import { usePromise } from "@mittwald/react-use-promise";
@@ -11,7 +10,7 @@ export default class Get extends RenderBaseCommand {
11
10
  static description = "Show details of a backup.";
12
11
  static args = { ...backupArgs };
13
12
  static flags = {
14
- ...GetBaseCommand.baseFlags,
13
+ ...RenderBaseCommand.buildFlags(),
15
14
  };
16
15
  static aliases = ["project:backup:get"];
17
16
  static deprecateAliases = true;
@@ -16,6 +16,7 @@ export declare class List extends ListBaseCommand<typeof List, ListItem, ListRes
16
16
  "no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
17
  "no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
18
  "csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
19
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
20
  };
20
21
  static aliases: string[];
21
22
  static deprecateAliases: boolean;
@@ -16,6 +16,7 @@ export declare class List extends ListBaseCommand<typeof List, ResponseItem, Res
16
16
  "no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
17
  "no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
18
  "csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
19
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
20
  };
20
21
  static aliases: string[];
21
22
  static deprecateAliases: boolean;
@@ -7,6 +7,7 @@ export default class Delete extends DeleteBaseCommand<typeof Delete> {
7
7
  "project-id": import("@oclif/core/interfaces").OptionFlag<string>;
8
8
  force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
9
  quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
11
  };
11
12
  static args: {
12
13
  "container-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
@@ -16,6 +16,7 @@ export declare class List extends ListBaseCommand<typeof List, ResponseItem, Res
16
16
  "no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
17
  "no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
18
  "csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
19
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
20
  };
20
21
  getData(): Promise<Response>;
21
22
  protected getColumns(data: ResponseItem[]): ListColumns<ResponseItem>;
@@ -6,6 +6,7 @@ export declare class Logs extends BaseCommand {
6
6
  static flags: {
7
7
  "no-pager": import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
8
  "project-id": import("@oclif/core/interfaces").OptionFlag<string>;
9
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
10
  };
10
11
  static args: {
11
12
  "container-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
@@ -34,23 +34,7 @@ export declare class Run extends ExecRenderBaseCommand<typeof Run, Result> {
34
34
  * @returns A properly formatted container service request
35
35
  */
36
36
  private buildServiceRequest;
37
- /**
38
- * Parses environment variables from command line flags and env files
39
- *
40
- * @returns An object containing environment variable key-value pairs
41
- */
42
- private parseEnvironmentVariables;
43
- private parseEnvironmentVariablesFromFile;
44
- private parseEnvironmentVariablesFromEnvFlags;
45
- /**
46
- * Determines which ports to expose based on flags and image metadata
47
- *
48
- * @param imageMeta Metadata about the container image
49
- * @returns An array of port mappings
50
- */
51
- private getPortMappings;
52
37
  private getImageAndMeta;
53
- private getImageMeta;
54
38
  private getServiceName;
55
39
  protected render({ serviceId }: Result): ReactNode;
56
40
  }
@@ -7,9 +7,7 @@ import { Success } from "../../rendering/react/components/Success.js";
7
7
  import { Value } from "../../rendering/react/components/Value.js";
8
8
  import * as dockerNames from "docker-names";
9
9
  import { assertStatus } from "@mittwald/api-client";
10
- import * as fs from "fs/promises";
11
- import { parse } from "envfile";
12
- import { pathExists } from "../../lib/util/fs/pathExists.js";
10
+ import { parseEnvironmentVariables, getPortMappings, getImageMeta, } from "../../lib/resources/container/containerconfig.js";
13
11
  export class Run extends ExecRenderBaseCommand {
14
12
  static summary = "Creates and starts a new container.";
15
13
  static flags = {
@@ -133,8 +131,8 @@ export class Run extends ExecRenderBaseCommand {
133
131
  ? [this.flags.entrypoint]
134
132
  : imageMeta.entrypoint;
135
133
  const description = this.flags.description ?? serviceName;
136
- const envs = await this.parseEnvironmentVariables();
137
- const ports = this.getPortMappings(imageMeta);
134
+ const envs = await parseEnvironmentVariables(this.flags.env, this.flags["env-file"]);
135
+ const ports = getPortMappings(imageMeta, this.flags["publish-all"], this.flags.publish);
138
136
  const volumes = this.flags.volume;
139
137
  return {
140
138
  image,
@@ -146,66 +144,11 @@ export class Run extends ExecRenderBaseCommand {
146
144
  volumes,
147
145
  };
148
146
  }
149
- /**
150
- * Parses environment variables from command line flags and env files
151
- *
152
- * @returns An object containing environment variable key-value pairs
153
- */
154
- async parseEnvironmentVariables() {
155
- return {
156
- ...this.parseEnvironmentVariablesFromEnvFlags(),
157
- ...(await this.parseEnvironmentVariablesFromFile()),
158
- };
159
- }
160
- async parseEnvironmentVariablesFromFile() {
161
- const result = {};
162
- for (const envFile of this.flags["env-file"] ?? []) {
163
- if (!(await pathExists(envFile))) {
164
- throw new Error(`Env file not found: ${envFile}`);
165
- }
166
- const fileContent = await fs.readFile(envFile, { encoding: "utf-8" });
167
- const parsed = parse(fileContent);
168
- Object.assign(result, parsed);
169
- }
170
- return result;
171
- }
172
- parseEnvironmentVariablesFromEnvFlags() {
173
- const splitIntoKeyAndValue = (e) => e.split("=", 2);
174
- const envFlags = this.flags.env ?? [];
175
- return Object.fromEntries(envFlags.map(splitIntoKeyAndValue));
176
- }
177
- /**
178
- * Determines which ports to expose based on flags and image metadata
179
- *
180
- * @param imageMeta Metadata about the container image
181
- * @returns An array of port mappings
182
- */
183
- getPortMappings(imageMeta) {
184
- if (this.flags["publish-all"]) {
185
- const definedPorts = imageMeta.exposedPorts ?? [];
186
- const concatPort = (p) => {
187
- const [port, protocol = "tcp"] = p.port.split("/", 2);
188
- return `${port}:${port}/${protocol}`;
189
- };
190
- return definedPorts.map(concatPort);
191
- }
192
- return this.flags.publish ?? [];
193
- }
194
147
  async getImageAndMeta(projectId) {
195
148
  const { image } = this.args;
196
- const meta = await this.getImageMeta(image, projectId);
149
+ const meta = await getImageMeta(this.apiClient, image, projectId);
197
150
  return { image, meta };
198
151
  }
199
- async getImageMeta(image, projectId) {
200
- const resp = await this.apiClient.container.getContainerImageConfig({
201
- queryParameters: {
202
- imageReference: image,
203
- useCredentialsForProjectId: projectId,
204
- },
205
- });
206
- assertStatus(resp, 200);
207
- return resp.data;
208
- }
209
152
  getServiceName() {
210
153
  const { name } = this.flags;
211
154
  if (name !== undefined) {
@@ -0,0 +1,36 @@
1
+ import { ReactNode } from "react";
2
+ import { ExecRenderBaseCommand } from "../../lib/basecommands/ExecRenderBaseCommand.js";
3
+ type Result = {
4
+ serviceId: string;
5
+ };
6
+ export declare class Update extends ExecRenderBaseCommand<typeof Update, Result> {
7
+ static summary: string;
8
+ static description: string;
9
+ static flags: {
10
+ image: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ env: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ "env-file": import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
+ entrypoint: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
15
+ command: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
16
+ publish: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
+ "publish-all": import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
+ volume: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
+ recreate: import("@oclif/core/interfaces").BooleanFlag<boolean>;
20
+ "project-id": import("@oclif/core/interfaces").OptionFlag<string>;
21
+ quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
22
+ };
23
+ static args: {
24
+ "container-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
25
+ };
26
+ protected exec(): Promise<Result>;
27
+ /**
28
+ * Builds a container service update request from command line flags
29
+ *
30
+ * @returns A properly formatted container service request with only the
31
+ * fields to update
32
+ */
33
+ private buildUpdateRequest;
34
+ protected render({ serviceId }: Result): ReactNode;
35
+ }
36
+ export {};
@@ -0,0 +1,174 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Args, Flags } from "@oclif/core";
3
+ import { ExecRenderBaseCommand } from "../../lib/basecommands/ExecRenderBaseCommand.js";
4
+ import { makeProcessRenderer, processFlags, } from "../../rendering/process/process_flags.js";
5
+ import { projectFlags } from "../../lib/resources/project/flags.js";
6
+ import { withContainerAndStackId } from "../../lib/resources/container/flags.js";
7
+ import assertSuccess from "../../lib/apiutil/assert_success.js";
8
+ import { Success } from "../../rendering/react/components/Success.js";
9
+ import { Value } from "../../rendering/react/components/Value.js";
10
+ import { assertStatus } from "@mittwald/api-client";
11
+ import { parseEnvironmentVariables, getPortMappings, getImageMeta, } from "../../lib/resources/container/containerconfig.js";
12
+ export class Update extends ExecRenderBaseCommand {
13
+ static summary = "Updates an existing container.";
14
+ static description = "Updates attributes of an existing container such as image, environment variables, etc.";
15
+ static flags = {
16
+ ...processFlags,
17
+ ...projectFlags,
18
+ image: Flags.string({
19
+ summary: "update the container image",
20
+ description: "Specify a new image to use for the container.",
21
+ required: false,
22
+ }),
23
+ env: Flags.string({
24
+ summary: "set environment variables in the container",
25
+ description: "Format: KEY=VALUE. Multiple environment variables can be specified with multiple --env flags.",
26
+ required: false,
27
+ multiple: true,
28
+ char: "e",
29
+ }),
30
+ "env-file": Flags.string({
31
+ summary: "read environment variables from a file",
32
+ description: "The file should contain lines in the format KEY=VALUE. Multiple files can be specified with multiple --env-file flags.",
33
+ multiple: true,
34
+ required: false,
35
+ }),
36
+ description: Flags.string({
37
+ summary: "update the descriptive label of the container",
38
+ description: "This helps identify the container's purpose or contents.",
39
+ required: false,
40
+ }),
41
+ entrypoint: Flags.string({
42
+ summary: "override the entrypoint of the container",
43
+ description: "The entrypoint is the command that will be executed when the container starts.",
44
+ required: false,
45
+ }),
46
+ command: Flags.string({
47
+ summary: "update the command to run in the container",
48
+ description: "This overrides the default command specified in the container image.",
49
+ required: false,
50
+ }),
51
+ publish: Flags.string({
52
+ summary: "update the container's port mappings",
53
+ description: "Map a container's port to a port on the host system. " +
54
+ "Format: <host-port>:<container-port> or just <container-port> (in which case the host port will be automatically assigned). " +
55
+ "Use multiple -p flags to publish multiple ports.",
56
+ required: false,
57
+ multiple: true,
58
+ char: "p",
59
+ }),
60
+ "publish-all": Flags.boolean({
61
+ summary: "publish all ports that are defined in the image",
62
+ description: "Automatically publish all ports that are exposed by the container image to random ports on the host.",
63
+ required: false,
64
+ char: "P",
65
+ }),
66
+ volume: Flags.string({
67
+ summary: "update volume mounts for the container",
68
+ description: "This flag can be used to add volume mounts to the container. It can be used multiple times to mount multiple volumes." +
69
+ "" +
70
+ "Needs to be in the format <host-path>:<container-path>. " +
71
+ "" +
72
+ "If you specify a file path as volume, this will mount a path from your hosting environment's file system (NOT your local file system) into the container. " +
73
+ "You can also specify a named volume, which needs to be created beforehand.",
74
+ required: false,
75
+ char: "v",
76
+ multiple: true,
77
+ }),
78
+ recreate: Flags.boolean({
79
+ summary: "recreate the container after updating",
80
+ description: "If set, the container will be automatically recreated after updating its configuration.",
81
+ required: false,
82
+ default: false,
83
+ }),
84
+ };
85
+ static args = {
86
+ "container-id": Args.string({
87
+ description: "ID or short ID of the container to update",
88
+ required: true,
89
+ }),
90
+ };
91
+ async exec() {
92
+ const p = makeProcessRenderer(this.flags, "Updating container");
93
+ const [serviceId, stackId] = await withContainerAndStackId(this.apiClient, Update, this.flags, this.args, this.config);
94
+ const service = await p.runStep("getting container configuration", async () => {
95
+ const r = await this.apiClient.container.getService({
96
+ serviceId,
97
+ stackId,
98
+ });
99
+ assertStatus(r, 200);
100
+ return r.data;
101
+ });
102
+ const updatePayload = await p.runStep("preparing update request", this.buildUpdateRequest());
103
+ if (Object.keys(updatePayload).length === 0) {
104
+ await p.complete(_jsx(Success, { children: "Nothing to change. Have a good day!" }));
105
+ return { serviceId };
106
+ }
107
+ await p.runStep("updating container configuration", async () => {
108
+ const r = await this.apiClient.container.updateStack({
109
+ stackId,
110
+ data: {
111
+ services: {
112
+ [service.serviceName]: updatePayload,
113
+ },
114
+ },
115
+ });
116
+ assertStatus(r, 200);
117
+ });
118
+ // Recreate the container if requested
119
+ if (this.flags.recreate) {
120
+ await p.runStep("recreating container", async () => {
121
+ const r = await this.apiClient.container.recreateService({
122
+ serviceId,
123
+ stackId,
124
+ });
125
+ assertSuccess(r);
126
+ });
127
+ }
128
+ await p.complete(_jsxs(Success, { children: ["Container ", _jsx(Value, { children: serviceId }), " was successfully updated.", this.flags.recreate &&
129
+ " The container was recreated with the new configuration."] }));
130
+ return { serviceId };
131
+ }
132
+ /**
133
+ * Builds a container service update request from command line flags
134
+ *
135
+ * @returns A properly formatted container service request with only the
136
+ * fields to update
137
+ */
138
+ async buildUpdateRequest() {
139
+ const updateRequest = {};
140
+ if (this.flags.image) {
141
+ updateRequest.image = this.flags.image;
142
+ // Get image metadata for port mappings if publish-all is specified
143
+ if (this.flags["publish-all"]) {
144
+ const projectId = await this.withProjectId(Update);
145
+ const imageMeta = await getImageMeta(this.apiClient, this.flags.image, projectId);
146
+ updateRequest.ports = getPortMappings(imageMeta, true);
147
+ }
148
+ }
149
+ if (this.flags.command) {
150
+ updateRequest.command = [this.flags.command];
151
+ }
152
+ if (this.flags.entrypoint) {
153
+ updateRequest.entrypoint = [this.flags.entrypoint];
154
+ }
155
+ if (this.flags.description) {
156
+ updateRequest.description = this.flags.description;
157
+ }
158
+ if (this.flags.env || this.flags["env-file"]) {
159
+ updateRequest.envs = await parseEnvironmentVariables(this.flags.env, this.flags["env-file"]);
160
+ }
161
+ if (this.flags.publish) {
162
+ updateRequest.ports = this.flags.publish;
163
+ }
164
+ if (this.flags.volume) {
165
+ updateRequest.volumes = this.flags.volume;
166
+ }
167
+ return updateRequest;
168
+ }
169
+ render({ serviceId }) {
170
+ if (this.flags.quiet) {
171
+ return serviceId;
172
+ }
173
+ }
174
+ }
@@ -14,6 +14,7 @@ export default class Categories extends ListBaseCommand<typeof Categories, Respo
14
14
  "no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
15
  "no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
16
  "csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
17
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
18
  };
18
19
  getData(): Promise<Response>;
19
20
  protected getColumns(): ListColumns<ResponseItem>;
@@ -7,6 +7,7 @@ export default class Create extends BaseCommand {
7
7
  message: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
8
  "message-from": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
9
  editor: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
11
  };
11
12
  private getCategoryId;
12
13
  run(): Promise<void>;
@@ -14,6 +14,7 @@ export default class List extends ListBaseCommand<typeof List, ResponseItem, Res
14
14
  "no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
15
  "no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
16
  "csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
17
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
18
  };
18
19
  getData(): Promise<Response>;
19
20
  protected getColumns(): ListColumns<ResponseItem>;
@@ -8,6 +8,7 @@ export default class Reply extends ExtendedBaseCommand<typeof Reply> {
8
8
  message: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
9
  "message-from": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
10
  editor: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
12
  };
12
13
  run(): Promise<void>;
13
14
  }
@@ -5,6 +5,7 @@ export default class Delete extends DeleteBaseCommand<typeof Delete> {
5
5
  static flags: {
6
6
  force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
7
  quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
9
  };
9
10
  static args: {
10
11
  "cronjob-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
@@ -6,7 +6,7 @@ export declare class Get extends GetBaseCommand<typeof Get, APIResponse> {
6
6
  static aliases: string[];
7
7
  static deprecateAliases: boolean;
8
8
  static flags: {
9
- [x: string]: import("@oclif/core/interfaces").Flag<any>;
9
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
10
  };
11
11
  static args: {
12
12
  "cronjob-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
@@ -17,6 +17,7 @@ export declare class List extends ListBaseCommand<typeof List, ResponseItem, Res
17
17
  "no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
18
  "no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
19
19
  "csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
20
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
21
  };
21
22
  getData(): Promise<Response>;
22
23
  protected getColumns(): ListColumns<ResponseItem>;
@@ -8,6 +8,7 @@ export declare class Logs extends BaseCommand {
8
8
  static deprecateAliases: boolean;
9
9
  static flags: {
10
10
  "no-pager": import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
12
  };
12
13
  static args: {
13
14
  "cronjob-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
@@ -1,5 +1,4 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { GetBaseCommand } from "../../lib/basecommands/GetBaseCommand.js";
3
2
  import { Args } from "@oclif/core";
4
3
  import { RenderBaseCommand } from "../../lib/basecommands/RenderBaseCommand.js";
5
4
  import { ComponentPrinter } from "../../rendering/react/ComponentPrinter.js";
@@ -10,7 +9,7 @@ import { CronJobDetails } from "../../rendering/react/components/CronJob/CronJob
10
9
  import { GetFormatter } from "../../rendering/formatter/GetFormatter.js";
11
10
  export class Get extends RenderBaseCommand {
12
11
  static description = "Get details of a cron job";
13
- static flags = { ...GetBaseCommand.baseFlags };
12
+ static flags = { ...RenderBaseCommand.buildFlags() };
14
13
  static args = {
15
14
  "cronjob-id": Args.string({
16
15
  description: "ID of the cron job to be retrieved.",
@@ -17,6 +17,7 @@ export declare class List extends ListBaseCommand<typeof List, ResponseItem, Res
17
17
  "no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
18
  "no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
19
19
  "csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
20
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
21
  };
21
22
  getData(): Promise<Response>;
22
23
  protected getColumns(data: ResponseItem[]): ListColumns<ResponseItem>;
@@ -23,6 +23,7 @@ export declare class List extends ListBaseCommand<typeof List, ResponseItem, Res
23
23
  "no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
24
24
  "no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
25
25
  "csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
26
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
26
27
  };
27
28
  getData(): Promise<ResponseItem[]>;
28
29
  protected getColumns(ignoredData: ResponseItem[]): ListColumns<ResponseItem>;
@@ -14,6 +14,7 @@ export declare class Charsets extends ListBaseCommand<typeof Charsets, ResponseI
14
14
  "no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
15
  "no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
16
  "csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
17
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
18
  };
18
19
  protected sorter: (a: ResponseItem, b: ResponseItem) => number;
19
20
  getData(): Promise<Response>;
@@ -5,6 +5,7 @@ export default class Delete extends DeleteBaseCommand<typeof Delete> {
5
5
  static flags: {
6
6
  force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
7
  quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
9
  };
9
10
  static args: {
10
11
  "database-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
@@ -5,7 +5,7 @@ type APIResponse = Awaited<ReturnType<MittwaldAPIV2Client["database"]["getMysqlD
5
5
  export declare abstract class Get extends GetBaseCommand<typeof Get, APIResponse> {
6
6
  static description: string;
7
7
  static flags: {
8
- [x: string]: import("@oclif/core/interfaces").Flag<any>;
8
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
9
  };
10
10
  static args: {
11
11
  "database-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
@@ -15,6 +15,7 @@ export declare class List extends ListBaseCommand<typeof List, ResponseItem, Res
15
15
  "no-truncate": import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
16
  "no-relative-dates": import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
17
  "csv-separator": import("@oclif/core/interfaces").OptionFlag<"," | ";">;
18
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
19
  };
19
20
  getData(): Promise<Response>;
20
21
  protected getColumns(ignoredData: ResponseItem[]): ListColumns<ResponseItem>;
@@ -5,6 +5,7 @@ export default class Delete extends DeleteBaseCommand<typeof Delete> {
5
5
  static flags: {
6
6
  force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
7
  quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
9
  };
9
10
  static args: {
10
11
  "user-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
@@ -4,7 +4,7 @@ type APIResponse = Awaited<ReturnType<MittwaldAPIV2Client["database"]["getMysqlU
4
4
  export default class Get extends GetBaseCommand<typeof Get, APIResponse> {
5
5
  static description: string;
6
6
  static flags: {
7
- [x: string]: import("@oclif/core/interfaces").Flag<any>;
7
+ token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
8
  };
9
9
  static args: {
10
10
  id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;