All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.hyscale.controller.manager.impl.LocalRegistryManagerImpl Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2019 Pramati Prism, Inc.
 *
 * 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.
 */
package io.hyscale.controller.manager.impl;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import io.hyscale.commons.config.SetupConfig;
import io.hyscale.commons.exception.HyscaleException;
import io.hyscale.commons.logger.WorkflowLogger;
import io.hyscale.commons.models.DockerConfig;
import io.hyscale.commons.models.DockerCredHelper;
import io.hyscale.commons.models.DockerHubAliases;
import io.hyscale.commons.models.ImageRegistry;
import io.hyscale.commons.utils.ObjectMapperFactory;
import io.hyscale.commons.utils.WindowsUtil;
import io.hyscale.controller.activity.ControllerActivity;
import io.hyscale.controller.builder.ImageRegistryBuilder;
import io.hyscale.controller.config.ControllerConfig;
import io.hyscale.controller.exception.ControllerErrorCodes;
import io.hyscale.controller.manager.RegistryManager;

/**
 * Provides registry credentials.
 * Reads local docker registry config.
 * Takes registry name as input,tries to find the matching registry in credential helpers if present and return credentials,else searches in
 * credStore if specified in config file,else tries to get from the auths.
 */
@Component
public class LocalRegistryManagerImpl implements RegistryManager {

    private static final Logger logger = LoggerFactory.getLogger(LocalRegistryManagerImpl.class);

    private LocalDockerConfigBuilder dockerConfigBuilder;

    private DockerConfig externalRegistryConf;

    @Autowired
    private ControllerConfig controllerConfig;

    @PostConstruct
    public void init() {
        this.dockerConfigBuilder = new LocalDockerConfigBuilder();
    }

    /**
     * returns image registry credentials if found in docker config in the credHelpers,credsStore or Auths else returns null.
     *
     * @param registry
     * @return ImageRegistry object if found in credHelpers,credsStore or Auths else returns null.
     */
    @Override
    public ImageRegistry getImageRegistry(String registry) throws HyscaleException {
        if (!SetupConfig.hasExternalRegistryConf()) {
            return getImageRegistry(dockerConfigBuilder.getDockerConfig(), registry);
        }
        logger.debug("Found External registry Conf");
        buildExternalRegistryConf();
        return getImageRegistry(externalRegistryConf, registry);
    }

    public ImageRegistry getImageRegistry(DockerConfig dockerConfig, String registry) {

        if (dockerConfig == null) {
            return null;
        }

        List dockerRegistryAliases = null;
        if (registry != null) {
            dockerRegistryAliases = DockerHubAliases.getDockerRegistryAliases(registry);
        } else {
            dockerRegistryAliases = DockerHubAliases.getDefaultDockerRegistryAlias();
        }

        List registryPatterns = new ArrayList<>();
        for (String registryAlias : dockerRegistryAliases) {
            registryPatterns.addAll(getRegistryPatterns(registryAlias));
        }
        for (String pattern : registryPatterns) {
            ImageRegistryBuilder builder = new ImageRegistryBuilder(pattern);
            DockerCredHelper dockerCredHelper = getDockerCredHelper(dockerConfig, pattern);
            ImageRegistry imageRegistry = dockerCredHelper != null ? builder.from(dockerCredHelper) : builder.from(dockerConfig.getAuths());
            if (imageRegistry != null) {
                return imageRegistry;
            }
        }
        return null;

    }

    /**
     * Returns credential helper if registry pattern found  in credHelpers if specified
     * or directly credsStore if specified else returns null.
     *
     * @param pattern
     * @return docker credential helper else returns null
     */
    private DockerCredHelper getDockerCredHelper(DockerConfig dockerConfig, String pattern) {
        String helperFunc = dockerConfig.getCredHelpers() != null ? getHelperFunction(dockerConfig, pattern) : null;
        if (helperFunc != null) {
            return new DockerCredHelper(helperFunc);
        } else if (dockerConfig.getCredsStore() != null) {
            return new DockerCredHelper(dockerConfig.getCredsStore());
        }
        return null;
    }

    private static String getHelperFunction(DockerConfig dockerConfig, String registry) {
        return dockerConfig.getCredHelpers().containsKey(registry) ? dockerConfig.getCredHelpers().get(registry) : null;
    }

    private static List getRegistryPatterns(String registry) {
        String exactMatch = registry;
        String withHttps = "https://" + registry;
        String withSuffix = registry + "/";
        String withHttpsAndSuffix = "https://" + registry + "/";
        return Arrays.asList(exactMatch, withHttps, withSuffix, withHttpsAndSuffix);
    }


    private void validate(String path) throws HyscaleException {
        File confFile = new File(path);
        if (confFile != null && !confFile.exists()) {
            String confPath = SetupConfig.getMountOfDockerConf(path);
            confPath = WindowsUtil.updateToHostFileSeparator(confPath);
            WorkflowLogger.error(ControllerActivity.CANNOT_FIND_FILE,
                    confPath);
            throw new HyscaleException(ControllerErrorCodes.DOCKER_CONFIG_NOT_FOUND, confPath);
        }
    }

    public class LocalDockerConfigBuilder {

        private LocalDockerConfigBuilder() {
        }

        private DockerConfig dockerConfig;

        public DockerConfig getDockerConfig() throws HyscaleException {
            if (dockerConfig != null) {
                return dockerConfig;
            } else {
                build();
                return dockerConfig;
            }
        }

        /**
         * Reads local docker config
         */
        private void build() throws HyscaleException {
            if (dockerConfig != null) {
                return;
            }
            validate(controllerConfig.getDefaultRegistryConf());
            ObjectMapper mapper = ObjectMapperFactory.jsonMapper();
            try {
                TypeReference dockerConfigTypeReference = new TypeReference() {
                };

                this.dockerConfig = mapper.readValue(new File(controllerConfig.getDefaultRegistryConf()),
                        dockerConfigTypeReference);

            } catch (IOException e) {
                String dockerConfPath = SetupConfig.getMountOfDockerConf(controllerConfig.getDefaultRegistryConf());
                WorkflowLogger.error(ControllerActivity.ERROR_WHILE_READING, dockerConfPath, e.getMessage());
                HyscaleException ex = new HyscaleException(e, ControllerErrorCodes.DOCKER_CONFIG_NOT_FOUND, dockerConfPath);
                logger.error("Error while deserializing image registries {}", ex.toString());
                throw ex;
            }
        }
    }

    /*
     *   Builds docker config from Standard Input of the process
     */
    private void buildExternalRegistryConf() throws HyscaleException {
        if (externalRegistryConf == null) {
            logger.debug("Reading the external registry conf input");
            try (Scanner scanner = new Scanner(System.in)){
                if (scanner.hasNextLine()) {
                    String json = scanner.nextLine();
                    ObjectMapper mapper = ObjectMapperFactory.jsonMapper();
                    try {
                        TypeReference dockerConfigTypeReference = new TypeReference() {
                        };
                        this.externalRegistryConf = mapper.readValue(json,
                                dockerConfigTypeReference);
                        logger.debug("Initialized the external registry conf input");
                    } catch (IOException e) {
                        logger.error("Error while building external registry config", e);
                        String dockerConfPath = SetupConfig.getMountOfDockerConf(controllerConfig.getDefaultRegistryConf());
                        WorkflowLogger.error(ControllerActivity.ERROR_WHILE_READING, dockerConfPath, e.getMessage());
                        HyscaleException ex = new HyscaleException(e, ControllerErrorCodes.DOCKER_CONFIG_NOT_FOUND, dockerConfPath);
                        throw ex;
                    }
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy