Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MSSQLServer module #645

Merged
merged 20 commits into from
Jan 15, 2024
Merged

Add MSSQLServer module #645

merged 20 commits into from
Jan 15, 2024

Conversation

wjin17
Copy link
Contributor

@wjin17 wjin17 commented Aug 24, 2023

Add MS Server module

  • acceptLicense
  • select edition
  • connect and query, connection uri, and secure password tests
  • container start
  • update docs

@netlify
Copy link

netlify bot commented Aug 24, 2023

Deploy Preview for testcontainers-node ready!

Name Link
🔨 Latest commit 56e90a1
🔍 Latest deploy log https://app.netlify.com/sites/testcontainers-node/deploys/65a059190ab1c40008773e5e
😎 Deploy Preview https://deploy-preview-645--testcontainers-node.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

private readonly password: string
) {
super(startedTestContainer);
this.port = startedTestContainer.getMappedPort(MSSQL_PORT);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I was writing the redis module (#642), I also oriented on this style from mysql. But when I start testing it by restaring the container, it will fail, because the container gots new ports after restart. So I moved it to the getter function.

}

public getPort(): number {
return this.port;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better use getMappedPort in the getter, to get actual port, also when container was restarted.

 return this.getMappedPort(MSSQL_PORT);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review! I updated the PR to use getMappedPort in the getter and I also removed the wait strategy in the module to so users can define their own.

@wjin17 wjin17 marked this pull request as ready for review August 29, 2023 07:58
Copy link
Member

@eddumelendez eddumelendez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution. I've left some comments. Also, please add more tests where is needed.

packages/modules/mssqlserver/src/mssqlserver-container.ts Outdated Show resolved Hide resolved

type Edition = "Evaluation" | "Developer" | "Express" | "Web" | "Standard" | "Enterprise" | ProductKey;

const PASSWORD_CATEGORY_VALIDATION_PATTERNS = [/[A-Z]+/, /[a-z]+/, /[0-9]+/, /[@$!%*?&]+/];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although, this is similar to what testcontainers-java does, the current approach is to leave it to the service itself. Because, it can change and the container implementation in Testcontainers would fail when it shouldn't

Comment on lines +27 to +30
public withDatabase(database: string): this {
this.database = database;
return this;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, you can not set the database name in MSSQL and due to there is no test covering the case I wonder if that works, nowadays.

Copy link
Contributor Author

@wjin17 wjin17 Aug 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left this in as a convenience method for the generating the connection string should the user want to seed the instance during initialization. I can also add a test/example for seeding the database with SQL files and bash scripts but I was worried about adding too many files/adding things out of scope. Let me know how I should proceed.

private database = "master";
private username = "SA";
private password = "Passw0rd";
private edition: Edition = "Developer";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Developer is the default value for MSSQL_PID, so I don't think it is needed. Also, this can added .withEnvironment({ "MSSQL_PID": "Express }) if required.


const MSSQL_PORT = 1433;

type ProductKey = `${string}-${string}-${string}-${string}-${string}`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Product key comes from the official documentation here:

https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-configure-environment-variables?view=sql-server-ver16#environment-variables

If specifying a product key, it must be in the form of #####-#####-#####-#####-#####, where '#' is a number or a letter.

However, if the edition should be added in by the user using withEnvironment, I can remove all PID/Edition code.

it("should connect and return a query result", async () => {
const container = await new MSSQLServerContainer()
.acceptLicense()
.withWaitStrategy(Wait.forLogMessage(/.*Recovery is complete.*/, 1))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this wait strategy be configured in the module itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left the wait strategy out of the module to allow users to use their own. You can see an example below. I can merge this branch into the PR and update the docs to include this but I wanted to keep the changes to a minimum just in case.

https://github.com/wjin17/testcontainers-node/blob/40385d0af17ef2d9af75165ac99da83c96787470/packages/modules/mssqlserver/src/mssqlserver-container.test.ts#L84

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wjin17 take into account that Testcontainers modules are pre-configured, so, it is totally fair to use the wait strategy in the mssql-server-container.ts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eddumelendez Great point!

I've

  1. Merged the change from SA to sa
  2. Removed password validation
  3. Created a default wait strategy* that can be overwritten
  4. Added tests for password validation using the native MSSql instance and a test using the Express edition with environment variables

I had to allow the wait strategy regex to be overwritten because the Express edition requires a different wait regex before the db can be queried.

Let me know if I should add any more changes.

Thanks again for your review!

@cristianrgreco
Copy link
Collaborator

cristianrgreco commented Nov 23, 2023

Hi @wjin17, thanks for the contribution! The test are failing on my M1 mac with the following:

testcontainers:containers [0dbfd11c6c3f] /opt/mssql/bin/sqlservr: Invalid mapping of address 0x400395b000 in reserved address space below 0x400000000000. Possible causes: +65ms
testcontainers:containers [0dbfd11c6c3f] 1) the process (itself, or via a wrapper) starts-up its own running environment sets the stack size limit to unlimited via syscall setrlimit(2); +0ms
testcontainers:containers [0dbfd11c6c3f] 2) the process (itself, or via a wrapper) adjusts its own execution domain and flag the system its legacy personality via syscall personality(2); +0ms
testcontainers:containers [0dbfd11c6c3f] 3) sysadmin deliberately sets the system to run on legacy VA layout mode by adjusting a sysctl knob vm.legacy_va_layout. +0ms

Could it be an issue with ARM/is a fix possible?

Also looks like the Azure dependencies are incompatible with Node 20 which is LTS, perhaps it's supported with a newer version of the dependency?

@wjin17
Copy link
Contributor Author

wjin17 commented Nov 29, 2023

Hi @wjin17, thanks for the contribution! The test are failing on my M1 mac with the following:

testcontainers:containers [0dbfd11c6c3f] /opt/mssql/bin/sqlservr: Invalid mapping of address 0x400395b000 in reserved address space below 0x400000000000. Possible causes: +65ms
testcontainers:containers [0dbfd11c6c3f] 1) the process (itself, or via a wrapper) starts-up its own running environment sets the stack size limit to unlimited via syscall setrlimit(2); +0ms
testcontainers:containers [0dbfd11c6c3f] 2) the process (itself, or via a wrapper) adjusts its own execution domain and flag the system its legacy personality via syscall personality(2); +0ms
testcontainers:containers [0dbfd11c6c3f] 3) sysadmin deliberately sets the system to run on legacy VA layout mode by adjusting a sysctl knob vm.legacy_va_layout. +0ms

Could it be an issue with ARM/is a fix possible?

Also looks like the Azure dependencies are incompatible with Node 20 which is LTS, perhaps it's supported with a newer version of the dependency?

Hi @cristianrgreco

Unfortunately, I do not have access to an M1 mac but trying to run mssql on M1 macs seems to be a known issue. Here's a link to a fix from the official MSSQL docker repo mssql docker issue #668.

For the Azure dependency, I tried updating to the latest version of node-mssql using Node 20 but it seems like the official library is still using the deprecated Azure module.

Please let me know how to proceed.

@cristianrgreco
Copy link
Collaborator

According to tediousjs/node-mssql#1540, node 20 is now supported, will re-run the build now.

@wjin17
Copy link
Contributor Author

wjin17 commented Jan 11, 2024

According to tediousjs/node-mssql#1540, node 20 is now supported, will re-run the build now.

Awesome! Thank you for the update.

@cristianrgreco cristianrgreco merged commit 0129a82 into testcontainers:main Jan 15, 2024
93 of 94 checks passed
@cristianrgreco
Copy link
Collaborator

Thanks for the contribution @wjin17 !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request minor Backward compatible functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants