Skip to content

Commit

Permalink
Detect if port for local Fauna is already occupied. Allow users to co…
Browse files Browse the repository at this point in the history
…ntrol hostIp. (#512)

* Tests for health checks.

* Argument checks

* Skip pull test

* Tests for pull failing

* Tests for pull failing

* Support for hostIp

* Port occupied tests

* Remove only

* Fail gracefully if the container is already present but on a different port.

* Doc fixes
  • Loading branch information
cleve-fauna authored Dec 13, 2024
1 parent c963ec9 commit 2b9c521
Show file tree
Hide file tree
Showing 6 changed files with 481 additions and 77 deletions.
82 changes: 59 additions & 23 deletions src/commands/local.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ensureContainerRunning } from "../lib/docker-containers.mjs";
import { CommandError } from "../lib/errors.mjs";

/**
* Starts the local Fauna container
Expand All @@ -10,9 +11,12 @@ async function startLocal(argv) {
await ensureContainerRunning({
imageName: argv.image,
containerName: argv.name,
hostIp: argv.hostIp,
hostPort: argv.hostPort,
containerPort: argv.containerPort,
pull: argv.pull,
interval: argv.interval,
maxAttempts: argv.maxAttempts,
});
}

Expand All @@ -22,29 +26,61 @@ async function startLocal(argv) {
* @returns {import('yargs').Argv} The yargs instance
*/
function buildLocalCommand(yargs) {
return yargs.options({
containerPort: {
describe: "The port inside the container Fauna listens on.",
type: "number",
default: "8443",
},
hostPort: {
describe:
"The port on the host machine mapped to the container's port. This is the port you'll connect to Fauna on.",
type: "number",
default: "8443",
},
name: {
describe: "The name to give the container",
type: "string",
default: "faunadb",
},
pull: {
describe: "Pull the latest image before starting the container.",
type: "boolean",
default: true,
},
});
return yargs
.options({
containerPort: {
describe: "The port inside the container Fauna listens on.",
type: "number",
default: 8443,
},
hostPort: {
describe:
"The port on the host machine mapped to the container's port. This is the port you'll connect to Fauna on.",
type: "number",
default: 8443,
},
hostIp: {
describe: `The IP address to bind the container's exposed port on the host.`,
type: "string",
default: "0.0.0.0",
},
interval: {
describe:
"The interval (in milliseconds) between health check attempts. Determines how often the CLI checks if the Fauna container is ready.",
type: "number",
default: 10000,
},
maxAttempts: {
describe:
"The maximum number of health check attempts before declaring the start Fauna continer process as failed.",
type: "number",
default: 100,
},
name: {
describe: "The name to give the container",
type: "string",
default: "faunadb",
},
pull: {
describe: "Pull the latest image before starting the container.",
type: "boolean",
default: true,
},
})
.check((argv) => {
if (argv.maxAttempts < 1) {
throw new CommandError("--maxAttempts must be greater than 0.", {
hideHelp: false,
});
}
if (argv.interval < 0) {
throw new CommandError(
"--interval must be greater than or equal to 0.",
{ hideHelp: false },
);
}
return true;
});
}

export default {
Expand Down
2 changes: 2 additions & 0 deletions src/config/setup-container.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from "node:fs";
import * as fsp from "node:fs/promises";
import net from "node:net";
import os from "node:os";
import path from "node:path";
import { exit } from "node:process";
Expand Down Expand Up @@ -60,6 +61,7 @@ export const injectables = {
fetch: awilix.asValue(fetchWrapper),
fs: awilix.asValue(fs),
fsp: awilix.asValue(fsp),
net: awilix.asValue(net),
dirname: awilix.asValue(path.dirname),
normalize: awilix.asValue(path.normalize),
homedir: awilix.asValue(os.homedir),
Expand Down
3 changes: 3 additions & 0 deletions src/config/setup-test-container.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import fs from "node:fs";
import net from "node:net";
import path from "node:path";
import { PassThrough } from "node:stream";

Expand Down Expand Up @@ -43,6 +44,7 @@ export function setupTestContainer() {

const thingsToManuallyMock = automock(container);
const customfs = stub({ ...fs });
const customNet = stub({ ...net });
// this is a mock used by the default profile behavior
customfs.readdirSync.withArgs(process.cwd()).returns([]);

Expand All @@ -58,6 +60,7 @@ export function setupTestContainer() {
// real implementation
parseYargs: awilix.asValue(spy(parseYargs)),
fs: awilix.asValue(customfs),
net: awilix.asValue(customNet),
homedir: awilix.asValue(
stub().returns(path.join(__dirname, "../../test/test-homedir")),
),
Expand Down
Loading

0 comments on commit 2b9c521

Please sign in to comment.