Skip to content

Commit

Permalink
Add DatastoreEmulatorContainer to gcloud module (#782)
Browse files Browse the repository at this point in the history
  • Loading branch information
oskarwidmark authored Jul 26, 2024
1 parent 96250a8 commit 693ea8c
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 8 deletions.
22 changes: 16 additions & 6 deletions docs/modules/gcloud.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ Testcontainers module for the Google Cloud Platform's [Cloud SDK](https://cloud.
npm install @testcontainers/gcloud --save-dev
```

Currently, the module supports `Firestore` emulators in Native mode and Datastore mode. In order to use them, you should use the following classes:

Currently, the module supports `Firestore` emulators. In order to use it, you should use the following classes:

Class | Container Image
-|-
FirestoreEmulatorContainer | [gcr.io/google.com/cloudsdktool/google-cloud-cli:emulators](https://gcr.io/google.com/cloudsdktool/google-cloud-cli)
Mode | Class | Container Image
-|-|-
Native mode | FirestoreEmulatorContainer | [gcr.io/google.com/cloudsdktool/google-cloud-cli:emulators](https://gcr.io/google.com/cloudsdktool/google-cloud-cli)
Datastore mode | DatastoreEmulatorContainer | [gcr.io/google.com/cloudsdktool/google-cloud-cli:emulators](https://gcr.io/google.com/cloudsdktool/google-cloud-cli)

## Examples

### Firestore
### Firestore Native mode

<!--codeinclude-->
[Starting a Firestore Emulator container with the default image](../../packages/modules/gcloud/src/firestore-emulator-container.test.ts) inside_block:firestore4
Expand All @@ -26,3 +26,13 @@ FirestoreEmulatorContainer | [gcr.io/google.com/cloudsdktool/google-cloud-cli:em
<!--codeinclude-->
[Starting a Firestore Emulator container with a custom emulator image](../../packages/modules/gcloud/src/firestore-emulator-container.test.ts) inside_block:firestore5
<!--/codeinclude-->

### Firestore Datastore mode

<!--codeinclude-->
[Starting a Datastore Emulator container with the default image](../../packages/modules/gcloud/src/datastore-emulator-container.test.ts) inside_block:datastore4
<!--/codeinclude-->

<!--codeinclude-->
[Starting a Datastore Emulator container with a custom emulator image](../../packages/modules/gcloud/src/datastore-emulator-container.test.ts) inside_block:datastore5
<!--/codeinclude-->
53 changes: 51 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/modules/gcloud/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"testcontainers": "^10.10.4"
},
"devDependencies": {
"@google-cloud/datastore": "^9.0.0",
"@google-cloud/firestore": "7.9.0",
"firebase-admin": "12.2.0"
}
Expand Down
45 changes: 45 additions & 0 deletions packages/modules/gcloud/src/datastore-emulator-container.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { DatastoreEmulatorContainer, StartedDatastoreEmulatorContainer } from "./datastore-emulator-container";
import { Datastore } from "@google-cloud/datastore";

describe("DatastoreEmulatorContainer", () => {
jest.setTimeout(240_000);

// datastore4 {
it("should work using default version", async () => {
const datastoreEmulatorContainer = await new DatastoreEmulatorContainer().start();

await checkDatastore(datastoreEmulatorContainer);

await datastoreEmulatorContainer.stop();
});
// }

// datastore5 {
it("should work using version 468.0.0", async () => {
const datastoreEmulatorContainer = await new DatastoreEmulatorContainer(
"gcr.io/google.com/cloudsdktool/google-cloud-cli:468.0.0-emulators"
).start();

await checkDatastore(datastoreEmulatorContainer);

await datastoreEmulatorContainer.stop();
});

// }

async function checkDatastore(datastoreEmulatorContainer: StartedDatastoreEmulatorContainer) {
expect(datastoreEmulatorContainer).toBeDefined();
const testProjectId = "test-project";
const testKind = "test-kind";
const testId = "123";
const databaseConfig = { projectId: testProjectId, apiEndpoint: datastoreEmulatorContainer.getEmulatorEndpoint() };
const datastore = new Datastore(databaseConfig);

const key = datastore.key([testKind, testId]);
const data = { message: "Hello, Datastore!" };
await datastore.save({ key, data });
const [entity] = await datastore.get(key);

expect(entity).toEqual({ message: "Hello, Datastore!", [Datastore.KEY]: key });
}
});
33 changes: 33 additions & 0 deletions packages/modules/gcloud/src/datastore-emulator-container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { AbstractStartedContainer, GenericContainer, StartedTestContainer, Wait } from "testcontainers";

const EMULATOR_PORT = 8080;
const CMD = `gcloud beta emulators firestore start --host-port 0.0.0.0:${EMULATOR_PORT} --database-mode=datastore-mode`;
const DEFAULT_IMAGE = "gcr.io/google.com/cloudsdktool/cloud-sdk";

export class DatastoreEmulatorContainer extends GenericContainer {
constructor(image = DEFAULT_IMAGE) {
super(image);
this.withExposedPorts(EMULATOR_PORT)
.withCommand(["/bin/sh", "-c", CMD])
.withWaitStrategy(Wait.forLogMessage(RegExp(".*running.*"), 1))
.withStartupTimeout(120_000);
}

public override async start(): Promise<StartedDatastoreEmulatorContainer> {
return new StartedDatastoreEmulatorContainer(await super.start());
}
}

export class StartedDatastoreEmulatorContainer extends AbstractStartedContainer {
constructor(startedTestContainer: StartedTestContainer) {
super(startedTestContainer);
}

/**
* @return a <code>host:port</code> pair corresponding to the address on which the emulator is
* reachable from the test host machine.
*/
public getEmulatorEndpoint(): string {
return `${this.getHost()}:${this.getMappedPort(EMULATOR_PORT)}`;
}
}
1 change: 1 addition & 0 deletions packages/modules/gcloud/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { FirestoreEmulatorContainer, StartedFirestoreEmulatorContainer } from "./firestore-emulator-container";
export { DatastoreEmulatorContainer, StartedDatastoreEmulatorContainer } from "./datastore-emulator-container";

0 comments on commit 693ea8c

Please sign in to comment.