From 2a9e30a3581f984e97aaf56f4368ef30a2267631 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 23 Apr 2025 21:53:00 -0700 Subject: [PATCH] Polish 'Update `DockerConfigurationMetadata` to support credentials' See gh-45269 --- .../DockerConfigurationMetadata.java | 40 ++++++------------- .../buildpack/platform/json/MappedObject.java | 22 +++++++++- .../DockerConfigurationMetadataTests.java | 1 + 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadata.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadata.java index 8613ebfb42..841b2ddfdc 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadata.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadata.java @@ -24,9 +24,7 @@ import java.nio.file.Path; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Base64; -import java.util.Collections; import java.util.HexFormat; -import java.util.LinkedHashMap; import java.util.Map; import com.fasterxml.jackson.core.JsonProcessingException; @@ -36,11 +34,14 @@ import com.fasterxml.jackson.databind.node.NullNode; import org.springframework.boot.buildpack.platform.json.MappedObject; import org.springframework.boot.buildpack.platform.json.SharedObjectMapper; import org.springframework.boot.buildpack.platform.system.Environment; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Docker configuration stored in metadata files managed by the Docker CLI. * * @author Scott Frederick + * @author Dmytro Nosan */ final class DockerConfigurationMetadata { @@ -162,22 +163,8 @@ final class DockerConfigurationMetadata { super(node, MethodHandles.lookup()); this.currentContext = valueAt("/currentContext", String.class); this.credsStore = valueAt("/credsStore", String.class); - this.credHelpers = extractCredHelpers(); - this.auths = extractAuths(); - } - - private Map extractAuths() { - Map auths = new LinkedHashMap<>(); - getNode().at("/auths") - .fields() - .forEachRemaining((entry) -> auths.put(entry.getKey(), new Auth(entry.getValue()))); - return Map.copyOf(auths); - } - - @SuppressWarnings("unchecked") - private Map extractCredHelpers() { - Map credHelpers = valueAt("/credHelpers", Map.class); - return (credHelpers != null) ? Map.copyOf(credHelpers) : Collections.emptyMap(); + this.credHelpers = mapAt("/credHelpers", JsonNode::textValue); + this.auths = mapAt("/auths", Auth::new); } String getCurrentContext() { @@ -216,18 +203,17 @@ final class DockerConfigurationMetadata { Auth(JsonNode node) { super(node, MethodHandles.lookup()); - String username = valueAt("/username", String.class); - String password = valueAt("/password", String.class); String auth = valueAt("/auth", String.class); - if (auth != null) { + if (StringUtils.hasText(auth)) { String[] parts = new String(Base64.getDecoder().decode(auth)).split(":", 2); - if (parts.length == 2) { - username = parts[0]; - password = parts[1]; - } + Assert.state(parts.length == 2, "Malformed auth in docker configuration metadata"); + this.username = parts[0]; + this.password = parts[1]; + } + else { + this.username = valueAt("/username", String.class); + this.password = valueAt("/password", String.class); } - this.username = username; - this.password = password; this.email = valueAt("/email", String.class); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/json/MappedObject.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/json/MappedObject.java index 08a16a206a..936e57bfe8 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/json/MappedObject.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/json/MappedObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 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,9 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.function.Function; import com.fasterxml.jackson.databind.JsonNode; @@ -38,6 +40,7 @@ import org.springframework.util.StreamUtils; * Base class for mapped JSON objects. * * @author Phillip Webb + * @author Dmytro Nosan * @since 2.3.0 */ public class MappedObject { @@ -75,6 +78,23 @@ public class MappedObject { return valueAt(this, this.node, this.lookup, expression, type); } + /** + * Get a {@link Map} at the given JSON path expression with a value mapped from a + * related {@link JsonNode}. + * @param the value type + * @param expression the JSON path expression + * @param valueMapper function to map the value from the {@link JsonNode} + * @return the map + * @since 3.5.0 + */ + protected Map mapAt(String expression, Function valueMapper) { + Map map = new LinkedHashMap<>(); + getNode().at(expression) + .fields() + .forEachRemaining((entry) -> map.put(entry.getKey(), valueMapper.apply(entry.getValue()))); + return Collections.unmodifiableMap(map); + } + /** * Get children at the given JSON path expression by constructing them using the given * factory. diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadataTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadataTests.java index 962b38443f..4e90ab8530 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadataTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadataTests.java @@ -37,6 +37,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException * Tests for {@link DockerConfigurationMetadata}. * * @author Scott Frederick + * @author Dmytro Nosan */ class DockerConfigurationMetadataTests extends AbstractJsonTests {