Skip to content

Commit 428f5af

Browse files
committed
feat(cli): support --use-host on compas docker commands
1 parent a2b4ef1 commit 428f5af

File tree

2 files changed

+105
-56
lines changed

2 files changed

+105
-56
lines changed

docs/references/cli.md

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -94,19 +94,21 @@ Minio credentials:
9494

9595
Don't use this command and secrets for your production deployment.
9696

97-
| Option | Description |
98-
| ------------------ | --------------------------------------------------------------- |
99-
| --postgres-version | Specify the PostgreSQL version to use. Defaults to 12. (number) |
100-
| -h, --help | Display information about the current command. (boolean) |
97+
| Option | Description |
98+
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
99+
| --postgres-version | Specify the PostgreSQL version to use. Defaults to 12. (number) |
100+
| --use-host | Skip Docker altogether and assume that Postgres and Minio are enabled on the host. Alternatively, set COMPAS_SKIP_DOCKER=true. (boolean) |
101+
| -h, --help | Display information about the current command. (boolean) |
101102

102103
### `compas docker up`
103104

104105
Start the managed containers.
105106

106-
| Option | Description |
107-
| ------------------ | --------------------------------------------------------------- |
108-
| --postgres-version | Specify the PostgreSQL version to use. Defaults to 12. (number) |
109-
| -h, --help | Display information about the current command. (boolean) |
107+
| Option | Description |
108+
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
109+
| --postgres-version | Specify the PostgreSQL version to use. Defaults to 12. (number) |
110+
| --use-host | Skip Docker altogether and assume that Postgres and Minio are enabled on the host. Alternatively, set COMPAS_SKIP_DOCKER=true. (boolean) |
111+
| -h, --help | Display information about the current command. (boolean) |
110112

111113
### `compas docker down`
112114

@@ -116,10 +118,11 @@ Stop any of the containers that could possibly be started by this CLI. It
116118
ignores context and stops any PostgreSQL container started by this CLI, ignoring
117119
`--postgres-version`.
118120

119-
| Option | Description |
120-
| ------------------ | --------------------------------------------------------------- |
121-
| --postgres-version | Specify the PostgreSQL version to use. Defaults to 12. (number) |
122-
| -h, --help | Display information about the current command. (boolean) |
121+
| Option | Description |
122+
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
123+
| --postgres-version | Specify the PostgreSQL version to use. Defaults to 12. (number) |
124+
| --use-host | Skip Docker altogether and assume that Postgres and Minio are enabled on the host. Alternatively, set COMPAS_SKIP_DOCKER=true. (boolean) |
125+
| -h, --help | Display information about the current command. (boolean) |
123126

124127
### `compas docker clean`
125128

@@ -134,11 +137,12 @@ restart the containers. The flag is repeatable, so multiple projects can be
134137
cleaned at the same time. If no value is passed, it defaults to
135138
'process.env.APP_NAME'.
136139

137-
| Option | Description |
138-
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
139-
| --project | Specify the project(s) to remove. If no value is passed, the current project is read from `environment.APP_NAME`. (booleanOrString[]) |
140-
| --postgres-version | Specify the PostgreSQL version to use. Defaults to 12. (number) |
141-
| -h, --help | Display information about the current command. (boolean) |
140+
| Option | Description |
141+
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
142+
| --project | Specify the project(s) to remove. If no value is passed, the current project is read from `environment.APP_NAME`. (booleanOrString[]) |
143+
| --postgres-version | Specify the PostgreSQL version to use. Defaults to 12. (number) |
144+
| --use-host | Skip Docker altogether and assume that Postgres and Minio are enabled on the host. Alternatively, set COMPAS_SKIP_DOCKER=true. (boolean) |
145+
| -h, --help | Display information about the current command. (boolean) |
142146

143147
## `compas init`
144148

packages/cli/src/compas/commands/docker.js

Lines changed: 84 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { environment, exec, isNil, spawn } from "@compas/stdlib";
22

33
/**
44
* @typedef {{
5+
* useHost: boolean,
56
* containersForContext: {
67
* [p: string]: {
78
* createCommand: string,
@@ -96,6 +97,15 @@ The flag is repeatable, so multiple projects can be cleaned at the same time. If
9697
},
9798
},
9899
},
100+
{
101+
name: "useHost",
102+
rawName: "--use-host",
103+
description:
104+
"Skip Docker altogether and assume that Postgres and Minio are enabled on the host. Alternatively, set COMPAS_SKIP_DOCKER=true.",
105+
value: {
106+
specification: "boolean",
107+
},
108+
},
99109
],
100110
executor: cliExecutor,
101111
};
@@ -107,43 +117,50 @@ The flag is repeatable, so multiple projects can be cleaned at the same time. If
107117
* @returns {Promise<import("../../cli/types.js").CliResult>}
108118
*/
109119
export async function cliExecutor(logger, state) {
110-
const context = getContainerInformation(state.flags.postgresVersion ?? "12");
120+
const useHost =
121+
state.flags.useHost ?? environment.COMPAS_SKIP_DOCKER === "true";
122+
const postgresVersion = state.flags.postgresVersion ?? "12";
111123

112-
if (!(await isDockerAvailable())) {
113-
logger.error(
114-
"Make sure to install Docker first. See https://docs.docker.com/install/",
115-
);
124+
// @ts-expect-error
125+
const context = getContainerInformation(postgresVersion, useHost);
116126

117-
return { exitStatus: "failed" };
118-
}
127+
if (!useHost) {
128+
if (!(await isDockerAvailable())) {
129+
logger.error(
130+
"Make sure to install Docker first. See https://docs.docker.com/install/",
131+
);
119132

120-
const { exitCode, stdout, stderr } = await exec(
121-
"docker container ls -a --format '{{.Names}}'",
122-
);
133+
return { exitStatus: "failed" };
134+
}
123135

124-
if (exitCode !== 0) {
125-
logger.error(
126-
"Could not list containers available on host. Is Docker correctly installed?",
136+
const { exitCode, stdout, stderr } = await exec(
137+
"docker container ls -a --format '{{.Names}}'",
127138
);
128139

129-
// TODO: Enable with verbose flag?
130-
if (state.flags.verbose) {
131-
logger.error({
132-
stdout,
133-
stderr,
134-
});
140+
if (exitCode !== 0) {
141+
logger.error(
142+
"Could not list containers available on host. Is Docker correctly installed?",
143+
);
144+
145+
// TODO: Enable with verbose flag?
146+
if (state.flags.verbose) {
147+
logger.error({
148+
stdout,
149+
stderr,
150+
});
151+
}
152+
153+
return {
154+
exitStatus: "failed",
155+
};
135156
}
136157

137-
return {
138-
exitStatus: "failed",
139-
};
158+
context.containersOnHost = stdout
159+
.split("\n")
160+
.map((it) => it.trim())
161+
.filter((it) => it.length > 0);
140162
}
141163

142-
context.containersOnHost = stdout
143-
.split("\n")
144-
.map((it) => it.trim())
145-
.filter((it) => it.length > 0);
146-
147164
if (state.command.includes("up")) {
148165
return await startContainers(logger, state, context);
149166
} else if (state.command.includes("down")) {
@@ -166,9 +183,17 @@ export async function cliExecutor(logger, state) {
166183
* @returns {Promise<import("../../cli/types.js").CliResult>}
167184
*/
168185
async function startContainers(logger, state, context) {
186+
if (context.useHost) {
187+
logger.info(`Using host values. Skipping 'up' command...`);
188+
return {
189+
exitStatus: "failed",
190+
};
191+
}
192+
169193
// Stop all containers that should not be brought up by this context.
170194
// Prevent conflicts of having multiple PostgreSQL containers using the same ports.
171195
const stopResult = await stopContainers(logger, state, {
196+
useHost: context.useHost,
172197
globalContainers: context.globalContainers,
173198
containersOnHost: context.containersOnHost.filter((it) =>
174199
isNil(context.containersForContext[it]),
@@ -261,6 +286,13 @@ async function startContainers(logger, state, context) {
261286
* @returns {Promise<import("../../cli/types.js").CliResult>}
262287
*/
263288
async function stopContainers(logger, state, context) {
289+
if (context.useHost) {
290+
logger.info(`Using host values. Skipping 'down' command...`);
291+
return {
292+
exitStatus: "failed",
293+
};
294+
}
295+
264296
const containersToStop = context.globalContainers.filter((it) =>
265297
context.containersOnHost.includes(it),
266298
);
@@ -299,6 +331,15 @@ async function cleanContainers(logger, state, context) {
299331
const allProjects = isNil(state.flags.projects);
300332

301333
if (allProjects) {
334+
if (context.useHost) {
335+
logger.info(
336+
`Using host values. Skipping 'clean' command without projects specified...`,
337+
);
338+
return {
339+
exitStatus: "failed",
340+
};
341+
}
342+
302343
logger.info("Removing all containers and volumes.");
303344

304345
const stopResult = await stopContainers(logger, state, context);
@@ -352,21 +393,23 @@ async function cleanContainers(logger, state, context) {
352393
logger.info(`Resetting databases for '${projects.join("', '")}'.`);
353394

354395
// Make sure containers are started
355-
const startResult = await startContainers(logger, state, context);
356-
if (startResult.exitStatus === "failed") {
357-
return startResult;
396+
if (!context.useHost) {
397+
const startResult = await startContainers(logger, state, context);
398+
if (startResult.exitStatus === "failed") {
399+
return startResult;
400+
}
358401
}
359402

360-
const postgresContainer = Object.keys(context.containersForContext).find(
361-
(it) => it.startsWith("compas-postgres-"),
362-
);
403+
const psqlCommand = context.useHost
404+
? `psql --user postgres`
405+
: `docker exec -i ${Object.keys(context.containersForContext).find((it) =>
406+
it.startsWith("compas-postgres-"),
407+
)} psql --user postgres`;
363408

364409
const { stdout } = await exec(
365410
`echo "SELECT 'DROP DATABASE ' || quote_ident(datname) || ';' FROM pg_database WHERE (${projects
366411
.map((it) => `datname LIKE '${it}%'`)
367-
.join(
368-
" OR ",
369-
)}) AND datistemplate=false" | docker exec -i ${postgresContainer} psql --user postgres`,
412+
.join(" OR ")}) AND datistemplate=false" | ${psqlCommand}`,
370413
);
371414

372415
logger.info(
@@ -388,7 +431,7 @@ async function cleanContainers(logger, state, context) {
388431
}
389432

390433
const { exitCode, ...dockerLogs } = await exec(
391-
`echo '${pgCommand}' | docker exec -i ${postgresContainer} psql --user postgres`,
434+
`echo '${pgCommand}' | ${psqlCommand}`,
392435
);
393436

394437
if (exitCode !== 0) {
@@ -403,11 +446,13 @@ async function cleanContainers(logger, state, context) {
403446

404447
/**
405448
*
406-
* @param postgresVersion
449+
* @param {string} postgresVersion
450+
* @param {boolean} useHost
407451
* @returns {DockerContext}
408452
*/
409-
function getContainerInformation(postgresVersion) {
453+
function getContainerInformation(postgresVersion, useHost) {
410454
return {
455+
useHost,
411456
containersForContext: {
412457
[`compas-postgres-${postgresVersion}`]: {
413458
pullCommand: ["docker", ["pull", `postgres:${postgresVersion}`]],

0 commit comments

Comments
 (0)