diff --git a/.ci/get-docker-com.sh b/.ci/get-docker-com.sh deleted file mode 100755 index d9c0142a2..000000000 --- a/.ci/get-docker-com.sh +++ /dev/null @@ -1,313 +0,0 @@ -#!/bin/sh -set -e -# -# This script is meant for quick & easy install via: -# 'curl -sSL https://get.docker.com/ | sh' -# or: -# 'wget -qO- https://get.docker.com/ | sh' -# -# For test builds (ie. release candidates): -# 'curl -fsSL https://test.docker.com/ | sh' -# or: -# 'wget -qO- https://test.docker.com/ | sh' -# -# For experimental builds: -# 'curl -fsSL https://experimental.docker.com/ | sh' -# or: -# 'wget -qO- https://experimental.docker.com/ | sh' -# -# Docker Maintainers: -# To update this script on https://get.docker.com, -# use hack/release.sh during a normal release, -# or the following one-liner for script hotfixes: -# aws s3 cp --acl public-read hack/install.sh s3://get.docker.com/index -# - -url="https://get.docker.com/" -apt_url="https://apt.dockerproject.org" -yum_url="https://yum.dockerproject.org" -gpg_fingerprint="58118E89F3A912897C070ADBF76221572C52609D" - -key_servers=" -ha.pool.sks-keyservers.net -pgp.mit.edu -keyserver.ubuntu.com -" - -command_exists() { - command -v "$@" > /dev/null 2>&1 -} - -semverParse() { - major="${1%%.*}" - minor="${1#$major.}" - minor="${minor%%.*}" - patch="${1#$major.$minor.}" - patch="${patch%%[-.]*}" -} - -do_install() { - case "$(uname -m)" in - *64) - ;; - *) - cat >&2 <<-'EOF' - Error: you are not using a 64bit platform. - Docker currently only supports 64bit platforms. - EOF - exit 1 - ;; - esac - - user="$(id -un 2>/dev/null || true)" - - sh_c='sh -c' - if [ "$user" != 'root' ]; then - if command_exists sudo; then - sh_c='sudo -E sh -c' - elif command_exists su; then - sh_c='su -c' - else - cat >&2 <<-'EOF' - Error: this installer needs the ability to run commands as root. - We are unable to find either "sudo" or "su" available to make this happen. - EOF - exit 1 - fi - fi - - curl='' - if command_exists curl; then - curl='curl -sSL' - elif command_exists wget; then - curl='wget -qO-' - elif command_exists busybox && busybox --list-modules | grep -q wget; then - curl='busybox wget -qO-' - fi - - # check to see which repo they are trying to install from - if [ -z "$repo" ]; then - repo='main' - if [ "https://test.docker.com/" = "$url" ]; then - repo='testing' - elif [ "https://experimental.docker.com/" = "$url" ]; then - repo='experimental' - fi - fi - - # perform some very rudimentary platform detection - lsb_dist='' - dist_version='' - if command_exists lsb_release; then - lsb_dist="$(lsb_release -si)" - fi - if [ -z "$lsb_dist" ] && [ -r /etc/lsb-release ]; then - lsb_dist="$(. /etc/lsb-release && echo "$DISTRIB_ID")" - fi - if [ -z "$lsb_dist" ] && [ -r /etc/debian_version ]; then - lsb_dist='debian' - fi - if [ -z "$lsb_dist" ] && [ -r /etc/fedora-release ]; then - lsb_dist='fedora' - fi - if [ -z "$lsb_dist" ] && [ -r /etc/oracle-release ]; then - lsb_dist='oracleserver' - fi - if [ -z "$lsb_dist" ]; then - if [ -r /etc/centos-release ] || [ -r /etc/redhat-release ]; then - lsb_dist='centos' - fi - fi - if [ -z "$lsb_dist" ] && [ -r /etc/os-release ]; then - lsb_dist="$(. /etc/os-release && echo "$ID")" - fi - - lsb_dist="$(echo "$lsb_dist" | tr '[:upper:]' '[:lower:]')" - - case "$lsb_dist" in - - ubuntu) - if command_exists lsb_release; then - dist_version="$(lsb_release --codename | cut -f2)" - fi - if [ -z "$dist_version" ] && [ -r /etc/lsb-release ]; then - dist_version="$(. /etc/lsb-release && echo "$DISTRIB_CODENAME")" - fi - ;; - - debian) - dist_version="$(cat /etc/debian_version | sed 's/\/.*//' | sed 's/\..*//')" - case "$dist_version" in - 8) - dist_version="jessie" - ;; - 7) - dist_version="wheezy" - ;; - esac - ;; - - oracleserver) - # need to switch lsb_dist to match yum repo URL - lsb_dist="oraclelinux" - dist_version="$(rpm -q --whatprovides redhat-release --queryformat "%{VERSION}\n" | sed 's/\/.*//' | sed 's/\..*//' | sed 's/Server*//')" - ;; - - fedora|centos) - dist_version="$(rpm -q --whatprovides redhat-release --queryformat "%{VERSION}\n" | sed 's/\/.*//' | sed 's/\..*//' | sed 's/Server*//')" - ;; - - *) - if command_exists lsb_release; then - dist_version="$(lsb_release --codename | cut -f2)" - fi - if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then - dist_version="$(. /etc/os-release && echo "$VERSION_ID")" - fi - ;; - - - esac - - - # Run setup for each distro accordingly - case "$lsb_dist" in - ubuntu|debian) - export DEBIAN_FRONTEND=noninteractive - - did_apt_get_update= - apt_get_update() { - if [ -z "$did_apt_get_update" ]; then - ( set -x; $sh_c 'sleep 3; apt-get update' ) - did_apt_get_update=1 - fi - } - - # aufs is preferred over devicemapper; try to ensure the driver is available. - if ! grep -q aufs /proc/filesystems && ! $sh_c 'modprobe aufs'; then - if uname -r | grep -q -- '-generic' && dpkg -l 'linux-image-*-generic' | grep -qE '^ii|^hi' 2>/dev/null; then - kern_extras="linux-image-extra-$(uname -r) linux-image-extra-virtual" - - apt_get_update - ( set -x; $sh_c 'sleep 3; apt-get install -y -q '"$kern_extras" ) || true - - if ! grep -q aufs /proc/filesystems && ! $sh_c 'modprobe aufs'; then - echo >&2 'Warning: tried to install '"$kern_extras"' (for AUFS)' - echo >&2 ' but we still have no AUFS. Docker may not work. Proceeding anyways!' - ( set -x; sleep 10 ) - fi - else - echo >&2 'Warning: current kernel is not supported by the linux-image-extra-virtual' - echo >&2 ' package. We have no AUFS support. Consider installing the packages' - echo >&2 ' linux-image-virtual kernel and linux-image-extra-virtual for AUFS support.' - ( set -x; sleep 10 ) - fi - fi - - # install apparmor utils if they're missing and apparmor is enabled in the kernel - # otherwise Docker will fail to start - if [ "$(cat /sys/module/apparmor/parameters/enabled 2>/dev/null)" = 'Y' ]; then - if command -v apparmor_parser >/dev/null 2>&1; then - echo 'apparmor is enabled in the kernel and apparmor utils were already installed' - else - echo 'apparmor is enabled in the kernel, but apparmor_parser missing' - apt_get_update - ( set -x; $sh_c 'sleep 3; apt-get install -y -q apparmor' ) - fi - fi - - if [ ! -e /usr/lib/apt/methods/https ]; then - apt_get_update - ( set -x; $sh_c 'sleep 3; apt-get install -y -q apt-transport-https ca-certificates' ) - fi - if [ -z "$curl" ]; then - apt_get_update - ( set -x; $sh_c 'sleep 3; apt-get install -y -q curl ca-certificates' ) - curl='curl -sSL' - fi - ( - set -x - for key_server in $key_servers ; do - $sh_c "apt-key adv --keyserver hkp://${key_server}:80 --recv-keys ${gpg_fingerprint}" && break - done - $sh_c "apt-key adv -k ${gpg_fingerprint} >/dev/null" - $sh_c "mkdir -p /etc/apt/sources.list.d" - $sh_c "echo deb [arch=$(dpkg --print-architecture)] ${apt_url}/repo ${lsb_dist}-${dist_version} ${repo} > /etc/apt/sources.list.d/docker.list" - $sh_c 'sleep 3; apt-get update' - if [ -z "$DOCKER_VERSION" ]; then - $sh_c 'apt-get -o Dpkg::Options::="--force-confnew" install -y -q docker-engine' - else - $sh_c "apt-get -o Dpkg::Options::=\"--force-confnew\" install -y -q docker-engine=$DOCKER_VERSION" - fi - ) - exit 0 - ;; - - fedora|centos|oraclelinux) - $sh_c "cat >/etc/yum.repos.d/docker-${repo}.repo" <<-EOF - [docker-${repo}-repo] - name=Docker ${repo} Repository - baseurl=${yum_url}/repo/${repo}/${lsb_dist}/${dist_version} - enabled=1 - gpgcheck=1 - gpgkey=${yum_url}/gpg - EOF - if [ "$lsb_dist" = "fedora" ] && [ "$dist_version" -ge "22" ]; then - ( - set -x - $sh_c 'sleep 3; dnf -y -q install docker-engine' - ) - else - ( - set -x - $sh_c 'sleep 3; yum -y -q install docker-engine' - ) - fi - exit 0 - ;; - gentoo) - if [ "$url" = "https://test.docker.com/" ]; then - # intentionally mixed spaces and tabs here -- tabs are stripped by "<<-'EOF'", spaces are kept in the output - cat >&2 <<-'EOF' - - You appear to be trying to install the latest nightly build in Gentoo.' - The portage tree should contain the latest stable release of Docker, but' - if you want something more recent, you can always use the live ebuild' - provided in the "docker" overlay available via layman. For more' - instructions, please see the following URL:' - - https://github.com/tianon/docker-overlay#using-this-overlay' - - After adding the "docker" overlay, you should be able to:' - - emerge -av =app-emulation/docker-9999' - - EOF - exit 1 - fi - - ( - set -x - $sh_c 'sleep 3; emerge app-emulation/docker' - ) - exit 0 - ;; - esac - - # intentionally mixed spaces and tabs here -- tabs are stripped by "<<-'EOF'", spaces are kept in the output - cat >&2 <<-'EOF' - - Either your platform is not easily detectable, is not supported by this - installer script (yet - PRs welcome! [hack/install.sh]), or does not yet have - a package for Docker. Please visit the following URL for more detailed - installation instructions: - - https://docs.docker.com/engine/installation/ - - EOF - exit 1 -} - -# wrapped up in a function so that we have some protection against only getting -# half the file during "curl | sh" -do_install diff --git a/.ci/setup_docker.sh b/.ci/setup_docker.sh deleted file mode 100755 index df9cf205a..000000000 --- a/.ci/setup_docker.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -set -exu - -DOCKER_VERSION="${DOCKER_VERSION:-}" -DOCKER_HOST="${DOCKER_HOST:-}" - -if [[ -n $DOCKER_VERSION ]]; then - sudo -E apt-get -q -y --purge remove docker-engine docker-ce - - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" - sudo apt-get update - sudo apt-cache madison docker-ce - sudo apt-get install "docker-ce=$DOCKER_VERSION" -fi - -if [[ -n $DOCKER_HOST ]]; then - sudo mkdir -p /etc/systemd/system/docker.service.d/ - - echo " -[Service] -ExecStart= -ExecStart=/usr/bin/dockerd -H $DOCKER_HOST -H unix:///var/run/docker.sock - " | sudo tee -a /etc/systemd/system/docker.service.d/override.conf - - sudo systemctl daemon-reload - sudo service docker restart || sudo journalctl -xe - sudo service docker status -fi - -while (! docker ps ); do - echo "Waiting for Docker to launch..." - sleep 1 -done -docker version -docker info - -docker run --rm hello-world diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7dec19aef..9bcef2d88 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,5 +4,13 @@ updates: directory: "/" schedule: interval: weekly + day: monday open-pull-requests-limit: 99 rebase-strategy: disabled + ignore: + - dependency-name: "org.glassfish.jersey.connectors:jersey-apache-connector" + update-types: [ "version-update:semver-major" ] + - dependency-name: "org.glassfish.jersey.core:jersey-client" + update-types: [ "version-update:semver-major" ] + - dependency-name: "org.glassfish.jersey.inject:jersey-hk2" + update-types: [ "version-update:semver-major" ] diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index d03b3f5f5..f570cce43 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -1,5 +1,5 @@ tag-template: $NEXT_PATCH_VERSION -name-template: '$NEXT_PATCH_VERSION 🌈' +name-template: '$NEXT_PATCH_VERSION' categories: - title: '🚀 Features' labels: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f1ef43de..5a87a3c3f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,34 +3,53 @@ name: CI on: pull_request: {} push: { branches: [ main ] } + workflow_dispatch: jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: include: - { name: "default", javaVersion: 8 } - { name: "default", javaVersion: 17 } - - { name: "over TCP", dockerHost: "tcp://127.0.0.1:2375", javaVersion: 8 } - - { name: "Docker 19.03.9", dockerVersion: "5:19.03.9~3-0~ubuntu-focal", javaVersion: 8 } - + - { name: "default", javaVersion: 21 } steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v6 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v5 with: java-version: ${{matrix.javaVersion}} distribution: temurin + cache: maven - name: Configure Docker + id: setup_docker + uses: docker/setup-docker-action@v4 + with: + channel: stable + - name: Build with Maven env: - DOCKER_VERSION: ${{matrix.dockerVersion}} - DOCKER_HOST: ${{matrix.dockerHost}} - run: .ci/setup_docker.sh + DOCKER_HOST: ${{steps.setup_docker.outputs.sock}} + run: ./mvnw --no-transfer-progress verify + + tcp: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 + - name: Set up JDK + uses: actions/setup-java@v5 + with: + java-version: 8 + distribution: temurin + cache: maven + - name: Configure Docker + id: setup_docker + uses: docker/setup-docker-action@v4 + with: + channel: stable + tcp-port: 2375 - name: Build with Maven env: - DOCKER_HOST: ${{matrix.dockerHost}} - run: | - [[ -z "$DOCKER_HOST" ]] && unset DOCKER_HOST - ./mvnw --no-transfer-progress verify + DOCKER_HOST: ${{steps.setup_docker.outputs.tcp}} + run: ./mvnw --no-transfer-progress verify diff --git a/.github/workflows/main.yml b/.github/workflows/release-drafter.yml similarity index 100% rename from .github/workflows/main.yml rename to .github/workflows/release-drafter.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7ee128801..d3ddc4b2e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,18 +8,25 @@ on: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v6 - name: Set up JDK 8 - uses: actions/setup-java@v3 + uses: actions/setup-java@v5 with: java-version: 8 distribution: temurin + server-id: central + server-username: MAVEN_USERNAME + server-password: MAVEN_CENTRAL_TOKEN + gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE - name: Set version run: ./mvnw versions:set -DnewVersion="${{github.event.release.tag_name}}" # TODO check main's CI status - name: Deploy with Maven env: - MAVEN_DEPLOYMENT_REPOSITORY: ${{ secrets.MAVEN_DEPLOYMENT_REPOSITORY }} - run: ./mvnw deploy -DaltReleaseDeploymentRepository="$MAVEN_DEPLOYMENT_REPOSITORY" -DskipTests + MAVEN_USERNAME: ${{ secrets.SONATYPE_CENTRAL_USERNAME }} + MAVEN_CENTRAL_TOKEN: ${{ secrets.SONATYPE_CENTRAL_PASSWORD }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} + run: ./mvnw -Prelease deploy -DskipTests diff --git a/.gitignore b/.gitignore index 201acaa5f..006641e8c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ # Ignore all build/dist directories target +dependency-reduced-pom.xml # Ignore InteliJ Idea project files .idea/ diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index b901097f2..000000000 --- a/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2007-present the original author or authors. - * - * 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. - */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.6"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 2cc7d4a55..000000000 Binary files a/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 642d572ce..8dea6c227 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,2 +1,3 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar +wrapperVersion=3.3.4 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip diff --git a/circle.sh b/circle.sh index c84ca3fe6..b5b7cdbb0 100755 --- a/circle.sh +++ b/circle.sh @@ -6,7 +6,7 @@ case "$1" in mkdir .docker cp $CIRCLE_PROJECT_REPONAME/etc/certs/* .docker - # configure docker deamon to use SSL and provide the path to the certificates + # configure docker daemon to use SSL and provide the path to the certificates docker_opts='DOCKER_OPTS="$DOCKER_OPTS -H tcp://127.0.0.1:2376 --tlsverify --tlscacert='$HOME'/.docker/ca.pem --tlscert='$HOME'/.docker/server-cert.pem --tlskey='$HOME'/.docker/server-key.pem"' sudo sh -c "echo '$docker_opts' >> /etc/default/docker" diff --git a/docker-java-api/pom.xml b/docker-java-api/pom.xml index dca404bc1..dda682ab1 100644 --- a/docker-java-api/pom.xml +++ b/docker-java-api/pom.xml @@ -23,7 +23,7 @@ com.fasterxml.jackson.core jackson-annotations - ${jackson.version} + 2.20 @@ -42,7 +42,7 @@ org.projectlombok lombok - 1.18.22 + 1.18.38 provided @@ -50,14 +50,14 @@ org.junit.jupiter junit-jupiter - 5.7.2 + 5.13.4 test com.tngtech.archunit archunit-junit5 - 0.18.0 + 1.4.1 test @@ -81,6 +81,22 @@ + + com.github.siom79.japicmp + japicmp-maven-plugin + + + + com.github.dockerjava.api.command.UpdateContainerCmd#getCpuPeriod() + com.github.dockerjava.api.command.UpdateContainerCmd#withCpuPeriod(java.lang.Integer) + com.github.dockerjava.api.command.UpdateContainerCmd#getCpuQuota() + com.github.dockerjava.api.command.UpdateContainerCmd#withCpuQuota(java.lang.Integer) + com.github.dockerjava.api.command.InspectContainerResponse#getSizeRootFs() + com.github.dockerjava.api.command.InspectContainerResponse#getSizeRw() + + + + diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/DockerClient.java b/docker-java-api/src/main/java/com/github/dockerjava/api/DockerClient.java index e5f57e1bb..bf6acdee0 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/DockerClient.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/DockerClient.java @@ -6,6 +6,7 @@ import com.github.dockerjava.api.command.CommitCmd; import com.github.dockerjava.api.command.ConnectToNetworkCmd; import com.github.dockerjava.api.command.ContainerDiffCmd; +import com.github.dockerjava.api.command.ExportContainerCmd; import com.github.dockerjava.api.command.CopyArchiveFromContainerCmd; import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; import com.github.dockerjava.api.command.CopyFileFromContainerCmd; @@ -26,6 +27,7 @@ import com.github.dockerjava.api.command.InspectContainerCmd; import com.github.dockerjava.api.command.InspectExecCmd; import com.github.dockerjava.api.command.InspectImageCmd; +import com.github.dockerjava.api.command.ImageHistoryCmd; import com.github.dockerjava.api.command.InspectNetworkCmd; import com.github.dockerjava.api.command.InspectServiceCmd; import com.github.dockerjava.api.command.InspectSwarmCmd; @@ -142,6 +144,8 @@ public interface DockerClient extends Closeable { InspectImageCmd inspectImageCmd(@Nonnull String imageId); + ImageHistoryCmd imageHistoryCmd(@Nonnull String imageId); + /** * @param name * The name, e.g. "alexec/busybox" or just "busybox" if you want to default. Not null. @@ -230,6 +234,15 @@ public interface DockerClient extends Closeable { ContainerDiffCmd containerDiffCmd(@Nonnull String containerId); + /** + * Export the contents of a container's filesystem as a tar archive. + * + * @param containerId + * id of the container + * @return created command + */ + ExportContainerCmd exportContainerCmd(@Nonnull String containerId); + StopContainerCmd stopContainerCmd(@Nonnull String containerId); KillContainerCmd killContainerCmd(@Nonnull String containerId); diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/DockerClientDelegate.java b/docker-java-api/src/main/java/com/github/dockerjava/api/DockerClientDelegate.java index 5de64641f..da600bd4d 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/DockerClientDelegate.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/DockerClientDelegate.java @@ -6,6 +6,7 @@ import com.github.dockerjava.api.command.CommitCmd; import com.github.dockerjava.api.command.ConnectToNetworkCmd; import com.github.dockerjava.api.command.ContainerDiffCmd; +import com.github.dockerjava.api.command.ExportContainerCmd; import com.github.dockerjava.api.command.CopyArchiveFromContainerCmd; import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; import com.github.dockerjava.api.command.CopyFileFromContainerCmd; @@ -26,6 +27,7 @@ import com.github.dockerjava.api.command.InspectContainerCmd; import com.github.dockerjava.api.command.InspectExecCmd; import com.github.dockerjava.api.command.InspectImageCmd; +import com.github.dockerjava.api.command.ImageHistoryCmd; import com.github.dockerjava.api.command.InspectNetworkCmd; import com.github.dockerjava.api.command.InspectServiceCmd; import com.github.dockerjava.api.command.InspectSwarmCmd; @@ -179,6 +181,11 @@ public InspectImageCmd inspectImageCmd(@Nonnull String imageId) { return getDockerClient().inspectImageCmd(imageId); } + @Override + public ImageHistoryCmd imageHistoryCmd(@Nonnull String imageId) { + return getDockerClient().imageHistoryCmd(imageId); + } + @Override public SaveImageCmd saveImageCmd(@Nonnull String name) { return getDockerClient().saveImageCmd(name); @@ -270,6 +277,11 @@ public ContainerDiffCmd containerDiffCmd(@Nonnull String containerId) { return getDockerClient().containerDiffCmd(containerId); } + @Override + public ExportContainerCmd exportContainerCmd(@Nonnull String containerId) { + return getDockerClient().exportContainerCmd(containerId); + } + @Override public StopContainerCmd stopContainerCmd(@Nonnull String containerId) { return getDockerClient().stopContainerCmd(containerId); diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/BuildImageResultCallback.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/BuildImageResultCallback.java index 0bb0f0884..9db21a6c4 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/command/BuildImageResultCallback.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/BuildImageResultCallback.java @@ -31,7 +31,7 @@ public void onNext(BuildResponseItem item) { } else if (item.isErrorIndicated()) { this.error = item.getError(); } - LOGGER.debug(item.toString()); + LOGGER.debug("{}", item); } /** @@ -67,14 +67,14 @@ public String awaitImageId(long timeout, TimeUnit timeUnit) { } private String getImageId() { - if (imageId != null) { - return imageId; + if (error != null) { + throw new DockerClientException("Could not build image: " + error); } - if (error == null) { - throw new DockerClientException("Could not build image"); + if (imageId != null) { + return imageId; } - throw new DockerClientException("Could not build image: " + error); + throw new DockerClientException("Could not build image"); } } diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/DelegatingDockerCmdExecFactory.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/DelegatingDockerCmdExecFactory.java index 161ff2c29..d7cdd97a9 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/command/DelegatingDockerCmdExecFactory.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/DelegatingDockerCmdExecFactory.java @@ -100,6 +100,11 @@ public InspectImageCmd.Exec createInspectImageCmdExec() { return getDockerCmdExecFactory().createInspectImageCmdExec(); } + @Override + public ImageHistoryCmd.Exec createImageHistoryCmdExec() { + return getDockerCmdExecFactory().createImageHistoryCmdExec(); + } + @Override public ListContainersCmd.Exec createListContainersCmdExec() { return getDockerCmdExecFactory().createListContainersCmdExec(); @@ -175,6 +180,11 @@ public ContainerDiffCmd.Exec createContainerDiffCmdExec() { return getDockerCmdExecFactory().createContainerDiffCmdExec(); } + @Override + public ExportContainerCmd.Exec createExportContainerCmdExec() { + return getDockerCmdExecFactory().createExportContainerCmdExec(); + } + @Override public KillContainerCmd.Exec createKillContainerCmdExec() { return getDockerCmdExecFactory().createKillContainerCmdExec(); diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java index cedf6d40d..bdf39269d 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java @@ -37,6 +37,8 @@ public interface DockerCmdExecFactory extends Closeable { InspectImageCmd.Exec createInspectImageCmdExec(); + ImageHistoryCmd.Exec createImageHistoryCmdExec(); + ListContainersCmd.Exec createListContainersCmdExec(); CreateContainerCmd.Exec createCreateContainerCmdExec(); @@ -71,6 +73,8 @@ public interface DockerCmdExecFactory extends Closeable { ContainerDiffCmd.Exec createContainerDiffCmdExec(); + ExportContainerCmd.Exec createExportContainerCmdExec(); + KillContainerCmd.Exec createKillContainerCmdExec(); UpdateContainerCmd.Exec createUpdateContainerCmdExec(); diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/ExportContainerCmd.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/ExportContainerCmd.java new file mode 100644 index 000000000..bef73d261 --- /dev/null +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/ExportContainerCmd.java @@ -0,0 +1,31 @@ +package com.github.dockerjava.api.command; + +import java.io.InputStream; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; + +import com.github.dockerjava.api.exception.NotFoundException; + +/** + * Export the contents of a container as a tar archive. + */ +public interface ExportContainerCmd extends SyncDockerCmd { + + @CheckForNull + String getContainerId(); + + ExportContainerCmd withContainerId(@Nonnull String containerId); + + /** + * Its the responsibility of the caller to consume and/or close the {@link InputStream} to prevent connection leaks. + * + * @throws NotFoundException + * No such container + */ + @Override + InputStream exec() throws NotFoundException; + + interface Exec extends DockerCmdSyncExec { + } +} diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/ImageHistoryCmd.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/ImageHistoryCmd.java new file mode 100644 index 000000000..d93796ad2 --- /dev/null +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/ImageHistoryCmd.java @@ -0,0 +1,31 @@ +package com.github.dockerjava.api.command; + +import java.util.List; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; + +import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.api.model.ImageHistory; + +/** + * Get the history of an image. + */ +public interface ImageHistoryCmd extends SyncDockerCmd> { + + @CheckForNull + String getImageId(); + + ImageHistoryCmd withImageId(@Nonnull String imageId); + + /** + * @throws NotFoundException + * No such image + */ + @Override + List exec() throws NotFoundException; + + interface Exec extends DockerCmdSyncExec> { + } + +} diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java index 05492c51f..f06bd4ed9 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java @@ -61,7 +61,10 @@ public class InspectContainerResponse extends DockerObject { private String id; @JsonProperty("SizeRootFs") - private Integer sizeRootFs; + private Long sizeRootFs; + + @JsonProperty("SizeRw") + private Long sizeRw; @JsonProperty("Image") private String imageId; @@ -121,10 +124,14 @@ public String getId() { return id; } - public Integer getSizeRootFs() { + public Long getSizeRootFs() { return sizeRootFs; } + public Long getSizeRw() { + return sizeRw; + } + public String getCreated() { return created; } diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/ListImagesCmd.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/ListImagesCmd.java index cc60a5bcc..99a9fc200 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/command/ListImagesCmd.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/ListImagesCmd.java @@ -26,6 +26,11 @@ public interface ListImagesCmd extends SyncDockerCmd> { */ ListImagesCmd withShowAll(Boolean showAll); + /** + * Filter images by name + * @deprecated use {@link #withFilter(String, Collection)} + */ + @Deprecated ListImagesCmd withImageNameFilter(String imageName); /** diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/LoadImageCallback.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/LoadImageCallback.java index 741598465..80cca18de 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/command/LoadImageCallback.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/LoadImageCallback.java @@ -22,7 +22,7 @@ public void onNext(LoadResponseItem item) { this.error = item.getError(); } - LOGGER.debug(item.toString()); + LOGGER.debug("{}", item); } public String awaitMessage() { diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/PullImageResultCallback.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/PullImageResultCallback.java index a4e9e9f9b..5980ce3df 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/command/PullImageResultCallback.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/PullImageResultCallback.java @@ -41,7 +41,7 @@ public void onNext(PullResponseItem item) { handleDockerClientResponse(item); } - LOGGER.debug(item.toString()); + LOGGER.debug("{}", item); } private void checkForDockerSwarmResponse(PullResponseItem item) { diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/RestartContainerCmd.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/RestartContainerCmd.java index 5f60f1125..372456813 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/command/RestartContainerCmd.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/RestartContainerCmd.java @@ -8,9 +8,8 @@ /** * Restart a running container. * - * @param timeout - * - Timeout in seconds before killing the container. Defaults to 10 seconds. - * + * @param signal - Signal to send to the container as an integer or string (e.g. SIGINT). + * @param timeout - Timeout in seconds before killing the container. Defaults to 10 seconds. */ public interface RestartContainerCmd extends SyncDockerCmd { @@ -20,6 +19,12 @@ public interface RestartContainerCmd extends SyncDockerCmd { @CheckForNull Integer getTimeout(); + /** + * @since {@link com.github.dockerjava.core.RemoteApiVersion#VERSION_1_42} + */ + @CheckForNull + String getSignal(); + RestartContainerCmd withContainerId(@Nonnull String containerId); /** @@ -32,9 +37,10 @@ default RestartContainerCmd withtTimeout(Integer timeout) { RestartContainerCmd withTimeout(Integer timeout); + RestartContainerCmd withSignal(String signal); + /** - * @throws NotFoundException - * No such container + * @throws NotFoundException No such container */ @Override Void exec() throws NotFoundException; diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/UpdateContainerCmd.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/UpdateContainerCmd.java index 82fbca5f8..d53bcdcdf 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/command/UpdateContainerCmd.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/UpdateContainerCmd.java @@ -1,9 +1,16 @@ package com.github.dockerjava.api.command; +import com.github.dockerjava.api.model.BlkioRateDevice; +import com.github.dockerjava.api.model.BlkioWeightDevice; +import com.github.dockerjava.api.model.Device; +import com.github.dockerjava.api.model.DeviceRequest; +import com.github.dockerjava.api.model.RestartPolicy; +import com.github.dockerjava.api.model.Ulimit; import com.github.dockerjava.api.model.UpdateContainerResponse; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; +import java.util.List; /** * @author Kanstantsin Shautsou @@ -13,22 +20,47 @@ public interface UpdateContainerCmd extends SyncDockerCmd getBlkioWeightDevice(); + + UpdateContainerCmd withBlkioWeightDevice(List blkioWeightDevice); @CheckForNull - Integer getCpuPeriod(); + List getBlkioDeviceReadBps(); - UpdateContainerCmd withCpuPeriod(Integer cpuPeriod); + UpdateContainerCmd withBlkioDeviceReadBps(List blkioDeviceReadBps); @CheckForNull - Integer getCpuQuota(); + List getBlkioDeviceWriteBps(); - UpdateContainerCmd withCpuQuota(Integer cpuQuota); + UpdateContainerCmd withBlkioDeviceWriteBps(List blkioDeviceWriteBps); + + @CheckForNull + List getBlkioDeviceReadIOps(); + + UpdateContainerCmd withBlkioDeviceReadIOps(List blkioDeviceReadIOps); + + @CheckForNull + List getBlkioDeviceWriteIOps(); + + UpdateContainerCmd withBlkioDeviceWriteIOps(List blkioDeviceWriteIOps); + + @CheckForNull + Long getCpuPeriod(); + + UpdateContainerCmd withCpuPeriod(Long cpuPeriod); + + @CheckForNull + Long getCpuQuota(); + + UpdateContainerCmd withCpuQuota(Long cpuQuota); @CheckForNull String getCpusetCpus(); @@ -45,6 +77,31 @@ public interface UpdateContainerCmd extends SyncDockerCmd getDevices(); + + UpdateContainerCmd withDevices(List devices); + + @CheckForNull + List getDeviceCgroupRules(); + + UpdateContainerCmd withDeviceCgroupRules(List deviceCgroupRules); + + @CheckForNull + List getDeviceRequests(); + + UpdateContainerCmd withDeviceRequests(List deviceRequests); + @CheckForNull Long getKernelMemory(); @@ -65,6 +122,36 @@ public interface UpdateContainerCmd extends SyncDockerCmd getUlimits(); + + UpdateContainerCmd withUlimits(List ulimits); + + @CheckForNull + RestartPolicy getRestartPolicy(); + + UpdateContainerCmd withRestartPolicy(RestartPolicy restartPolicy); + interface Exec extends DockerCmdSyncExec { } } diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/WaitContainerCmd.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/WaitContainerCmd.java index 3117cf7e4..7b910cd69 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/command/WaitContainerCmd.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/WaitContainerCmd.java @@ -2,9 +2,11 @@ import javax.annotation.CheckForNull; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import com.github.dockerjava.api.async.ResultCallback; import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.api.model.WaitContainerCondition; import com.github.dockerjava.api.model.WaitResponse; /** @@ -20,8 +22,20 @@ public interface WaitContainerCmd extends AsyncDockerCmd> T exec(T resultCallback); diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/command/WaitContainerResultCallback.java b/docker-java-api/src/main/java/com/github/dockerjava/api/command/WaitContainerResultCallback.java index b4a6d3cc6..6cb160151 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/command/WaitContainerResultCallback.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/command/WaitContainerResultCallback.java @@ -27,7 +27,7 @@ public class WaitContainerResultCallback extends ResultCallbackTemplate annotations; + @JsonProperty("CapAdd") private Capability[] capAdd; @@ -304,6 +307,11 @@ public Integer getBlkioWeight() { return blkioWeight; } + @CheckForNull + public Map getAnnotations() { + return annotations; + } + public Capability[] getCapAdd() { return capAdd; } @@ -636,6 +644,11 @@ public HostConfig withBlkioWeightDevice(List blkioWeightDevic return this; } + public HostConfig withAnnotations(Map annotations) { + this.annotations = annotations; + return this; + } + /** * @see #capAdd */ diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/model/ImageHistory.java b/docker-java-api/src/main/java/com/github/dockerjava/api/model/ImageHistory.java new file mode 100644 index 000000000..fb8f5d95c --- /dev/null +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/model/ImageHistory.java @@ -0,0 +1,97 @@ +package com.github.dockerjava.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.annotation.CheckForNull; +import java.io.Serializable; +import java.util.List; + +/** + * Represents an individual image layer information in response to the ImageHistory operation. + */ +@EqualsAndHashCode +@ToString +public class ImageHistory extends DockerObject implements Serializable { + + private static final long serialVersionUID = 1L; + + @JsonProperty("Id") + private String id; + + @JsonProperty("Created") + private Long created; + + @JsonProperty("CreatedBy") + private String createdBy; + + @JsonProperty("Tags") + private List tags; + + @JsonProperty("Size") + private Long size; + + @JsonProperty("Comment") + private String comment; + + @CheckForNull + public String getId() { + return id; + } + + public ImageHistory withId(String id) { + this.id = id; + return this; + } + + @CheckForNull + public Long getCreated() { + return created; + } + + public ImageHistory withCreated(Long created) { + this.created = created; + return this; + } + + @CheckForNull + public String getCreatedBy() { + return createdBy; + } + + public ImageHistory withCreatedBy(String createdBy) { + this.createdBy = createdBy; + return this; + } + + @CheckForNull + public List getTags() { + return tags; + } + + public ImageHistory withTags(List tags) { + this.tags = tags; + return this; + } + + @CheckForNull + public Long getSize() { + return size; + } + + public ImageHistory withSize(Long size) { + this.size = size; + return this; + } + + @CheckForNull + public String getComment() { + return comment; + } + + public ImageHistory withComment(String comment) { + this.comment = comment; + return this; + } +} diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/model/ImageOptions.java b/docker-java-api/src/main/java/com/github/dockerjava/api/model/ImageOptions.java new file mode 100644 index 000000000..bc8b89acb --- /dev/null +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/model/ImageOptions.java @@ -0,0 +1,27 @@ +package com.github.dockerjava.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.io.Serializable; + +/** + * @since {@link RemoteApiVersion#VERSION_1_48} + */ +@EqualsAndHashCode +@ToString +public class ImageOptions extends DockerObject implements Serializable { + private static final long serialVersionUID = 1L; + @JsonProperty("Subpath") + private String subpath; + + public String getSubpath() { + return subpath; + } + + public ImageOptions withSubpath(String subpath) { + this.subpath = subpath; + return this; + } +} diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/model/Info.java b/docker-java-api/src/main/java/com/github/dockerjava/api/model/Info.java index 0752778e3..67348b86b 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/model/Info.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/model/Info.java @@ -97,6 +97,12 @@ public class Info extends DockerObject implements Serializable { @JsonProperty("LoggingDriver") private String loggingDriver; + @JsonProperty("CgroupDriver") + private String cGroupDriver; + + @JsonProperty("CgroupVersion") + private String cGroupVersion; + /** * @since {@link com.github.dockerjava.core.RemoteApiVersion#VERSION_1_20} */ @@ -235,6 +241,9 @@ public class Info extends DockerObject implements Serializable { @JsonProperty("SecurityOptions") private List securityOptions; + @JsonProperty("Runtimes") + private Map runtimes; + /** * @see #architecture */ @@ -483,6 +492,22 @@ public String getLoggingDriver() { return loggingDriver; } + /** + * @see #cGroupDriver + */ + @CheckForNull + public String getCGroupDriver() { + return cGroupDriver; + } + + /** + * @see #cGroupVersion + */ + @CheckForNull + public String getCGroupVersion() { + return cGroupVersion; + } + /** * @see #loggingDriver */ @@ -491,6 +516,22 @@ public Info withLoggingDriver(String loggingDriver) { return this; } + /** + * @see #cGroupDriver + */ + public Info withCGroupDriver(String cGroupDriver) { + this.cGroupDriver = cGroupDriver; + return this; + } + + /** + * @see #cGroupVersion + */ + public Info withCGroupVersion(String cGroupVersion) { + this.cGroupVersion = cGroupVersion; + return this; + } + /** * @see #experimentalBuild */ @@ -1067,7 +1108,33 @@ public Info withIsolation(String isolation) { return this; } + /** + * @see #securityOptions + */ public List getSecurityOptions() { return securityOptions; } + + /** + * @see #securityOptions + */ + public Info withSecurityOptions(List securityOptions) { + this.securityOptions = securityOptions; + return this; + } + + /** + * @see #runtimes + */ + public Map getRuntimes() { + return runtimes; + } + + /** + * @see #runtimes + */ + public Info withRuntimes(Map runtimes) { + this.runtimes = runtimes; + return this; + } } diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/model/Mount.java b/docker-java-api/src/main/java/com/github/dockerjava/api/model/Mount.java index 9bfe9b16e..3f17343c3 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/model/Mount.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/model/Mount.java @@ -57,6 +57,12 @@ public class Mount extends DockerObject implements Serializable { @JsonProperty("TmpfsOptions") private TmpfsOptions tmpfsOptions; + /** + * @since 1.48 + */ + @JsonProperty("ImageOptions") + private ImageOptions imageOptions; + /** * @see #type */ @@ -177,4 +183,23 @@ public Mount withTmpfsOptions(TmpfsOptions tmpfsOptions) { } return this; } + + /** + * @see #imageOptions + */ + @CheckForNull + public ImageOptions getImageOptions() { + return imageOptions; + } + + /** + * @see #imageOptions + */ + public Mount withImageOptions(ImageOptions imageOptions) { + this.imageOptions = imageOptions; + if (imageOptions != null) { + this.type = MountType.IMAGE; + } + return this; + } } diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/model/MountType.java b/docker-java-api/src/main/java/com/github/dockerjava/api/model/MountType.java index 219782a56..b522c9612 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/model/MountType.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/model/MountType.java @@ -18,6 +18,10 @@ public enum MountType { //@since 1.40 @JsonProperty("npipe") - NPIPE + NPIPE, + + //@since 1.48 + @JsonProperty("image") + IMAGE, } diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/model/Network.java b/docker-java-api/src/main/java/com/github/dockerjava/api/model/Network.java index 7e5110ce6..7e9d3b2fd 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/model/Network.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/model/Network.java @@ -7,6 +7,7 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.List; import java.util.Map; @@ -18,6 +19,9 @@ public class Network extends DockerObject implements Serializable { @JsonProperty("Id") private String id; + @JsonProperty("Created") + private Date created; + @JsonProperty("Name") private String name; @@ -52,6 +56,10 @@ public String getId() { return id; } + public Date getCreated() { + return created; + } + public String getName() { return name; } diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/model/PullResponseItem.java b/docker-java-api/src/main/java/com/github/dockerjava/api/model/PullResponseItem.java index 66a559934..1d3f33c8e 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/model/PullResponseItem.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/model/PullResponseItem.java @@ -19,6 +19,8 @@ public class PullResponseItem extends ResponseItem { private static final String DOWNLOADED_SWARM = ": downloaded"; + private static final String ALREADY_EXISTS = "Already exists"; + /** * Returns whether the status indicates a successful pull operation * @@ -34,7 +36,8 @@ public boolean isPullSuccessIndicated() { getStatus().contains(IMAGE_UP_TO_DATE) || getStatus().contains(DOWNLOADED_NEWER_IMAGE) || getStatus().contains(LEGACY_REGISTRY) || - getStatus().contains(DOWNLOADED_SWARM) + getStatus().contains(DOWNLOADED_SWARM) || + getStatus().contains(ALREADY_EXISTS) ); } } diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/model/RuntimeInfo.java b/docker-java-api/src/main/java/com/github/dockerjava/api/model/RuntimeInfo.java new file mode 100644 index 000000000..c64511cda --- /dev/null +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/model/RuntimeInfo.java @@ -0,0 +1,23 @@ +package com.github.dockerjava.api.model; + +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.io.Serializable; + +@EqualsAndHashCode +@ToString +public class RuntimeInfo extends DockerObject implements Serializable { + private static final long serialVersionUID = 1L; + + private String path; + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + +} diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/model/ServiceUpdateState.java b/docker-java-api/src/main/java/com/github/dockerjava/api/model/ServiceUpdateState.java index e748bbd4a..d22f8999e 100644 --- a/docker-java-api/src/main/java/com/github/dockerjava/api/model/ServiceUpdateState.java +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/model/ServiceUpdateState.java @@ -6,6 +6,9 @@ * @since {@link RemoteApiVersion#VERSION_1_24} */ public enum ServiceUpdateState { + @JsonProperty("unknown") + UNKNOWN, + @JsonProperty("updating") UPDATING, @@ -15,6 +18,12 @@ public enum ServiceUpdateState { @JsonProperty("completed") COMPLETED, + @JsonProperty("rollback_started") + ROLLBACK_STARTED, + + @JsonProperty("rollback_paused") + ROLLBACK_PAUSED, + @JsonProperty("rollback_completed") ROLLBACK_COMPLETED } diff --git a/docker-java-api/src/main/java/com/github/dockerjava/api/model/WaitContainerCondition.java b/docker-java-api/src/main/java/com/github/dockerjava/api/model/WaitContainerCondition.java new file mode 100644 index 000000000..8af0efa35 --- /dev/null +++ b/docker-java-api/src/main/java/com/github/dockerjava/api/model/WaitContainerCondition.java @@ -0,0 +1,26 @@ +package com.github.dockerjava.api.model; + +import javax.annotation.Nonnull; + +/** + * Docker Engine API wait conditions (added in v1.30). + * + * @since {@link RemoteApiVersion#VERSION_1_30} + */ +public enum WaitContainerCondition { + NOT_RUNNING("not-running"), + NEXT_EXIT("next-exit"), + REMOVED("removed"); + + @Nonnull + private final String value; + + WaitContainerCondition(@Nonnull String value) { + this.value = value; + } + + @Nonnull + public String getValue() { + return value; + } +} diff --git a/docker-java-core/pom.xml b/docker-java-core/pom.xml index cec97d25d..89c72c024 100644 --- a/docker-java-core/pom.xml +++ b/docker-java-core/pom.xml @@ -58,7 +58,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson.version} + 2.20.1 @@ -69,7 +69,7 @@ org.bouncycastle - bcpkix-jdk15on + bcpkix-jdk18on ${bouncycastle.version} @@ -99,6 +99,7 @@ 8 8 + true diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/AbstractDockerCmdExecFactory.java b/docker-java-core/src/main/java/com/github/dockerjava/core/AbstractDockerCmdExecFactory.java index e04ab8e3e..9e1d71020 100644 --- a/docker-java-core/src/main/java/com/github/dockerjava/core/AbstractDockerCmdExecFactory.java +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/AbstractDockerCmdExecFactory.java @@ -8,6 +8,7 @@ import com.github.dockerjava.api.command.CommitCmd; import com.github.dockerjava.api.command.ConnectToNetworkCmd; import com.github.dockerjava.api.command.ContainerDiffCmd; +import com.github.dockerjava.api.command.ExportContainerCmd; import com.github.dockerjava.api.command.CopyArchiveFromContainerCmd; import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; import com.github.dockerjava.api.command.CopyFileFromContainerCmd; @@ -29,6 +30,7 @@ import com.github.dockerjava.api.command.InspectContainerCmd; import com.github.dockerjava.api.command.InspectExecCmd; import com.github.dockerjava.api.command.InspectImageCmd; +import com.github.dockerjava.api.command.ImageHistoryCmd; import com.github.dockerjava.api.command.InspectNetworkCmd; import com.github.dockerjava.api.command.InspectServiceCmd; import com.github.dockerjava.api.command.InspectSwarmCmd; @@ -88,6 +90,7 @@ import com.github.dockerjava.core.exec.CommitCmdExec; import com.github.dockerjava.core.exec.ConnectToNetworkCmdExec; import com.github.dockerjava.core.exec.ContainerDiffCmdExec; +import com.github.dockerjava.core.exec.ExportContainerCmdExec; import com.github.dockerjava.core.exec.CopyArchiveFromContainerCmdExec; import com.github.dockerjava.core.exec.CopyArchiveToContainerCmdExec; import com.github.dockerjava.core.exec.CopyFileFromContainerCmdExec; @@ -113,6 +116,7 @@ import com.github.dockerjava.core.exec.InspectContainerCmdExec; import com.github.dockerjava.core.exec.InspectExecCmdExec; import com.github.dockerjava.core.exec.InspectImageCmdExec; +import com.github.dockerjava.core.exec.ImageHistoryCmdExec; import com.github.dockerjava.core.exec.InspectNetworkCmdExec; import com.github.dockerjava.core.exec.InspectServiceCmdExec; import com.github.dockerjava.core.exec.InspectSwarmCmdExec; @@ -281,6 +285,11 @@ public InspectImageCmd.Exec createInspectImageCmdExec() { return new InspectImageCmdExec(getBaseResource(), getDockerClientConfig()); } + @Override + public ImageHistoryCmd.Exec createImageHistoryCmdExec() { + return new ImageHistoryCmdExec(getBaseResource(), getDockerClientConfig()); + } + @Override public ListContainersCmd.Exec createListContainersCmdExec() { return new ListContainersCmdExec(getBaseResource(), getDockerClientConfig()); @@ -361,6 +370,11 @@ public ContainerDiffCmd.Exec createContainerDiffCmdExec() { return new ContainerDiffCmdExec(getBaseResource(), getDockerClientConfig()); } + @Override + public ExportContainerCmd.Exec createExportContainerCmdExec() { + return new ExportContainerCmdExec(getBaseResource(), getDockerClientConfig()); + } + @Override public KillContainerCmd.Exec createKillContainerCmdExec() { return new KillContainerCmdExec(getBaseResource(), getDockerClientConfig()); diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java b/docker-java-core/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java index 8a1f6193a..dad75b360 100644 --- a/docker-java-core/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/DefaultDockerClientConfig.java @@ -5,6 +5,8 @@ import com.github.dockerjava.api.model.AuthConfigurations; import com.github.dockerjava.core.NameParser.HostnameReposName; import com.github.dockerjava.core.NameParser.ReposTag; + +import java.util.Map.Entry; import java.util.Optional; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; @@ -128,9 +130,11 @@ private static Properties loadIncludedDockerProperties(Properties systemProperti } private static void replaceProperties(Properties properties, Properties replacements) { - for (Object objectKey : properties.keySet()) { - String key = objectKey.toString(); - properties.setProperty(key, replaceProperties(properties.getProperty(key), replacements)); + for (Entry entry : properties.entrySet()) { + final String key = entry.getKey().toString(); + // no entry.getValue here because it does not have the same semantics as getProperty (defaults handling) + final String value = properties.getProperty(key); + entry.setValue(replaceProperties(value, replacements)); } } @@ -446,6 +450,9 @@ private void applyContextConfiguration(final String context) { Optional.ofNullable(context) .flatMap(ctx -> DockerContextMetaFile.resolveContextMetaFile(DockerClientConfig.getDefaultObjectMapper(), new File(this.dockerConfig), ctx)); + final Optional dockerContextTLSFile = + Optional.ofNullable(context) + .flatMap(ctx -> DockerContextMetaFile.resolveContextTLSFile(new File(this.dockerConfig), ctx)); if (dockerContextMetaFile.isPresent()) { final Optional dockerEndpoint = @@ -453,14 +460,10 @@ private void applyContextConfiguration(final String context) { if (this.dockerHost == null) { this.dockerHost = dockerEndpoint.map(endpoint -> endpoint.host).map(URI::create).orElse(null); } - if (this.dockerCertPath == null) { - this.dockerCertPath = dockerContextMetaFile.map(metaFile -> metaFile.storage) - .map(storage -> storage.tlsPath) - .filter(file -> new File(file).exists()).orElse(null); - if (this.dockerCertPath != null) { - this.dockerTlsVerify = dockerEndpoint.map(endpoint -> !endpoint.skipTLSVerify).orElse(true); - } - } + } + if (dockerContextTLSFile.isPresent() && this.dockerCertPath == null) { + this.dockerCertPath = dockerContextTLSFile.get().getAbsolutePath(); + this.dockerTlsVerify = true; } } diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/DockerClientImpl.java b/docker-java-core/src/main/java/com/github/dockerjava/core/DockerClientImpl.java index 55f530057..a1ddc2897 100644 --- a/docker-java-core/src/main/java/com/github/dockerjava/core/DockerClientImpl.java +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/DockerClientImpl.java @@ -7,6 +7,7 @@ import com.github.dockerjava.api.command.CommitCmd; import com.github.dockerjava.api.command.ConnectToNetworkCmd; import com.github.dockerjava.api.command.ContainerDiffCmd; +import com.github.dockerjava.api.command.ExportContainerCmd; import com.github.dockerjava.api.command.CopyArchiveFromContainerCmd; import com.github.dockerjava.api.command.CopyArchiveToContainerCmd; import com.github.dockerjava.api.command.CopyFileFromContainerCmd; @@ -28,6 +29,7 @@ import com.github.dockerjava.api.command.InspectContainerCmd; import com.github.dockerjava.api.command.InspectExecCmd; import com.github.dockerjava.api.command.InspectImageCmd; +import com.github.dockerjava.api.command.ImageHistoryCmd; import com.github.dockerjava.api.command.InspectNetworkCmd; import com.github.dockerjava.api.command.InspectServiceCmd; import com.github.dockerjava.api.command.InspectSwarmCmd; @@ -92,6 +94,7 @@ import com.github.dockerjava.core.command.CommitCmdImpl; import com.github.dockerjava.core.command.ConnectToNetworkCmdImpl; import com.github.dockerjava.core.command.ContainerDiffCmdImpl; +import com.github.dockerjava.core.command.ExportContainerCmdImpl; import com.github.dockerjava.core.command.CopyArchiveFromContainerCmdImpl; import com.github.dockerjava.core.command.CopyArchiveToContainerCmdImpl; import com.github.dockerjava.core.command.CopyFileFromContainerCmdImpl; @@ -113,6 +116,7 @@ import com.github.dockerjava.core.command.InspectContainerCmdImpl; import com.github.dockerjava.core.command.InspectExecCmdImpl; import com.github.dockerjava.core.command.InspectImageCmdImpl; +import com.github.dockerjava.core.command.ImageHistoryCmdImpl; import com.github.dockerjava.core.command.InspectServiceCmdImpl; import com.github.dockerjava.core.command.InspectSwarmCmdImpl; import com.github.dockerjava.core.command.InspectVolumeCmdImpl; @@ -375,6 +379,11 @@ public InspectImageCmd inspectImageCmd(String imageId) { return new InspectImageCmdImpl(getDockerCmdExecFactory().createInspectImageCmdExec(), imageId); } + @Override + public ImageHistoryCmd imageHistoryCmd(String imageId) { + return new ImageHistoryCmdImpl(getDockerCmdExecFactory().createImageHistoryCmdExec(), imageId); + } + /** * * CONTAINER API * */ @@ -463,6 +472,11 @@ public ContainerDiffCmd containerDiffCmd(String containerId) { return new ContainerDiffCmdImpl(getDockerCmdExecFactory().createContainerDiffCmdExec(), containerId); } + @Override + public ExportContainerCmd exportContainerCmd(String containerId) { + return new ExportContainerCmdImpl(getDockerCmdExecFactory().createExportContainerCmdExec(), containerId); + } + @Override public StopContainerCmd stopContainerCmd(String containerId) { return new StopContainerCmdImpl(getDockerCmdExecFactory().createStopContainerCmdExec(), containerId); diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/DockerConfigFile.java b/docker-java-core/src/main/java/com/github/dockerjava/core/DockerConfigFile.java index 825796a74..39ef15271 100644 --- a/docker-java-core/src/main/java/com/github/dockerjava/core/DockerConfigFile.java +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/DockerConfigFile.java @@ -1,6 +1,7 @@ package com.github.dockerjava.core; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.dockerjava.api.model.AuthConfig; @@ -28,7 +29,7 @@ public class DockerConfigFile { }; @JsonProperty - private final Map auths; + private Map auths; @JsonProperty private String currentContext; @@ -46,6 +47,11 @@ public Map getAuths() { return auths; } + @JsonSetter + public void setAuths(Map authConfigMap) { + auths = (authConfigMap == null || authConfigMap.size() == 0) ? new HashMap<>() : authConfigMap; + } + void addAuthConfig(AuthConfig config) { auths.put(config.getRegistryAddress(), config); } diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/DockerContextMetaFile.java b/docker-java-core/src/main/java/com/github/dockerjava/core/DockerContextMetaFile.java index d74c4949f..e10db4498 100644 --- a/docker-java-core/src/main/java/com/github/dockerjava/core/DockerContextMetaFile.java +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/DockerContextMetaFile.java @@ -18,8 +18,6 @@ public class DockerContextMetaFile { @JsonProperty("Endpoints") Endpoints endpoints; - @JsonProperty("Storage") - Storage storage; public static class Endpoints { @JsonProperty("docker") @@ -34,13 +32,6 @@ public static class Docker { } } - public static class Storage { - - @JsonProperty("TLSPath") - String tlsPath; - @JsonProperty("MetadataPath") - String metadataPath; - } public static Optional resolveContextMetaFile(ObjectMapper objectMapper, File dockerConfigPath, String context) { final File path = dockerConfigPath.toPath() @@ -52,6 +43,16 @@ public static Optional resolveContextMetaFile(ObjectMappe return Optional.ofNullable(loadContextMetaFile(objectMapper, path)); } + public static Optional resolveContextTLSFile(File dockerConfigPath, String context) { + final File path = dockerConfigPath.toPath() + .resolve("contexts") + .resolve("tls") + .resolve(metaHashFunction.hashString(context, StandardCharsets.UTF_8).toString()) + .resolve("docker") + .toFile(); + return Optional.ofNullable(path).filter(File::exists); + } + public static DockerContextMetaFile loadContextMetaFile(ObjectMapper objectMapper, File dockerContextMetaFile) { try { return parseContextMetaFile(objectMapper, dockerContextMetaFile); diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/LocalDirectorySSLConfig.java b/docker-java-core/src/main/java/com/github/dockerjava/core/LocalDirectorySSLConfig.java index 665f48f06..0f50f561d 100644 --- a/docker-java-core/src/main/java/com/github/dockerjava/core/LocalDirectorySSLConfig.java +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/LocalDirectorySSLConfig.java @@ -64,7 +64,8 @@ public SSLContext getSSLContext() { TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm); trustManagerFactory.init(CertificateUtils.createTrustStore(capem)); - SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + SSLContext sslContext = SSLContext.getInstance(AccessController.doPrivileged(getSystemProperty("ssl.protocol", + "TLSv1.2"))); sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); return sslContext; diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/NameParser.java b/docker-java-core/src/main/java/com/github/dockerjava/core/NameParser.java index ae39029ed..f06adb6d8 100644 --- a/docker-java-core/src/main/java/com/github/dockerjava/core/NameParser.java +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/NameParser.java @@ -22,6 +22,7 @@ private NameParser() { private static final int RepositoryNameTotalLengthMax = 255; private static final String SHA256_SEPARATOR = "@sha256:"; + private static final String COLON_SEPARATOR = ":"; private static final Pattern RepositoryNameComponentRegexp = Pattern.compile("[a-z0-9]+(?:[._-][a-z0-9]+)*"); @@ -106,6 +107,13 @@ public static HostnameReposName resolveRepositoryName(String reposName) { String[] nameParts = reposName.split("/", 2); if (nameParts.length == 1 || (!nameParts[0].contains(".") && !nameParts[0].contains(":") && !nameParts[0].equals("localhost"))) { + if (StringUtils.containsIgnoreCase(reposName, SHA256_SEPARATOR)) { + reposName = StringUtils.substringBeforeLast(reposName, SHA256_SEPARATOR); + } + + if (StringUtils.contains(reposName, COLON_SEPARATOR)) { + reposName = StringUtils.substringBeforeLast(reposName, COLON_SEPARATOR); + } return new HostnameReposName(AuthConfig.DEFAULT_SERVER_ADDRESS, reposName); } @@ -119,6 +127,10 @@ public static HostnameReposName resolveRepositoryName(String reposName) { reposName = StringUtils.substringBeforeLast(reposName, SHA256_SEPARATOR); } + if (StringUtils.contains(reposName, COLON_SEPARATOR)) { + reposName = StringUtils.substringBeforeLast(reposName, COLON_SEPARATOR); + } + validateRepoName(reposName); return new HostnameReposName(hostname, reposName); } diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java b/docker-java-core/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java index a38930cb3..373a67332 100644 --- a/docker-java-core/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/RemoteApiVersion.java @@ -91,6 +91,10 @@ public class RemoteApiVersion implements Serializable { public static final RemoteApiVersion VERSION_1_37 = RemoteApiVersion.create(1, 37); public static final RemoteApiVersion VERSION_1_38 = RemoteApiVersion.create(1, 38); public static final RemoteApiVersion VERSION_1_40 = RemoteApiVersion.create(1, 40); + public static final RemoteApiVersion VERSION_1_41 = RemoteApiVersion.create(1, 41); + public static final RemoteApiVersion VERSION_1_42 = RemoteApiVersion.create(1, 42); + public static final RemoteApiVersion VERSION_1_43 = RemoteApiVersion.create(1, 43); + public static final RemoteApiVersion VERSION_1_44 = RemoteApiVersion.create(1, 44); /** diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/command/ExportContainerCmdImpl.java b/docker-java-core/src/main/java/com/github/dockerjava/core/command/ExportContainerCmdImpl.java new file mode 100644 index 000000000..92070a2e2 --- /dev/null +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/command/ExportContainerCmdImpl.java @@ -0,0 +1,41 @@ +package com.github.dockerjava.core.command; + +import java.io.InputStream; +import java.util.Objects; + +import com.github.dockerjava.api.command.ExportContainerCmd; +import com.github.dockerjava.api.exception.NotFoundException; + +/** + * Export the contents of a container as a tar archive. + */ +public class ExportContainerCmdImpl extends AbstrDockerCmd implements + ExportContainerCmd { + + private String containerId; + + public ExportContainerCmdImpl(ExportContainerCmd.Exec exec, String containerId) { + super(exec); + withContainerId(containerId); + } + + @Override + public String getContainerId() { + return containerId; + } + + @Override + public ExportContainerCmdImpl withContainerId(String containerId) { + this.containerId = Objects.requireNonNull(containerId, "containerId was not specified"); + return this; + } + + /** + * @throws NotFoundException + * No such container + */ + @Override + public InputStream exec() throws NotFoundException { + return super.exec(); + } +} diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/command/ImageHistoryCmdImpl.java b/docker-java-core/src/main/java/com/github/dockerjava/core/command/ImageHistoryCmdImpl.java new file mode 100644 index 000000000..fafbd8da1 --- /dev/null +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/command/ImageHistoryCmdImpl.java @@ -0,0 +1,42 @@ +package com.github.dockerjava.core.command; + +import java.util.List; +import java.util.Objects; + +import com.github.dockerjava.api.command.ImageHistoryCmd; +import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.api.model.ImageHistory; + +/** + * Get the history of an image. + */ +public class ImageHistoryCmdImpl extends AbstrDockerCmd> implements + ImageHistoryCmd { + + private String imageId; + + public ImageHistoryCmdImpl(ImageHistoryCmd.Exec exec, String imageId) { + super(exec); + withImageId(imageId); + } + + @Override + public String getImageId() { + return imageId; + } + + @Override + public ImageHistoryCmd withImageId(String imageId) { + this.imageId = Objects.requireNonNull(imageId, "imageId was not specified"); + return this; + } + + /** + * @throws NotFoundException + * No such image + */ + @Override + public List exec() throws NotFoundException { + return super.exec(); + } +} diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/command/RestartContainerCmdImpl.java b/docker-java-core/src/main/java/com/github/dockerjava/core/command/RestartContainerCmdImpl.java index 03454d6a8..3b1df465b 100644 --- a/docker-java-core/src/main/java/com/github/dockerjava/core/command/RestartContainerCmdImpl.java +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/command/RestartContainerCmdImpl.java @@ -7,12 +7,13 @@ import com.github.dockerjava.api.command.RestartContainerCmd; import com.github.dockerjava.api.exception.NotFoundException; +import javax.annotation.CheckForNull; + /** * Restart a running container. * - * @param timeout - * - Timeout in seconds before killing the container. Defaults to 10 seconds. - * + * @param signal - Signal to send to the container as an integer or string (e.g. SIGINT). + * @param timeout - Timeout in seconds before killing the container. Defaults to 10 seconds. */ public class RestartContainerCmdImpl extends AbstrDockerCmd implements RestartContainerCmd { @@ -20,6 +21,8 @@ public class RestartContainerCmdImpl extends AbstrDockerCmd blkioWeightDevice; + + @JsonProperty("BlkioDeviceReadBps") + private List blkioDeviceReadBps; + + @JsonProperty("BlkioDeviceWriteBps") + private List blkioDeviceWriteBps; + + @JsonProperty("BlkioDeviceReadIOps") + private List blkioDeviceReadIOps; + + @JsonProperty("BlkioDeviceWriteIOps") + private List blkioDeviceWriteIOps; + @JsonProperty("CpuShares") private Integer cpuShares; @JsonProperty("CpuPeriod") - private Integer cpuPeriod; + private Long cpuPeriod; @JsonProperty("CpuQuota") - private Integer cpuQuota; + private Long cpuQuota; + + @JsonProperty("CpuRealtimePeriod") + private Long cpuRealtimePeriod; + + @JsonProperty("CpuRealtimeRuntime") + private Long cpuRealtimeRuntime; + + @JsonProperty("NanoCpus") + private Long nanoCPUs; @JsonProperty("CpusetCpus") private String cpusetCpus; @@ -43,6 +74,18 @@ public class UpdateContainerCmdImpl extends AbstrDockerCmd devices; + + @JsonProperty("DeviceCgroupRules") + private List deviceCgroupRules; + + /** + * @since {@link com.github.dockerjava.core.RemoteApiVersion#VERSION_1_40} + */ + @JsonProperty("DeviceRequests") + private List deviceRequests; + @JsonProperty("Memory") private Long memory; @@ -55,11 +98,43 @@ public class UpdateContainerCmdImpl extends AbstrDockerCmd ulimits; + + @JsonProperty("RestartPolicy") + private RestartPolicy restartPolicy; + public UpdateContainerCmdImpl(UpdateContainerCmd.Exec exec, String containerId) { super(exec); withContainerId(containerId); } + /** + * @see #containerId + */ + @CheckForNull + @JsonIgnore + public String getContainerId() { + return containerId; + } + + /** + * @see #containerId + */ + public UpdateContainerCmd withContainerId(@Nonnull String containerId) { + this.containerId = containerId; + return this; + } + /** * @see #blkioWeight */ @@ -77,19 +152,68 @@ public UpdateContainerCmd withBlkioWeight(Integer blkioWeight) { } /** - * @see #containerId + * @see #blkioWeightDevice */ @CheckForNull - @JsonIgnore - public String getContainerId() { - return containerId; + public List getBlkioWeightDevice() { + return blkioWeightDevice; + } + + public UpdateContainerCmd withBlkioWeightDevice(List blkioWeightDevice) { + this.blkioWeightDevice = blkioWeightDevice; + return this; } /** - * @see #containerId + * @see #blkioDeviceReadBps */ - public UpdateContainerCmd withContainerId(@Nonnull String containerId) { - this.containerId = containerId; + @CheckForNull + public List getBlkioDeviceReadBps() { + return blkioDeviceReadBps; + } + + public UpdateContainerCmd withBlkioDeviceReadBps(List blkioDeviceReadBps) { + this.blkioDeviceReadBps = blkioDeviceReadBps; + return this; + } + + /** + * @see #blkioDeviceWriteBps + */ + @CheckForNull + public List getBlkioDeviceWriteBps() { + return blkioDeviceWriteBps; + } + + public UpdateContainerCmd withBlkioDeviceWriteBps(List blkioDeviceWriteBps) { + this.blkioDeviceWriteBps = blkioDeviceWriteBps; + return this; + } + + /** + * @see #blkioDeviceReadIOps + */ + @CheckForNull + public List getBlkioDeviceReadIOps() { + return blkioDeviceReadIOps; + } + + public UpdateContainerCmd withBlkioDeviceReadIOps(List blkioDeviceReadIOps) { + this.blkioDeviceReadIOps = blkioDeviceReadIOps; + return this; + } + + /** + * @see #blkioDeviceWriteIOps + */ + @CheckForNull + public List getBlkioDeviceWriteIOps() { + return blkioDeviceWriteIOps; + } + + @Override + public UpdateContainerCmd withBlkioDeviceWriteIOps(List blkioDeviceWriteIOps) { + this.blkioDeviceWriteIOps = blkioDeviceWriteIOps; return this; } @@ -97,14 +221,14 @@ public UpdateContainerCmd withContainerId(@Nonnull String containerId) { * @see #cpuPeriod */ @CheckForNull - public Integer getCpuPeriod() { + public Long getCpuPeriod() { return cpuPeriod; } /** * @see #cpuPeriod */ - public UpdateContainerCmd withCpuPeriod(Integer cpuPeriod) { + public UpdateContainerCmd withCpuPeriod(Long cpuPeriod) { this.cpuPeriod = cpuPeriod; return this; } @@ -113,14 +237,14 @@ public UpdateContainerCmd withCpuPeriod(Integer cpuPeriod) { * @see #cpuQuota */ @CheckForNull - public Integer getCpuQuota() { + public Long getCpuQuota() { return cpuQuota; } /** * @see #cpuQuota */ - public UpdateContainerCmd withCpuQuota(Integer cpuQuota) { + public UpdateContainerCmd withCpuQuota(Long cpuQuota) { this.cpuQuota = cpuQuota; return this; } @@ -173,6 +297,71 @@ public UpdateContainerCmd withCpuShares(Integer cpuShares) { return this; } + /** + * @see #cpuRealtimePeriod + */ + @CheckForNull + public Long getCpuRealtimePeriod() { + return cpuRealtimePeriod; + } + + public UpdateContainerCmd withCpuRealtimePeriod(Long cpuRealtimePeriod) { + this.cpuRealtimePeriod = cpuRealtimePeriod; + return this; + } + + /** + * @see #cpuRealtimeRuntime + */ + @CheckForNull + public Long getCpuRealtimeRuntime() { + return cpuRealtimeRuntime; + } + + public UpdateContainerCmd withCpuRealtimeRuntime(Long cpuRealtimeRuntime) { + this.cpuRealtimeRuntime = cpuRealtimeRuntime; + return this; + } + + /** + * @see #devices + */ + @CheckForNull + public List getDevices() { + return devices; + } + + public UpdateContainerCmd withDevices(List devices) { + this.devices = devices; + return this; + } + + /** + * @see #deviceCgroupRules + */ + @CheckForNull + public List getDeviceCgroupRules() { + return deviceCgroupRules; + } + + public UpdateContainerCmd withDeviceCgroupRules(List deviceCgroupRules) { + this.deviceCgroupRules = deviceCgroupRules; + return this; + } + + /** + * @see #deviceRequests + */ + @CheckForNull + public List getDeviceRequests() { + return deviceRequests; + } + + public UpdateContainerCmd withDeviceRequests(List deviceRequests) { + this.deviceRequests = deviceRequests; + return this; + } + /** * @see #kernelMemory */ @@ -237,6 +426,84 @@ public UpdateContainerCmd withMemorySwap(Long memorySwap) { return this; } + /** + * @see #nanoCPUs + */ + @CheckForNull + public Long getNanoCPUs() { + return nanoCPUs; + } + + public UpdateContainerCmd withNanoCPUs(Long nanoCPUs) { + this.nanoCPUs = nanoCPUs; + return this; + } + + /** + * @see #oomKillDisable + */ + @CheckForNull + public Boolean getOomKillDisable() { + return oomKillDisable; + } + + public UpdateContainerCmd withOomKillDisable(Boolean oomKillDisable) { + this.oomKillDisable = oomKillDisable; + return this; + } + + /** + * @see #init + */ + @CheckForNull + public Boolean getInit() { + return init; + } + + public UpdateContainerCmd withInit(Boolean init) { + this.init = init; + return this; + } + + /** + * @see #pidsLimit + */ + @CheckForNull + public Long getPidsLimit() { + return pidsLimit; + } + + public UpdateContainerCmd withPidsLimit(Long pidsLimit) { + this.pidsLimit = pidsLimit; + return this; + } + + /** + * @see #ulimits + */ + @CheckForNull + public List getUlimits() { + return ulimits; + } + + public UpdateContainerCmd withUlimits(List ulimits) { + this.ulimits = ulimits; + return this; + } + + /** + * @see #restartPolicy + */ + @CheckForNull + public RestartPolicy getRestartPolicy() { + return restartPolicy; + } + + public UpdateContainerCmd withRestartPolicy(RestartPolicy restartPolicy) { + this.restartPolicy = restartPolicy; + return this; + } + /** * @throws NotFoundException No such container */ diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/command/WaitContainerCmdImpl.java b/docker-java-core/src/main/java/com/github/dockerjava/core/command/WaitContainerCmdImpl.java index 91b2255bc..b627e2ccd 100644 --- a/docker-java-core/src/main/java/com/github/dockerjava/core/command/WaitContainerCmdImpl.java +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/command/WaitContainerCmdImpl.java @@ -2,7 +2,10 @@ import java.util.Objects; +import javax.annotation.Nullable; + import com.github.dockerjava.api.command.WaitContainerCmd; +import com.github.dockerjava.api.model.WaitContainerCondition; import com.github.dockerjava.api.model.WaitResponse; /** @@ -15,6 +18,8 @@ public class WaitContainerCmdImpl extends AbstrAsyncDockerCmd + implements ExportContainerCmd.Exec { + + private static final Logger LOGGER = LoggerFactory.getLogger(ExportContainerCmdExec.class); + + public ExportContainerCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) { + super(baseResource, dockerClientConfig); + } + + @Override + protected InputStream execute(ExportContainerCmd command) { + WebTarget webResource = getBaseResource().path("/containers/{id}/export").resolveTemplate("id", + command.getContainerId()); + + LOGGER.trace("GET: {}", webResource); + + return webResource.request().accept(MediaType.APPLICATION_X_TAR).get(); + } +} diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/exec/ImageHistoryCmdExec.java b/docker-java-core/src/main/java/com/github/dockerjava/core/exec/ImageHistoryCmdExec.java new file mode 100644 index 000000000..8ba2a066d --- /dev/null +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/exec/ImageHistoryCmdExec.java @@ -0,0 +1,35 @@ +package com.github.dockerjava.core.exec; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.github.dockerjava.api.command.ImageHistoryCmd; +import com.github.dockerjava.api.model.ImageHistory; +import com.github.dockerjava.core.DockerClientConfig; +import com.github.dockerjava.core.MediaType; +import com.github.dockerjava.core.WebTarget; + +public class ImageHistoryCmdExec extends AbstrSyncDockerCmdExec> implements + ImageHistoryCmd.Exec { + + private static final Logger LOGGER = LoggerFactory.getLogger(ImageHistoryCmdExec.class); + + public ImageHistoryCmdExec(WebTarget baseResource, DockerClientConfig dockerClientConfig) { + super(baseResource, dockerClientConfig); + } + + @Override + protected List execute(ImageHistoryCmd command) { + WebTarget webResource = getBaseResource().path("/images/{id}/history").resolveTemplate("id", + command.getImageId()); + + LOGGER.trace("GET: {}", webResource); + + return webResource.request().accept(MediaType.APPLICATION_JSON).get(new TypeReference>() { + }); + } + +} diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/exec/RestartContainerCmdExec.java b/docker-java-core/src/main/java/com/github/dockerjava/core/exec/RestartContainerCmdExec.java index ecb317a34..42f2579e6 100644 --- a/docker-java-core/src/main/java/com/github/dockerjava/core/exec/RestartContainerCmdExec.java +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/exec/RestartContainerCmdExec.java @@ -24,6 +24,10 @@ protected Void execute(RestartContainerCmd command) { WebTarget webResource = getBaseResource().path("/containers/{id}/restart").resolveTemplate("id", command.getContainerId()); + if (command.getSignal() != null) { + webResource = webResource.queryParam("signal", command.getSignal()); + } + if (command.getTimeout() != null) { webResource = webResource.queryParam("t", String.valueOf(command.getTimeout())); } diff --git a/docker-java-core/src/main/java/com/github/dockerjava/core/exec/WaitContainerCmdExec.java b/docker-java-core/src/main/java/com/github/dockerjava/core/exec/WaitContainerCmdExec.java index 57cc727fe..3d2b2fa8e 100644 --- a/docker-java-core/src/main/java/com/github/dockerjava/core/exec/WaitContainerCmdExec.java +++ b/docker-java-core/src/main/java/com/github/dockerjava/core/exec/WaitContainerCmdExec.java @@ -1,5 +1,6 @@ package com.github.dockerjava.core.exec; +import com.github.dockerjava.api.model.WaitContainerCondition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,6 +26,11 @@ protected Void execute0(WaitContainerCmd command, ResultCallback r WebTarget webTarget = getBaseResource().path("/containers/{id}/wait").resolveTemplate("id", command.getContainerId()); + WaitContainerCondition condition = command.getCondition(); + if (condition != null) { + webTarget = webTarget.queryParam("condition", condition.getValue()); + } + LOGGER.trace("POST: {}", webTarget); webTarget.request().accept(MediaType.APPLICATION_JSON).post((Object) null, new TypeReference() { diff --git a/docker-java-transport-httpclient5/pom.xml b/docker-java-transport-httpclient5/pom.xml index 5800fb994..52cf66de2 100644 --- a/docker-java-transport-httpclient5/pom.xml +++ b/docker-java-transport-httpclient5/pom.xml @@ -29,19 +29,13 @@ org.apache.httpcomponents.client5 httpclient5 - 5.0.3 - - - org.apache.httpcomponents.core5 - httpcore5-h2 - - + 5.5.1 net.java.dev.jna jna - 5.12.1 + 5.18.1 diff --git a/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/ApacheDockerHttpClientImpl.java b/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/ApacheDockerHttpClientImpl.java index 93677bd36..c97a2bc45 100644 --- a/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/ApacheDockerHttpClientImpl.java +++ b/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/ApacheDockerHttpClientImpl.java @@ -4,31 +4,34 @@ import com.github.dockerjava.transport.NamedPipeSocket; import com.github.dockerjava.transport.SSLConfig; import com.github.dockerjava.transport.UnixSocket; + +import org.apache.hc.client5.http.SystemDefaultDnsResolver; import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.client5.http.config.ConnectionConfig; import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.DefaultSchemePortResolver; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.io.DefaultHttpClientConnectionOperator; import org.apache.hc.client5.http.impl.io.ManagedHttpClientConnectionFactory; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; -import org.apache.hc.client5.http.socket.ConnectionSocketFactory; -import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory; -import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.client5.http.io.HttpClientConnectionOperator; +import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; +import org.apache.hc.client5.http.ssl.TlsSocketStrategy; +import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.ConnectionClosedException; import org.apache.hc.core5.http.ContentLengthStrategy; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.NameValuePair; -import org.apache.hc.core5.http.config.Registry; -import org.apache.hc.core5.http.config.RegistryBuilder; import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy; -import org.apache.hc.core5.http.impl.io.EmptyInputStream; import org.apache.hc.core5.http.io.SocketConfig; import org.apache.hc.core5.http.io.entity.ByteArrayEntity; +import org.apache.hc.core5.http.io.entity.EmptyInputStream; import org.apache.hc.core5.http.io.entity.InputStreamEntity; -import org.apache.hc.core5.http.protocol.BasicHttpContext; import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.hc.core5.http.protocol.HttpCoreContext; import org.apache.hc.core5.net.URIAuthority; import org.apache.hc.core5.util.TimeValue; import org.apache.hc.core5.util.Timeout; @@ -60,7 +63,13 @@ protected ApacheDockerHttpClientImpl( Duration connectionTimeout, Duration responseTimeout ) { - Registry socketFactoryRegistry = createConnectionSocketFactoryRegistry(sslConfig, dockerHost); + SSLContext sslContext; + try { + sslContext = sslConfig != null ? sslConfig.getSSLContext() : null; + } catch (Exception e) { + throw new RuntimeException(e); + } + HttpClientConnectionOperator connectionOperator = createConnectionOperator(dockerHost, sslContext); switch (dockerHost.getScheme()) { case "unix": @@ -74,7 +83,7 @@ protected ApacheDockerHttpClientImpl( ? rawPath.substring(0, rawPath.length() - 1) : rawPath; host = new HttpHost( - socketFactoryRegistry.lookup("https") != null ? "https" : "http", + sslContext != null ? "https" : "http", dockerHost.getHost(), dockerHost.getPort() ); @@ -84,7 +93,10 @@ protected ApacheDockerHttpClientImpl( } PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager( - socketFactoryRegistry, + connectionOperator, + null, + null, + null, new ManagedHttpClientConnectionFactory( null, null, @@ -108,63 +120,49 @@ protected ApacheDockerHttpClientImpl( .setSoTimeout(Timeout.ZERO_MILLISECONDS) .build() ); - connectionManager.setValidateAfterInactivity(TimeValue.NEG_ONE_SECOND); connectionManager.setMaxTotal(maxConnections); connectionManager.setDefaultMaxPerRoute(maxConnections); - RequestConfig.Builder defaultRequest = RequestConfig.custom(); - if (connectionTimeout != null) { - defaultRequest.setConnectTimeout(connectionTimeout.toNanos(), TimeUnit.NANOSECONDS); - } - if (responseTimeout != null) { - defaultRequest.setResponseTimeout(responseTimeout.toNanos(), TimeUnit.NANOSECONDS); - } + connectionManager.setDefaultConnectionConfig(ConnectionConfig.custom() + .setValidateAfterInactivity(TimeValue.NEG_ONE_SECOND) + .setConnectTimeout(connectionTimeout != null ? Timeout.of(connectionTimeout.toNanos(), TimeUnit.NANOSECONDS) : null) + .build()); httpClient = HttpClients.custom() .setRequestExecutor(new HijackingHttpRequestExecutor(null)) .setConnectionManager(connectionManager) - .setDefaultRequestConfig(defaultRequest.build()) + .setDefaultRequestConfig(RequestConfig.custom() + .setResponseTimeout(responseTimeout != null ? Timeout.of(responseTimeout.toNanos(), TimeUnit.NANOSECONDS) : null) + .build()) .disableConnectionState() .build(); } - private Registry createConnectionSocketFactoryRegistry( - SSLConfig sslConfig, - URI dockerHost + private HttpClientConnectionOperator createConnectionOperator( + URI dockerHost, + SSLContext sslContext ) { - RegistryBuilder socketFactoryRegistryBuilder = RegistryBuilder.create(); - - if (sslConfig != null) { - try { - SSLContext sslContext = sslConfig.getSSLContext(); - if (sslContext != null) { - socketFactoryRegistryBuilder.register("https", new SSLConnectionSocketFactory(sslContext)); + String dockerHostScheme = dockerHost.getScheme(); + String dockerHostPath = dockerHost.getPath(); + TlsSocketStrategy tlsSocketStrategy = sslContext != null ? + new DefaultClientTlsStrategy(sslContext) : DefaultClientTlsStrategy.createSystemDefault(); + return new DefaultHttpClientConnectionOperator( + socksProxy -> { + if ("unix".equalsIgnoreCase(dockerHostScheme)) { + return UnixSocket.get(dockerHostPath); + } else if ("npipe".equalsIgnoreCase(dockerHostScheme)) { + return new NamedPipeSocket(dockerHostPath); + } else { + return socksProxy == null ? new Socket() : new Socket(socksProxy); } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - return socketFactoryRegistryBuilder - .register("tcp", PlainConnectionSocketFactory.INSTANCE) - .register("http", PlainConnectionSocketFactory.INSTANCE) - .register("unix", new PlainConnectionSocketFactory() { - @Override - public Socket createSocket(HttpContext context) throws IOException { - return UnixSocket.get(dockerHost.getPath()); - } - }) - .register("npipe", new PlainConnectionSocketFactory() { - @Override - public Socket createSocket(HttpContext context) { - return new NamedPipeSocket(dockerHost.getPath()); - } - }) - .build(); + }, + DefaultSchemePortResolver.INSTANCE, + SystemDefaultDnsResolver.INSTANCE, + name -> "https".equalsIgnoreCase(name) ? tlsSocketStrategy : null); } @Override public Response execute(Request request) { - HttpContext context = new BasicHttpContext(); + HttpContext context = new HttpCoreContext(); HttpUriRequestBase httpUriRequest = new HttpUriRequestBase(request.method(), URI.create(pathPrefix + request.path())); httpUriRequest.setScheme(host.getSchemeName()); httpUriRequest.setAuthority(new URIAuthority(host.getHostName(), host.getPort())); @@ -188,7 +186,7 @@ public Response execute(Request request) { } try { - CloseableHttpResponse response = httpClient.execute(host, httpUriRequest, context); + ClassicHttpResponse response = httpClient.executeOpen(host, httpUriRequest, context); return new ApacheResponse(httpUriRequest, response); } catch (IOException e) { @@ -207,9 +205,9 @@ static class ApacheResponse implements Response { private final HttpUriRequestBase request; - private final CloseableHttpResponse response; + private final ClassicHttpResponse response; - ApacheResponse(HttpUriRequestBase httpUriRequest, CloseableHttpResponse response) { + ApacheResponse(HttpUriRequestBase httpUriRequest, ClassicHttpResponse response) { this.request = httpUriRequest; this.response = response; } diff --git a/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/HijackingHttpRequestExecutor.java b/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/HijackingHttpRequestExecutor.java index 59888a5dd..df8fbd059 100644 --- a/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/HijackingHttpRequestExecutor.java +++ b/docker-java-transport-httpclient5/src/main/java/com/github/dockerjava/httpclient5/HijackingHttpRequestExecutor.java @@ -44,7 +44,7 @@ public ClassicHttpResponse execute( InputStream hijackedInput = (InputStream) context.getAttribute(HIJACKED_INPUT_ATTRIBUTE); if (hijackedInput != null) { - return executeHijacked(request, conn, context, hijackedInput); + return executeHijacked(request, conn, (HttpCoreContext) context, hijackedInput); } return super.execute(request, conn, informationCallback, context); @@ -53,12 +53,12 @@ public ClassicHttpResponse execute( private ClassicHttpResponse executeHijacked( ClassicHttpRequest request, HttpClientConnection conn, - HttpContext context, + HttpCoreContext context, InputStream hijackedInput ) throws HttpException, IOException { try { - context.setAttribute(HttpCoreContext.SSL_SESSION, conn.getSSLSession()); - context.setAttribute(HttpCoreContext.CONNECTION_ENDPOINT, conn.getEndpointDetails()); + context.setSSLSession(conn.getSSLSession()); + context.setEndpointDetails(conn.getEndpointDetails()); final ProtocolVersion transportVersion = request.getVersion(); if (transportVersion != null) { context.setProtocolVersion(transportVersion); diff --git a/docker-java-transport-jersey/pom.xml b/docker-java-transport-jersey/pom.xml index fbef13f1e..a600c208d 100644 --- a/docker-java-transport-jersey/pom.xml +++ b/docker-java-transport-jersey/pom.xml @@ -26,11 +26,6 @@ ${project.version} - - com.fasterxml.jackson.jaxrs - jackson-jaxrs-json-provider - ${jackson-jaxrs.version} - org.glassfish.jersey.connectors jersey-apache-connector diff --git a/docker-java-transport-okhttp/pom.xml b/docker-java-transport-okhttp/pom.xml index 351005461..2a0ae4227 100644 --- a/docker-java-transport-okhttp/pom.xml +++ b/docker-java-transport-okhttp/pom.xml @@ -35,7 +35,7 @@ net.java.dev.jna jna - 5.12.1 + 5.18.1 diff --git a/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixSocketFactory.java b/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixSocketFactory.java index dc19b1351..d25bcb3d3 100644 --- a/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixSocketFactory.java +++ b/docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/UnixSocketFactory.java @@ -20,7 +20,7 @@ public Socket createSocket() { try { return UnixSocket.get(socketPath); } catch (IOException e) { - throw new RuntimeException(e); + throw new RuntimeException("Failed create socket with path " + socketPath, e); } } diff --git a/docker-java-transport-tck/pom.xml b/docker-java-transport-tck/pom.xml index 9ad692c1f..76ffe1a6b 100644 --- a/docker-java-transport-tck/pom.xml +++ b/docker-java-transport-tck/pom.xml @@ -34,7 +34,7 @@ org.assertj assertj-core - 3.22.0 + 3.27.7 @@ -46,7 +46,7 @@ org.testcontainers testcontainers - 1.16.3 + 2.0.4 diff --git a/docker-java-transport/pom.xml b/docker-java-transport/pom.xml index 633053c39..8be456dd1 100644 --- a/docker-java-transport/pom.xml +++ b/docker-java-transport/pom.xml @@ -30,14 +30,14 @@ org.immutables value - 2.8.2 + 2.10.1 provided net.java.dev.jna jna - 5.12.1 + 5.18.1 provided diff --git a/docker-java-transport/src/main/java/com/github/dockerjava/transport/UnixSocket.java b/docker-java-transport/src/main/java/com/github/dockerjava/transport/UnixSocket.java index de447db61..eb7a49b51 100644 --- a/docker-java-transport/src/main/java/com/github/dockerjava/transport/UnixSocket.java +++ b/docker-java-transport/src/main/java/com/github/dockerjava/transport/UnixSocket.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; import java.net.Socket; import java.net.SocketAddress; import java.net.SocketException; @@ -24,7 +25,8 @@ public class UnixSocket extends AbstractSocket { public static Socket get(String path) throws IOException { try { return new UnixSocket(path); - } catch (Exception e) { + } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | + IllegalAccessException e) { //noinspection deprecation return DomainSocket.get(path); } @@ -34,7 +36,8 @@ public static Socket get(String path) throws IOException { private final SocketChannel socketChannel; - private UnixSocket(String path) throws Exception { + private UnixSocket(String path) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, + IllegalAccessException, IOException { Class unixDomainSocketAddress = Class.forName("java.net.UnixDomainSocketAddress"); this.socketAddress = (SocketAddress) unixDomainSocketAddress.getMethod("of", String.class) diff --git a/docker-java/pom.xml b/docker-java/pom.xml index 39e1b1b65..3cfd7f255 100644 --- a/docker-java/pom.xml +++ b/docker-java/pom.xml @@ -118,30 +118,30 @@ org.awaitility awaitility - 4.0.1 + 4.3.0 test com.fasterxml.jackson.core jackson-databind - - 2.8.8 + + 2.20.1 test com.fasterxml.jackson.core jackson-annotations - - 2.8.8 + + 2.20 test org.projectlombok lombok - 1.18.22 + 1.18.38 provided diff --git a/docker-java/src/main/java/com/github/dockerjava/core/DockerClientBuilder.java b/docker-java/src/main/java/com/github/dockerjava/core/DockerClientBuilder.java index a3e4c3909..8100f285e 100644 --- a/docker-java/src/main/java/com/github/dockerjava/core/DockerClientBuilder.java +++ b/docker-java/src/main/java/com/github/dockerjava/core/DockerClientBuilder.java @@ -94,7 +94,7 @@ public DockerClient build() { } else { Logger log = LoggerFactory.getLogger(DockerClientBuilder.class); log.warn( - "'dockerHttpClient' should be set." + + "'dockerHttpClient' should be set. " + "Falling back to Jersey, will be an error in future releases." ); diff --git a/docker-java/src/test/java/com/github/dockerjava/api/command/CommandJSONSamples.java b/docker-java/src/test/java/com/github/dockerjava/api/command/CommandJSONSamples.java index 0cf5141d4..23ef4b7f2 100644 --- a/docker-java/src/test/java/com/github/dockerjava/api/command/CommandJSONSamples.java +++ b/docker-java/src/test/java/com/github/dockerjava/api/command/CommandJSONSamples.java @@ -28,7 +28,9 @@ public enum CommandJSONSamples implements JSONResourceRef { inspectContainerResponse_full_1_21, inspectContainerResponse_full_1_26a, inspectContainerResponse_full_1_26b, - inspectContainerResponse_empty; + inspectContainerResponse_empty, + updateContainerResponse_empty, + updateContainerResponse_warnings; @Override public String getFileName() { diff --git a/docker-java/src/test/java/com/github/dockerjava/api/command/UpdateContainerResponseTest.java b/docker-java/src/test/java/com/github/dockerjava/api/command/UpdateContainerResponseTest.java new file mode 100644 index 000000000..300a5c324 --- /dev/null +++ b/docker-java/src/test/java/com/github/dockerjava/api/command/UpdateContainerResponseTest.java @@ -0,0 +1,33 @@ +package com.github.dockerjava.api.command; + +import com.github.dockerjava.api.model.UpdateContainerResponse; +import org.junit.Test; + +import java.io.IOException; +import java.util.List; + +import static com.github.dockerjava.test.serdes.JSONTestHelper.testRoundTrip; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +public class UpdateContainerResponseTest { + @Test + public void roundTrip_empty() throws IOException { + UpdateContainerResponse response = testRoundTrip(CommandJSONSamples.updateContainerResponse_empty, UpdateContainerResponse.class); + assertNull(response.getWarnings()); + } + + @Test + public void roundTrip_warnings() throws IOException { + UpdateContainerResponse response = testRoundTrip(CommandJSONSamples.updateContainerResponse_warnings, + UpdateContainerResponse.class); + + List warnings = response.getWarnings(); + assertNotNull(warnings); + assertEquals(1, warnings.size()); + + final String warning = warnings.get(0); + assertEquals("Published ports are discarded when using host network mode", warning); + } +} diff --git a/docker-java/src/test/java/com/github/dockerjava/api/model/BindTest.java b/docker-java/src/test/java/com/github/dockerjava/api/model/BindTest.java index 663231151..d31a66dde 100644 --- a/docker-java/src/test/java/com/github/dockerjava/api/model/BindTest.java +++ b/docker-java/src/test/java/com/github/dockerjava/api/model/BindTest.java @@ -166,6 +166,17 @@ public void parseReadWriteShared() { assertThat(bind.getPropagationMode(), is(PropagationMode.SHARED)); } + @Test + public void parseReadWriteRshared() { + Bind bind = Bind.parse("/host:/container:rw,rshared"); + assertThat(bind.getPath(), is("/host")); + assertThat(bind.getVolume().getPath(), is("/container")); + assertThat(bind.getAccessMode(), is(rw)); + assertThat(bind.getSecMode(), is(SELContext.none)); + assertThat(bind.getNoCopy(), nullValue()); + assertThat(bind.getPropagationMode(), is(PropagationMode.RSHARED)); + } + @Test public void parseReadWriteSlave() { Bind bind = Bind.parse("/host:/container:rw,slave"); @@ -177,6 +188,17 @@ public void parseReadWriteSlave() { assertThat(bind.getPropagationMode(), is(PropagationMode.SLAVE)); } + @Test + public void parseReadWriteRslave() { + Bind bind = Bind.parse("/host:/container:rw,rslave"); + assertThat(bind.getPath(), is("/host")); + assertThat(bind.getVolume().getPath(), is("/container")); + assertThat(bind.getAccessMode(), is(rw)); + assertThat(bind.getSecMode(), is(SELContext.none)); + assertThat(bind.getNoCopy(), nullValue()); + assertThat(bind.getPropagationMode(), is(PropagationMode.RSLAVE)); + } + @Test public void parseReadWritePrivate() { Bind bind = Bind.parse("/host:/container:rw,private"); @@ -188,6 +210,17 @@ public void parseReadWritePrivate() { assertThat(bind.getPropagationMode(), is(PropagationMode.PRIVATE)); } + @Test + public void parseReadWriteRprivate() { + Bind bind = Bind.parse("/host:/container:rw,rprivate"); + assertThat(bind.getPath(), is("/host")); + assertThat(bind.getVolume().getPath(), is("/container")); + assertThat(bind.getAccessMode(), is(rw)); + assertThat(bind.getSecMode(), is(SELContext.none)); + assertThat(bind.getNoCopy(), nullValue()); + assertThat(bind.getPropagationMode(), is(PropagationMode.RPRIVATE)); + } + @Test public void parseReadOnly() { Bind bind = Bind.parse("/host:/container:ro"); @@ -284,16 +317,31 @@ public void toStringReadWriteShared() { assertThat(Bind.parse("/host:/container:rw,shared").toString(), is("/host:/container:rw,shared")); } + @Test + public void toStringReadWriteRshared() { + assertThat(Bind.parse("/host:/container:rw,rshared").toString(), is("/host:/container:rw,rshared")); + } + @Test public void toStringReadWriteSlave() { assertThat(Bind.parse("/host:/container:rw,slave").toString(), is("/host:/container:rw,slave")); } + @Test + public void toStringReadWriteRslave() { + assertThat(Bind.parse("/host:/container:rw,rslave").toString(), is("/host:/container:rw,rslave")); + } + @Test public void toStringReadWritePrivate() { assertThat(Bind.parse("/host:/container:rw,private").toString(), is("/host:/container:rw,private")); } + @Test + public void toStringReadWriteRprivate() { + assertThat(Bind.parse("/host:/container:rw,rprivate").toString(), is("/host:/container:rw,rprivate")); + } + @Test public void toStringDefaultAccessMode() { assertThat(Bind.parse("/host:/container").toString(), is("/host:/container:rw")); diff --git a/docker-java/src/test/java/com/github/dockerjava/api/model/CapabilityTest.java b/docker-java/src/test/java/com/github/dockerjava/api/model/CapabilityTest.java index aa6167b8c..b0652d945 100644 --- a/docker-java/src/test/java/com/github/dockerjava/api/model/CapabilityTest.java +++ b/docker-java/src/test/java/com/github/dockerjava/api/model/CapabilityTest.java @@ -18,6 +18,9 @@ public void serializeCapability() throws Exception { public void deserializeCapability() throws Exception { Capability capability = JSONTestHelper.getMapper().readValue("\"ALL\"", Capability.class); assertEquals(Capability.ALL, capability); + + Capability compatibleCapability = JSONTestHelper.getMapper().readValue("\"CAP_ALL\"", Capability.class); + assertEquals(Capability.ALL, compatibleCapability); } @Test(expected = JsonMappingException.class) diff --git a/docker-java/src/test/java/com/github/dockerjava/api/model/ImageHistoryTest.java b/docker-java/src/test/java/com/github/dockerjava/api/model/ImageHistoryTest.java new file mode 100644 index 000000000..8f18facf0 --- /dev/null +++ b/docker-java/src/test/java/com/github/dockerjava/api/model/ImageHistoryTest.java @@ -0,0 +1,90 @@ +package com.github.dockerjava.api.model; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.github.dockerjava.test.serdes.JSONSamples; +import com.github.dockerjava.test.serdes.JSONTestHelper; +import org.junit.Test; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static com.github.dockerjava.core.RemoteApiVersion.VERSION_1_22; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class ImageHistoryTest { + + @Test + public void serderJson() throws IOException { + final List history = JSONTestHelper.getMapper().readValue( + JSONSamples.getSampleContent(VERSION_1_22, "images/history/history.json"), + new TypeReference>() { + } + ); + + assertThat(history, notNullValue()); + assertThat(history, hasSize(3)); + + final ImageHistory first = history.get(0); + assertThat(first.getId(), is("3db9c44f45209632d6050b35958829c3a2aa256d81b9a7be45b362ff85c54710")); + assertThat(first.getCreated(), is(1398108230L)); + assertThat(first.getCreatedBy(), is("/bin/sh -c #(nop) ADD file:eb15dbd63394e063b805a3c32ca7bf0266ef64676d5a6fab4801f2e81e2a5148 in /")); + assertThat(first.getTags(), hasSize(2)); + assertThat(first.getTags(), contains("ubuntu:lucid", "ubuntu:10.04")); + assertThat(first.getSize(), is(182964289L)); + assertThat(first.getComment(), is("")); + + final ImageHistory second = history.get(1); + assertThat(second.getId(), is("6cfa4d1f33fb861d4d114f43b25abd0ac737509268065cdfd69d544a59c85ab8")); + assertThat(second.getCreated(), is(1398108222L)); + assertThat(second.getTags(), empty()); + assertThat(second.getSize(), is(0L)); + + final ImageHistory third = history.get(2); + assertThat(third.getId(), is("511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158")); + assertThat(third.getCreated(), is(1371157430L)); + assertThat(third.getCreatedBy(), is("")); + assertThat(third.getTags(), contains("scratch12:latest", "scratch:latest")); + assertThat(third.getSize(), is(0L)); + assertThat(third.getComment(), is("Imported from -")); + + // Test round-trip serialization + final String serialized = JSONTestHelper.getMapper().writeValueAsString(history); + final List deserialized = JSONTestHelper.getMapper().readValue( + serialized, + new TypeReference>() { + } + ); + assertThat(deserialized, hasSize(3)); + assertThat(deserialized.get(0).getId(), is(first.getId())); + assertThat(deserialized.get(0).getCreated(), is(first.getCreated())); + assertThat(deserialized.get(0).getCreatedBy(), is(first.getCreatedBy())); + assertThat(deserialized.get(0).getTags(), is(first.getTags())); + assertThat(deserialized.get(0).getSize(), is(first.getSize())); + assertThat(deserialized.get(0).getComment(), is(first.getComment())); + } + + @Test + public void builderPattern() { + final ImageHistory history = new ImageHistory() + .withId("abc123") + .withCreated(1234567890L) + .withCreatedBy("/bin/sh -c echo hello") + .withTags(Arrays.asList("myimage:latest")) + .withSize(1024L) + .withComment("test comment"); + + assertThat(history.getId(), is("abc123")); + assertThat(history.getCreated(), is(1234567890L)); + assertThat(history.getCreatedBy(), is("/bin/sh -c echo hello")); + assertThat(history.getTags(), contains("myimage:latest")); + assertThat(history.getSize(), is(1024L)); + assertThat(history.getComment(), is("test comment")); + } +} diff --git a/docker-java/src/test/java/com/github/dockerjava/api/model/PullResponseItemTest.java b/docker-java/src/test/java/com/github/dockerjava/api/model/PullResponseItemTest.java index 486badd55..f73036864 100644 --- a/docker-java/src/test/java/com/github/dockerjava/api/model/PullResponseItemTest.java +++ b/docker-java/src/test/java/com/github/dockerjava/api/model/PullResponseItemTest.java @@ -29,6 +29,14 @@ * @author Zach Marshall */ public class PullResponseItemTest { + @Test + public void imageAlreadyExists() throws IOException { + PullResponseItem response = testRoundTrip(PullResponseJSONSamples.pullImageResponse_alreadyExists, + PullResponseItem.class); + assertTrue(response.isPullSuccessIndicated()); + assertFalse(response.isErrorIndicated()); + } + @Test public void pullNewerImage() throws IOException { PullResponseItem response = testRoundTrip(PullResponseJSONSamples.pullImageResponse_newerImage, diff --git a/docker-java/src/test/java/com/github/dockerjava/api/model/PullResponseJSONSamples.java b/docker-java/src/test/java/com/github/dockerjava/api/model/PullResponseJSONSamples.java index 31cdf0f3b..4997a390a 100644 --- a/docker-java/src/test/java/com/github/dockerjava/api/model/PullResponseJSONSamples.java +++ b/docker-java/src/test/java/com/github/dockerjava/api/model/PullResponseJSONSamples.java @@ -23,7 +23,9 @@ * @author Zach Marshall */ public enum PullResponseJSONSamples implements JSONResourceRef { - pullImageResponse_legacy, pullImageResponse_error, pullImageResponse_newerImage, pullImageResponse_upToDate; + pullImageResponse_legacy, pullImageResponse_error, + pullImageResponse_newerImage, pullImageResponse_upToDate, + pullImageResponse_alreadyExists; @Override public String getFileName() { diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/CommitCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/CommitCmdIT.java index 39f51adc7..bd87d4aab 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/CommitCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/CommitCmdIT.java @@ -46,9 +46,6 @@ public void commit() throws DockerException, InterruptedException { InspectImageResponse inspectImageResponse = dockerRule.getClient().inspectImageCmd(imageId).exec(); LOG.info("Image Inspect: {}", inspectImageResponse.toString()); - assertThat(inspectImageResponse, hasField("container", startsWith(container.getId()))); - assertThat(inspectImageResponse.getContainerConfig().getImage(), equalTo(DEFAULT_IMAGE)); - InspectImageResponse busyboxImg = dockerRule.getClient().inspectImageCmd("busybox").exec(); assertThat(inspectImageResponse.getParent(), equalTo(busyboxImg.getId())); diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/CopyArchiveToContainerCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/CopyArchiveToContainerCmdIT.java index bbd98932f..efce65c29 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/CopyArchiveToContainerCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/CopyArchiveToContainerCmdIT.java @@ -6,6 +6,7 @@ import com.github.dockerjava.core.util.CompressArchiveUtil; import com.github.dockerjava.utils.LogContainerTestCallback; import org.apache.commons.io.FileUtils; +import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -148,6 +149,7 @@ public void copyFileWithExecutePermission() throws Exception { assertThat(exitCode, equalTo(0)); } + @Ignore("Docker issue https://github.com/moby/moby/issues/46388") @Test public void copyFileWithUIDGID() throws Exception { Path with = Files.createFile(Files.createTempDirectory("copyFileWithUIDGID").resolve("uidgid.with")); diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/CreateContainerCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/CreateContainerCmdIT.java index de9f564e4..99d5dd997 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/CreateContainerCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/CreateContainerCmdIT.java @@ -10,6 +10,8 @@ import com.github.dockerjava.api.command.InspectContainerResponse; import com.github.dockerjava.api.exception.ConflictException; import com.github.dockerjava.api.exception.DockerException; +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.core.DefaultDockerClientConfig; import com.github.dockerjava.api.exception.InternalServerErrorException; import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.api.model.AuthConfig; @@ -34,7 +36,9 @@ import com.github.dockerjava.utils.TestUtils; import net.jcip.annotations.NotThreadSafe; import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.SystemUtils; import org.junit.ClassRule; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -56,6 +60,7 @@ import static com.github.dockerjava.api.model.HostConfig.newHostConfig; import static com.github.dockerjava.core.RemoteApiVersion.VERSION_1_23; import static com.github.dockerjava.core.RemoteApiVersion.VERSION_1_24; +import static com.github.dockerjava.core.RemoteApiVersion.VERSION_1_44; import static com.github.dockerjava.junit.DockerMatchers.isGreaterOrEqual; import static com.github.dockerjava.junit.DockerMatchers.mountedVolumes; import static com.github.dockerjava.core.DockerRule.DEFAULT_IMAGE; @@ -420,6 +425,7 @@ public void createContainerWithLink() throws DockerException { } @Test + @Ignore public void createContainerWithMemorySwappiness() throws DockerException { CreateContainerResponse container = dockerRule.getClient().createContainerCmd(DEFAULT_IMAGE) .withCmd("sleep", "9999") @@ -959,6 +965,8 @@ public void onNext(Frame item) { @Test public void createContainerWithCgroupParent() throws DockerException { + assumeThat(!SystemUtils.IS_OS_LINUX, is(true)); + CreateContainerResponse container = dockerRule.getClient().createContainerCmd("busybox") .withHostConfig(newHostConfig() .withCgroupParent("/parent")) @@ -1136,4 +1144,33 @@ public void shouldHandleANetworkAliasWithoutACustomNetworkGracefully() { .withCmd("sleep", "9999") .exec(); } + + @Test + public void createContainerWithAnnotations() throws DockerException { + DefaultDockerClientConfig forcedConfig = DefaultDockerClientConfig.createDefaultConfigBuilder() + .withApiVersion(VERSION_1_44) + .withRegistryUrl("https://index.docker.io/v1/") + .build(); + + DockerClient forcedClient = CmdIT.createDockerClient(forcedConfig); + Map annotations = new HashMap<>(); + annotations.put("com.example.key1", "value1"); + annotations.put("com.example.key2", "value2"); + + CreateContainerResponse container = forcedClient.createContainerCmd(DEFAULT_IMAGE) + .withCmd("sleep", "9999") + .withHostConfig(newHostConfig() + .withAnnotations(annotations)) + .exec(); + + LOG.info("Created container {}", container.toString()); + + assertThat(container.getId(), not(is(emptyString()))); + + InspectContainerResponse inspectContainerResponse = forcedClient.inspectContainerCmd(container.getId()).exec(); + + assertThat(inspectContainerResponse.getHostConfig().getAnnotations(), equalTo(annotations)); + assertThat(inspectContainerResponse.getHostConfig().getAnnotations().get("com.example.key1"), equalTo("value1")); + assertThat(inspectContainerResponse.getHostConfig().getAnnotations().get("com.example.key2"), equalTo("value2")); + } } diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/CreateNetworkCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/CreateNetworkCmdIT.java index deb8a4718..d60425a2a 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/CreateNetworkCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/CreateNetworkCmdIT.java @@ -15,9 +15,11 @@ import static com.github.dockerjava.junit.DockerMatchers.isGreaterOrEqual; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThan; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeThat; @@ -37,6 +39,7 @@ public void createNetwork() throws DockerException { Network network = dockerRule.getClient().inspectNetworkCmd().withNetworkId(createNetworkResponse.getId()).exec(); assertThat(network.getName(), is(networkName)); assertThat(network.getDriver(), is("bridge")); + assertThat(network.getCreated().getTime(), greaterThan(0L)); } @Test diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/ExecStartCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/ExecStartCmdIT.java index cf096aa26..fc111f0e2 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/ExecStartCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/ExecStartCmdIT.java @@ -4,6 +4,7 @@ import com.github.dockerjava.api.command.ExecCreateCmdResponse; import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.core.command.ExecStartResultCallback; +import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -77,6 +78,7 @@ public void execStartAttached() throws Exception { assertTrue(responseAsString.length() > 0); } + @Ignore @Test(expected = NotFoundException.class) public void execStartWithNonExistentUser() throws Exception { String containerName = "generated_" + new SecureRandom().nextInt(); diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/ExportContainerCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/ExportContainerCmdIT.java new file mode 100644 index 000000000..8e4712d84 --- /dev/null +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/ExportContainerCmdIT.java @@ -0,0 +1,52 @@ +package com.github.dockerjava.cmd; + +import com.github.dockerjava.api.command.CreateContainerResponse; +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.InputStream; + +import static com.github.dockerjava.core.DockerRule.DEFAULT_IMAGE; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.emptyString; + +public class ExportContainerCmdIT extends CmdIT { + + private static final Logger LOG = LoggerFactory.getLogger(ExportContainerCmdIT.class); + + @Test + public void exportContainerHasCreatedFile() throws Exception { + CreateContainerResponse container = dockerRule.getClient().createContainerCmd(DEFAULT_IMAGE) + .withCmd("touch", "/myExportedFile") + .exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(is(emptyString()))); + + dockerRule.getClient().startContainerCmd(container.getId()).exec(); + + int exitCode = dockerRule.getClient().waitContainerCmd(container.getId()).start() + .awaitStatusCode(); + assertThat(exitCode, is(0)); + + try (InputStream response = dockerRule.getClient().exportContainerCmd(container.getId()).exec()) { + boolean foundFile = false; + try (TarArchiveInputStream tarStream = new TarArchiveInputStream(response)) { + TarArchiveEntry entry; + while ((entry = tarStream.getNextTarEntry()) != null) { + if (entry.getName().contains("myExportedFile")) { + foundFile = true; + break; + } + } + } + assertThat("Exported archive should contain the created file", foundFile, is(true)); + } + } + +} diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/HealthCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/HealthCmdIT.java new file mode 100644 index 000000000..bdca27572 --- /dev/null +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/HealthCmdIT.java @@ -0,0 +1,88 @@ +package com.github.dockerjava.cmd; + +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.HealthStateLog; +import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerjava.api.model.HealthCheck; +import com.github.dockerjava.core.RemoteApiVersion; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static com.github.dockerjava.junit.DockerMatchers.isGreaterOrEqual; +import static org.awaitility.Awaitility.await; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.junit.Assume.assumeThat; + +public class HealthCmdIT extends CmdIT { + private final Logger LOG = LoggerFactory.getLogger(HealthCmdIT.class); + + @Test + public void healthiness() { + CreateContainerResponse container = dockerRule.getClient().createContainerCmd("busybox") + .withCmd("nc", "-l", "-p", "8080") + .withHealthcheck(new HealthCheck() + .withTest(Arrays.asList("CMD", "sh", "-c", "netstat -ltn | grep 8080")) + .withInterval(TimeUnit.SECONDS.toNanos(1)) + .withTimeout(TimeUnit.MINUTES.toNanos(1)) + .withStartPeriod(TimeUnit.SECONDS.toNanos(30)) + .withRetries(10)) + .exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(is(emptyString()))); + dockerRule.getClient().startContainerCmd(container.getId()).exec(); + + await().atMost(60L, TimeUnit.SECONDS).untilAsserted( + () -> { + InspectContainerResponse inspectContainerResponse = dockerRule.getClient().inspectContainerCmd(container.getId()).exec(); + assertThat(inspectContainerResponse.getState().getHealth().getStatus(), is(equalTo("healthy"))); + } + ); + } + + @Test + public void healthiness_startInterval() { + assumeThat("API version should be >= 1.44", dockerRule, isGreaterOrEqual(RemoteApiVersion.VERSION_1_44)); + + CreateContainerResponse container = dockerRule.getClient().createContainerCmd("busybox") + .withCmd("nc", "-l", "-p", "8080") + .withHealthcheck(new HealthCheck() + .withTest(Arrays.asList("CMD", "sh", "-c", "netstat -ltn | grep 8080")) + .withInterval(TimeUnit.SECONDS.toNanos(5)) + .withTimeout(TimeUnit.MINUTES.toNanos(1)) + .withStartPeriod(TimeUnit.SECONDS.toNanos(2)) + .withStartInterval(TimeUnit.SECONDS.toNanos(1)) + .withRetries(10)) + .exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(is(emptyString()))); + dockerRule.getClient().startContainerCmd(container.getId()).exec(); + + await().atMost(60L, TimeUnit.SECONDS).untilAsserted( + () -> { + InspectContainerResponse inspectContainerResponse = dockerRule.getClient().inspectContainerCmd(container.getId()).exec(); + List healthStateLogs = inspectContainerResponse.getState().getHealth().getLog(); + assertThat(healthStateLogs.size(), is(greaterThanOrEqualTo(2))); + healthStateLogs.forEach(log -> LOG.info("Health log: {}", log.getStart())); + HealthStateLog log1 = healthStateLogs.get(healthStateLogs.size() - 1); + HealthStateLog log2 = healthStateLogs.get(healthStateLogs.size() - 2); + long diff = ChronoUnit.NANOS.between(ZonedDateTime.parse(log2.getStart()), ZonedDateTime.parse(log1.getStart())); + assertThat(diff, is(greaterThanOrEqualTo(inspectContainerResponse.getConfig().getHealthcheck().getInterval()))); + } + ); + } + +} diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/ImageHistoryCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/ImageHistoryCmdIT.java new file mode 100644 index 000000000..16ae7e6a2 --- /dev/null +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/ImageHistoryCmdIT.java @@ -0,0 +1,29 @@ +package com.github.dockerjava.cmd; + +import com.github.dockerjava.api.model.ImageHistory; +import org.junit.Test; + +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.notNullValue; + +public class ImageHistoryCmdIT extends CmdIT { + + @Test + public void imageHistory() { + List history = dockerRule.getClient().imageHistoryCmd("busybox").exec(); + + assertThat(history, notNullValue()); + assertThat(history, hasSize(greaterThan(0))); + + ImageHistory entry = history.get(0); + assertThat(entry.getId(), notNullValue()); + assertThat(entry.getCreated(), notNullValue()); + assertThat(entry.getCreatedBy(), notNullValue()); + assertThat(entry.getSize(), notNullValue()); + assertThat(entry.getComment(), notNullValue()); + } +} diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/InfoCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/InfoCmdIT.java index d7917326b..74fc2cbda 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/InfoCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/InfoCmdIT.java @@ -48,6 +48,7 @@ public void infoTest() throws DockerException { assertThat(dockerInfo.getImages(), notNullValue()); assertThat(dockerInfo.getImages(), greaterThan(0)); assertThat(dockerInfo.getDebug(), notNullValue()); + assertThat(dockerInfo.getRuntimes(), notNullValue()); if (isNotSwarm(dockerClient)) { assertThat(dockerInfo.getNFd(), greaterThan(0)); diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/InspectContainerCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/InspectContainerCmdIT.java index fed85df73..e47a911d7 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/InspectContainerCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/InspectContainerCmdIT.java @@ -6,6 +6,7 @@ import com.github.dockerjava.api.exception.DockerException; import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.api.model.Container; +import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -100,7 +101,9 @@ public void inspectContainerWithSize() throws DockerException { // TODO check swarm if (isNotSwarm(dockerRule.getClient())) { assertNotNull(containerInfo.getSizeRootFs()); - assertTrue(containerInfo.getSizeRootFs().intValue() > 0); + assertTrue(containerInfo.getSizeRootFs() > 0L); + assertNotNull(containerInfo.getSizeRw()); + assertEquals(4096, containerInfo.getSizeRw().longValue()); } } @@ -125,6 +128,7 @@ public void inspectContainerRestartCount() throws DockerException { } @Test + @Ignore public void inspectContainerNetworkSettings() throws DockerException { CreateContainerResponse container = dockerRule.getClient().createContainerCmd("busybox") diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/InspectNetworkCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/InspectNetworkCmdIT.java index eca86497d..035d3d767 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/InspectNetworkCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/InspectNetworkCmdIT.java @@ -10,6 +10,7 @@ import static com.github.dockerjava.utils.TestUtils.findNetwork; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; public class InspectNetworkCmdIT extends CmdIT { @@ -28,5 +29,6 @@ public void inspectNetwork() throws DockerException { assertThat(network.getDriver(), equalTo(expected.getDriver())); assertThat(network.getIpam().getConfig().get(0).getSubnet(), equalTo(expected.getIpam().getConfig().get(0).getSubnet())); assertThat(network.getIpam().getDriver(), equalTo(expected.getIpam().getDriver())); + assertThat(network.getCreated().getTime(), greaterThan(0L)); } } diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/ListContainersCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/ListContainersCmdIT.java index a94a02f82..3490924c7 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/ListContainersCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/ListContainersCmdIT.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.TimeUnit; import static ch.lambdaj.Lambda.filter; import static com.github.dockerjava.api.model.HostConfig.newHostConfig; @@ -25,11 +26,12 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.emptyString; -import static org.hamcrest.Matchers.isOneOf; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.oneOf; import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertEquals; import static org.testinfected.hamcrest.jpa.PersistenceMatchers.hasField; @@ -160,8 +162,8 @@ public void testNameFilter() { .exec(); assertThat(filteredContainers.size(), is(2)); - assertThat(filteredContainers.get(0).getId(), isOneOf(id1, id2)); - assertThat(filteredContainers.get(1).getId(), isOneOf(id1, id2)); + assertThat(filteredContainers.get(0).getId(), is(oneOf(id1, id2))); + assertThat(filteredContainers.get(1).getId(), is(oneOf(id1, id2))); } @Test @@ -183,21 +185,13 @@ public void testIdsFilter() { .exec(); assertThat(filteredContainers.size(), is(2)); - assertThat(filteredContainers.get(0).getId(), isOneOf(id1, id2)); - assertThat(filteredContainers.get(1).getId(), isOneOf(id1, id2)); + assertThat(filteredContainers.get(0).getId(), is(oneOf(id1, id2))); + assertThat(filteredContainers.get(1).getId(), is(oneOf(id1, id2))); } @Test - public void testStatusFilter() { - String id1, id2; - id1 = dockerRule.getClient().createContainerCmd(DEFAULT_IMAGE) - .withCmd("sh", "-c", "sleep 99999") - .withLabels(testLabel) - .exec() - .getId(); - - id2 = dockerRule.getClient().createContainerCmd(DEFAULT_IMAGE) - .withCmd("sh", "-c", "sleep 99999") + public void shouldFilterByCreatedStatus() { + String containerId = dockerRule.getClient().createContainerCmd(DEFAULT_IMAGE) .withLabels(testLabel) .exec() .getId(); @@ -208,42 +202,67 @@ public void testStatusFilter() { .withStatusFilter(singletonList("created")) .exec(); - assertThat(filteredContainers.size(), is(2)); - assertThat(filteredContainers.get(1).getId(), isOneOf(id1, id2)); + assertThat(filteredContainers.size(), is(1)); + assertThat(filteredContainers.get(0).getId(), is(containerId)); + } - dockerRule.getClient().startContainerCmd(id1).exec(); + @Test + public void shouldFilterByRunningStatus() { + String containerId = dockerRule.getClient().createContainerCmd(DEFAULT_IMAGE) + .withLabels(testLabel) + .exec() + .getId(); + dockerRule.getClient().startContainerCmd(containerId).exec(); - filteredContainers = dockerRule.getClient().listContainersCmd() + List filteredContainers = dockerRule.getClient().listContainersCmd() .withShowAll(true) .withLabelFilter(testLabel) .withStatusFilter(singletonList("running")) .exec(); - assertThat(filteredContainers.size(), is(1)); - assertThat(filteredContainers.get(0).getId(), is(id1)); + assertThat(filteredContainers, hasSize(1)); + assertThat(filteredContainers.get(0).getId(), is(containerId)); + } - dockerRule.getClient().pauseContainerCmd(id1).exec(); + @Test + public void shouldFilterByPausedStatus() { + String containerId = dockerRule.getClient().createContainerCmd(DEFAULT_IMAGE) + .withCmd("sh", "-c", "sleep 99999") + .withLabels(testLabel) + .exec() + .getId(); + dockerRule.getClient().startContainerCmd(containerId).exec(); + dockerRule.getClient().pauseContainerCmd(containerId).exec(); - filteredContainers = dockerRule.getClient().listContainersCmd() + List filteredContainers = dockerRule.getClient().listContainersCmd() .withShowAll(true) .withLabelFilter(testLabel) .withStatusFilter(singletonList("paused")) .exec(); - assertThat(filteredContainers.size(), is(1)); - assertThat(filteredContainers.get(0).getId(), is(id1)); + assertThat(filteredContainers, hasSize(1)); + assertThat(filteredContainers.get(0).getId(), is(containerId)); + } - dockerRule.getClient().unpauseContainerCmd(id1).exec(); - dockerRule.getClient().stopContainerCmd(id1).exec(); + @Test + public void shouldFilterByExitedStatus() throws InterruptedException { + String containerId = dockerRule.getClient().createContainerCmd(DEFAULT_IMAGE) + .withCmd("sh", "-c", "sleep 99999") + .withLabels(testLabel) + .exec() + .getId(); + dockerRule.getClient().startContainerCmd(containerId).exec(); + dockerRule.getClient().stopContainerCmd(containerId).exec(); + dockerRule.getClient().waitContainerCmd(containerId).start().awaitCompletion(15, TimeUnit.SECONDS); - filteredContainers = dockerRule.getClient().listContainersCmd() + List filteredContainers = dockerRule.getClient().listContainersCmd() .withShowAll(true) .withLabelFilter(testLabel) .withStatusFilter(singletonList("exited")) .exec(); - assertThat(filteredContainers.size(), is(1)); - assertThat(filteredContainers.get(0).getId(), is(id1)); + assertThat(filteredContainers, hasSize(1)); + assertThat(filteredContainers.get(0).getId(), is(containerId)); } @Test @@ -271,7 +290,7 @@ public void testVolumeFilter() { .withVolumeFilter(singletonList("TestFilterVolume")) .exec(); - assertThat(filteredContainers.size(), is(1)); + assertThat(filteredContainers, hasSize(1)); assertThat(filteredContainers.get(0).getId(), is(id)); } @@ -311,11 +330,11 @@ public void testAncestorFilter() throws Exception { DockerAssume.assumeNotSwarm(dockerRule.getClient()); dockerRule.getClient().pullImageCmd("busybox") - .withTag("1.24") + .withTag("1.35") .start() .awaitCompletion(); - dockerRule.getClient().createContainerCmd("busybox:1.24") + dockerRule.getClient().createContainerCmd("busybox:1.35") .withLabels(testLabel) .exec(); diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/ListImagesCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/ListImagesCmdIT.java index 38b756dab..67ba85672 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/ListImagesCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/ListImagesCmdIT.java @@ -40,9 +40,9 @@ public void listImages() throws DockerException { Image img = images.get(0); assertThat(img.getCreated(), is(greaterThan(0L))); - assertThat(img.getVirtualSize(), is(greaterThan(0L))); + assertThat(img.getSize(), is(greaterThan(0L))); assertThat(img.getId(), not(is(emptyString()))); - assertThat(img.getRepoTags(), not(emptyArray())); + assertThat(img.getRepoTags(), emptyArray()); } @Test diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/LoadImageCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/LoadImageCmdIT.java index 5b87f17a6..36a8d51fc 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/LoadImageCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/LoadImageCmdIT.java @@ -25,7 +25,7 @@ public class LoadImageCmdIT extends CmdIT { @Before public void beforeMethod() { - expectedImageId = "sha256:56031f66eb0cef2e2e5cb2d1dabafaa0ebcd0a18a507d313b5bdb8c0472c5eba"; + expectedImageId = "sha256:28a8ed28c8b7bd9d7fc00f22ac7df6d385436b93e88ac978943f3dba06d836b4"; if (findImageWithId(expectedImageId, dockerRule.getClient().listImagesCmd().exec()) != null) { dockerRule.getClient().removeImageCmd(expectedImageId).exec(); } diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/PullImageCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/PullImageCmdIT.java index 539a2b606..3b8dde3ff 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/PullImageCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/PullImageCmdIT.java @@ -45,7 +45,7 @@ public void testPullImage() throws Exception { // pulled down, preferably small in size. If tag is not used pull will // download all images in that repository but tmpImgs will only // deleted 'latest' image but not images with other tags - String testImage = "hackmann/empty"; + String testImage = "alpine:3.17"; LOG.info("Removing image: {}", testImage); diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/RestartContainerCmdImplIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/RestartContainerCmdImplIT.java index 8017d229f..592c9c650 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/RestartContainerCmdImplIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/RestartContainerCmdImplIT.java @@ -1,18 +1,24 @@ package com.github.dockerjava.cmd; +import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.InspectContainerResponse; import com.github.dockerjava.api.exception.DockerException; import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.core.DefaultDockerClientConfig; +import com.github.dockerjava.core.RemoteApiVersion; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static com.github.dockerjava.core.DockerRule.DEFAULT_IMAGE; +import static com.github.dockerjava.junit.DockerMatchers.isGreaterOrEqual; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.not; +import static org.junit.Assume.assumeThat; public class RestartContainerCmdImplIT extends CmdIT { public static final Logger LOG = LoggerFactory.getLogger(RestartContainerCmdImplIT.class); @@ -44,6 +50,41 @@ public void restartContainer() throws DockerException { dockerRule.getClient().killContainerCmd(container.getId()).exec(); } + @Test + public void restartContainerWithSignal() throws Exception { + assumeThat("API version should be >= 1.42", dockerRule, isGreaterOrEqual(RemoteApiVersion.VERSION_1_42)); + + DefaultDockerClientConfig dockerClientConfig = DefaultDockerClientConfig.createDefaultConfigBuilder() + .withApiVersion(RemoteApiVersion.VERSION_1_44) + .withRegistryUrl("https://index.docker.io/v1/") + .build(); + try (DockerClient dockerClient = createDockerClient(dockerClientConfig)) { + String expectedUserSignal = "10"; + String initialCommandWithTrap = "trap 'echo \"exit trapped\"' %s; while :; do sleep 1; done"; + final String containerId = dockerClient + .createContainerCmd(DEFAULT_IMAGE) + .withCmd( + "/bin/sh", + "-c", + String.format(initialCommandWithTrap, expectedUserSignal)) + .exec() + .getId(); + assertThat(containerId, not(is(emptyString()))); + dockerClient.startContainerCmd(containerId).exec(); + + // Restart container without signal + dockerClient.restartContainerCmd(containerId).exec(); + String log = dockerRule.containerLog(containerId); + assertThat(log.trim(), emptyString()); + + dockerClient.restartContainerCmd(containerId).withSignal(expectedUserSignal).exec(); + log = dockerRule.containerLog(containerId); + assertThat(log.trim(), is("exit trapped")); + + dockerClient.removeContainerCmd(containerId).withForce(true).withRemoveVolumes(true).exec(); + } + } + @Test(expected = NotFoundException.class) public void restartNonExistingContainer() throws DockerException { diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/UpdateContainerCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/UpdateContainerCmdIT.java index e5bb55499..e1e637809 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/UpdateContainerCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/UpdateContainerCmdIT.java @@ -48,8 +48,8 @@ public void updateContainer() throws DockerException { dockerRule.getClient().updateContainerCmd(containerId) .withBlkioWeight(300) .withCpuShares(512) - .withCpuPeriod(100000) - .withCpuQuota(50000) + .withCpuPeriod(100000L) + .withCpuQuota(50000L) // .withCpusetCpus("0") // depends on env .withCpusetMems("0") // .withMemory(209715200L + 2L) diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/WaitContainerCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/WaitContainerCmdIT.java index e2ad2a643..3a39b3eea 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/WaitContainerCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/WaitContainerCmdIT.java @@ -8,18 +8,25 @@ import com.github.dockerjava.api.exception.DockerClientException; import com.github.dockerjava.api.exception.DockerException; import com.github.dockerjava.api.exception.NotFoundException; +import com.github.dockerjava.api.model.WaitContainerCondition; import com.github.dockerjava.api.model.WaitResponse; +import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.TimeUnit; +import static com.github.dockerjava.api.model.HostConfig.newHostConfig; +import static com.github.dockerjava.core.RemoteApiVersion.VERSION_1_25; +import static com.github.dockerjava.core.RemoteApiVersion.VERSION_1_30; +import static com.github.dockerjava.junit.DockerMatchers.isGreaterOrEqual; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.not; +import static org.junit.Assume.assumeThat; public class WaitContainerCmdIT extends CmdIT { public static final Logger LOG = LoggerFactory.getLogger(BuildImageCmd.class); @@ -102,4 +109,77 @@ public void testWaitContainerTimeout() { LOG.info(e.getMessage()); } } + + @Test + public void testWaitNotStartedContainer() { + assumeThat("API version should be > 1.25", dockerRule, isGreaterOrEqual(VERSION_1_25)); + + CreateContainerResponse container = dockerRule.getClient().createContainerCmd("busybox") + .withHostConfig(newHostConfig().withAutoRemove(true)) + .exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(is(emptyString()))); + + WaitContainerResultCallback callback = dockerRule.getClient().waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback()); + + Integer statusCode = callback.awaitStatusCode(100, TimeUnit.MILLISECONDS); + Assert.assertEquals(0, statusCode.intValue()); + } + + @Test + public void testWaitContainerWithAutoRemoval() { + assumeThat("API version should be > 1.30", dockerRule, isGreaterOrEqual(VERSION_1_30)); + + CreateContainerResponse container = dockerRule.getClient().createContainerCmd("busybox") + .withCmd("false") + .withHostConfig(newHostConfig().withAutoRemove(true)) + .exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(is(emptyString()))); + + WaitContainerResultCallback removedCondition = dockerRule.getClient().waitContainerCmd(container.getId()) + .withCondition(WaitContainerCondition.REMOVED) + .exec(new WaitContainerResultCallback()); + + WaitContainerResultCallback nextExitCondition = dockerRule.getClient().waitContainerCmd(container.getId()) + .withCondition(WaitContainerCondition.NEXT_EXIT) + .exec(new WaitContainerResultCallback()); + + dockerRule.getClient().startContainerCmd(container.getId()).exec(); + + Assert.assertEquals(1, removedCondition.awaitStatusCode(100, TimeUnit.MILLISECONDS).intValue()); + Assert.assertEquals(1, nextExitCondition.awaitStatusCode(100, TimeUnit.MILLISECONDS).intValue()); + } + + @Test + public void testWaitRestartedContainer() { + assumeThat("API version should be > 1.30", dockerRule, isGreaterOrEqual(VERSION_1_30)); + + CreateContainerResponse container = dockerRule.getClient().createContainerCmd("busybox") + .withCmd("sh", "-c", "[ -f \"$HOME/.first_run_marker\" ] && exit 2 || { touch \"$HOME/.first_run_marker\"; exit 1; }") + .exec(); + + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(is(emptyString()))); + + WaitContainerResultCallback firstExitCallback = dockerRule.getClient().waitContainerCmd(container.getId()) + .withCondition(WaitContainerCondition.NEXT_EXIT) + .exec(new WaitContainerResultCallback()); + + dockerRule.getClient().startContainerCmd(container.getId()).exec(); + + Integer firstStatusCode = firstExitCallback.awaitStatusCode(100, TimeUnit.MILLISECONDS); + Assert.assertEquals(1, firstStatusCode.intValue()); + + WaitContainerResultCallback callback = dockerRule.getClient().waitContainerCmd(container.getId()) + .withCondition(WaitContainerCondition.NEXT_EXIT) + .exec(new WaitContainerResultCallback()); + + dockerRule.getClient().startContainerCmd(container.getId()).exec(); + + Integer statusCode = callback.awaitStatusCode(100, TimeUnit.MILLISECONDS); + Assert.assertEquals(2, statusCode.intValue()); + } } diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/swarm/LogSwarmObjectIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/swarm/LogSwarmObjectIT.java index ddaf86fb6..11606dce0 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/swarm/LogSwarmObjectIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/swarm/LogSwarmObjectIT.java @@ -12,6 +12,7 @@ import com.github.dockerjava.api.model.TaskSpec; import com.github.dockerjava.api.model.TaskState; import com.github.dockerjava.utils.LogContainerTestCallback; +import org.junit.Ignore; import org.junit.Test; import java.io.IOException; @@ -25,6 +26,8 @@ import static org.hamcrest.core.Is.is; public class LogSwarmObjectIT extends SwarmCmdIT { + + @Ignore @Test public void testLogsCmd() throws InterruptedException, IOException { DockerClient dockerClient = startSwarm(); diff --git a/docker-java/src/test/java/com/github/dockerjava/cmd/swarm/SwarmCmdIT.java b/docker-java/src/test/java/com/github/dockerjava/cmd/swarm/SwarmCmdIT.java index 87f35161c..36bcab840 100644 --- a/docker-java/src/test/java/com/github/dockerjava/cmd/swarm/SwarmCmdIT.java +++ b/docker-java/src/test/java/com/github/dockerjava/cmd/swarm/SwarmCmdIT.java @@ -20,6 +20,8 @@ import org.junit.experimental.categories.Category; import java.io.IOException; +import java.time.Duration; +import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -36,7 +38,7 @@ public abstract class SwarmCmdIT extends CmdIT { private static final String DOCKER_IN_DOCKER_IMAGE_REPOSITORY = "docker"; - private static final String DOCKER_IN_DOCKER_IMAGE_TAG = "17.12-dind"; + private static final String DOCKER_IN_DOCKER_IMAGE_TAG = "26.1.3-dind"; private static final String DOCKER_IN_DOCKER_CONTAINER_PREFIX = "docker"; @@ -105,6 +107,8 @@ protected DockerClient startDockerInDocker() throws InterruptedException { ExposedPort exposedPort = ExposedPort.tcp(2375); CreateContainerResponse response = hostDockerClient .createContainerCmd(DOCKER_IN_DOCKER_IMAGE_REPOSITORY + ":" + DOCKER_IN_DOCKER_IMAGE_TAG) + .withEntrypoint("dockerd") + .withCmd(Arrays.asList("--host=tcp://0.0.0.0:2375", "--host=unix:///var/run/docker.sock", "--tls=false")) .withHostConfig(newHostConfig() .withNetworkMode(NETWORK_NAME) .withPortBindings(new PortBinding( @@ -125,7 +129,7 @@ protected DockerClient startDockerInDocker() throws InterruptedException { DockerClient dockerClient = initializeDockerClient(binding); - await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> { + await().pollDelay(Duration.ofSeconds(5)).atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { dockerClient.pingCmd().exec(); }); diff --git a/docker-java/src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java b/docker-java/src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java index 7e03a9159..6c7787caf 100644 --- a/docker-java/src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java +++ b/docker-java/src/test/java/com/github/dockerjava/core/DefaultDockerClientConfigTest.java @@ -129,8 +129,7 @@ public void dockerContextWithDockerHostAndTLS() { assertEquals(URI.create("tcp://remote:2376"), config.getDockerHost()); assertTrue("SSL config is set", config.getSSLConfig() instanceof LocalDirectorySSLConfig); - assertEquals("target/test-classes/com/github/dockerjava/core/util/CertificateUtilsTest/allFilesExist", - ((LocalDirectorySSLConfig)config.getSSLConfig()).getDockerCertPath()); + assertTrue("SSL directory is set", ((LocalDirectorySSLConfig)config.getSSLConfig()).getDockerCertPath().endsWith("dockerContextHomeDir/.docker/contexts/tls/b71199ebd070b36beab7317920c2c2f1d777df8d05e5527d8458fda57cb17a7a/docker")); } @Test diff --git a/docker-java/src/test/java/com/github/dockerjava/core/DockerConfigFileTest.java b/docker-java/src/test/java/com/github/dockerjava/core/DockerConfigFileTest.java index ce1a59cc0..76211fc55 100644 --- a/docker-java/src/test/java/com/github/dockerjava/core/DockerConfigFileTest.java +++ b/docker-java/src/test/java/com/github/dockerjava/core/DockerConfigFileTest.java @@ -164,6 +164,12 @@ public void nonExistent() throws IOException { assertThat(runTest("idontexist"), is(expected)); } + @Test + public void validJsonAuthsNull() throws IOException { + DockerConfigFile expected = new DockerConfigFile(); + assertThat(runTest("validJsonAuthsNull"), is(expected)); + } + private DockerConfigFile runTest(String testFileName) throws IOException { return DockerConfigFile.loadConfig(JSONTestHelper.getMapper(), new File(FILESROOT, testFileName).getAbsolutePath()); } diff --git a/docker-java/src/test/java/com/github/dockerjava/core/DockerRule.java b/docker-java/src/test/java/com/github/dockerjava/core/DockerRule.java index 3fc5c40d7..af606a5b1 100644 --- a/docker-java/src/test/java/com/github/dockerjava/core/DockerRule.java +++ b/docker-java/src/test/java/com/github/dockerjava/core/DockerRule.java @@ -174,7 +174,7 @@ private static DefaultDockerClientConfig config() { public static DefaultDockerClientConfig config(String password) { DefaultDockerClientConfig.Builder builder = DefaultDockerClientConfig.createDefaultConfigBuilder() - .withApiVersion(RemoteApiVersion.VERSION_1_30) + .withApiVersion(RemoteApiVersion.VERSION_1_44) .withRegistryUrl("https://index.docker.io/v1/"); if (password != null) { builder = builder.withRegistryPassword(password); diff --git a/docker-java/src/test/java/com/github/dockerjava/core/NameParserTest.java b/docker-java/src/test/java/com/github/dockerjava/core/NameParserTest.java index c6332ba4b..89ad131f6 100644 --- a/docker-java/src/test/java/com/github/dockerjava/core/NameParserTest.java +++ b/docker-java/src/test/java/com/github/dockerjava/core/NameParserTest.java @@ -83,6 +83,24 @@ public void testResolveSimpleRepositoryName() { assertEquals(new HostnameReposName(AuthConfig.DEFAULT_SERVER_ADDRESS, "repository"), resolved); } + @Test + public void testResolveRepositoryNameWithTag() { + HostnameReposName resolved = NameParser.resolveRepositoryName("repository:tag"); + assertEquals(new HostnameReposName(AuthConfig.DEFAULT_SERVER_ADDRESS, "repository"), resolved); + } + + @Test + public void testResolveRepositoryNameWithSHA256() { + HostnameReposName resolved = NameParser.resolveRepositoryName("repository@sha256:sha256"); + assertEquals(new HostnameReposName(AuthConfig.DEFAULT_SERVER_ADDRESS, "repository"), resolved); + } + + @Test + public void testResolveRepositoryNameWithTagAndSHA256() { + HostnameReposName resolved = NameParser.resolveRepositoryName("repository:tag@sha256:sha256"); + assertEquals(new HostnameReposName(AuthConfig.DEFAULT_SERVER_ADDRESS, "repository"), resolved); + } + @Test public void testResolveRepositoryNameWithNamespace() { HostnameReposName resolved = NameParser.resolveRepositoryName("namespace/repository"); @@ -92,7 +110,7 @@ public void testResolveRepositoryNameWithNamespace() { @Test public void testResolveRepositoryNameWithNamespaceAndSHA256() { HostnameReposName resolved = NameParser.resolveRepositoryName("namespace/repository@sha256:sha256"); - assertEquals(new HostnameReposName(AuthConfig.DEFAULT_SERVER_ADDRESS, "namespace/repository@sha256:sha256"), resolved); + assertEquals(new HostnameReposName(AuthConfig.DEFAULT_SERVER_ADDRESS, "namespace/repository"), resolved); } @Test @@ -107,6 +125,17 @@ public void testResolveRepositoryNameWithNamespaceAndHostnameAndSHA256() { assertEquals(new HostnameReposName("localhost:5000", "namespace/repository"), resolved); } + @Test + public void testResolveRepositoryNameWithNamespaceAndHostnameAndTag() { + HostnameReposName resolved = NameParser.resolveRepositoryName("localhost:5000/namespace/repository:tag"); + assertEquals(new HostnameReposName("localhost:5000", "namespace/repository"), resolved); + } + @Test + public void testResolveRepositoryNameWithNamespaceAndHostnameAndTagAndSHA256() { + HostnameReposName resolved = NameParser.resolveRepositoryName("localhost:5000/namespace/repository:tag@sha256:sha256"); + assertEquals(new HostnameReposName("localhost:5000", "namespace/repository"), resolved); + } + @Test(expected = InvalidRepositoryNameException.class) public void testResolveRepositoryNameWithIndex() { NameParser.resolveRepositoryName("index.docker.io/repository"); @@ -147,4 +176,16 @@ public void testResolveReposTagWithSHA256() { resolved = NameParser.parseRepositoryTag("localhost:5000/namespace/repository@sha256:sha256"); assertEquals(new ReposTag("localhost:5000/namespace/repository@sha256:sha256", ""), resolved); } + + @Test + public void testResolveReposTagWithTagAndSHA256() { + ReposTag resolved = NameParser.parseRepositoryTag("repository:tag@sha256:sha256"); + assertEquals(new ReposTag("repository:tag@sha256:sha256", ""), resolved); + + resolved = NameParser.parseRepositoryTag("namespace/repository:tag@sha256:sha256"); + assertEquals(new ReposTag("namespace/repository:tag@sha256:sha256", ""), resolved); + + resolved = NameParser.parseRepositoryTag("localhost:5000/namespace/repository:tag@sha256:sha256"); + assertEquals(new ReposTag("localhost:5000/namespace/repository:tag@sha256:sha256", ""), resolved); + } } diff --git a/docker-java/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java b/docker-java/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java index 5f7d200bf..03019f383 100644 --- a/docker-java/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java +++ b/docker-java/src/test/java/com/github/dockerjava/netty/NettyDockerCmdExecFactoryConfigTest.java @@ -43,7 +43,7 @@ public void testNettyDockerCmdExecFactoryConfigWithApiVersion() throws Exception Builder configBuilder = new DefaultDockerClientConfig.Builder() .withDockerTlsVerify(false) .withDockerHost("tcp://localhost:" + dockerPort) - .withApiVersion("1.23"); + .withApiVersion("1.44"); DockerClient client = DockerClientBuilder.getInstance(configBuilder) .withDockerCmdExecFactory(factory) @@ -57,7 +57,7 @@ public void testNettyDockerCmdExecFactoryConfigWithApiVersion() throws Exception List requests = server.getRequests(); assertEquals(1, requests.size()); - assertEquals("/v1.23/version", requests.get(0).uri()); + assertEquals("/v1.44/version", requests.get(0).uri()); } finally { server.stop(); } diff --git a/docker-java/src/test/resources/buildTests/ADD/url/Dockerfile b/docker-java/src/test/resources/buildTests/ADD/url/Dockerfile index 4fbfa3236..3036dbbe6 100644 --- a/docker-java/src/test/resources/buildTests/ADD/url/Dockerfile +++ b/docker-java/src/test/resources/buildTests/ADD/url/Dockerfile @@ -2,9 +2,9 @@ FROM busybox:latest # Copy testrun.sh files into the container -ADD http://www.example.com/index.html /tmp/some.html +ADD https://www.example.com/ /tmp/some.html ADD ./testrun.sh /tmp/ RUN mkdir -p /usr/local/bin RUN cp /tmp/testrun.sh /usr/local/bin/ && chmod +x /usr/local/bin/testrun.sh -CMD ["testrun.sh"] \ No newline at end of file +CMD ["testrun.sh"] diff --git a/docker-java/src/test/resources/com/github/dockerjava/api/command/inspectContainerResponse_full_1_26a.json b/docker-java/src/test/resources/com/github/dockerjava/api/command/inspectContainerResponse_full_1_26a.json index 2f3428d7a..688ea2689 100644 --- a/docker-java/src/test/resources/com/github/dockerjava/api/command/inspectContainerResponse_full_1_26a.json +++ b/docker-java/src/test/resources/com/github/dockerjava/api/command/inspectContainerResponse_full_1_26a.json @@ -6,6 +6,7 @@ "postgres" ], "SizeRootFs" : null, + "SizeRw" : null, "HostConfig" : { "KernelMemory" : 0, "MemorySwappiness" : -1, diff --git a/docker-java/src/test/resources/com/github/dockerjava/api/command/updateContainerResponse_empty.json b/docker-java/src/test/resources/com/github/dockerjava/api/command/updateContainerResponse_empty.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/docker-java/src/test/resources/com/github/dockerjava/api/command/updateContainerResponse_empty.json @@ -0,0 +1 @@ +{} diff --git a/docker-java/src/test/resources/com/github/dockerjava/api/command/updateContainerResponse_warnings.json b/docker-java/src/test/resources/com/github/dockerjava/api/command/updateContainerResponse_warnings.json new file mode 100644 index 000000000..edeaedc7a --- /dev/null +++ b/docker-java/src/test/resources/com/github/dockerjava/api/command/updateContainerResponse_warnings.json @@ -0,0 +1,5 @@ +{ + "Warnings": [ + "Published ports are discarded when using host network mode" + ] +} diff --git a/docker-java/src/test/resources/com/github/dockerjava/api/model/pullImageResponse_alreadyExists.json b/docker-java/src/test/resources/com/github/dockerjava/api/model/pullImageResponse_alreadyExists.json new file mode 100644 index 000000000..ae318e29d --- /dev/null +++ b/docker-java/src/test/resources/com/github/dockerjava/api/model/pullImageResponse_alreadyExists.json @@ -0,0 +1 @@ +{"status":"Already exists"} diff --git a/docker-java/src/test/resources/dockerContextHomeDir/.docker/contexts/tls/b71199ebd070b36beab7317920c2c2f1d777df8d05e5527d8458fda57cb17a7a/docker/ca.pem b/docker-java/src/test/resources/dockerContextHomeDir/.docker/contexts/tls/b71199ebd070b36beab7317920c2c2f1d777df8d05e5527d8458fda57cb17a7a/docker/ca.pem new file mode 100644 index 000000000..e69de29bb diff --git a/docker-java/src/test/resources/dockerContextHomeDir/.docker/contexts/tls/b71199ebd070b36beab7317920c2c2f1d777df8d05e5527d8458fda57cb17a7a/docker/cert.pem b/docker-java/src/test/resources/dockerContextHomeDir/.docker/contexts/tls/b71199ebd070b36beab7317920c2c2f1d777df8d05e5527d8458fda57cb17a7a/docker/cert.pem new file mode 100644 index 000000000..e69de29bb diff --git a/docker-java/src/test/resources/dockerContextHomeDir/.docker/contexts/tls/b71199ebd070b36beab7317920c2c2f1d777df8d05e5527d8458fda57cb17a7a/docker/key.pem b/docker-java/src/test/resources/dockerContextHomeDir/.docker/contexts/tls/b71199ebd070b36beab7317920c2c2f1d777df8d05e5527d8458fda57cb17a7a/docker/key.pem new file mode 100644 index 000000000..e69de29bb diff --git a/docker-java/src/test/resources/samples/1.22/containers/json/filter1.json b/docker-java/src/test/resources/samples/1.22/containers/json/filter1.json index 159e62da6..51329bb63 100644 --- a/docker-java/src/test/resources/samples/1.22/containers/json/filter1.json +++ b/docker-java/src/test/resources/samples/1.22/containers/json/filter1.json @@ -10,6 +10,7 @@ "Created": 1455662451, "Ports": [], "SizeRootFs": 1113554, + "SizeRw": 0, "Labels": {}, "Status": "Up Less than a second", "HostConfig": { diff --git a/docker-java/src/test/resources/samples/1.22/images/history/history.json b/docker-java/src/test/resources/samples/1.22/images/history/history.json new file mode 100644 index 000000000..a38da2d8f --- /dev/null +++ b/docker-java/src/test/resources/samples/1.22/images/history/history.json @@ -0,0 +1,32 @@ +[ + { + "Id": "3db9c44f45209632d6050b35958829c3a2aa256d81b9a7be45b362ff85c54710", + "Created": 1398108230, + "CreatedBy": "/bin/sh -c #(nop) ADD file:eb15dbd63394e063b805a3c32ca7bf0266ef64676d5a6fab4801f2e81e2a5148 in /", + "Tags": [ + "ubuntu:lucid", + "ubuntu:10.04" + ], + "Size": 182964289, + "Comment": "" + }, + { + "Id": "6cfa4d1f33fb861d4d114f43b25abd0ac737509268065cdfd69d544a59c85ab8", + "Created": 1398108222, + "CreatedBy": "/bin/sh -c #(nop) MAINTAINER Tianon Gravi - mkimage-debootstrap.sh -i iproute,iputils-ping,ubuntu-minimal -t lucid.tar.xz lucid http://archive.ubuntu.com/ubuntu/", + "Tags": [], + "Size": 0, + "Comment": "" + }, + { + "Id": "511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158", + "Created": 1371157430, + "CreatedBy": "", + "Tags": [ + "scratch12:latest", + "scratch:latest" + ], + "Size": 0, + "Comment": "Imported from -" + } +] diff --git a/docker-java/src/test/resources/testAuthConfigFile/validJsonAuthsNull/config.json b/docker-java/src/test/resources/testAuthConfigFile/validJsonAuthsNull/config.json new file mode 100644 index 000000000..d104c357c --- /dev/null +++ b/docker-java/src/test/resources/testAuthConfigFile/validJsonAuthsNull/config.json @@ -0,0 +1,9 @@ +{ + "auths": null, + "credsStore": "desktop", + "plugins": { + "-x-cli-hints": { + "enabled": "true" + } + } +} diff --git a/mvnw b/mvnw index 41c0f0c23..bd8896bf2 100755 --- a/mvnw +++ b/mvnw @@ -19,292 +19,277 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir +# Apache Maven Wrapper startup batch script, version 3.3.4 # # Optional ENV vars # ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output # ---------------------------------------------------------------------------- -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac -fi +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 fi fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" +} - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" done + printf %x\\n $h +} - saveddir=`pwd` +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } - M2_HOME=`dirname "$PRG"`/.. +die() { + printf %s\\n "$1" >&2 + exit 1 +} - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi +scriptDir="$(dirname "$0")" +scriptName="$(basename "$0")" + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" fi -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" fi -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi +mkdir -p -- "${MAVEN_HOME%/*}" -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" fi -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then + distributionSha256Result=true fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; fi -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi +# Find the actual extracted directory name (handles snapshots where filename != directory name) +actualDistributionDir="" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi +# First try the expected directory name (for regular distributions) +if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then + if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then + actualDistributionDir="$distributionUrlNameMain" + fi fi -########################################################################################## -# End of extension -########################################################################################## -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +# If not found, search for any directory with the Maven executable (for snapshots) +if [ -z "$actualDistributionDir" ]; then + # enable globbing to iterate over items + set +f + for dir in "$TMP_DOWNLOAD_DIR"/*; do + if [ -d "$dir" ]; then + if [ -f "$dir/bin/$MVN_CMD" ]; then + actualDistributionDir="$(basename "$dir")" + break + fi + fi + done + set -f fi -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS +if [ -z "$actualDistributionDir" ]; then + verbose "Contents of $TMP_DOWNLOAD_DIR:" + verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" + die "Could not find Maven distribution directory in extracted archive" +fi -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain +verbose "Found extracted Maven distribution directory: $actualDistributionDir" +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" +clean || : +exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd index 86115719e..92450f932 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -1,3 +1,4 @@ +<# : batch portion @REM ---------------------------------------------------------------------------- @REM Licensed to the Apache Software Foundation (ASF) under one @REM or more contributor license agreements. See the NOTICE file @@ -18,165 +19,171 @@ @REM ---------------------------------------------------------------------------- @REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir +@REM Apache Maven Wrapper startup batch script, version 3.3.4 @REM @REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output @REM ---------------------------------------------------------------------------- -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) ) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' + +$MAVEN_M2_PATH = "$HOME/.m2" +if ($env:MAVEN_USER_HOME) { + $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" +} + +if (-not (Test-Path -Path $MAVEN_M2_PATH)) { + New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null +} + +$MAVEN_WRAPPER_DISTS = $null +if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { + $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" +} else { + $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" +} + +$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" +$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +$actualDistributionDir = "" + +# First try the expected directory name (for regular distributions) +$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" +$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" +if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { + $actualDistributionDir = $distributionUrlNameMain +} + +# If not found, search for any directory with the Maven executable (for snapshots) +if (!$actualDistributionDir) { + Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { + $testPath = Join-Path $_.FullName "bin/$MVN_CMD" + if (Test-Path -Path $testPath -PathType Leaf) { + $actualDistributionDir = $_.Name + } + } +} + +if (!$actualDistributionDir) { + Write-Error "Could not find Maven distribution directory in extracted archive" +} + +Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/pom.xml b/pom.xml index fe1e6d472..f5f16405c 100644 --- a/pom.xml +++ b/pom.xml @@ -57,22 +57,20 @@ 1.8 1.8 - 2.30.1 - 2.10.3 - 2.10.3 + 2.47 4.5.12 - 1.21 - 2.6 - 3.12.0 + 1.28.0 + 2.21.0 + 3.19.0 1.7.30 - 1.64 - 2.6.1 - 19.0 + 1.82 + 2.10.1 + 33.4.8-jre 1.2.3 - 4.1.46.Final + 4.2.12.Final 2.2 1.8 2.3.3 @@ -148,6 +146,7 @@ ${jdk.target} ${jdk.debug} ${jdk.optimize} + true @@ -243,13 +242,13 @@ com.github.siom79.japicmp japicmp-maven-plugin - 0.15.4 + 0.25.4 com.github.docker-java ${project.artifactId} - 3.2.0 + 3.3.4 jar @@ -285,6 +284,17 @@ + + org.sonatype.central + central-publishing-maven-plugin + 0.10.0 + true + + central + docker-java-transport-tck + com.github.docker-java + + @@ -296,6 +306,9 @@ org.apache.maven.plugins maven-javadoc-plugin + + org.sonatype.central + central-publishing-maven-plugin @@ -307,6 +320,13 @@ org.apache.maven.plugins maven-gpg-plugin + + + + --pinentry-mode + loopback + + sign-artifacts