DockerConfigurationMetadata Class — spring-boot Architecture
Architecture documentation for the DockerConfigurationMetadata class in DockerConfigurationMetadata.java from the spring-boot codebase.
Entity Profile
Relationship Graph
Source Code
buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerConfigurationMetadata.java lines 49–298
final class DockerConfigurationMetadata {
private static final String DOCKER_CONFIG = "DOCKER_CONFIG";
private static final String DEFAULT_CONTEXT = "default";
private static final String CONFIG_DIR = ".docker";
private static final String CONTEXTS_DIR = "contexts";
private static final String META_DIR = "meta";
private static final String TLS_DIR = "tls";
private static final String DOCKER_ENDPOINT = "docker";
private static final String CONFIG_FILE_NAME = "config.json";
private static final String CONTEXT_FILE_NAME = "meta.json";
private static final Supplier<DockerConfigurationMetadata> systemEnvironmentConfigurationMetadata = SingletonSupplier
.of(() -> DockerConfigurationMetadata.create(Environment.SYSTEM));
private final String configLocation;
private final DockerConfig config;
private final DockerContext context;
private DockerConfigurationMetadata(String configLocation, DockerConfig config, DockerContext context) {
this.configLocation = configLocation;
this.config = config;
this.context = context;
}
DockerConfig getConfiguration() {
return this.config;
}
DockerContext getContext() {
return this.context;
}
DockerContext forContext(@Nullable String context) {
return createDockerContext(this.configLocation, context);
}
static DockerConfigurationMetadata from(Environment environment) {
if (environment == Environment.SYSTEM) {
return systemEnvironmentConfigurationMetadata.get();
}
return create(environment);
}
private static DockerConfigurationMetadata create(Environment environment) {
String configLocation = environment.get(DOCKER_CONFIG);
configLocation = (configLocation != null) ? configLocation : getUserHomeConfigLocation();
DockerConfig dockerConfig = createDockerConfig(configLocation);
DockerContext dockerContext = createDockerContext(configLocation, dockerConfig.getCurrentContext());
return new DockerConfigurationMetadata(configLocation, dockerConfig, dockerContext);
}
private static String getUserHomeConfigLocation() {
return Path.of(System.getProperty("user.home"), CONFIG_DIR).toString();
}
private static DockerConfig createDockerConfig(String configLocation) {
Path path = Path.of(configLocation, CONFIG_FILE_NAME);
if (!path.toFile().exists()) {
return DockerConfig.empty();
}
try {
return DockerConfig.fromJson(readPathContent(path));
}
catch (JacksonException ex) {
throw new IllegalStateException("Error parsing Docker configuration file '" + path + "'", ex);
}
}
private static DockerContext createDockerContext(String configLocation, @Nullable String currentContext) {
if (currentContext == null || DEFAULT_CONTEXT.equals(currentContext)) {
return DockerContext.empty();
}
String hash = asHash(currentContext);
Path metaPath = Path.of(configLocation, CONTEXTS_DIR, META_DIR, hash, CONTEXT_FILE_NAME);
Path tlsPath = Path.of(configLocation, CONTEXTS_DIR, TLS_DIR, hash, DOCKER_ENDPOINT);
if (!metaPath.toFile().exists()) {
throw new IllegalArgumentException("Docker context '" + currentContext + "' does not exist");
}
try {
DockerContext context = DockerContext.fromJson(readPathContent(metaPath));
if (tlsPath.toFile().isDirectory()) {
return context.withTlsPath(tlsPath.toString());
}
return context;
}
catch (JacksonException ex) {
throw new IllegalStateException("Error parsing Docker context metadata file '" + metaPath + "'", ex);
}
}
private static String asHash(String currentContext) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(currentContext.getBytes(StandardCharsets.UTF_8));
return HexFormat.of().formatHex(hash);
}
catch (NoSuchAlgorithmException ex) {
throw new IllegalStateException("SHA-256 is not available", ex);
}
}
private static String readPathContent(Path path) {
try {
return Files.readString(path);
}
catch (IOException ex) {
throw new IllegalStateException("Error reading Docker configuration file '" + path + "'", ex);
}
}
static final class DockerConfig extends MappedObject {
private final @Nullable String currentContext;
private final @Nullable String credsStore;
private final Map<String, String> credHelpers;
private final Map<String, Auth> auths;
private DockerConfig(JsonNode node) {
super(node, MethodHandles.lookup());
this.currentContext = valueAt("/currentContext", String.class);
this.credsStore = valueAt("/credsStore", String.class);
this.credHelpers = mapAt("/credHelpers", JsonNode::stringValue);
this.auths = mapAt("/auths", Auth::new);
}
@Nullable String getCurrentContext() {
return this.currentContext;
}
@Nullable String getCredsStore() {
return this.credsStore;
}
Map<String, String> getCredHelpers() {
return this.credHelpers;
}
Map<String, Auth> getAuths() {
return this.auths;
}
static DockerConfig fromJson(String json) {
return new DockerConfig(SharedJsonMapper.get().readTree(json));
}
static DockerConfig empty() {
return new DockerConfig(NullNode.instance);
}
}
static final class Auth extends MappedObject {
private final @Nullable String username;
private final @Nullable String password;
private final @Nullable String email;
Auth(JsonNode node) {
super(node, MethodHandles.lookup());
String auth = valueAt("/auth", String.class);
if (StringUtils.hasLength(auth)) {
String[] parts = new String(Base64.getDecoder().decode(auth)).split(":", 2);
Assert.state(parts.length == 2, "Malformed auth in docker configuration metadata");
this.username = parts[0];
this.password = trim(parts[1], Character.MIN_VALUE);
}
else {
this.username = valueAt("/username", String.class);
this.password = valueAt("/password", String.class);
}
this.email = valueAt("/email", String.class);
}
@Nullable String getUsername() {
return this.username;
}
@Nullable String getPassword() {
return this.password;
}
@Nullable String getEmail() {
return this.email;
}
private static String trim(String source, char character) {
source = StringUtils.trimLeadingCharacter(source, character);
return StringUtils.trimTrailingCharacter(source, character);
}
}
static final class DockerContext extends MappedObject {
private final @Nullable String dockerHost;
private final @Nullable Boolean skipTlsVerify;
private final @Nullable String tlsPath;
private DockerContext(JsonNode node, @Nullable String tlsPath) {
super(node, MethodHandles.lookup());
this.dockerHost = valueAt("/Endpoints/" + DOCKER_ENDPOINT + "/Host", String.class);
this.skipTlsVerify = valueAt("/Endpoints/" + DOCKER_ENDPOINT + "/SkipTLSVerify", Boolean.class);
this.tlsPath = tlsPath;
}
@Nullable String getDockerHost() {
return this.dockerHost;
}
Boolean isTlsVerify() {
return this.skipTlsVerify != null && !this.skipTlsVerify;
}
@Nullable String getTlsPath() {
return this.tlsPath;
}
DockerContext withTlsPath(String tlsPath) {
return new DockerContext(this.getNode(), tlsPath);
}
static DockerContext fromJson(String json) {
return new DockerContext(SharedJsonMapper.get().readTree(json), null);
}
static DockerContext empty() {
return new DockerContext(NullNode.instance, null);
}
}
}
Domain
Source
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free