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 db2 jdbc module #860

Closed
wants to merge 1 commit into from
Closed

Add db2 jdbc module #860

wants to merge 1 commit into from

Conversation

kiview
Copy link
Member

@kiview kiview commented Sep 8, 2018

Created during the Softwerkskammer Ruhr Hackergarten together with Felix Winkler.

I have some concerns regarding the license issues, similar to Oracle. On the one hand, we to provide an environment variable to accept the license when running the official IBM DB2 image.

The other problem is the JDBC driver. IBM doesn't provide the JAR on Maven Central. A search on Maven Central resulted in finding this Maven Repository: https://artifacts.alfresco.com/nexus/content/repositories/public/

Any good ideas how to proceed from here?

The general implementation works, as well as the JDBC-URL support, however the JDBC-URL support has some vendor specific SQL, so the test fails.

closes #432

@rnorth
Copy link
Member

rnorth commented Sep 9, 2018

Thanks for this! Our database coverage continues to grow!

I've not looked into the licence situation yet, other than your comment above, but I think we mainly just need to divide and conquer the licence issues:

  • Our users' licence position; basically we shouldn't let them accidentally or deliberately circumvent the IBM licence. So:

    • If we automatically pull an image for users, it ought to be an official one, and it looks like this is the case.
    • If that image requires an env var signal to indicate licence acceptance, we should give Testcontainers users a way to confirm that they have accepted the licence on behalf of their organisation, and want this signal to be applied. We have exactly the same situation for the SQL Server module.
    • We shouldn't have a transitive Java dependency on unofficial DB2 drivers (i.e. they should be a 'provided' scope dependency, and let users bring-their-own drivers, which they probably will have anyway if they're using DB2).
  • Secondly, our own licence position with respect to running Testcontainers' own automatic 'self test' suite during our CI pipeline build:

    • Let's check what it means to accept the image licence for our own testing purposes. I'd be happy to accept a reasonable licence on behalf of the Testcontainers project.
    • Also let's check what JDBC drivers we can use. I don't want to be in a situation where we're at risk of 'distributing' drivers wrongly, so they shouldn't be binaries within our repo. Let's think about the third-party repository and see whether they're suitable for us.

@kiview
Copy link
Member Author

kiview commented Sep 9, 2018

If that image requires an env var signal to indicate licence acceptance, we should give Testcontainers users a way to confirm that they have accepted the licence on behalf of their organisation, and want this signal to be applied. We have exactly the same situation for the SQL Server module.

I kind of remembered, we have a similar situation for the other modules. I will implement the license agreement check in a similar fashion.

Here is the license information regarding the official IBM image:

The Dockerfile and associated scripts are licensed under the Apache License 2.0. DB2 Express-C is licensed under the IBM International License Agreement for Non-Warranted Programs. This license for DB2 Express-C can be found online. Note that this license does not permit further distribution.

http://www-03.ibm.com/software/sla/sladb.nsf/displaylis/5DF1EE126832D3F185257DAB0064BEFA?OpenDocument

We shouldn't have a transitive Java dependency on unofficial DB2 drivers (i.e. they should be a 'provided' scope dependency, and let users bring-their-own drivers, which they probably will have anyway if they're using DB2).

We are only using the (unofficial? at least unofficially hosted) JDBC driver for our own integration tests (with testCompile dependency ATM). And I 100% agree, I don't want any binaries in our repo either.

@THD-Thomas-Lang
Copy link

Dear Kevin,
thanks for your reply. For licensing issues i have the mechanism used (i did the mssql integration tests for spring data jdbc with testcontainers) that is suggested from the mssql module (store a plain text file on the ressources root). This works great and is very feasible.
I have found an article to get ibm db2 (community edition) running on docker:
https://vladmihalcea.com/how-to-install-db2-express-c-on-docker-and-set-up-the-jdbc-connection-properties/
I don´t know if this is helpful for you?
Please let me know if i can support you in any way.
Kind regards!
Thomas

@THD-Thomas-Lang
Copy link

Yo. It´s me again, comming up with another idea:
In my test case scenario (for spring data jdbc) it may be imaginable if the user places the vendor´s jdbc driver in a certain directory (ressources for example) and the testcontainers images uses this jar (if this is possible).
Would that be an option to take in count?
So in short:

  • user gets the "official" jdbc driver from IBM (wich requires an IBM account) (other vendors may be the same procedure)
  • user places this jar in a certain fixed directory
  • if the jar is there, the testcontainer image (pulled from docker) starts
  • if the jar is not there, cancel the process

Maybe it would also reasonable to just start the image and the user has to deal with the jdbc driver?
I don´t know if this is possible. I either don´t know if this make sense for you.
But maybe it´s worth a try?
Let me know if i can help somewhere/somehow.

Kind regards
Thomas

@stale
Copy link

stale bot commented Feb 10, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you believe this is a mistake, please reply to this comment to keep it open. If there isn't one already, a PR to fix or at least reproduce the problem in a test case will always help us get back on track to tackle this.

@stale stale bot added the stale label Feb 10, 2019
@kiview
Copy link
Member Author

kiview commented Feb 10, 2019

Let's leave it open.

@rnorth
WDYT about ignoring the tests as default (and therefore on CI), thereby solving the JDBC driver issue. We can add something in the docs to inform users, that this module isn't automatically tested.

I still think there is some value in having this module though, I've talked with different users that very much like to use Testcontainers with DB2 (and I normally recommend them to implement this PR as their own custom container).

@stale stale bot removed the stale label Feb 10, 2019
@sporkisfaster
Copy link

I use the DB2 official image for testing at my firm constantly. I’d love to see this go through.

@sporkisfaster
Copy link

If there is anything I can do to help please point me in the right direction.

@@ -59,6 +59,7 @@
{"jdbc:tc:mariadb:10.2.14://hostname/databasename?TC_INITFUNCTION=org.testcontainers.jdbc.JDBCDriverTest::sampleInitFunction", EnumSet.of(Options.ScriptedSchema)},
{"jdbc:tc:mariadb:10.2.14://hostname/databasename?TC_MY_CNF=somepath/mariadb_conf_override", EnumSet.of(Options.CustomIniFile)},
{"jdbc:tc:clickhouse://hostname/databasename", EnumSet.of(Options.PmdKnownBroken)},
// {"jdbc:tc:db2://hostname/databasename", EnumSet.noneOf(Options.class)}, // Test queries don't work
Copy link
Member Author

Choose a reason for hiding this comment

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

@rnorth Should I leave this commented, or just delete the line?

Copy link
Member

@bsideup bsideup May 13, 2019

Choose a reason for hiding this comment

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

Not sure I understand the reason why it is commented out...

@@ -19,6 +25,7 @@ dependencies {
testCompile 'com.oracle:ojdbc6:12.1.0.1-atlassian-hosted'
testCompile 'com.microsoft.sqlserver:mssql-jdbc:6.1.0.jre8'
testCompile 'ru.yandex.clickhouse:clickhouse-jdbc:0.1.41'
testCompile 'com.ibm.db2.jcc:db2jcc4:10.1'
Copy link
Member Author

Choose a reason for hiding this comment

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

I'll switch this to testRuntime

import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals;


public class SimpleDb2Test {
Copy link
Member Author

Choose a reason for hiding this comment

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

Ignore those tests by default, like Oracle

@kiview
Copy link
Member Author

kiview commented Feb 27, 2019

@rnorth Do you think we can integrate after I've resolved the parts I've commented?

@sporkisfaster Thanks for the offer, I think it's basically finished from an implementation standpoint.

@sporkisfaster
Copy link

Should this point at Developer-C instead of Express or does it matter? As far as I know the Express image is deprecated

@sporkisfaster
Copy link

Any updates on this? Would be super helpful as I’m running into issues with genericcontainer for db2

@scottkurz
Copy link

scottkurz commented Apr 23, 2019

Hi @kiview ..thank you for pointing us here in your comment on an issue (from another repo). I'm interested to understand the status. Is it the case that the issues raised in early comments have been addressed, and now it's just a matter of someone addressing the merge conflicts and completing the PR?

Or, if there are other issues still remaining to work out here, could you please give an update of where we stand when you have a chance?

Thank you.

addEnv("LICENSE", "accept"); // TODO: explicit?
addEnv("DB2INST1_PASSWORD", password);

withCommand("db2start");
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be set in the ctor, rather than here in configure(). Setting it here blocks any users from overriding the command (we had the same issue with the PostgreSQL module)

protected void configure() {
addExposedPort(DB2_PORT);

addEnv("LICENSE", "accept"); // TODO: explicit?
Copy link
Contributor

Choose a reason for hiding this comment

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

perhaps this could be moved to an acceptLicense() method, so that the developer has to explicitly type it out and set it when they construct the container? If it's not set, we can blow up in configure() with a clear error msg indicating that the license needs to accepted via acceptLicense()

Copy link
Member

Choose a reason for hiding this comment

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

There is LicenseAcceptance helper, used by MSSQL and Oracle, should be used here too


try {
waitingConsumer.waitUntil(waitPredicate);
execInContainer("/bin/sh", "-c", "runuser -l db2inst1 -c 'db2 create db tc'");
Copy link
Contributor

Choose a reason for hiding this comment

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

this forces the DB name to always be tc. This ought to be configurable via withDatabaseName(String)


@Override
public String getJdbcUrl() {
return "jdbc:db2://" + getContainerIpAddress() + ":" + getMappedPort(DB2_PORT) + "/tc";
Copy link
Contributor

Choose a reason for hiding this comment

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

same comment here about hard-coding the DB name to tc

@frowe
Copy link

frowe commented Apr 23, 2019

IBM has licensed the IP of the db2 jdbc driver (jcc) to Rocket, and they have made it available in maven central https://search.maven.org/artifact/com.ibm.db2/jcc/11.1.4.4/jar. Like the db server, it is still IPLA license though.

@mp911de
Copy link

mp911de commented Apr 23, 2019

@frowe probably different thread, what about the source jar?

@frowe
Copy link

frowe commented Apr 23, 2019

@frowe probably different thread, what about the source jar?
Since it's IPLA license, there is no source jar published.

@frederikb
Copy link

@kiview / @aguibert: Do you need some more support in order to get this fixed and merged? Is anything else left except for fixing the Codacy/PR Quality Review, review comments and merge conflicts?

@aguibert
Copy link
Contributor

The hard parts (legal and where to get the artifact on MC) seem to be figured out. All that's left now is addressing review comments and such AFAIK.

import java.util.concurrent.TimeoutException;
import java.util.function.Predicate;

public class Db2Container<SELF extends Db2Container<SELF>> extends JdbcDatabaseContainer<SELF> {
Copy link
Member

Choose a reason for hiding this comment

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

No need for self-typing here

Suggested change
public class Db2Container<SELF extends Db2Container<SELF>> extends JdbcDatabaseContainer<SELF> {
public class Db2Container extends JdbcDatabaseContainer<Db2Container> {


@Override
protected void configure() {
addExposedPort(DB2_PORT);
Copy link
Member

Choose a reason for hiding this comment

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

please move every static configuration to the constructor, so that it can be overridden without extending the class



try {
waitingConsumer.waitUntil(waitPredicate);
Copy link
Member

Choose a reason for hiding this comment

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

please configure waitingFor. If you need to run the command after it, you can override containerStarted method instead

@@ -172,7 +172,7 @@ private void parseUrl() {
* @author manikmagar
*/
public interface Patterns {
Pattern URL_MATCHING_PATTERN = Pattern.compile("jdbc:tc:([a-z]+)(:([^:]+))?://([^\\?]+)(\\?.*)?");
Pattern URL_MATCHING_PATTERN = Pattern.compile("jdbc:tc:([a-z]+2?)(:([^:]+))?://([^\\?]+)(\\?.*)?");
Copy link
Member

Choose a reason for hiding this comment

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

just add the digits range to the pattern, this 2? is too specific

@frederikb
Copy link

Should this point at Developer-C instead of Express or does it matter? As far as I know the Express image is deprecated

Unfortunately you need to log-in and accept the license agreement in order to pull the new docker image for Developer-C ( https://hub.docker.com/_/db2-developer-c-edition ). Not sure if that's the default we want to provide. In addition that container image exposes additional configuration options.

Do you have any experience with that image?

On the other hand I do agree that using three year old image does not sound like a long-term solution. Upgrading the Db2Container to the new image in a later step could represent a breaking change for any clients.

@frederikb
Copy link

I've rebased the pull request, cleaned up and incorporated the feedback from the review comments to the best of my understanding and fixed the test. I could create my own pull request with the changes if someone is interested however I do not want to step on anyone's (@kiview in particular) toes.

What do you say, @aguibert @bsideup ?

@aguibert
Copy link
Contributor

aguibert commented May 23, 2019

Since I'm an IBM employee I'm going to fish around a bit internally for a few days to try and get in touch with some DB2 folks and see what Docker image we should be using.

Right now my preference would be going with the more current image (Developer-C image), even if it does mean accepting a license. I think people would just use an in-memory DB like H2 before they would use a 3 year old deprecated version of DB2.

@rnorth
Copy link
Member

rnorth commented May 28, 2019

FWIW I've raised this ticket around the current gap in our docs for new module contributors. I'd like to have a bit of a think about the third point specifically before merging this, but otherwise I'm fine with this new module at an overall level: #1503

@aguibert
Copy link
Contributor

ok, reporting back...

I anticipate a new DB2-C docker image that will not require any docker hub logins is going to be released in the near enough future that it would make sense to hold off on this PR in favor of the future DB2-C image.

@bsideup
Copy link
Member

bsideup commented May 29, 2019

@aguibert thanks a lot for pushing it forward!

It is so great to see a progress here, especially in such a sensitive topic as commercial DBs from giants like IBM :)

If this is not the magic of OSS communities then what is? 😀

@aguibert
Copy link
Contributor

aguibert commented Jul 3, 2019

@bsideup @kiview ok, the new DB2 images are here and they no longer require any sort of docker login!

https://hub.docker.com/r/ibmcom/db2

The doc is also much more clear on how to configure them. The startup time isn't great (4m on my machine), but I spoke with the DB2 team and they are have plans to reduce the startup time in the future.

I'm kicking the tires with this new image w/ Testcontainers now, and will contribute back my findings. Should I contribute my findings to this PR, or open a fresh one?

@frederikb
Copy link

Sounds promising, @aguibert.

Could you perhaps compare the start up times between the two containers? Is the long start up time a regression? Did you start it with the default configuration which creates a database on startup? That could perhaps explain (some) of the differences.

In our custom Db2Container I've set up DB2 to run in some sort of a (unsupported) in-memory setup. In our use case we're destroying the container anyway and therefore don't care about the durability of any data.

Extra configuration:
db2set DB2_DIRECT_IO=OFF
db2set DB2_LOGGER_NON_BUFFERED_IO=OFF

Setting up the tmpfs:
withTmpFs(Collections.singletonMap("/home/db2inst1/tmpfs", "rw"));

Creating the database:
db2inst1 -c 'db2 create db " + getDatabaseName() + " on /home/db2inst1/tmpfs'

@aguibert
Copy link
Contributor

aguibert commented Jul 8, 2019

@frederikb thanks for the suggestions. I didn't do a detailed comparison, but here is a rough breakdown of the start time activities on my machine:

  • Configuring DB2 instances (20-30s)
  • Configuring DB2 instances (second pass?) not sure why we go through this twice (20-30s)
  • Starting text search service (15s)
  • Creating DB (50s)
  • CIE00001 Operation completed successfully. (16s)

I'll inquire on the "configuring instances" second pass, as well as the text search service, which perhaps can be disabled with an extra switch. However, this biggest time sink was creating the DB itself (50s) and I doubt that can be sped up further, but I will check.

@irinadel
Copy link

I put an update to the container here - https://hub.docker.com/r/ibmcom/db2 to address some of the concerns with the start up time. There is more to be done, so subsequently we will continue making updates.
With this latest update, you should set the following env variables to increase speed up:
ARCHIVE_LOGS=false - It will not set up transaction log archiving, which forces us to create a backup and restart the database
AUTOCONFIG=false - It will not invoke auto-tuning, which requires a database restart
and TEXT_SEARCH=false is by default, so you will not get the secondary instance update, which by Andrew's approximations takes up another 20-30sec.
Create database will take longest in this round, which is something that will be addressed later on. So stay tuned for updates.

@frederikb
Copy link

Thanks, @irinadel!
On my machine and setup this reduced start up time from 159 seconds down to 103 seconds. That definitely helps! I'm looking forward to any other improvements you can make.

I'm still seeing something in the setup_db2_instance.sh script which looks like a bug:

if [[ $1 = "db2start" ]]; then
    su - ${instance_name?} -c "db2start"
fi

I'm pretty sure that ${instance_name?} is meant to be ${DB2INSTANCE?}. Otherwise you get the following error on startup:
/var/db2_setup/lib/setup_db2_instance.sh: line 193: instance_name: parameter null or not set

Workaround: Set the environment variable instance_name to db2inst1.

@irinadel
Copy link

@frederikb that piece of code path you showed never executes, so never mind it, its legacy, ill remove it on the next iteration
Don't use db2start as a parameter to the docker run.
Example command to start up the container in faster mode is:

docker run -itd -e AUTOCONFIG=false -e ARCHIVE_LOGS=false -e DBNAME=test -e LICENSE=accept -e DB2INST1_PASSWORD=password -v /database:/database -p 50000 --privileged=true ibmcom/db2

@frederikb
Copy link

@irinadel you're absolutely right. That was a leftover from our previous integration of the db2express-c image.

@aguibert aguibert mentioned this pull request Jul 13, 2019
@aguibert
Copy link
Contributor

@kiview @bsideup I opened a new PR (#1611) for the a DB2 module with the new DB2 image. Can one of you please review it?

Sorry for the separate PR, but when I tried to do a PR from aguibert:db2 --> testcontainers:db2 it dragged in a bunch of other commits since I had rebased with testcontainers:master and the testcontainers:db2 branch was pretty old.

@kiview
Copy link
Member Author

kiview commented Jul 15, 2019

@aguibert
Thanks, that's perfect. I'll close this PR, let's continue in #1611.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add specialized container support for DB2