From 227316d1f0e20ba29ee4ef1784c4d2d66955dae9 Mon Sep 17 00:00:00 2001 From: Daegeon Song Date: Thu, 28 Nov 2024 18:19:25 +0900 Subject: [PATCH 1/7] Remove explicit port binding in Azurite container Switched from explicitly binding ports to relying on automatic assignment to avoid manual management of ports. Simplifies configuration and reduces potential conflicts. --- .../azurite/src/azurite-container.test.ts | 28 --------- .../modules/azurite/src/azurite-container.ts | 60 ++++--------------- 2 files changed, 10 insertions(+), 78 deletions(-) diff --git a/packages/modules/azurite/src/azurite-container.test.ts b/packages/modules/azurite/src/azurite-container.test.ts index a25bae083..b972f4158 100644 --- a/packages/modules/azurite/src/azurite-container.test.ts +++ b/packages/modules/azurite/src/azurite-container.test.ts @@ -113,34 +113,6 @@ describe("Azurite", () => { }); // } - // customPorts { - it("should be able to specify custom ports", async () => { - const blobPort = 13000; - const queuePort = 14000; - const tablePort = 15000; - const container = await new AzuriteContainer() - .withBlobPort(blobPort) - .withQueuePort(queuePort) - .withTablePort(tablePort) - .start(); - - expect(container.getBlobPort()).toBe(blobPort); - expect(container.getQueuePort()).toBe(queuePort); - expect(container.getTablePort()).toBe(tablePort); - - const connectionString = container.getConnectionString(); - expect(connectionString).toContain("13000"); - expect(connectionString).toContain("14000"); - expect(connectionString).toContain("15000"); - - const serviceClient = BlobServiceClient.fromConnectionString(connectionString); - const containerClient = serviceClient.getContainerClient("test"); - await containerClient.createIfNotExists(); - - await container.stop(); - }); - // } - // inMemoryPersistence { it("should be able to use in-memory persistence", async () => { const container = await new AzuriteContainer().withInMemoryPersistence().start(); diff --git a/packages/modules/azurite/src/azurite-container.ts b/packages/modules/azurite/src/azurite-container.ts index 1af1b289c..f1922bf42 100755 --- a/packages/modules/azurite/src/azurite-container.ts +++ b/packages/modules/azurite/src/azurite-container.ts @@ -21,9 +21,6 @@ export class AzuriteContainer extends GenericContainer { .withStartupTimeout(120_000); } - private blobPort: number = BLOB_PORT; - private queuePort: number = QUEUE_PORT; - private tablePort: number = TABLE_PORT; private accountName: string = DEFAULT_ACCOUNT_NAME; private accountKey: string = DEFAULT_ACCOUNT_KEY; @@ -49,33 +46,6 @@ export class AzuriteContainer extends GenericContainer { return this; } - /** - * Sets the port to expose the Blob service on. - * @param port The port to expose the Blob service on. Default is 10000. - */ - public withBlobPort(port: number): this { - this.blobPort = port; - return this; - } - - /** - * Sets the port to expose the Queue service on. - * @param port The port to expose the Queue service on. Default is 10001. - */ - public withQueuePort(port: number): this { - this.queuePort = port; - return this; - } - - /** - * Sets the port to expose the Table service on. - * @param port The port to expose the Table service on. Default is 10002. - */ - public withTablePort(port: number): this { - this.tablePort = port; - return this; - } - /** * Disable persisting any data to disk and only store data in-memory. If the Azurite process is terminated, all data is lost. */ @@ -119,11 +89,7 @@ export class AzuriteContainer extends GenericContainer { command.push("--skipApiVersionCheck"); } - this.withCommand(command).withExposedPorts( - { container: BLOB_PORT, host: this.blobPort }, - { container: QUEUE_PORT, host: this.queuePort }, - { container: TABLE_PORT, host: this.tablePort } - ); + this.withCommand(command).withExposedPorts(BLOB_PORT, QUEUE_PORT, TABLE_PORT); if (this.accountName !== DEFAULT_ACCOUNT_NAME || this.accountKey !== DEFAULT_ACCOUNT_KEY) { this.withEnvironment({ @@ -137,9 +103,6 @@ export class AzuriteContainer extends GenericContainer { startedContainer, this.accountName, this.accountKey, - this.blobPort, - this.queuePort, - this.tablePort ); } } @@ -149,9 +112,6 @@ export class StartedAzuriteContainer extends AbstractStartedContainer { startedTestContainer: StartedTestContainer, private readonly accountName: string, private readonly accountKey: string, - private readonly blobPort: number, - private readonly queuePort: number, - private readonly tablePort: number ) { super(startedTestContainer); } @@ -164,28 +124,28 @@ export class StartedAzuriteContainer extends AbstractStartedContainer { return this.accountKey; } - public getBlobPort(): number { - return this.blobPort; + public getMappedBlobPort(): number { + return this.getMappedPort(BLOB_PORT); } - public getQueuePort(): number { - return this.queuePort; + public getMappedQueuePort(): number { + return this.getMappedPort(QUEUE_PORT); } - public getTablePort(): number { - return this.tablePort; + public getMappedTablePort(): number { + return this.getMappedPort(TABLE_PORT); } public getBlobEndpoint(): string { - return this.getEndpoint(this.blobPort, this.accountName); + return this.getEndpoint(this.getMappedBlobPort(), this.accountName); } public getQueueEndpoint(): string { - return this.getEndpoint(this.queuePort, this.accountName); + return this.getEndpoint(this.getMappedQueuePort(), this.accountName); } public getTableEndpoint(): string { - return this.getEndpoint(this.tablePort, this.accountName); + return this.getEndpoint(this.getMappedTablePort(), this.accountName); } /** From 2c91ad739aa0dbf27f10d413bdb83686e6902cdf Mon Sep 17 00:00:00 2001 From: Daegeon Song Date: Thu, 28 Nov 2024 18:27:55 +0900 Subject: [PATCH 2/7] Fix to cache mapped port --- .../modules/azurite/src/azurite-container.ts | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/modules/azurite/src/azurite-container.ts b/packages/modules/azurite/src/azurite-container.ts index f1922bf42..6b368fe05 100755 --- a/packages/modules/azurite/src/azurite-container.ts +++ b/packages/modules/azurite/src/azurite-container.ts @@ -99,21 +99,24 @@ export class AzuriteContainer extends GenericContainer { const startedContainer = await super.start(); - return new StartedAzuriteContainer( - startedContainer, - this.accountName, - this.accountKey, - ); + return new StartedAzuriteContainer(startedContainer, this.accountName, this.accountKey); } } export class StartedAzuriteContainer extends AbstractStartedContainer { + private readonly blobPort: number; + private readonly queuePort: number; + private readonly tablePort: number; + constructor( startedTestContainer: StartedTestContainer, private readonly accountName: string, - private readonly accountKey: string, + private readonly accountKey: string ) { super(startedTestContainer); + this.blobPort = this.getMappedPort(BLOB_PORT); + this.queuePort = this.getMappedPort(QUEUE_PORT); + this.tablePort = this.getMappedPort(TABLE_PORT); } public getAccountName(): string { @@ -124,28 +127,28 @@ export class StartedAzuriteContainer extends AbstractStartedContainer { return this.accountKey; } - public getMappedBlobPort(): number { - return this.getMappedPort(BLOB_PORT); + public getBlobPort(): number { + return this.blobPort; } - public getMappedQueuePort(): number { - return this.getMappedPort(QUEUE_PORT); + public getQueuePort(): number { + return this.queuePort; } - public getMappedTablePort(): number { - return this.getMappedPort(TABLE_PORT); + public getTablePort(): number { + return this.tablePort; } public getBlobEndpoint(): string { - return this.getEndpoint(this.getMappedBlobPort(), this.accountName); + return this.getEndpoint(this.blobPort, this.accountName); } public getQueueEndpoint(): string { - return this.getEndpoint(this.getMappedQueuePort(), this.accountName); + return this.getEndpoint(this.queuePort, this.accountName); } public getTableEndpoint(): string { - return this.getEndpoint(this.getMappedTablePort(), this.accountName); + return this.getEndpoint(this.tablePort, this.accountName); } /** From 914c096da79e44d07210d0adbe0562d361024370 Mon Sep 17 00:00:00 2001 From: Daegeon Song Date: Fri, 29 Nov 2024 12:47:44 +0900 Subject: [PATCH 3/7] Restore custom ports --- .../azurite/src/azurite-container.test.ts | 28 ++++++++ .../modules/azurite/src/azurite-container.ts | 69 ++++++++++++++++--- 2 files changed, 86 insertions(+), 11 deletions(-) diff --git a/packages/modules/azurite/src/azurite-container.test.ts b/packages/modules/azurite/src/azurite-container.test.ts index b972f4158..a25bae083 100644 --- a/packages/modules/azurite/src/azurite-container.test.ts +++ b/packages/modules/azurite/src/azurite-container.test.ts @@ -113,6 +113,34 @@ describe("Azurite", () => { }); // } + // customPorts { + it("should be able to specify custom ports", async () => { + const blobPort = 13000; + const queuePort = 14000; + const tablePort = 15000; + const container = await new AzuriteContainer() + .withBlobPort(blobPort) + .withQueuePort(queuePort) + .withTablePort(tablePort) + .start(); + + expect(container.getBlobPort()).toBe(blobPort); + expect(container.getQueuePort()).toBe(queuePort); + expect(container.getTablePort()).toBe(tablePort); + + const connectionString = container.getConnectionString(); + expect(connectionString).toContain("13000"); + expect(connectionString).toContain("14000"); + expect(connectionString).toContain("15000"); + + const serviceClient = BlobServiceClient.fromConnectionString(connectionString); + const containerClient = serviceClient.getContainerClient("test"); + await containerClient.createIfNotExists(); + + await container.stop(); + }); + // } + // inMemoryPersistence { it("should be able to use in-memory persistence", async () => { const container = await new AzuriteContainer().withInMemoryPersistence().start(); diff --git a/packages/modules/azurite/src/azurite-container.ts b/packages/modules/azurite/src/azurite-container.ts index 6b368fe05..eb7d2c509 100755 --- a/packages/modules/azurite/src/azurite-container.ts +++ b/packages/modules/azurite/src/azurite-container.ts @@ -1,4 +1,11 @@ -import { AbstractStartedContainer, GenericContainer, StartedTestContainer, Wait } from "testcontainers"; +import { + AbstractStartedContainer, + GenericContainer, + hasHostBinding, + PortWithOptionalBinding, + StartedTestContainer, + Wait, +} from "testcontainers"; const AZURITE_IMAGE = "mcr.microsoft.com/azure-storage/azurite:3.33.0"; const BLOB_PORT = 10000; @@ -21,6 +28,25 @@ export class AzuriteContainer extends GenericContainer { .withStartupTimeout(120_000); } + private blobPort: PortWithOptionalBinding = BLOB_PORT; + private queuePort: PortWithOptionalBinding = QUEUE_PORT; + private tablePort: PortWithOptionalBinding = TABLE_PORT; + + public withBlobPort(blobPort: PortWithOptionalBinding): AzuriteContainer { + this.blobPort = blobPort; + return this; + } + + public withQueuePort(queuePort: PortWithOptionalBinding): AzuriteContainer { + this.queuePort = queuePort; + return this; + } + + public withTablePort(tablePort: PortWithOptionalBinding): AzuriteContainer { + this.tablePort = tablePort; + return this; + } + private accountName: string = DEFAULT_ACCOUNT_NAME; private accountKey: string = DEFAULT_ACCOUNT_KEY; @@ -89,7 +115,7 @@ export class AzuriteContainer extends GenericContainer { command.push("--skipApiVersionCheck"); } - this.withCommand(command).withExposedPorts(BLOB_PORT, QUEUE_PORT, TABLE_PORT); + this.withCommand(command).withExposedPorts(this.blobPort, this.queuePort, this.tablePort); if (this.accountName !== DEFAULT_ACCOUNT_NAME || this.accountKey !== DEFAULT_ACCOUNT_KEY) { this.withEnvironment({ @@ -99,24 +125,45 @@ export class AzuriteContainer extends GenericContainer { const startedContainer = await super.start(); - return new StartedAzuriteContainer(startedContainer, this.accountName, this.accountKey); + return new StartedAzuriteContainer( + startedContainer, + this.accountName, + this.accountKey, + this.blobPort, + this.queuePort, + this.tablePort + ); } } export class StartedAzuriteContainer extends AbstractStartedContainer { - private readonly blobPort: number; - private readonly queuePort: number; - private readonly tablePort: number; - + private blobPort: number; + private queuePort: number; + private tablePort: number; constructor( startedTestContainer: StartedTestContainer, private readonly accountName: string, - private readonly accountKey: string + private readonly accountKey: string, + blobPort: PortWithOptionalBinding, + queuePort: PortWithOptionalBinding, + tablePort: PortWithOptionalBinding ) { super(startedTestContainer); - this.blobPort = this.getMappedPort(BLOB_PORT); - this.queuePort = this.getMappedPort(QUEUE_PORT); - this.tablePort = this.getMappedPort(TABLE_PORT); + if (hasHostBinding(blobPort)) { + this.blobPort = blobPort.host; + } else { + this.blobPort = this.getMappedPort(blobPort); + } + if (hasHostBinding(queuePort)) { + this.queuePort = queuePort.host; + } else { + this.queuePort = this.getMappedPort(queuePort); + } + if (hasHostBinding(tablePort)) { + this.tablePort = tablePort.host; + } else { + this.tablePort = this.getMappedPort(tablePort); + } } public getAccountName(): string { From e7c12ba7ae9a8bcc043b680f41aa9ff46e5e5873 Mon Sep 17 00:00:00 2001 From: Daegeon Song Date: Fri, 29 Nov 2024 12:57:25 +0900 Subject: [PATCH 4/7] Refactor code --- .../modules/azurite/src/azurite-container.ts | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/packages/modules/azurite/src/azurite-container.ts b/packages/modules/azurite/src/azurite-container.ts index eb7d2c509..814f0dfd0 100755 --- a/packages/modules/azurite/src/azurite-container.ts +++ b/packages/modules/azurite/src/azurite-container.ts @@ -32,21 +32,6 @@ export class AzuriteContainer extends GenericContainer { private queuePort: PortWithOptionalBinding = QUEUE_PORT; private tablePort: PortWithOptionalBinding = TABLE_PORT; - public withBlobPort(blobPort: PortWithOptionalBinding): AzuriteContainer { - this.blobPort = blobPort; - return this; - } - - public withQueuePort(queuePort: PortWithOptionalBinding): AzuriteContainer { - this.queuePort = queuePort; - return this; - } - - public withTablePort(tablePort: PortWithOptionalBinding): AzuriteContainer { - this.tablePort = tablePort; - return this; - } - private accountName: string = DEFAULT_ACCOUNT_NAME; private accountKey: string = DEFAULT_ACCOUNT_KEY; @@ -72,6 +57,33 @@ export class AzuriteContainer extends GenericContainer { return this; } + /** + * Sets the port to expose the Blob service on. + * @param port The port to expose the Blob service on. Default is 10000. + */ + public withBlobPort(blobPort: PortWithOptionalBinding): this { + this.blobPort = blobPort; + return this; + } + + /** + * Sets the port to expose the Queue service on. + * @param port The port to expose the Queue service on. Default is 10001. + */ + public withQueuePort(queuePort: PortWithOptionalBinding): this { + this.queuePort = queuePort; + return this; + } + + /** + * Sets the port to expose the Table service on. + * @param port The port to expose the Table service on. Default is 10002. + */ + public withTablePort(tablePort: PortWithOptionalBinding): this { + this.tablePort = tablePort; + return this; + } + /** * Disable persisting any data to disk and only store data in-memory. If the Azurite process is terminated, all data is lost. */ From 97e27de94141f774b119ad15778c03d5a1cf78a4 Mon Sep 17 00:00:00 2001 From: Daegeon Song Date: Fri, 29 Nov 2024 12:58:23 +0900 Subject: [PATCH 5/7] Add missing readonly keywords --- packages/modules/azurite/src/azurite-container.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/modules/azurite/src/azurite-container.ts b/packages/modules/azurite/src/azurite-container.ts index 814f0dfd0..400432e85 100755 --- a/packages/modules/azurite/src/azurite-container.ts +++ b/packages/modules/azurite/src/azurite-container.ts @@ -149,9 +149,9 @@ export class AzuriteContainer extends GenericContainer { } export class StartedAzuriteContainer extends AbstractStartedContainer { - private blobPort: number; - private queuePort: number; - private tablePort: number; + private readonly blobPort: number; + private readonly queuePort: number; + private readonly tablePort: number; constructor( startedTestContainer: StartedTestContainer, private readonly accountName: string, From bb19d4359e4cef1f284d50f4c104a34dd1e51bcc Mon Sep 17 00:00:00 2001 From: Daegeon Song Date: Sun, 1 Dec 2024 14:49:29 +0900 Subject: [PATCH 6/7] Fix azurite-container test errors --- .../modules/azurite/src/azurite-container.test.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/modules/azurite/src/azurite-container.test.ts b/packages/modules/azurite/src/azurite-container.test.ts index a25bae083..445417933 100644 --- a/packages/modules/azurite/src/azurite-container.test.ts +++ b/packages/modules/azurite/src/azurite-container.test.ts @@ -119,9 +119,9 @@ describe("Azurite", () => { const queuePort = 14000; const tablePort = 15000; const container = await new AzuriteContainer() - .withBlobPort(blobPort) - .withQueuePort(queuePort) - .withTablePort(tablePort) + .withBlobPort({ container: 10001, host: blobPort }) + .withQueuePort({ container: 10002, host: queuePort }) + .withTablePort({ container: 10003, host: tablePort }) .start(); expect(container.getBlobPort()).toBe(blobPort); @@ -160,8 +160,13 @@ describe("Azurite", () => { expect(blobExists).toBeTruthy(); await container.restart(); + const connectionString2 = container.getConnectionString(); + expect(connectionString2).toBeTruthy(); + const serviceClient2 = BlobServiceClient.fromConnectionString(connectionString); + const containerClient2 = serviceClient2.getContainerClient("test"); + const blobClient2 = containerClient2.getBlockBlobClient(blobName); - const blobExistsAfterRestart = await blobClient.exists(); + const blobExistsAfterRestart = await blobClient2.exists(); expect(blobExistsAfterRestart).toBeFalsy(); }); // } From 3ec5ac6607159aaf00dcf7ece754392a340c53b8 Mon Sep 17 00:00:00 2001 From: Daegeon Song Date: Sun, 1 Dec 2024 15:05:12 +0900 Subject: [PATCH 7/7] Fix azurite test --- .../azurite/src/azurite-container.test.ts | 44 +++++++++-------- .../modules/azurite/src/azurite-container.ts | 48 ++++++++----------- 2 files changed, 45 insertions(+), 47 deletions(-) diff --git a/packages/modules/azurite/src/azurite-container.test.ts b/packages/modules/azurite/src/azurite-container.test.ts index 445417933..1d118a536 100644 --- a/packages/modules/azurite/src/azurite-container.test.ts +++ b/packages/modules/azurite/src/azurite-container.test.ts @@ -144,30 +144,34 @@ describe("Azurite", () => { // inMemoryPersistence { it("should be able to use in-memory persistence", async () => { const container = await new AzuriteContainer().withInMemoryPersistence().start(); - - const connectionString = container.getConnectionString(); - expect(connectionString).toBeTruthy(); - - const serviceClient = BlobServiceClient.fromConnectionString(connectionString); - const containerClient = serviceClient.getContainerClient("test"); - await containerClient.createIfNotExists(); const blobName = "hello.txt"; - const content = "Hello world!"; - await containerClient.uploadBlockBlob(blobName, content, Buffer.byteLength(content)); - const blobClient = containerClient.getBlockBlobClient(blobName); - const blobExists = await blobClient.exists(); - expect(blobExists).toBeTruthy(); + { + const connectionString = container.getConnectionString(); + expect(connectionString).toBeTruthy(); + + const serviceClient = BlobServiceClient.fromConnectionString(connectionString); + const containerClient = serviceClient.getContainerClient("test"); + await containerClient.createIfNotExists(); + const content = "Hello world!"; + await containerClient.uploadBlockBlob(blobName, content, Buffer.byteLength(content)); + const blobClient = containerClient.getBlockBlobClient(blobName); + const blobExists = await blobClient.exists(); + expect(blobExists).toBeTruthy(); + } await container.restart(); - const connectionString2 = container.getConnectionString(); - expect(connectionString2).toBeTruthy(); - const serviceClient2 = BlobServiceClient.fromConnectionString(connectionString); - const containerClient2 = serviceClient2.getContainerClient("test"); - const blobClient2 = containerClient2.getBlockBlobClient(blobName); - - const blobExistsAfterRestart = await blobClient2.exists(); - expect(blobExistsAfterRestart).toBeFalsy(); + + { + const connectionString = container.getConnectionString(); + expect(connectionString).toBeTruthy(); + + const serviceClient = BlobServiceClient.fromConnectionString(connectionString); + const containerClient = serviceClient.getContainerClient("test"); + const blobClient = containerClient.getBlockBlobClient(blobName); + const blobExistsAfterRestart = await blobClient.exists(); + expect(blobExistsAfterRestart).toBeFalsy(); + } }); // } }); diff --git a/packages/modules/azurite/src/azurite-container.ts b/packages/modules/azurite/src/azurite-container.ts index 400432e85..aae6a0338 100755 --- a/packages/modules/azurite/src/azurite-container.ts +++ b/packages/modules/azurite/src/azurite-container.ts @@ -149,33 +149,15 @@ export class AzuriteContainer extends GenericContainer { } export class StartedAzuriteContainer extends AbstractStartedContainer { - private readonly blobPort: number; - private readonly queuePort: number; - private readonly tablePort: number; constructor( startedTestContainer: StartedTestContainer, private readonly accountName: string, private readonly accountKey: string, - blobPort: PortWithOptionalBinding, - queuePort: PortWithOptionalBinding, - tablePort: PortWithOptionalBinding + private readonly blobPort: PortWithOptionalBinding, + private readonly queuePort: PortWithOptionalBinding, + private readonly tablePort: PortWithOptionalBinding ) { super(startedTestContainer); - if (hasHostBinding(blobPort)) { - this.blobPort = blobPort.host; - } else { - this.blobPort = this.getMappedPort(blobPort); - } - if (hasHostBinding(queuePort)) { - this.queuePort = queuePort.host; - } else { - this.queuePort = this.getMappedPort(queuePort); - } - if (hasHostBinding(tablePort)) { - this.tablePort = tablePort.host; - } else { - this.tablePort = this.getMappedPort(tablePort); - } } public getAccountName(): string { @@ -187,27 +169,39 @@ export class StartedAzuriteContainer extends AbstractStartedContainer { } public getBlobPort(): number { - return this.blobPort; + if (hasHostBinding(this.blobPort)) { + return this.blobPort.host; + } else { + return this.getMappedPort(this.blobPort); + } } public getQueuePort(): number { - return this.queuePort; + if (hasHostBinding(this.queuePort)) { + return this.queuePort.host; + } else { + return this.getMappedPort(this.queuePort); + } } public getTablePort(): number { - return this.tablePort; + if (hasHostBinding(this.tablePort)) { + return this.tablePort.host; + } else { + return this.getMappedPort(this.tablePort); + } } public getBlobEndpoint(): string { - return this.getEndpoint(this.blobPort, this.accountName); + return this.getEndpoint(this.getBlobPort(), this.accountName); } public getQueueEndpoint(): string { - return this.getEndpoint(this.queuePort, this.accountName); + return this.getEndpoint(this.getQueuePort(), this.accountName); } public getTableEndpoint(): string { - return this.getEndpoint(this.tablePort, this.accountName); + return this.getEndpoint(this.getTablePort(), this.accountName); } /**