Simplify support for pushing images to unauthenticated registries
This commit removes the requirement that `docker.publishRegistry` configuration must be provided when an image is published by the Gradle or Maven plugin. Fixes gh-28844
This commit is contained in:
parent
e48f5de20f
commit
9b0cdac58a
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
|
@ -90,4 +90,9 @@ public final class DockerConfiguration {
|
|||
new DockerRegistryUserAuthentication(username, password, url, email));
|
||||
}
|
||||
|
||||
public DockerConfiguration withEmptyPublishRegistryAuthentication() {
|
||||
return new DockerConfiguration(this.host, this.builderAuthentication,
|
||||
new DockerRegistryUserAuthentication("", "", "", ""));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -368,7 +368,10 @@ An OCI image containing a https://buildpacks.io/docs/buildpack-author-guide/pack
|
|||
|
||||
[[build-image.examples.publish]]
|
||||
=== Image Publishing
|
||||
The generated image can be published to a Docker registry by enabling a `publish` option and configuring authentication for the registry using `docker.publishRegistry` properties.
|
||||
The generated image can be published to a Docker registry by enabling a `publish` option.
|
||||
|
||||
If the Docker registry requires authentication, the credentials can be configured using `docker.publishRegistry` properties.
|
||||
If the Docker registry does not require authentication, the `docker.publishRegistry` configuration can be omitted.
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
|
||||
.Groovy
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
|
@ -25,7 +25,6 @@ import java.util.stream.Collectors;
|
|||
import groovy.lang.Closure;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.JavaVersion;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
|
@ -605,11 +604,6 @@ public class BootBuildImage extends DefaultTask {
|
|||
}
|
||||
|
||||
private BuildRequest customizePublish(BuildRequest request) {
|
||||
boolean publishRegistryAuthNotConfigured = this.docker == null || this.docker.getPublishRegistry() == null
|
||||
|| this.docker.getPublishRegistry().hasEmptyAuth();
|
||||
if (this.publish && publishRegistryAuthNotConfigured) {
|
||||
throw new GradleException("Publishing an image requires docker.publishRegistry to be configured");
|
||||
}
|
||||
request = request.withPublish(this.publish);
|
||||
return request;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
|
@ -179,7 +179,7 @@ public class DockerSpec {
|
|||
|
||||
private DockerConfiguration customizePublishAuthentication(DockerConfiguration dockerConfiguration) {
|
||||
if (this.publishRegistry == null || this.publishRegistry.hasEmptyAuth()) {
|
||||
return dockerConfiguration;
|
||||
return dockerConfiguration.withEmptyPublishRegistryAuthentication();
|
||||
}
|
||||
if (this.publishRegistry.hasTokenAuth() && !this.publishRegistry.hasUserAuth()) {
|
||||
return dockerConfiguration.withPublishRegistryTokenAuthentication(this.publishRegistry.getToken());
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
|
@ -313,15 +313,6 @@ class BootBuildImageIntegrationTests {
|
|||
.containsPattern("example/Invalid-Image-Name");
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void failsWithPublishMissingPublishRegistry() throws IOException {
|
||||
writeMainClass();
|
||||
writeLongNameResource();
|
||||
BuildResult result = this.gradleBuild.buildAndFail("bootBuildImage", "--publishImage");
|
||||
assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.FAILED);
|
||||
assertThat(result.getOutput()).contains("requires docker.publishRegistry");
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void failsWithBuildpackNotInBuilder() throws IOException {
|
||||
writeMainClass();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
|
@ -21,7 +21,6 @@ import java.util.Arrays;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.JavaVersion;
|
||||
import org.gradle.api.Project;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
@ -36,7 +35,6 @@ import org.springframework.boot.buildpack.platform.docker.type.ImageReference;
|
|||
import org.springframework.boot.gradle.junit.GradleProjectBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Tests for {@link BootBuildImage}.
|
||||
|
@ -189,13 +187,6 @@ class BootBuildImageTests {
|
|||
assertThat(this.buildImage.createRequest().isPublish()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPublishIsEnabledWithoutPublishRegistryThenExceptionIsThrown() {
|
||||
this.buildImage.setPublish(true);
|
||||
assertThatExceptionOfType(GradleException.class).isThrownBy(this.buildImage::createRequest)
|
||||
.withMessageContaining("Publishing an image requires docker.publishRegistry to be configured");
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenNoBuilderIsConfiguredThenRequestHasDefaultBuilder() {
|
||||
assertThat(this.buildImage.createRequest().getBuilder().getName()).isEqualTo("paketobuildpacks/builder");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
|
@ -37,9 +37,12 @@ class DockerSpecTests {
|
|||
@Test
|
||||
void asDockerConfigurationWithDefaults() {
|
||||
DockerSpec dockerSpec = new DockerSpec();
|
||||
assertThat(dockerSpec.asDockerConfiguration().getHost()).isNull();
|
||||
assertThat(dockerSpec.asDockerConfiguration().getBuilderRegistryAuthentication()).isNull();
|
||||
assertThat(dockerSpec.asDockerConfiguration().getPublishRegistryAuthentication()).isNull();
|
||||
DockerConfiguration dockerConfiguration = dockerSpec.asDockerConfiguration();
|
||||
assertThat(dockerConfiguration.getHost()).isNull();
|
||||
assertThat(dockerConfiguration.getBuilderRegistryAuthentication()).isNull();
|
||||
assertThat(decoded(dockerConfiguration.getPublishRegistryAuthentication().getAuthHeader()))
|
||||
.contains("\"username\" : \"\"").contains("\"password\" : \"\"").contains("\"email\" : \"\"")
|
||||
.contains("\"serveraddress\" : \"\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -54,7 +57,9 @@ class DockerSpecTests {
|
|||
assertThat(host.isSecure()).isEqualTo(true);
|
||||
assertThat(host.getCertificatePath()).isEqualTo("/tmp/ca-cert");
|
||||
assertThat(dockerSpec.asDockerConfiguration().getBuilderRegistryAuthentication()).isNull();
|
||||
assertThat(dockerSpec.asDockerConfiguration().getPublishRegistryAuthentication()).isNull();
|
||||
assertThat(decoded(dockerConfiguration.getPublishRegistryAuthentication().getAuthHeader()))
|
||||
.contains("\"username\" : \"\"").contains("\"password\" : \"\"").contains("\"email\" : \"\"")
|
||||
.contains("\"serveraddress\" : \"\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -67,7 +72,9 @@ class DockerSpecTests {
|
|||
assertThat(host.isSecure()).isEqualTo(false);
|
||||
assertThat(host.getCertificatePath()).isNull();
|
||||
assertThat(dockerSpec.asDockerConfiguration().getBuilderRegistryAuthentication()).isNull();
|
||||
assertThat(dockerSpec.asDockerConfiguration().getPublishRegistryAuthentication()).isNull();
|
||||
assertThat(decoded(dockerConfiguration.getPublishRegistryAuthentication().getAuthHeader()))
|
||||
.contains("\"username\" : \"\"").contains("\"password\" : \"\"").contains("\"email\" : \"\"")
|
||||
.contains("\"serveraddress\" : \"\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -7,11 +7,6 @@ sourceCompatibility = '1.8'
|
|||
targetCompatibility = '1.8'
|
||||
|
||||
bootBuildImage {
|
||||
builder = "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1"
|
||||
publish = true
|
||||
docker {
|
||||
publishRegistry {
|
||||
username = "user"
|
||||
password = "secret"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -338,7 +338,10 @@ An OCI image containing a https://buildpacks.io/docs/buildpack-author-guide/pack
|
|||
|
||||
[[build-image.examples.publish]]
|
||||
=== Image Publishing
|
||||
The generated image can be published to a Docker registry by enabling a `publish` option and configuring authentication for the registry using `docker.publishRegistry` parameters.
|
||||
The generated image can be published to a Docker registry by enabling a `publish` option.
|
||||
|
||||
If the Docker registry requires authentication, the credentials can be configured using `docker.publishRegistry` parameters.
|
||||
If the Docker registry does not require authentication, the `docker.publishRegistry` configuration can be omitted.
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
||||
----
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
|
@ -330,12 +330,6 @@ class BuildImageTests extends AbstractArchiveIntegrationTests {
|
|||
(project) -> assertThat(buildLog(project)).contains("Error packaging archive for image"));
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void failsWhenPublishWithoutPublishRegistryConfigured(MavenBuild mavenBuild) {
|
||||
mavenBuild.project("build-image").goals("package").systemProperty("spring-boot.build-image.publish", "true")
|
||||
.executeAndFail((project) -> assertThat(buildLog(project)).contains("requires docker.publishRegistry"));
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void failsWhenBuilderFails(MavenBuild mavenBuild) {
|
||||
mavenBuild.project("build-image-builder-error").goals("package")
|
||||
|
|
|
@ -23,14 +23,9 @@
|
|||
</goals>
|
||||
<configuration>
|
||||
<image>
|
||||
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1</builder>
|
||||
<publish>true</publish>
|
||||
</image>
|
||||
<docker>
|
||||
<publishRegistry>
|
||||
<username>user</username>
|
||||
<password>secret</password>
|
||||
</publishRegistry>
|
||||
</docker>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
|
|
|
@ -224,7 +224,7 @@ public class BuildImageMojo extends AbstractPackagerMojo {
|
|||
Libraries libraries = getLibraries(Collections.emptySet());
|
||||
try {
|
||||
DockerConfiguration dockerConfiguration = (this.docker != null) ? this.docker.asDockerConfiguration()
|
||||
: null;
|
||||
: new Docker().asDockerConfiguration();
|
||||
BuildRequest request = getBuildRequest(libraries);
|
||||
Builder builder = new Builder(new MojoBuildLog(this::getLog), dockerConfiguration);
|
||||
builder.build(request);
|
||||
|
@ -234,7 +234,7 @@ public class BuildImageMojo extends AbstractPackagerMojo {
|
|||
}
|
||||
}
|
||||
|
||||
private BuildRequest getBuildRequest(Libraries libraries) throws MojoExecutionException {
|
||||
private BuildRequest getBuildRequest(Libraries libraries) {
|
||||
ImagePackager imagePackager = new ImagePackager(getArchiveFile(), getBackupFile());
|
||||
Function<Owner, TarArchive> content = (owner) -> getApplicationContent(owner, libraries, imagePackager);
|
||||
Image image = (this.image != null) ? this.image : new Image();
|
||||
|
@ -259,17 +259,9 @@ public class BuildImageMojo extends AbstractPackagerMojo {
|
|||
if (image.network == null && this.network != null) {
|
||||
image.setNetwork(this.network);
|
||||
}
|
||||
if (image.publish != null && image.publish && publishRegistryNotConfigured()) {
|
||||
throw new MojoExecutionException("Publishing an image requires docker.publishRegistry to be configured");
|
||||
}
|
||||
return customize(image.getBuildRequest(this.project.getArtifact(), content));
|
||||
}
|
||||
|
||||
private boolean publishRegistryNotConfigured() {
|
||||
return this.docker == null || this.docker.getPublishRegistry() == null
|
||||
|| this.docker.getPublishRegistry().isEmpty();
|
||||
}
|
||||
|
||||
private TarArchive getApplicationContent(Owner owner, Libraries libraries, ImagePackager imagePackager) {
|
||||
ImagePackager packager = getConfiguredPackager(() -> imagePackager);
|
||||
return new PackagedTarArchive(owner, libraries, packager);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
|
@ -146,7 +146,7 @@ public class Docker {
|
|||
|
||||
private DockerConfiguration customizePublishAuthentication(DockerConfiguration dockerConfiguration) {
|
||||
if (this.publishRegistry == null || this.publishRegistry.isEmpty()) {
|
||||
return dockerConfiguration;
|
||||
return dockerConfiguration.withEmptyPublishRegistryAuthentication();
|
||||
}
|
||||
if (this.publishRegistry.hasTokenAuth() && !this.publishRegistry.hasUserAuth()) {
|
||||
return dockerConfiguration.withPublishRegistryTokenAuthentication(this.publishRegistry.getToken());
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
|
@ -36,9 +36,12 @@ class DockerTests {
|
|||
@Test
|
||||
void asDockerConfigurationWithDefaults() {
|
||||
Docker docker = new Docker();
|
||||
assertThat(docker.asDockerConfiguration().getHost()).isNull();
|
||||
assertThat(docker.asDockerConfiguration().getBuilderRegistryAuthentication()).isNull();
|
||||
assertThat(docker.asDockerConfiguration().getPublishRegistryAuthentication()).isNull();
|
||||
DockerConfiguration dockerConfiguration = docker.asDockerConfiguration();
|
||||
assertThat(dockerConfiguration.getHost()).isNull();
|
||||
assertThat(dockerConfiguration.getBuilderRegistryAuthentication()).isNull();
|
||||
assertThat(decoded(dockerConfiguration.getPublishRegistryAuthentication().getAuthHeader()))
|
||||
.contains("\"username\" : \"\"").contains("\"password\" : \"\"").contains("\"email\" : \"\"")
|
||||
.contains("\"serveraddress\" : \"\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -53,7 +56,9 @@ class DockerTests {
|
|||
assertThat(host.isSecure()).isEqualTo(true);
|
||||
assertThat(host.getCertificatePath()).isEqualTo("/tmp/ca-cert");
|
||||
assertThat(docker.asDockerConfiguration().getBuilderRegistryAuthentication()).isNull();
|
||||
assertThat(docker.asDockerConfiguration().getPublishRegistryAuthentication()).isNull();
|
||||
assertThat(decoded(dockerConfiguration.getPublishRegistryAuthentication().getAuthHeader()))
|
||||
.contains("\"username\" : \"\"").contains("\"password\" : \"\"").contains("\"email\" : \"\"")
|
||||
.contains("\"serveraddress\" : \"\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue