hadoop DockerClientConfigHandler 源码

  • 2022-10-20
  • 浏览 (216)

haddop DockerClientConfigHandler 代码

文件路径:/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/DockerClientConfigHandler.java

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.yarn.util;

import org.apache.commons.io.FileUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.commons.io.IOUtils;
import org.apache.hadoop.io.DataInputByteBuffer;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.security.Credentials;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier;
import org.apache.hadoop.yarn.security.DockerCredentialTokenIdentifier;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;

/**
 * Commonly needed actions for handling the Docker client configurations.
 *
 * Credentials that are used to access private Docker registries are supplied.
 * Actions include:
 * <ul>
 *   <li>Read the Docker client configuration json file from a
 *   {@link FileSystem}.</li>
 *   <li>Extract the authentication information from the configuration into
 *   {@link Token} and {@link Credentials} objects.</li>
 *   <li>Tokens are commonly shipped via the
 *   {@link org.apache.hadoop.yarn.api.records.ContainerLaunchContext} as a
 *   {@link ByteBuffer}, extract the {@link Credentials}.</li>
 *   <li>Write the Docker client configuration json back to the local filesystem
 *   to be used by the Docker command line.</li>
 * </ul>
 */
public final class DockerClientConfigHandler {
  private static final org.slf4j.Logger LOG =
      LoggerFactory.getLogger(DockerClientConfigHandler.class);

  private static final String CONFIG_AUTHS_KEY = "auths";
  private static final String CONFIG_AUTH_KEY = "auth";

  private DockerClientConfigHandler() { }

  /**
   * Read the Docker client configuration and extract the auth tokens into
   * Credentials.
   *
   * @param configFile the Path to the Docker client configuration.
   * @param conf the Configuration object, needed by the FileSystem.
   * @param applicationId the application ID to associate the Credentials with.
   * @return the populated Credential object with the Docker Tokens.
   * @throws IOException if the file can not be read.
   */
  public static Credentials readCredentialsFromConfigFile(Path configFile,
      Configuration conf, String applicationId) throws IOException {
    // Read the config file
    String contents = null;
    configFile = new Path(configFile.toUri());
    FileSystem fs = configFile.getFileSystem(conf);
    if (fs != null) {
      FSDataInputStream fileHandle = fs.open(configFile);
      if (fileHandle != null) {
        contents = IOUtils.toString(fileHandle, StandardCharsets.UTF_8);
      }
    }
    if (contents == null) {
      throw new IOException("Failed to read Docker client configuration: "
          + configFile);
    }

    // Parse the JSON and create the Tokens/Credentials.
    ObjectMapper mapper = new ObjectMapper();
    JsonFactory factory = mapper.getFactory();
    JsonParser parser = factory.createParser(contents);
    JsonNode rootNode = mapper.readTree(parser);

    Credentials credentials = new Credentials();
    if (rootNode.has(CONFIG_AUTHS_KEY)) {
      Iterator<String> iter = rootNode.get(CONFIG_AUTHS_KEY).fieldNames();
      for (; iter.hasNext();) {
        String registryUrl = iter.next();
        String registryCred = rootNode.get(CONFIG_AUTHS_KEY)
            .get(registryUrl)
            .get(CONFIG_AUTH_KEY)
            .asText();
        TokenIdentifier tokenId =
            new DockerCredentialTokenIdentifier(registryUrl, applicationId);
        Token<DockerCredentialTokenIdentifier> token =
            new Token<>(tokenId.getBytes(),
                registryCred.getBytes(Charset.forName("UTF-8")),
                tokenId.getKind(), new Text(registryUrl));
        credentials.addToken(
            new Text(registryUrl + "-" + applicationId), token);
        LOG.info("Token read from Docker client configuration file: "
                + token.toString());
      }
    }
    return credentials;
  }

  /**
   * Convert the Token ByteBuffer to the appropriate Credentials object.
   *
   * @param tokens the Tokens from the ContainerLaunchContext.
   * @return the Credentials object populated from the Tokens.
   */
  public static Credentials getCredentialsFromTokensByteBuffer(
      ByteBuffer tokens) throws IOException {
    Credentials credentials = new Credentials();
    DataInputByteBuffer dibb = new DataInputByteBuffer();
    tokens.rewind();
    dibb.reset(tokens);
    credentials.readTokenStorageStream(dibb);
    tokens.rewind();
    if (LOG.isDebugEnabled()) {
      for (Token token : credentials.getAllTokens()) {
        LOG.debug("Token read from token storage: {}", token);
      }
    }
    return credentials;
  }

  /**
   * Extract the Docker related tokens from the Credentials and write the Docker
   * client configuration to the supplied File.
   *
   * @param outConfigFile the File to write the Docker client configuration to.
   * @param credentials the populated Credentials object.
   * @throws IOException if the write fails.
   * @return true if a Docker credential is found in the supplied credentials.
   */
  public static boolean writeDockerCredentialsToPath(File outConfigFile,
      Credentials credentials) throws IOException {
    boolean foundDockerCred = false;
    if (credentials.numberOfTokens() > 0) {
      ObjectMapper mapper = new ObjectMapper();
      ObjectNode rootNode = mapper.createObjectNode();
      ObjectNode registryUrlNode = mapper.createObjectNode();
      for (Token<? extends TokenIdentifier> tk : credentials.getAllTokens()) {
        if (tk.getKind().equals(DockerCredentialTokenIdentifier.KIND)) {
          foundDockerCred = true;
          DockerCredentialTokenIdentifier ti =
              (DockerCredentialTokenIdentifier) tk.decodeIdentifier();
          ObjectNode registryCredNode = mapper.createObjectNode();
          registryUrlNode.set(ti.getRegistryUrl(), registryCredNode);
          registryCredNode.put(CONFIG_AUTH_KEY,
              new String(tk.getPassword(), Charset.forName("UTF-8")));
          LOG.debug("Prepared token for write: {}", tk);
        }
      }
      if (foundDockerCred) {
        rootNode.set(CONFIG_AUTHS_KEY, registryUrlNode);
        String json = mapper.writerWithDefaultPrettyPrinter()
            .writeValueAsString(rootNode);
        FileUtils.writeStringToFile(
            outConfigFile, json, StandardCharsets.UTF_8);
      }
    }
    return foundDockerCred;
  }
}

相关信息

hadoop 源码目录

相关文章

hadoop AbstractLivelinessMonitor 源码

hadoop AdHocLogDumper 源码

hadoop ApplicationClassLoader 源码

hadoop Apps 源码

hadoop AsyncCallback 源码

hadoop AuxiliaryServiceHelper 源码

hadoop BoundedAppender 源码

hadoop Clock 源码

hadoop ConverterUtils 源码

hadoop FSDownload 源码

0  赞