From 9d5e3daf122f9d91980e7f35e2ffdfed78dea717 Mon Sep 17 00:00:00 2001 From: Matt Bowersox Date: Wed, 13 Sep 2023 14:41:57 -0500 Subject: [PATCH 1/7] Update libertyDev task and docs for Podman --- .github/workflows/gradle.yml | 8 +- docs/libertyDev.md | 76 ++++++---- .../gradle/extensions/DevExtension.groovy | 11 +- .../tools/gradle/tasks/DevTask.groovy | 138 +++++++++++------- .../tools/gradle/BaseDevTest.groovy | 13 +- .../tools/gradle/DevContainerTest.groovy | 63 ++++++++ .../dev-test/dev-container/Containerfile | 33 +++++ .../dev-test/dev-container/build.gradle | 44 ++++++ .../dev-test/dev-container/settings.gradle | 1 + .../guides/rest/PropertiesResource.java | 43 ++++++ .../guides/rest/SystemApplication.java | 21 +++ .../src/main/liberty/config/server.xml | 16 ++ .../src/main/webapp/WEB-INF/web.xml | 10 ++ .../dev-container/src/main/webapp/index.html | 41 ++++++ .../openliberty/guides/rest/EndpointIT.java | 49 +++++++ 15 files changed, 481 insertions(+), 86 deletions(-) create mode 100644 src/test/groovy/io/openliberty/tools/gradle/DevContainerTest.groovy create mode 100644 src/test/resources/dev-test/dev-container/Containerfile create mode 100644 src/test/resources/dev-test/dev-container/build.gradle create mode 100644 src/test/resources/dev-test/dev-container/settings.gradle create mode 100644 src/test/resources/dev-test/dev-container/src/main/java/io/openliberty/guides/rest/PropertiesResource.java create mode 100644 src/test/resources/dev-test/dev-container/src/main/java/io/openliberty/guides/rest/SystemApplication.java create mode 100644 src/test/resources/dev-test/dev-container/src/main/liberty/config/server.xml create mode 100644 src/test/resources/dev-test/dev-container/src/main/webapp/WEB-INF/web.xml create mode 100644 src/test/resources/dev-test/dev-container/src/main/webapp/index.html create mode 100644 src/test/resources/dev-test/dev-container/src/test/java/it/io/openliberty/guides/rest/EndpointIT.java diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 86a805d9c..c4726deb8 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -27,6 +27,12 @@ jobs: RUNTIME_VERSION: 23.0.0.3 name: ${{ matrix.RUNTIME }} ${{ matrix.RUNTIME_VERSION }}, Java ${{ matrix.java }}, Linux steps: + - name: Setup Podman + run: | + sudo apt update + sudo apt-get -y install podman + sudo podman machine init --rootful=true + sudo podman machine start # Checkout repos - name: Checkout ci.gradle uses: actions/checkout@v3 @@ -149,7 +155,7 @@ jobs: - name: Run tests with Gradle on Windows working-directory: C:/ci.gradle # LibertyTest is excluded because test0_run hangs - run: ./gradlew clean install check -P"test.exclude"="**/Polling*,**/LibertyTest*,**/GenerateFeaturesTest*" -Druntime=${{ matrix.RUNTIME }} -DruntimeVersion="${{ matrix.RUNTIME_VERSION }}" --stacktrace --info --no-daemon + run: ./gradlew clean install check -P"test.exclude"="**/Polling*,**/LibertyTest*,**/GenerateFeaturesTest*,**/DevContainerTest*" -Druntime=${{ matrix.RUNTIME }} -DruntimeVersion="${{ matrix.RUNTIME_VERSION }}" --stacktrace --info --no-daemon timeout-minutes: 75 # Copy build reports and upload artifact if build failed - name: Copy build/report/tests/test for upload diff --git a/docs/libertyDev.md b/docs/libertyDev.md index b6756c0c6..675778bcd 100644 --- a/docs/libertyDev.md +++ b/docs/libertyDev.md @@ -109,7 +109,7 @@ test { ## libertyDevc Task, Container Mode -Start a Liberty server in a local container using the Dockerfile that you provide. An alternative to the `libertyDevc` task is to specify the `libertyDev` task with the `--container` option. +Start a Liberty server in a local container using the Containerfile/Dockerfile that you provide. An alternative to the `libertyDevc` task is to specify the `libertyDev` task with the `--container` option. When dev mode runs with container support, it builds a container image and runs the container. You can examine the commands that it uses to build and run the container by viewing the console output of dev mode. Additionally, it still provides the same features as the `libertyDev` task. It monitors files for changes and runs tests either automatically or on demand. This mode also allows you to attach a debugger to work on your application. You can review the logs generated by your server in the Liberty directory in your project e.g. build/wlp/usr/servers/defaultServer/logs. @@ -117,30 +117,30 @@ When dev mode runs with container support, it builds a container image and runs This task requires applications to be installed as loose applications. Information on configuring loose applications can be found in the [deploy task parameter documentation](deploy.md#Parameters) and the [Liberty server configuration](libertyExtensions.md#liberty-server-configuration). -N.B. starting in 3.4.1, dev mode invokes `generate-features` if the `generateFeatures` configuration parameter is set to true. Ensure that the `generated-features.xml` configuration file is copied to your Docker image via your Dockerfile. +N.B. starting in 3.4.1, dev mode invokes `generate-features` if the `generateFeatures` configuration parameter is set to true. Ensure that the `generated-features.xml` configuration file is copied to your container image via your Containerfile/Dockerfile. ```dockerfile COPY --chown=1001:0 build/wlp/usr/servers/defaultServer/configDropins/overrides/generated-features.xml /config/configDropins/overrides/ ``` -If on Linux, it is recommended that you copy the entire `configDropins/overrides` directory to your Docker image via your Dockerfile. +If on Linux, it is recommended that you copy the entire `configDropins/overrides` directory to your container image via your Containerfile/Dockerfile. ```dockerfile COPY --chown=1001:0 build/wlp/usr/servers/defaultServer/configDropins/overrides /config/configDropins/overrides ``` ### Prerequisites -You need to install the Docker runtime locally (Docker Desktop on macOS or Windows, or Docker on Linux) to use this Gradle task. The installed Docker Client and Engine versions must be 18.03.0 or higher. +You need to install Podman or the Docker runtime (Docker Desktop on macOS or Windows, or Docker on Linux) locally to use this Gradle task. If using Podman, version 4.4.4 or higher is required. If using Docker, the installed Docker Client and Engine versions must be 18.03.0 or higher. -### Dockerfile +### Containerfile and Dockerfile -Your project must have a Dockerfile to use dev mode in container mode. A sample Dockerfile is shown in [Building an application image](https://github.com/openliberty/ci.docker/#building-an-application-image). The parent image must be one of the [Open Liberty container images](https://github.com/openliberty/ci.docker/#container-images), or an image using Linux with Open Liberty configured with the same paths as the Open Liberty container images. The Dockerfile must copy the application .war file and the server configuration files that the application requires into the container. +Your project must have a Containerfile or Dockerfile to use dev mode in container mode. A sample Dockerfile is shown in [Building an application image](https://github.com/openliberty/ci.docker/#building-an-application-image). The parent image must be one of the [Open Liberty container images](https://github.com/openliberty/ci.docker/#container-images), or an image using Linux with Open Liberty configured with the same paths as the Open Liberty container images. The Containerfile/Dockerfile must copy the application .war file and the server configuration files that the application requires into the container. -Dev mode works with a temporary, modified copy of your Dockerfile to allow for hot deployment during development. When dev mode starts up, it pulls the latest version of the parent image defined in the Dockerfile, builds the container image, then runs the container. Note that the context of the `docker build` command used to generate the container image is the directory containing the Dockerfile, unless the `dockerBuildContext` parameter is specified. When dev mode exits, the container is stopped and deleted, and the logs are preserved in the directory mentioned above. +Dev mode works with a temporary, modified copy of your Containerfile/Dockerfile to allow for hot deployment during development. When dev mode starts up, it pulls the latest version of the parent image defined in the Containerfile/Dockerfile, builds the container image, then runs the container. Note that the context of the container `build` command used to generate the container image is the directory containing the Containerfile/Dockerfile, unless the `containerBuildContext` parameter is specified. When dev mode exits, the container is stopped and deleted, and the logs are preserved in the directory mentioned above. -Hot deployment is made possible because the application is installed as a loose application WAR. This method uses a file type of `.war.xml` which is functionally equivalent to the `.war` file. Dev mode only supports the application under development in the current project so to avoid application conflicts, dev mode removes all Dockerfile commands that copy or add a `.war` file. +Hot deployment is made possible because the application is installed as a loose application WAR. This method uses a file type of `.war.xml` which is functionally equivalent to the `.war` file. Dev mode only supports the application under development in the current project so to avoid application conflicts, dev mode removes all Containerfile/Dockerfile commands that copy or add a `.war` file. -The `.war.xml` file is generated in the `defaultServer/apps` or the `defaultServer/dropins` directory so these directories are mounted in the container. Therefore any files that the Dockerfile may have copied into these directories in the container image will not be accessible. +The `.war.xml` file is generated in the `defaultServer/apps` or the `defaultServer/dropins` directory so these directories are mounted in the container. Therefore any files that the Containerfile/Dockerfile may have copied into these directories in the container image will not be accessible. -There are other features of the Dockerfile which are not supported for hot deployment of changes. See the section on [File Tracking](#File-Tracking) for details. +There are other features of the Containerfile/Dockerfile which are not supported for hot deployment of changes. See the section on [File Tracking](#File-Tracking) for details. Finally, if dev mode detects the Liberty command `RUN configure.sh` it will insert the environment variable command `ENV OPENJ9_SCC=false` in order to skip the configuration of the [shared class cache](https://github.com/OpenLiberty/ci.docker/#openj9-shared-class-cache-scc). @@ -149,14 +149,14 @@ Finally, if dev mode detects the Liberty command `RUN configure.sh` it will inse Dev mode offers different levels of file tracking and deployment depending on the way the file is specified in the Dockerfile. 1. When you use the COPY command on an individual file, dev mode can track file changes and hot deploy them to the container subject to the limitations below. **This is the recommended way to deploy files for dev mode,** so that you can make changes to those files at any time without needing to rebuild the image or restart the container. - E.g. `COPY build/wlp/usr/servers/defaultServer/server.xml /config/` - - Note that the Dockerfile must copy only one `.war` file for the application. See the section on [Dockerfiles](#Dockerfile) for details. + - Note that the Containerfile/Dockerfile must copy only one `.war` file for the application. See the section on [Dockerfiles](#Dockerfile) for details. 2. You can use the COPY command to deploy an entire directory and its sub-directories. In this case, dev mode will detect file changes and automatically rebuild the image and restart the container upon changes. 3. The ADD command can be used on individual files, including tar files, as well as on directories. Again, dev mode will rebuild the image and restart the container when it detects file changes. -4. Certain Dockerfile features are not supported by dev mode. In these cases, the files specified are not tracked. If you change these files, you must rebuild the image and restart the container manually. **Type r and press Enter to rebuild the image and restart the container.** +4. Certain Containerfile/Dockerfile features are not supported by dev mode. In these cases, the files specified are not tracked. If you change these files, you must rebuild the image and restart the container manually. **Type r and press Enter to rebuild the image and restart the container.** - variable substitution used in the COPY or ADD command e.g. `$PROJECT/config` - wildcards used in the COPY or ADD command e.g. `build/wlp/usr/servers/defaultServer/configDropins/*` - paths relative to WORKDIR e.g. `WORKDIR /other/project` followed by `COPY test.txt relativeDir/` - - files copied from a different part of a multistage Docker build e.g. `COPY --from=` + - files copied from a different part of a multistage Podman or Docker build e.g. `COPY --from=` ### Console Actions @@ -165,7 +165,7 @@ While dev mode is running in container mode, perform the following in the comman * g - To toggle the automatic generation of features, type g and press Enter. A new server configuration file will be generated in the SOURCE configDropins/overrides configuration directory. * o - To optimize the list of generated features, type o and press Enter. A new server configuration file will be generated in the SOURCE configDropins/overrides configuration directory. * Enter - To run tests on demand, press Enter. -* r - To rebuild the Docker image and restart the container, type r and press Enter. +* r - To rebuild the container image and restart the container, type r and press Enter. * h - To see the help menu for available actions, type h and press Enter. * q - stop the server and quit dev mode, press Ctrl-C, or type q and press Enter. @@ -176,9 +176,25 @@ The following limitations apply to Linux: * In dev mode, the Open Liberty server runs in the container on the UID (user identifier) of the current user. This is so that the server can access the configuration files from your project and you can access the Open Liberty log files. Outside of dev mode, the Open Liberty server will run on the UID specified in the Docker image. * Use of editors like `vim`: when you edit a configuration file with `vim` it will delete the file and rewrite it when you save. This necessitates a container restart. To avoid the restart edit your .vimrc file and add the line `set backupcopy=yes` +### Podman Troubleshooting +Podman VMs may need to be configured to run in rootful mode depending on how permissions are used in the container. This can be done with the following commands: +``` +podman machine stop +podman machine set --rootful=true +podman machine start +``` + +If permissions issues continue with Podman the machine may need to be reinitialized. This can be done as follows: +``` +podman machine stop +podman machine +podman machine init --rootful=true +podman machine start +``` + ### Examples -Start dev mode with the server in a container using the Dockerfile in the project root. +Start dev mode with the server in a container using the Containerfile or Dockerfile in the project root. ``` $ gradle libertyDevc ``` @@ -188,8 +204,8 @@ Customizing the container configuration using `dev` extension properties in `bui liberty { dev { container = true - dockerRunOpts = '-e key=value' - dockerfile = file('myDockerfile') + containerRunOpts = '-e key=value' + containerfile = file('myDockerfile') } } ``` @@ -205,19 +221,19 @@ The container ports and mapped local ports will be displayed when dev mode start If you use the default ports and you run multiple instances of dev mode in container mode, the containers will use different local port mappings to avoid errors. The first instance will use the local ports 9080 and 9443, the second instance will use 9081 and 9444, and so on. -To publish additional ports, add them to the `dockerRunOpts` parameter either in `build.gradle` or on the `gradle` command line. For example: +To publish additional ports, add them to the `containerRunOpts` parameter either in `build.gradle` or on the `gradle` command line. For example: ``` ---dockerRunOpts="-p 8000:8000" +--containerRunOpts="-p 8000:8000" ``` -To map the container ports to specific local ports that are not the default, use the `skipDefaultPorts` parameter and specify Docker port mappings using the `dockerRunOpts` parameter: +To map the container ports to specific local ports that are not the default, use the `skipDefaultPorts` parameter and specify container port mappings using the `containerRunOpts` parameter: ``` ---skipDefaultPorts --dockerRunOpts="-p 10000:9080 -p 10001:9443" +--skipDefaultPorts --containerRunOpts="-p 10000:9080 -p 10001:9443" ``` -Alternatively, you can have Docker map random ephemeral local ports to the exposed container ports as follows. +Alternatively, you can have Container map random ephemeral local ports to the exposed container ports as follows. ``` ---skipDefaultPorts --dockerRunOpts="-P" +--skipDefaultPorts --containerRunOpts="-P" ``` Note that you do not need to specify an alternative for the debug port. Dev mode will automatically find an open local port to map the container debug port to. @@ -230,10 +246,10 @@ These can also be specified as command line parameters in addition to the ones i | Attribute | Type | Since | Description | Required | | --------- | ----- | ----- | ----------- | -------- | -| container | boolean | 3.1-M1 | If set to `true`, run the server in the container specified by the `dockerfile` parameter. Setting this to `true` and using the `libertyDev` task is equivalent to using the `libertyDevc` task. The default value is `false` when the `libertyDev` task is used, and `true` when the `libertyDevc` task is used. | No | -| dockerRunOpts | String | 3.1-M1 | Specifies options to add to the `docker run` command when using dev mode to launch your server in a container. For example, `-e key=value` is recognized by `docker run` to define an environment variable with the name `key` and value `value`. | No | -| dockerfile | File | 3.1-M1 | Location of a Dockerfile to be used by dev mode to build the Docker image for the container that will run your Liberty server. The default location is `Dockerfile` in the project root. | No | -| dockerBuildContext | File | 3.1.3 | The Docker build context directory to be used by dev mode for the `docker build` command. The default location is the directory of the Dockerfile. | No | -| dockerBuildTimeout | integer | 3.1-M3 | Maximum time to wait (in seconds) for the completion of the Docker operation to build the image. The value must be an integer greater than 0. The default value is `600` seconds. | No | -| skipDefaultPorts | boolean | 3.1-M3 | If set to `true`, dev mode will not publish the default Docker port mappings of `9080:9080` (HTTP) and `9443:9443` (HTTPS). Use this option if you would like to specify alternative local ports to map to the exposed container ports for HTTP and HTTPS using the `dockerRunOpts` parameter. | No | -| keepTempDockerfile | boolean | 3.1 | If set to `true`, dev mode will not delete the temporary modified copy of your Dockerfile used to build the Docker image. This file is handy in case you need to debug the process of building the Docker image. The path of the temporary Dockerfile can be seen when dev mode displays the `docker build` command. The default value is `false`.| No | +| container | boolean | 3.1-M1 | If set to `true`, run the server in the container specified by the `containerfile` parameter. Setting this to `true` and using the `libertyDev` task is equivalent to using the `libertyDevc` task. The default value is `false` when the `libertyDev` task is used, and `true` when the `libertyDevc` task is used. | No | +| containerRunOpts | String | 3.1-M1 | Specifies options to add to the container `run` command when using dev mode to launch your server in a container. For example, `-e key=value` is recognized by `docker run` to define an environment variable with the name `key` and value `value`. | No | +| containerfile | File | 3.1-M1 | Location of a Containerfile or Dockerfile to be used by dev mode to build the image for the container that will run your Liberty server. The default location is `Containerfile` or `Dockerfile` in the project root. | No | +| cotnainerBuildContext | File | 3.1.3 | The container build context directory to be used by dev mode for the container `build` command. The default location is the directory of the Containerfile/Dockerfile. | No | +| containerBuildTimeout | integer | 3.1-M3 | Maximum time to wait (in seconds) for the completion of the container operation to build the image. The value must be an integer greater than 0. The default value is `600` seconds. | No | +| skipDefaultPorts | boolean | 3.1-M3 | If set to `true`, dev mode will not publish the default container port mappings of `9080:9080` (HTTP) and `9443:9443` (HTTPS). Use this option if you would like to specify alternative local ports to map to the exposed container ports for HTTP and HTTPS using the `containerRunOpts` parameter. | No | +| keepTempContainerfile | boolean | 3.1 | If set to `true`, dev mode will not delete the temporary modified copy of your Containerfile/Dockerfile used to build the container image. This file is handy in case you need to debug the process of building the container image. The path of the temporary Containerfile/Dockerfile can be seen when dev mode displays the container `build` command. The default value is `false`.| No | diff --git a/src/main/groovy/io/openliberty/tools/gradle/extensions/DevExtension.groovy b/src/main/groovy/io/openliberty/tools/gradle/extensions/DevExtension.groovy index c3b89c4d8..f84a6d776 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/extensions/DevExtension.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/extensions/DevExtension.groovy @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2020. + * (C) Copyright IBM Corporation 2020, 2023. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,10 +18,17 @@ package io.openliberty.tools.gradle.extensions class DevExtension { boolean container = false + File containerfile + File containerBuildContext + String containerRunOpts + int containerBuildTimeout + boolean skipDefaultPorts = false + boolean keepTempContainerfile = false + + //Docker aliases to maintain backwards compatability File dockerfile File dockerBuildContext String dockerRunOpts int dockerBuildTimeout - boolean skipDefaultPorts = false boolean keepTempDockerfile = false } \ No newline at end of file diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy index 37b22cc67..a63059a17 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy @@ -85,7 +85,7 @@ class DevTask extends AbstractFeatureTask { private static final boolean DEFAULT_POLLING_TEST = false; private static final boolean DEFAULT_CONTAINER = false; private static final boolean DEFAULT_SKIP_DEFAULT_PORTS = false; - private static final boolean DEFAULT_KEEP_TEMP_DOCKERFILE = false; + private static final boolean DEFAULT_KEEP_TEMP_CONTAINERFILE = false; private static final boolean DEFAULT_GENERATE_FEATURES = false; private static final boolean DEFAULT_SKIP_INSTALL_FEATURE = false; @@ -184,7 +184,7 @@ class DevTask extends AbstractFeatureTask { @Input private Boolean container = null; - @Option(option = 'container', description = 'Run the server in a Docker container instead of locally. The default value is false for the libertyDev task, and true for the libertyDevc task.') + @Option(option = 'container', description = 'Run the server in a container instead of locally. The default value is false for the libertyDev task, and true for the libertyDevc task.') void setContainer(boolean container) { this.container = container; project.liberty.dev.container = container; // Needed in DeployTask and AbstractServerTask @@ -194,23 +194,41 @@ class DevTask extends AbstractFeatureTask { return container; } + private File containerfile; + + @Option(option = 'containerfile', description = 'Dev mode will build a container image from the provided Containerfile/Dockerfile and start a container from the new image.') + void setContainerfile(String containerfile) { + if (containerfile != null) { + // ensures the containerfile is defined with the full path - matches how maven behaves + this.containerfile = convertParameterToCanonicalFile(containerfile, "containerfile"); + } + } + private File dockerfile; - @Option(option = 'dockerfile', description = 'Dev mode will build a docker image from the provided Dockerfile and start a container from the new image.') + @Option(option = 'dockerfile', description = 'Alias for containerfile') void setDockerfile(String dockerfile) { - if (dockerfile != null) { - // ensures the dockerfile is defined with the full path - matches how maven behaves - this.dockerfile = convertParameterToCanonicalFile(dockerfile, "dockerfile"); + if (dockerfile != null && containerfile == null) { + setContainerFile(dockerfile) + } + } + + private File containerBuildContext; + + @Option(option = 'containerBuildContext', description = 'The container build context used when building the container in dev mode. Defaults to the directory of the Containerfile/Dockerfile if not specified.') + void setContainerBuildContext(String containerBuildContext) { + if (containerBuildContext != null) { + // ensures the containerBuildContext is defined with the full path - matches how maven behaves + this.containerBuildContext = convertParameterToCanonicalFile(containerBuildContext, "containerBuildContext"); } } private File dockerBuildContext; - @Option(option = 'dockerBuildContext', description = 'The Docker build context used when building the container in dev mode. Defaults to the directory of the Dockerfile if not specified.') + @Option(option = 'dockerBuildContext', description = 'Alias for containerBuildContext') void setDockerBuildContext(String dockerBuildContext) { - if (dockerBuildContext != null) { - // ensures the dockerBuildContext is defined with the full path - matches how maven behaves - this.dockerBuildContext = convertParameterToCanonicalFile(dockerBuildContext, "dockerBuildContext"); + if (dockerBuildContext != null && containerBuildContext == null) { + setContainerBuildContext(dockerBuildContext) } } @@ -231,37 +249,57 @@ class DevTask extends AbstractFeatureTask { return result; } - private String dockerRunOpts; + private String containerRunOpts; - @Option(option = 'dockerRunOpts', description = 'Additional options for the docker run command when dev mode starts a container.') + @Option(option = 'containerRunOpts', description = 'Additional options for the container run command when dev mode starts a container.') + void setContainerRunOpts(String containerRunOpts) { + this.containerRunOpts = containerRunOpts; + } + + private String dockerRunOpts; + @Option(option = 'dockerRunOpts', description = 'Alias for containerRunOpts') void setDockerRunOpts(String dockerRunOpts) { - this.dockerRunOpts = dockerRunOpts; + if (containerRunOpts == null) { + setContainerRunOpts(dockerRunOpts) + } } - private int dockerBuildTimeout; + private int containerBuildTimeout; - @Option(option = 'dockerBuildTimeout', description = 'Specifies the amount of time to wait (in seconds) for the completion of the Docker operation to build the image.') - void setDockerBuildTimeout(String inputValue) { + @Option(option = 'containerBuildTimeout', description = 'Specifies the amount of time to wait (in seconds) for the completion of the container operation to build the image.') + void setContainerBuildTimeout(String inputValue) { try { - this.dockerBuildTimeout = Integer.valueOf(inputValue); + this.containerBuildTimeout = Integer.valueOf(inputValue); } catch (NumberFormatException e) { - logger.error(String.format("Unexpected value: %s for dev mode option dockerBuildTimeout. dockerBuildTimeout should be a valid integer.", inputValue)); + logger.error(String.format("Unexpected value: %s for dev mode option containerBuildTimeout. containerBuildTimeout should be a valid integer.", inputValue)); throw e; } } + private int dockerBuildTimeout; + @Option(option = 'dockerBuildTimeout', description = 'Alias for containerBuildTimeout') + void setDockerBuildTimeout(String inputValue) { + setContainerBuildTimeout(inputValue) + } + private Boolean skipDefaultPorts; - @Option(option = 'skipDefaultPorts', description = 'If true, the default Docker port mappings are skipped in the docker run command.') + @Option(option = 'skipDefaultPorts', description = 'If true, the default container port mappings are skipped in the container run command.') void setSkipDefaultPorts(boolean skipDefaultPorts) { this.skipDefaultPorts = skipDefaultPorts; } - private Boolean keepTempDockerfile; + private Boolean keepTempContainerfile; - @Option(option = 'keepTempDockerfile', description = 'If true, preserve the temporary Dockerfile used to build the container.') + @Option(option = 'keepTempContainerfile', description = 'If true, preserve the temporary Containerfile/Dockerfile used to build the container.') + void setKeepTempContainerfile(boolean keepTempContainerfile) { + this.keepTempContainerfile = keepTempContainerfile; + } + + private Boolean keepTempDockerfile; + @Option(option = 'keepTempDockerfile', description = 'Alias for keepTempContainerfile') void setKeepTempDockerfile(boolean keepTempDockerfile) { - this.keepTempDockerfile = keepTempDockerfile; + setKeepTempContainerfile(keepTempDockerfile) } @Optional @@ -315,15 +353,15 @@ class DevTask extends AbstractFeatureTask { File configDirectory, File projectDirectory, List resourceDirs, boolean hotTests, boolean skipTests, boolean skipInstallFeature, String artifactId, int serverStartTimeout, int verifyAppStartTimeout, int appUpdateTimeout, double compileWait, - boolean libertyDebug, boolean pollingTest, boolean container, File dockerfile, File dockerBuildContext, - String dockerRunOpts, int dockerBuildTimeout, boolean skipDefaultPorts, boolean keepTempDockerfile, + boolean libertyDebug, boolean pollingTest, boolean container, File containerfile, File containerBuildContext, + String containerRunOpts, int containerBuildTimeout, boolean skipDefaultPorts, boolean keepTempContainerfile, String mavenCacheLocation, String packagingType, File buildFile, boolean generateFeatures ) throws IOException { super(buildDir, serverDirectory, sourceDirectory, testSourceDirectory, configDirectory, projectDirectory, /* multi module project directory */ projectDirectory, resourceDirs, hotTests, skipTests, false /* skipUTs */, false /* skipITs */, skipInstallFeature, artifactId, serverStartTimeout, verifyAppStartTimeout, appUpdateTimeout, ((long) (compileWait * 1000L)), libertyDebug, - true /* useBuildRecompile */, true /* gradle */, pollingTest, container, dockerfile, dockerBuildContext, dockerRunOpts, dockerBuildTimeout, skipDefaultPorts, - null /* compileOptions not needed since useBuildRecompile is true */, keepTempDockerfile, mavenCacheLocation, null /* multi module upstream projects */, + true /* useBuildRecompile */, true /* gradle */, pollingTest, container, containerfile, containerBuildContext, containerRunOpts, containerBuildTimeout, skipDefaultPorts, + null /* compileOptions not needed since useBuildRecompile is true */, keepTempContainerfile, mavenCacheLocation, null /* multi module upstream projects */, false /* recompileDependencies only supported in ci.maven */, packagingType, buildFile, null /* parent build files */, generateFeatures, null /* compileArtifactPaths */, null /* testArtifactPaths */, new ArrayList() /* webResources */ ); @@ -1133,8 +1171,8 @@ class DevTask extends AbstractFeatureTask { serverDirectory, sourceDirectory, testSourceDirectory, configDirectory, project.getRootDir(), resourceDirs, hotTests.booleanValue(), skipTests.booleanValue(), skipInstallFeature.booleanValue(), artifactId, serverStartTimeout.intValue(), verifyAppStartTimeout.intValue(), verifyAppStartTimeout.intValue(), compileWait.doubleValue(), - libertyDebug.booleanValue(), pollingTest.booleanValue(), container.booleanValue(), dockerfile, dockerBuildContext, dockerRunOpts, - dockerBuildTimeout, skipDefaultPorts.booleanValue(), keepTempDockerfile.booleanValue(), localMavenRepoForFeatureUtility, + libertyDebug.booleanValue(), pollingTest.booleanValue(), container.booleanValue(), containerfile, containerBuildContext, containerRunOpts, + containerBuildTimeout, skipDefaultPorts.booleanValue(), keepTempContainerfile.booleanValue(), localMavenRepoForFeatureUtility, getPackagingType(), buildFile, generateFeatures.booleanValue() ); @@ -1224,7 +1262,7 @@ class DevTask extends AbstractFeatureTask { } else { // skip creating the server and installing features and just propagate the option to 'deploy' createServerDirectories(); - gradleBuildLauncher.addArguments("--exclude-task", "installFeature"); // skip installing features at startup since Dockerfile should have RUN features.sh + gradleBuildLauncher.addArguments("--exclude-task", "installFeature"); // skip installing features at startup since Containerfile/Dockerfile should have RUN features.sh gradleBuildLauncher.addArguments(CONTAINER_PROPERTY_ARG); } runGradleTask(gradleBuildLauncher, 'deploy'); @@ -1302,31 +1340,31 @@ class DevTask extends AbstractFeatureTask { } } - if (dockerfile == null) { - File buildDockerfileSetting = project.liberty.dev.dockerfile; // get from build.gradle - if (buildDockerfileSetting != null) { - setDockerfile(buildDockerfileSetting.getAbsolutePath()); // setDockerfile will convert it to canonical path + if (containerfile == null) { + File buildcontainerfileSetting = project.liberty.dev.containerfile; // get from build.gradle + if (buildcontainerfileSetting != null) { + setContainerfile(buildcontainerfileSetting.getAbsolutePath()); // setContainerfile will convert it to canonical path } } - if (dockerBuildContext == null) { - File buildDockerBuildContextSetting = project.liberty.dev.dockerBuildContext; // get from build.gradle - if (buildDockerBuildContextSetting != null) { - setDockerBuildContext(buildDockerBuildContextSetting.getAbsolutePath()); // setDockerBuildContext will convert it to canonical path + if (containerBuildContext == null) { + File buildContainerBuildContextSetting = project.liberty.dev.containerBuildContext; // get from build.gradle + if (buildContainerBuildContextSetting != null) { + setContainerBuildContext(buildContainerBuildContextSetting.getAbsolutePath()); // setContainerBuildContext will convert it to canonical path } } - if (dockerRunOpts == null) { - String buildDockerRunOptsSetting = project.liberty.dev.dockerRunOpts; // get from build.gradle - if (buildDockerRunOptsSetting != null) { - setDockerRunOpts(buildDockerRunOptsSetting); + if (containerRunOpts == null) { + String buildContainerRunOptsSetting = project.liberty.dev.containerRunOpts; // get from build.gradle + if (buildContainerRunOptsSetting != null) { + setContainerRunOpts(buildContainerRunOptsSetting); } } - if (dockerBuildTimeout == 0) { - String buildDockerBuildTimeoutSetting = project.liberty.dev.dockerBuildTimeout; // get from build.gradle - if (buildDockerBuildTimeoutSetting != null) { - setDockerBuildTimeout(buildDockerBuildTimeoutSetting); + if (containerBuildTimeout == 0) { + String buildContainerBuildTimeoutSetting = project.liberty.dev.containerBuildTimeout; // get from build.gradle + if (buildContainerBuildTimeoutSetting != null) { + setContainerBuildTimeout(buildContainerBuildTimeoutSetting); } } @@ -1339,12 +1377,12 @@ class DevTask extends AbstractFeatureTask { } } - if (keepTempDockerfile == null) { - boolean buildKeepTempDockerfileSetting = project.liberty.dev.keepTempDockerfile; // get from build.gradle - if (buildKeepTempDockerfileSetting == null) { - setKeepTempDockerfile(DEFAULT_KEEP_TEMP_DOCKERFILE); + if (keepTempContainerfile == null) { + boolean buildKeepTempContainerfileSetting = project.liberty.dev.keepTempContainerfile; // get from build.gradle + if (buildKeepTempContainerfileSetting == null) { + setKeepTempContainerfile(DEFAULT_KEEP_TEMP_CONTAINERFILE); } else { - setKeepTempDockerfile(buildKeepTempDockerfileSetting); + setKeepTempContainerfile(buildKeepTempContainerfileSetting); } } } diff --git a/src/test/groovy/io/openliberty/tools/gradle/BaseDevTest.groovy b/src/test/groovy/io/openliberty/tools/gradle/BaseDevTest.groovy index e48a4ab39..0183f849a 100644 --- a/src/test/groovy/io/openliberty/tools/gradle/BaseDevTest.groovy +++ b/src/test/groovy/io/openliberty/tools/gradle/BaseDevTest.groovy @@ -279,13 +279,20 @@ class BaseDevTest extends AbstractIntegrationTest { } protected static void cleanUpAfterClass(boolean isDevMode) throws Exception { - stopProcess(isDevMode); + stopProcess(isDevMode, errFile); if (buildDir != null && buildDir.exists()) { FileUtils.deleteQuietly(buildDir); // try this method that does not throw an exception } } - private static void stopProcess(boolean isDevMode) throws IOException, InterruptedException, FileNotFoundException { + protected static void cleanUpAfterClassCheckLogFile(boolean isDevMode) throws Exception { + stopProcess(isDevMode, logFile); + if (buildDir != null && buildDir.exists()) { + FileUtils.deleteQuietly(buildDir); // try this method that does not throw an exception + } + } + + private static void stopProcess(boolean isDevMode, File testLogFile) throws IOException, InterruptedException, FileNotFoundException { // shut down dev mode if (writer != null) { int serverStoppedOccurrences = countOccurrences("CWWKE0036I", logFile); @@ -301,7 +308,7 @@ class BaseDevTest extends AbstractIntegrationTest { } // test that dev mode has stopped running - assertTrue(verifyLogMessage(100000, "CWWKE0036I", errFile, ++serverStoppedOccurrences)); + assertTrue(verifyLogMessage(100000, "CWWKE0036I", testLogFile, ++serverStoppedOccurrences)); Thread.sleep(5000); // wait 5s to ensure java process has stopped } } diff --git a/src/test/groovy/io/openliberty/tools/gradle/DevContainerTest.groovy b/src/test/groovy/io/openliberty/tools/gradle/DevContainerTest.groovy new file mode 100644 index 000000000..7c79e755f --- /dev/null +++ b/src/test/groovy/io/openliberty/tools/gradle/DevContainerTest.groovy @@ -0,0 +1,63 @@ +/* + * (C) Copyright IBM Corporation 2023. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.openliberty.tools.gradle; + +import static org.junit.Assert.*; + +import java.io.BufferedWriter; +import org.apache.commons.io.FileUtils; +import java.io.File; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.Test; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; + +class DevContainerTest extends BaseDevTest { + + static final String projectName = "dev-container"; + static File resourceDir = new File("build/resources/test/dev-test/" + projectName); + static File testBuildDir = new File(integTestDir, "/test-dev-container") + + @BeforeClass + public static void setup() throws IOException, InterruptedException, FileNotFoundException { + createDir(testBuildDir) + createTestProject(testBuildDir, resourceDir, "build.gradle", true) + + File buildFile = new File(resourceDir, buildFilename) + copyBuildFiles(buildFile, testBuildDir, false) + + runDevMode("--container", testBuildDir) + } + + @Test + public void devmodeContainerTest() throws Exception { + assertTrue("The container build did not complete.", verifyLogMessage(20000, "Completed building container image.", logFile)); + assertTrue("The application start message is missing.", verifyLogMessage(20000, "CWWKZ0001I: Application rest started", logFile)); + } + + @AfterClass + public static void cleanUpAfterClass() throws Exception { + String stdout = getContents(logFile, "Dev mode std output"); + System.out.println(stdout); + String stderr = getContents(errFile, "Dev mode std error"); + System.out.println(stderr); + cleanUpAfterClassCheckLogFile(true); + } +} diff --git a/src/test/resources/dev-test/dev-container/Containerfile b/src/test/resources/dev-test/dev-container/Containerfile new file mode 100644 index 000000000..26505beba --- /dev/null +++ b/src/test/resources/dev-test/dev-container/Containerfile @@ -0,0 +1,33 @@ +# Start with OL runtime. +# tag::from[] +FROM icr.io/appcafe/open-liberty:full-java11-openj9-ubi +# end::from[] + +ARG VERSION=1.0 +ARG REVISION=SNAPSHOT +# tag::label[] + +LABEL \ + org.opencontainers.image.authors="Your Name" \ + org.opencontainers.image.vendor="IBM" \ + org.opencontainers.image.url="local" \ + org.opencontainers.image.source="https://github.com/OpenLiberty/guide-docker" \ + org.opencontainers.image.version="$VERSION" \ + org.opencontainers.image.revision="$REVISION" \ + vendor="Open Liberty" \ + name="system" \ + version="$VERSION-$REVISION" \ + summary="The system microservice from the Docker Guide" \ + # tag::description[] + description="This image contains the system microservice running with the Open Liberty runtime." + # end::description[] +# end::label[] + + +USER root + +COPY --chown=1001:0 src/main/liberty/config/server.xml /config/ + +COPY --chown=1001:0 build/libs/*.war /config/apps/ + +USER 1001 diff --git a/src/test/resources/dev-test/dev-container/build.gradle b/src/test/resources/dev-test/dev-container/build.gradle new file mode 100644 index 000000000..6b7d42020 --- /dev/null +++ b/src/test/resources/dev-test/dev-container/build.gradle @@ -0,0 +1,44 @@ +apply plugin: "liberty" +apply plugin: "war" + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 +tasks.withType(JavaCompile) { + options.encoding = "UTF-8" +} + +buildscript { + repositories { + mavenCentral() + mavenLocal() + maven { + url 'https://oss.sonatype.org/content/repositories/snapshots/' + } + } + dependencies { + classpath "io.openliberty.tools:liberty-gradle-plugin:$lgpVersion" + } +} + +repositories { + mavenCentral() +} + +dependencies { + providedCompile 'jakarta.platform:jakarta.jakartaee-api:9.1.0' + providedCompile 'org.eclipse.microprofile:microprofile:5.0' + + testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2' + testImplementation 'org.jboss.resteasy:resteasy-client:6.0.0.Final' + testImplementation 'org.jboss.resteasy:resteasy-json-binding-provider:6.0.0.Final' + testImplementation 'org.glassfish:jakarta.json:2.0.1' + testImplementation 'javax.xml.bind:jaxb-api:2.3.1' +} + +war { + archiveBaseName = 'rest' +} + +test { + systemProperty 'liberty.test.port', '9080' +} \ No newline at end of file diff --git a/src/test/resources/dev-test/dev-container/settings.gradle b/src/test/resources/dev-test/dev-container/settings.gradle new file mode 100644 index 000000000..c2d3edc19 --- /dev/null +++ b/src/test/resources/dev-test/dev-container/settings.gradle @@ -0,0 +1 @@ +//Empty \ No newline at end of file diff --git a/src/test/resources/dev-test/dev-container/src/main/java/io/openliberty/guides/rest/PropertiesResource.java b/src/test/resources/dev-test/dev-container/src/main/java/io/openliberty/guides/rest/PropertiesResource.java new file mode 100644 index 000000000..eaa21955b --- /dev/null +++ b/src/test/resources/dev-test/dev-container/src/main/java/io/openliberty/guides/rest/PropertiesResource.java @@ -0,0 +1,43 @@ +// tag::copyright[] +/******************************************************************************* + * Copyright (c) 2017, 2022 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - Initial implementation + *******************************************************************************/ +// end::copyright[] +package io.openliberty.guides.rest; + +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Produces; + +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.Json; + +// tag::Path[] +@Path("properties") +// end::Path[] +public class PropertiesResource { + + @GET + @Produces(MediaType.APPLICATION_JSON) + public JsonObject getProperties() { + + JsonObjectBuilder builder = Json.createObjectBuilder(); + + System.getProperties() + .entrySet() + .stream() + .forEach(entry -> builder.add((String) entry.getKey(), + (String) entry.getValue())); + + return builder.build(); + } +} diff --git a/src/test/resources/dev-test/dev-container/src/main/java/io/openliberty/guides/rest/SystemApplication.java b/src/test/resources/dev-test/dev-container/src/main/java/io/openliberty/guides/rest/SystemApplication.java new file mode 100644 index 000000000..a1ee88610 --- /dev/null +++ b/src/test/resources/dev-test/dev-container/src/main/java/io/openliberty/guides/rest/SystemApplication.java @@ -0,0 +1,21 @@ +// tag::copyright[] +/******************************************************************************* + * Copyright (c) 2017, 2022 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - Initial implementation + *******************************************************************************/ +// end::copyright[] +package io.openliberty.guides.rest; + +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.ApplicationPath; + +@ApplicationPath("system") +public class SystemApplication extends Application { + +} diff --git a/src/test/resources/dev-test/dev-container/src/main/liberty/config/server.xml b/src/test/resources/dev-test/dev-container/src/main/liberty/config/server.xml new file mode 100644 index 000000000..35e7d6a49 --- /dev/null +++ b/src/test/resources/dev-test/dev-container/src/main/liberty/config/server.xml @@ -0,0 +1,16 @@ + + + + restfulWS-3.0 + jsonb-2.0 + jsonp-2.0 + + + + + + + + + diff --git a/src/test/resources/dev-test/dev-container/src/main/webapp/WEB-INF/web.xml b/src/test/resources/dev-test/dev-container/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..a3823f10b --- /dev/null +++ b/src/test/resources/dev-test/dev-container/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,10 @@ + + + Liberty Project + + + index.html + + \ No newline at end of file diff --git a/src/test/resources/dev-test/dev-container/src/main/webapp/index.html b/src/test/resources/dev-test/dev-container/src/main/webapp/index.html new file mode 100644 index 000000000..d4f1f67db --- /dev/null +++ b/src/test/resources/dev-test/dev-container/src/main/webapp/index.html @@ -0,0 +1,41 @@ + + + +

Welcome to your Open Liberty application

+

Open Liberty is a lightweight open framework for building fast and efficient cloud-native Java microservices. Find out more at openliberty.io.

+
+

Eclipse MicroProfile

+

+ The Eclipse MicroProfile project is an open community with the aim of optimizing enterprise Java for a microservices architecture. + MicroProfile evolves with guidance from the community. +

+

+ If you want to share your thoughts, you can post straight to the + MicroProfile Google group. +

+

+ For more information about the features used in this application, see the Open Liberty documentation: +

+

+
+ + diff --git a/src/test/resources/dev-test/dev-container/src/test/java/it/io/openliberty/guides/rest/EndpointIT.java b/src/test/resources/dev-test/dev-container/src/test/java/it/io/openliberty/guides/rest/EndpointIT.java new file mode 100644 index 000000000..c8e98ece8 --- /dev/null +++ b/src/test/resources/dev-test/dev-container/src/test/java/it/io/openliberty/guides/rest/EndpointIT.java @@ -0,0 +1,49 @@ +// tag::copyright[] +/******************************************************************************* + * Copyright (c) 2017, 2022 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - Initial implementation + *******************************************************************************/ +// end::copyright[] +package it.io.openliberty.guides.rest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +import jakarta.json.JsonObject; + +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.Response; + + +public class EndpointIT { + + @Test + public void testGetProperties() { + String port = System.getProperty("liberty.test.port"); + String url = "http://localhost:" + port + "/"; + + Client client = ClientBuilder.newClient(); + + WebTarget target = client.target(url + "system/properties-new"); + Response response = target.request().get(); + JsonObject obj = response.readEntity(JsonObject.class); + + assertEquals(200, response.getStatus(), "Incorrect response code from " + url); + + assertEquals("/opt/ol/wlp/output/defaultServer/", + obj.getString("server.output.dir"), + "The system property for the server output directory should match " + + "the Open Liberty container image."); + + response.close(); + } +} From c1961cce6e1d9744a5008b44ea9153cfb0436bfc Mon Sep 17 00:00:00 2001 From: Matt Bowersox Date: Tue, 19 Sep 2023 17:07:31 -0500 Subject: [PATCH 2/7] Use action to install Podman --- .github/workflows/gradle.yml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index c4726deb8..7fdb99e9a 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -27,12 +27,21 @@ jobs: RUNTIME_VERSION: 23.0.0.3 name: ${{ matrix.RUNTIME }} ${{ matrix.RUNTIME_VERSION }}, Java ${{ matrix.java }}, Linux steps: + - name: Install Podman + uses: gacts/install-podman@v1 + with: + qemu: true + - name: Setup qemu + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + sudo apt install qemu-system-x86 - name: Setup Podman run: | - sudo apt update - sudo apt-get -y install podman - sudo podman machine init --rootful=true - sudo podman machine start + podman version + podman machine init --rootful=true + podman machine start # Checkout repos - name: Checkout ci.gradle uses: actions/checkout@v3 From 06f97aa269e853cb0500a06d513f8e374ee8b302 Mon Sep 17 00:00:00 2001 From: Matt Bowersox Date: Tue, 19 Sep 2023 18:21:37 -0500 Subject: [PATCH 3/7] Disable DevContainerTest --- .github/workflows/gradle.yml | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 7fdb99e9a..eb9de0aa7 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -27,21 +27,6 @@ jobs: RUNTIME_VERSION: 23.0.0.3 name: ${{ matrix.RUNTIME }} ${{ matrix.RUNTIME_VERSION }}, Java ${{ matrix.java }}, Linux steps: - - name: Install Podman - uses: gacts/install-podman@v1 - with: - qemu: true - - name: Setup qemu - run: | - echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules - sudo udevadm control --reload-rules - sudo udevadm trigger --name-match=kvm - sudo apt install qemu-system-x86 - - name: Setup Podman - run: | - podman version - podman machine init --rootful=true - podman machine start # Checkout repos - name: Checkout ci.gradle uses: actions/checkout@v3 @@ -85,7 +70,7 @@ jobs: # Run tests - name: Run tests with Gradle on Ubuntu run: - ./gradlew clean install check -Druntime=${{ matrix.RUNTIME }} -DruntimeVersion="${{ matrix.RUNTIME_VERSION }}" --stacktrace --info + ./gradlew clean install check -Druntime=${{ matrix.RUNTIME }} -DruntimeVersion="${{ matrix.RUNTIME_VERSION }}" -P"test.exclude"="**/DevContainerTest*" --stacktrace --info # Copy build reports and upload artifact if build failed - name: Copy build/report/tests/test for upload if: ${{ failure() }} From d791ab99386b1e8da26fd7e5aed13e320f9d9d76 Mon Sep 17 00:00:00 2001 From: Matt Bowersox Date: Thu, 21 Sep 2023 14:16:46 -0500 Subject: [PATCH 4/7] Update libertyDev properties and docs --- docs/libertyDev.md | 10 +++++----- .../tools/gradle/tasks/DevTask.groovy | 20 +++++++++++-------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/docs/libertyDev.md b/docs/libertyDev.md index 675778bcd..d8ae1efa1 100644 --- a/docs/libertyDev.md +++ b/docs/libertyDev.md @@ -247,9 +247,9 @@ These can also be specified as command line parameters in addition to the ones i | Attribute | Type | Since | Description | Required | | --------- | ----- | ----- | ----------- | -------- | | container | boolean | 3.1-M1 | If set to `true`, run the server in the container specified by the `containerfile` parameter. Setting this to `true` and using the `libertyDev` task is equivalent to using the `libertyDevc` task. The default value is `false` when the `libertyDev` task is used, and `true` when the `libertyDevc` task is used. | No | -| containerRunOpts | String | 3.1-M1 | Specifies options to add to the container `run` command when using dev mode to launch your server in a container. For example, `-e key=value` is recognized by `docker run` to define an environment variable with the name `key` and value `value`. | No | -| containerfile | File | 3.1-M1 | Location of a Containerfile or Dockerfile to be used by dev mode to build the image for the container that will run your Liberty server. The default location is `Containerfile` or `Dockerfile` in the project root. | No | -| cotnainerBuildContext | File | 3.1.3 | The container build context directory to be used by dev mode for the container `build` command. The default location is the directory of the Containerfile/Dockerfile. | No | -| containerBuildTimeout | integer | 3.1-M3 | Maximum time to wait (in seconds) for the completion of the container operation to build the image. The value must be an integer greater than 0. The default value is `600` seconds. | No | +| containerRunOpts | String | 3.7 | Specifies options to add to the container `run` command when using dev mode to launch your server in a container. For example, `-e key=value` is recognized by `docker run` to define an environment variable with the name `key` and value `value`. This attribute replaces the deprecated `dockerRunOpts` attribute. | No | +| containerfile | File | 3.7 | Location of a Containerfile or Dockerfile to be used by dev mode to build the image for the container that will run your Liberty server. The default location is `Containerfile` or `Dockerfile` in the project root. This attribute replaces the deprecated `dockerfile` attribute. | No | +| cotnainerBuildContext | File | 3.7 | The container build context directory to be used by dev mode for the container `build` command. The default location is the directory of the Containerfile/Dockerfile. This attribute replaces the deprecated `dockerBuildContext` attribute. | No | +| containerBuildTimeout | integer | 3.7 | Maximum time to wait (in seconds) for the completion of the container operation to build the image. The value must be an integer greater than 0. The default value is `600` seconds. This attribute replaces the deprecated `dockerBuildTimeout` attribute. | No | | skipDefaultPorts | boolean | 3.1-M3 | If set to `true`, dev mode will not publish the default container port mappings of `9080:9080` (HTTP) and `9443:9443` (HTTPS). Use this option if you would like to specify alternative local ports to map to the exposed container ports for HTTP and HTTPS using the `containerRunOpts` parameter. | No | -| keepTempContainerfile | boolean | 3.1 | If set to `true`, dev mode will not delete the temporary modified copy of your Containerfile/Dockerfile used to build the container image. This file is handy in case you need to debug the process of building the container image. The path of the temporary Containerfile/Dockerfile can be seen when dev mode displays the container `build` command. The default value is `false`.| No | +| keepTempContainerfile | boolean | 3.7 | If set to `true`, dev mode will not delete the temporary modified copy of your Containerfile/Dockerfile used to build the container image. This file is handy in case you need to debug the process of building the container image. The path of the temporary Containerfile/Dockerfile can be seen when dev mode displays the container `build` command. The default value is `false`. This attribute replaces the deprecated `keepTempDockerfile` attribute. | No | diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy index a63059a17..d0f57de6d 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy @@ -259,7 +259,7 @@ class DevTask extends AbstractFeatureTask { private String dockerRunOpts; @Option(option = 'dockerRunOpts', description = 'Alias for containerRunOpts') void setDockerRunOpts(String dockerRunOpts) { - if (containerRunOpts == null) { + if (dockerRunOpts != null && containerRunOpts == null) { setContainerRunOpts(dockerRunOpts) } } @@ -279,7 +279,9 @@ class DevTask extends AbstractFeatureTask { private int dockerBuildTimeout; @Option(option = 'dockerBuildTimeout', description = 'Alias for containerBuildTimeout') void setDockerBuildTimeout(String inputValue) { - setContainerBuildTimeout(inputValue) + if (inputValue != null && containerBuildTimeout == null) { + setContainerBuildTimeout(inputValue) + } } private Boolean skipDefaultPorts; @@ -299,7 +301,9 @@ class DevTask extends AbstractFeatureTask { private Boolean keepTempDockerfile; @Option(option = 'keepTempDockerfile', description = 'Alias for keepTempContainerfile') void setKeepTempDockerfile(boolean keepTempDockerfile) { - setKeepTempContainerfile(keepTempDockerfile) + if (keepTempDockerfile != null && keepTempContainerfile == null) { + setKeepTempContainerfile(keepTempDockerfile) + } } @Optional @@ -1340,28 +1344,28 @@ class DevTask extends AbstractFeatureTask { } } - if (containerfile == null) { + if (containerfile == null && dockerfile == null) { File buildcontainerfileSetting = project.liberty.dev.containerfile; // get from build.gradle if (buildcontainerfileSetting != null) { setContainerfile(buildcontainerfileSetting.getAbsolutePath()); // setContainerfile will convert it to canonical path } } - if (containerBuildContext == null) { + if (containerBuildContext == null && dockerBuildContext == null) { File buildContainerBuildContextSetting = project.liberty.dev.containerBuildContext; // get from build.gradle if (buildContainerBuildContextSetting != null) { setContainerBuildContext(buildContainerBuildContextSetting.getAbsolutePath()); // setContainerBuildContext will convert it to canonical path } } - if (containerRunOpts == null) { + if (containerRunOpts == null && dockerRunOpts == null) { String buildContainerRunOptsSetting = project.liberty.dev.containerRunOpts; // get from build.gradle if (buildContainerRunOptsSetting != null) { setContainerRunOpts(buildContainerRunOptsSetting); } } - if (containerBuildTimeout == 0) { + if (containerBuildTimeout == 0 && dockerBuildTimeout == 0) { String buildContainerBuildTimeoutSetting = project.liberty.dev.containerBuildTimeout; // get from build.gradle if (buildContainerBuildTimeoutSetting != null) { setContainerBuildTimeout(buildContainerBuildTimeoutSetting); @@ -1377,7 +1381,7 @@ class DevTask extends AbstractFeatureTask { } } - if (keepTempContainerfile == null) { + if (keepTempContainerfile == null && keepTempDockerfile == null) { boolean buildKeepTempContainerfileSetting = project.liberty.dev.keepTempContainerfile; // get from build.gradle if (buildKeepTempContainerfileSetting == null) { setKeepTempContainerfile(DEFAULT_KEEP_TEMP_CONTAINERFILE); From aa5e82c1559cf3d5b0e48de8bcd3adde69631806 Mon Sep 17 00:00:00 2001 From: Matt Bowersox Date: Thu, 21 Sep 2023 14:41:58 -0500 Subject: [PATCH 5/7] Fix typo in attribute --- docs/libertyDev.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/libertyDev.md b/docs/libertyDev.md index d8ae1efa1..fbb779a2d 100644 --- a/docs/libertyDev.md +++ b/docs/libertyDev.md @@ -249,7 +249,7 @@ These can also be specified as command line parameters in addition to the ones i | container | boolean | 3.1-M1 | If set to `true`, run the server in the container specified by the `containerfile` parameter. Setting this to `true` and using the `libertyDev` task is equivalent to using the `libertyDevc` task. The default value is `false` when the `libertyDev` task is used, and `true` when the `libertyDevc` task is used. | No | | containerRunOpts | String | 3.7 | Specifies options to add to the container `run` command when using dev mode to launch your server in a container. For example, `-e key=value` is recognized by `docker run` to define an environment variable with the name `key` and value `value`. This attribute replaces the deprecated `dockerRunOpts` attribute. | No | | containerfile | File | 3.7 | Location of a Containerfile or Dockerfile to be used by dev mode to build the image for the container that will run your Liberty server. The default location is `Containerfile` or `Dockerfile` in the project root. This attribute replaces the deprecated `dockerfile` attribute. | No | -| cotnainerBuildContext | File | 3.7 | The container build context directory to be used by dev mode for the container `build` command. The default location is the directory of the Containerfile/Dockerfile. This attribute replaces the deprecated `dockerBuildContext` attribute. | No | +| containerBuildContext | File | 3.7 | The container build context directory to be used by dev mode for the container `build` command. The default location is the directory of the Containerfile/Dockerfile. This attribute replaces the deprecated `dockerBuildContext` attribute. | No | | containerBuildTimeout | integer | 3.7 | Maximum time to wait (in seconds) for the completion of the container operation to build the image. The value must be an integer greater than 0. The default value is `600` seconds. This attribute replaces the deprecated `dockerBuildTimeout` attribute. | No | | skipDefaultPorts | boolean | 3.1-M3 | If set to `true`, dev mode will not publish the default container port mappings of `9080:9080` (HTTP) and `9443:9443` (HTTPS). Use this option if you would like to specify alternative local ports to map to the exposed container ports for HTTP and HTTPS using the `containerRunOpts` parameter. | No | | keepTempContainerfile | boolean | 3.7 | If set to `true`, dev mode will not delete the temporary modified copy of your Containerfile/Dockerfile used to build the container image. This file is handy in case you need to debug the process of building the container image. The path of the temporary Containerfile/Dockerfile can be seen when dev mode displays the container `build` command. The default value is `false`. This attribute replaces the deprecated `keepTempDockerfile` attribute. | No | From 13ef0d5df4cccb5a21dfac882183a0d34cab124a Mon Sep 17 00:00:00 2001 From: Matt Bowersox Date: Thu, 21 Sep 2023 15:04:07 -0500 Subject: [PATCH 6/7] Update checks for DevExtension properties --- docs/libertyDev.md | 10 +++--- .../tools/gradle/tasks/DevTask.groovy | 31 ++++++++++++++----- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/docs/libertyDev.md b/docs/libertyDev.md index fbb779a2d..b8c0d05bf 100644 --- a/docs/libertyDev.md +++ b/docs/libertyDev.md @@ -247,9 +247,9 @@ These can also be specified as command line parameters in addition to the ones i | Attribute | Type | Since | Description | Required | | --------- | ----- | ----- | ----------- | -------- | | container | boolean | 3.1-M1 | If set to `true`, run the server in the container specified by the `containerfile` parameter. Setting this to `true` and using the `libertyDev` task is equivalent to using the `libertyDevc` task. The default value is `false` when the `libertyDev` task is used, and `true` when the `libertyDevc` task is used. | No | -| containerRunOpts | String | 3.7 | Specifies options to add to the container `run` command when using dev mode to launch your server in a container. For example, `-e key=value` is recognized by `docker run` to define an environment variable with the name `key` and value `value`. This attribute replaces the deprecated `dockerRunOpts` attribute. | No | -| containerfile | File | 3.7 | Location of a Containerfile or Dockerfile to be used by dev mode to build the image for the container that will run your Liberty server. The default location is `Containerfile` or `Dockerfile` in the project root. This attribute replaces the deprecated `dockerfile` attribute. | No | -| containerBuildContext | File | 3.7 | The container build context directory to be used by dev mode for the container `build` command. The default location is the directory of the Containerfile/Dockerfile. This attribute replaces the deprecated `dockerBuildContext` attribute. | No | -| containerBuildTimeout | integer | 3.7 | Maximum time to wait (in seconds) for the completion of the container operation to build the image. The value must be an integer greater than 0. The default value is `600` seconds. This attribute replaces the deprecated `dockerBuildTimeout` attribute. | No | +| containerRunOpts | String | 3.7 | Specifies options to add to the container `run` command when using dev mode to launch your server in a container. For example, `-e key=value` is recognized by `docker run` to define an environment variable with the name `key` and value `value`. This attribute replaces the deprecated `dockerRunOpts` attribute and will take precedence. | No | +| containerfile | File | 3.7 | Location of a Containerfile or Dockerfile to be used by dev mode to build the image for the container that will run your Liberty server. The default location is `Containerfile` or `Dockerfile` in the project root. This attribute replaces the deprecated `dockerfile` attribute and will take precedence. | No | +| containerBuildContext | File | 3.7 | The container build context directory to be used by dev mode for the container `build` command. The default location is the directory of the Containerfile/Dockerfile. This attribute replaces the deprecated `dockerBuildContext` attribute and will take precedence. | No | +| containerBuildTimeout | integer | 3.7 | Maximum time to wait (in seconds) for the completion of the container operation to build the image. The value must be an integer greater than 0. The default value is `600` seconds. This attribute replaces the deprecated `dockerBuildTimeout` attribute and will take precedence. | No | | skipDefaultPorts | boolean | 3.1-M3 | If set to `true`, dev mode will not publish the default container port mappings of `9080:9080` (HTTP) and `9443:9443` (HTTPS). Use this option if you would like to specify alternative local ports to map to the exposed container ports for HTTP and HTTPS using the `containerRunOpts` parameter. | No | -| keepTempContainerfile | boolean | 3.7 | If set to `true`, dev mode will not delete the temporary modified copy of your Containerfile/Dockerfile used to build the container image. This file is handy in case you need to debug the process of building the container image. The path of the temporary Containerfile/Dockerfile can be seen when dev mode displays the container `build` command. The default value is `false`. This attribute replaces the deprecated `keepTempDockerfile` attribute. | No | +| keepTempContainerfile | boolean | 3.7 | If set to `true`, dev mode will not delete the temporary modified copy of your Containerfile/Dockerfile used to build the container image. This file is handy in case you need to debug the process of building the container image. The path of the temporary Containerfile/Dockerfile can be seen when dev mode displays the container `build` command. The default value is `false`. This attribute replaces the deprecated `keepTempDockerfile` attribute and will take precedence. | No | diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy index d0f57de6d..629b1fe7b 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy @@ -1345,30 +1345,42 @@ class DevTask extends AbstractFeatureTask { } if (containerfile == null && dockerfile == null) { - File buildcontainerfileSetting = project.liberty.dev.containerfile; // get from build.gradle - if (buildcontainerfileSetting != null) { - setContainerfile(buildcontainerfileSetting.getAbsolutePath()); // setContainerfile will convert it to canonical path + File buildContainerfileSetting = project.liberty.dev.containerfile; + File buildDockerfileSetting = project.liberty.dev.dockerfile; // get from build.gradle + if (buildContainerfileSetting != null) { + setContainerfile(buildContainerfileSetting.getAbsolutePath()); // setContainerfile will convert it to canonical path + } else if (buildDockerfileSetting != null) { + setContainerfile(buildDockerfileSetting.getAbsolutePath()); } } if (containerBuildContext == null && dockerBuildContext == null) { File buildContainerBuildContextSetting = project.liberty.dev.containerBuildContext; // get from build.gradle + File buildDockerBuildContextSetting = project.liberty.dev.dockerBuildContext; if (buildContainerBuildContextSetting != null) { setContainerBuildContext(buildContainerBuildContextSetting.getAbsolutePath()); // setContainerBuildContext will convert it to canonical path + } else if (buildDockerBuildContextSetting != null) { + setContainerBuildContext(buildDockerBuildContextSetting.getAbsolutePath()); } } if (containerRunOpts == null && dockerRunOpts == null) { - String buildContainerRunOptsSetting = project.liberty.dev.containerRunOpts; // get from build.gradle + String buildContainerRunOptsSetting = project.liberty.dev.containerRunOpts; + String buildDockerRunOptsSetting = project.liberty.dev.dockerRunOpts; // get from build.gradle if (buildContainerRunOptsSetting != null) { setContainerRunOpts(buildContainerRunOptsSetting); + } else if (buildDockerRunOptsSetting != null) { + setContainerRunOpts(buildDockerRunOptsSetting); } } if (containerBuildTimeout == 0 && dockerBuildTimeout == 0) { - String buildContainerBuildTimeoutSetting = project.liberty.dev.containerBuildTimeout; // get from build.gradle + String buildContainerBuildTimeoutSetting = project.liberty.dev.containerBuildTimeout; + String buildDockerBuildTimeoutSetting = project.liberty.dev.dockerBuildTimeout; // get from build.gradle if (buildContainerBuildTimeoutSetting != null) { setContainerBuildTimeout(buildContainerBuildTimeoutSetting); + } else if (buildDockerBuildTimeoutSetting != null) { + setContainerBuildTimeout(buildDockerBuildTimeoutSetting); } } @@ -1383,10 +1395,13 @@ class DevTask extends AbstractFeatureTask { if (keepTempContainerfile == null && keepTempDockerfile == null) { boolean buildKeepTempContainerfileSetting = project.liberty.dev.keepTempContainerfile; // get from build.gradle - if (buildKeepTempContainerfileSetting == null) { - setKeepTempContainerfile(DEFAULT_KEEP_TEMP_CONTAINERFILE); - } else { + boolean buildKeepTempDockerfileSetting = project.liberty.dev.keepTempDockerfile; + if (buildKeepTempContainerfileSetting != null) { setKeepTempContainerfile(buildKeepTempContainerfileSetting); + } else if (buildKeepTempDockerfileSetting != null) { + setKeepTempContainerfile(buildKeepTempDockerfileSetting); + } else { + setKeepTempContainerfile(DEFAULT_KEEP_TEMP_CONTAINERFILE); } } } From 15833ed194da744ea85f87dc32295836935533d9 Mon Sep 17 00:00:00 2001 From: Matt Bowersox Date: Thu, 21 Sep 2023 15:47:59 -0500 Subject: [PATCH 7/7] Update DevExtension property checks --- .../tools/gradle/tasks/DevTask.groovy | 46 ++++++------------- 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy index 629b1fe7b..263bb3c95 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy @@ -1344,44 +1344,26 @@ class DevTask extends AbstractFeatureTask { } } - if (containerfile == null && dockerfile == null) { - File buildContainerfileSetting = project.liberty.dev.containerfile; - File buildDockerfileSetting = project.liberty.dev.dockerfile; // get from build.gradle - if (buildContainerfileSetting != null) { - setContainerfile(buildContainerfileSetting.getAbsolutePath()); // setContainerfile will convert it to canonical path - } else if (buildDockerfileSetting != null) { - setContainerfile(buildDockerfileSetting.getAbsolutePath()); - } + File buildContainerfileSetting = project.liberty.dev.containerfile == null ? project.liberty.dev.dockerfile : project.liberty.dev.containerfile; // get from build.gradle + if (buildContainerfileSetting != null) { + setContainerfile(buildContainerfileSetting.getAbsolutePath()); // setContainerfile will convert it to canonical path } - if (containerBuildContext == null && dockerBuildContext == null) { - File buildContainerBuildContextSetting = project.liberty.dev.containerBuildContext; // get from build.gradle - File buildDockerBuildContextSetting = project.liberty.dev.dockerBuildContext; - if (buildContainerBuildContextSetting != null) { - setContainerBuildContext(buildContainerBuildContextSetting.getAbsolutePath()); // setContainerBuildContext will convert it to canonical path - } else if (buildDockerBuildContextSetting != null) { - setContainerBuildContext(buildDockerBuildContextSetting.getAbsolutePath()); - } + File buildContainerBuildContextSetting = project.liberty.dev.containerBuildContext == null ? project.liberty.dev.dockerBuildContext : project.liberty.dev.containerBuildContext; // get from build.gradle + if (buildContainerBuildContextSetting != null) { + setContainerBuildContext(buildContainerBuildContextSetting.getAbsolutePath()); // setContainerBuildContext will convert it to canonical path } - if (containerRunOpts == null && dockerRunOpts == null) { - String buildContainerRunOptsSetting = project.liberty.dev.containerRunOpts; - String buildDockerRunOptsSetting = project.liberty.dev.dockerRunOpts; // get from build.gradle - if (buildContainerRunOptsSetting != null) { - setContainerRunOpts(buildContainerRunOptsSetting); - } else if (buildDockerRunOptsSetting != null) { - setContainerRunOpts(buildDockerRunOptsSetting); - } + + String buildContainerRunOptsSetting = project.liberty.dev.containerRunOpts == null ? project.liberty.dev.dockerRunOpts : project.liberty.dev.containerRunOpts; // get from build.gradle + if (buildContainerRunOptsSetting != null) { + setContainerRunOpts(buildContainerRunOptsSetting); } - if (containerBuildTimeout == 0 && dockerBuildTimeout == 0) { - String buildContainerBuildTimeoutSetting = project.liberty.dev.containerBuildTimeout; - String buildDockerBuildTimeoutSetting = project.liberty.dev.dockerBuildTimeout; // get from build.gradle - if (buildContainerBuildTimeoutSetting != null) { - setContainerBuildTimeout(buildContainerBuildTimeoutSetting); - } else if (buildDockerBuildTimeoutSetting != null) { - setContainerBuildTimeout(buildDockerBuildTimeoutSetting); - } + + String buildContainerBuildTimeoutSetting = project.liberty.dev.containerBuildTimeout == null ? project.liberty.dev.dockerBuildTimeout : project.liberty.dev.containerBuildTimeout; // get from build.gradle + if (buildContainerBuildTimeoutSetting != null) { + setContainerBuildTimeout(buildContainerBuildTimeoutSetting); } if (skipDefaultPorts == null) {