Skip to content

Commit a1b87ed

Browse files
Fix Couchbase service configuration (#1356)
1 parent 84aba48 commit a1b87ed

5 files changed

Lines changed: 55 additions & 7 deletions

File tree

package-lock.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/modules/couchbase/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"testcontainers": "^12.0.1"
3333
},
3434
"devDependencies": {
35-
"couchbase": "^4.7.0"
35+
"couchbase": "^4.7.0",
36+
"get-port": "^7.2.0"
3637
}
3738
}

packages/modules/couchbase/src/couchbase-container.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import couchbase, { Bucket, Cluster } from "couchbase";
2+
import getPort from "get-port";
23
import { getImage } from "../../../testcontainers/src/utils/test-helper";
34
import { BucketDefinition } from "./bucket-definition";
45
import { CouchbaseContainer } from "./couchbase-container";
56
import { CouchbaseService } from "./couchbase-service";
7+
import PORTS from "./ports";
68

79
const ENTERPRISE_IMAGE = getImage(__dirname, 0);
810
const COMMUNITY_IMAGE = getImage(__dirname, 1);
@@ -86,4 +88,42 @@ describe("CouchbaseContainer", { timeout: 180_000 }, () => {
8688
"The Eventing Service is only supported with the Enterprise version"
8789
);
8890
});
91+
92+
it("should start with analytics service enabled", async () => {
93+
await using container = await new CouchbaseContainer(ENTERPRISE_IMAGE)
94+
.withEnabledServices(CouchbaseService.KV, CouchbaseService.ANALYTICS)
95+
.start();
96+
97+
expect(container.getConnectionString()).toContain("couchbase://");
98+
});
99+
100+
it("should create and use a bucket with KV service only", async () => {
101+
const bucketDefinition = new BucketDefinition("kvbucket").withPrimaryIndex(false);
102+
await using container = await new CouchbaseContainer(COMMUNITY_IMAGE)
103+
.withEnabledServices(CouchbaseService.KV)
104+
.withBucket(bucketDefinition)
105+
.withStartupTimeout(30_000)
106+
.start();
107+
108+
const cluster = await couchbase.Cluster.connect(container.getConnectionString(), {
109+
username: container.getUsername(),
110+
password: container.getPassword(),
111+
});
112+
113+
const coll = cluster.bucket(bucketDefinition.getName()).defaultCollection();
114+
await coll.upsert("testdoc", { foo: "bar" });
115+
expect((await coll.get("testdoc")).content).toEqual({ foo: "bar" });
116+
117+
await cluster.close();
118+
});
119+
120+
it("should preserve fixed host port binding", async () => {
121+
const hostPort = await getPort();
122+
await using container = await new CouchbaseContainer(COMMUNITY_IMAGE)
123+
.withEnabledServices(CouchbaseService.KV)
124+
.withExposedPorts({ container: PORTS.MGMT_PORT, host: hostPort })
125+
.start();
126+
127+
expect(container.getMappedPort(PORTS.MGMT_PORT)).toBe(hostPort);
128+
});
89129
});

packages/modules/couchbase/src/couchbase-container.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,7 @@ export class CouchbaseContainer extends GenericContainer {
3434

3535
constructor(image: string) {
3636
super(image);
37-
this.withExposedPorts(...this.getPortsToExpose()).withWaitStrategy(
38-
Wait.forLogMessage("Starting Couchbase Server -- Web UI available at http://<ip>:8091")
39-
);
37+
this.withWaitStrategy(Wait.forLogMessage("Starting Couchbase Server -- Web UI available at http://<ip>:8091"));
4038
}
4139

4240
withCredentials(username: string, password: string) {
@@ -120,7 +118,7 @@ export class CouchbaseContainer extends GenericContainer {
120118
if (this.enabledServices.has(CouchbaseService.EVENTING)) {
121119
exposedPorts.push(PORTS.EVENTING_PORT, PORTS.EVENTING_SSL_PORT);
122120
}
123-
return exposedPorts;
121+
return exposedPorts.filter((port) => !this.hasExposedPort(port));
124122
}
125123

126124
private constructWaitStrategies() {
@@ -427,7 +425,7 @@ export class CouchbaseContainer extends GenericContainer {
427425
BoundPorts.fromInspectResult(client.info.containerRuntime.hostIps, inspectResult)
428426
);
429427

430-
if (this.enabledServices.has(CouchbaseService.KV)) {
428+
if (this.enabledServices.has(CouchbaseService.QUERY)) {
431429
await new IntervalRetry<Response | undefined, Error>(1000).retryUntil(
432430
async () => {
433431
try {
@@ -574,6 +572,7 @@ export class CouchbaseContainer extends GenericContainer {
574572
}
575573

576574
public override async start(): Promise<StartedCouchbaseContainer> {
575+
this.withExposedPorts(...this.getPortsToExpose());
577576
return new StartedCouchbaseContainer(await super.start(), this.username, this.password);
578577
}
579578
}

packages/testcontainers/src/generic-container/generic-container.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,13 @@ export class GenericContainer implements TestContainer {
425425
return this;
426426
}
427427

428+
protected hasExposedPort(port: PortWithOptionalBinding): boolean {
429+
const containerPort = getContainerPort(port);
430+
const protocol = getProtocol(port);
431+
432+
return Object.hasOwn(this.createOpts.ExposedPorts ?? {}, `${containerPort}/${protocol}`);
433+
}
434+
428435
public withBindMounts(bindMounts: BindMount[]): this {
429436
this.hostConfig.Binds = bindMounts
430437
.map((bindMount) => ({ mode: "rw", ...bindMount }))

0 commit comments

Comments
 (0)