wimdeblauwe / testcontainers-cypress

Testcontainers module for running Cypress tests
Apache License 2.0
64 stars 18 forks source link

Allow more overrides to make docker out of docker support work more transparently #25

Open slyoldfox opened 3 years ago

slyoldfox commented 3 years ago

Your setup is working perfectly fine when used in a normal environment when mvn is not containerized.

However, when running maven from a container, there are several parts where the code fails. I have put together a test project where I have made most of the things working. Some hacks are included, because most of your code has private fields and private functions.

I am raising this issue to:

DockerInDockerSupportingCypressContainer from the demo project below fixes several things:

  1. configure() has been overriden (unfortunately completely) because withClasspathResourceMapping will not be bound correctly when using docker out of docker. CypressContainer would mount the path location form the maven container. Which of course doesn't exist on the host.
  2. configure() sets the cypress base url to the IP of the maven container + the random port assigned by spring boot
  3. configure() had to fetch buildEntryPoint with reflection. It might be nice to make it protected, in case some people what to append their own flags to cypress run. Same goes for buildCypressRunArguments() getReportsPathInContainer() and gatherTestResultsStrategy field
  4. with the modified configure() it is not possible to use .withAutoCleanReports(true) - I have not looked into it in detail. But since the bind mount resides at another location (the host path, not the container path), it doesn't find it at the moment.
  5. After the CypressContainer is started - it needs to be connected to the mavenContainer network. This is happening in overriden doStart()

You can fetch the demo project from: testcontainers-cypress-fixed.zip

You can replicate the issue with: docker-compose up maven

I hope you find some time to incorporate some changes to make this easier in a future release.

wimdeblauwe commented 3 years ago

We are also running Maven in Docker and testcontainers-cypress works fine. Are you passing -v /var/run/docker.sock:/var/run/docker.sock ?

This is part of our Jenkins configuration:

            agent {
                docker {
                    label 'docker'
                    image 'maven:3.6.3-jdk-11'
                    args '-v /var/run/docker.sock:/var/run/docker.sock'
                }
            }
            stages {
                stage('Build') {
                    steps {
                        configFileProvider([configFile(fileId: 'mvn-settings-artifactory', variable: 'MAVEN_SETTINGS_XML')]) {
                            sh 'mvn -B -s "$MAVEN_SETTINGS_XML" clean verify -Pci'
                        }
            ...
slyoldfox commented 3 years ago

Yah we do, it is in the docker-compose.yml inside the demo project also:

version: "2.1"
services:
  maven:
    image: 'maven:3.6.2-jdk-11'
    working_dir: '/usr/src/app'
    command: 'mvn clean verify'
    volumes:
      - '${PWD}:/usr/src/app:delegated'
      - '${HOME}/.m2:/root/.m2:delegated'
      - '/var/run/docker.sock:/var/run/docker.sock'

I'm not exactly sure how jenkins or your environment resolve this correctly then (unless I am missing something from my side), or maybe by accident paths from your container and host are the same by chance?

When I start the demo project with docker-compose up maven. You would get a maven container and a cypress container. By the time we reach withClasspathResourceMapping(classpathResourcePath, "/e2e", BindMode.READ_WRITE); in configure() the value of classpathResourcePath is /usr/src/app/target/test-classes/e2e

Our working dir this inside the maven container is indeed /usr/src/app so this is accurate. However when this is supplied as the mount dir for cypress, this would bind mount /usr/src/app/target/test-classes/e2e (the path from the container, not the host) inside /e2e of the cypress container.

When running without a maven container, this is the output of the cypress container for Mounts:

        "Mounts": [
            {
                "Type": "bind",
                "Source": "/Users/username/Desktop/testcontainers-cypress/target/test-classes/e2e",
                "Destination": "/e2e",
                "Mode": "rw",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

When running with the maven container, this is the output:

        "Mounts": [
            {
                "Type": "bind",
                "Source": "/usr/src/app/target/test-classes/e2e",
                "Destination": "/e2e",
                "Mode": "rw",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

Not sure if this might different between OS' or testcontainer versions (now using 1.14.3), could you verify the demo project to see if it works as expected at your side?