io.kodokojo.service.DefaultProjectManager.java Source code

Java tutorial

Introduction

Here is the source code for io.kodokojo.service.DefaultProjectManager.java

Source

/**
 * Kodo Kojo - Software factory done right
 * Copyright  2016 Kodo Kojo (infos@kodokojo.io)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package io.kodokojo.service;

import io.kodokojo.brick.*;
import io.kodokojo.model.*;
import io.kodokojo.model.Stack;
import io.kodokojo.service.dns.DnsEntry;
import io.kodokojo.service.dns.DnsManager;
import io.kodokojo.service.store.ProjectStore;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.IteratorUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.apache.commons.lang.StringUtils.isBlank;

public class DefaultProjectManager implements ProjectManager {

    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultProjectManager.class);

    //  Source Regexp http://sroze.io/2008/10/09/regex-ipv4-et-ipv6/
    private static final Pattern IP_PATTERN = Pattern.compile(
            "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");

    private final String domain;

    private final ConfigurationStore configurationStore;

    private final ProjectStore projectStore;

    private final DnsManager dnsManager;

    private final BootstrapConfigurationProvider bootstrapConfigurationProvider;

    private final BrickConfigurationStarter brickConfigurationStarter;

    private final BrickUrlFactory brickUrlFactory;

    private final BrickConfigurerProvider brickConfigurerProvider;

    @Inject
    public DefaultProjectManager(String domain, ConfigurationStore configurationStore, ProjectStore projectStore,
            BootstrapConfigurationProvider bootstrapConfigurationProvider, DnsManager dnsManager,
            BrickConfigurerProvider brickConfigurerProvider, BrickConfigurationStarter brickConfigurationStarter,
            BrickUrlFactory brickUrlFactory) {

        if (isBlank(domain)) {
            throw new IllegalArgumentException("domain must be defined.");
        }
        if (configurationStore == null) {
            throw new IllegalArgumentException("configurationStore must be defined.");
        }
        if (projectStore == null) {
            throw new IllegalArgumentException("projectStore must be defined.");
        }
        if (bootstrapConfigurationProvider == null) {
            throw new IllegalArgumentException("bootstrapConfigurationProvider must be defined.");
        }
        if (brickConfigurationStarter == null) {
            throw new IllegalArgumentException("brickConfigurationStarter must be defined.");
        }
        if (dnsManager == null) {
            throw new IllegalArgumentException("dnsManager must be defined.");
        }
        if (brickConfigurerProvider == null) {
            throw new IllegalArgumentException("brickConfigurerProvider must be defined.");
        }
        if (brickUrlFactory == null) {
            throw new IllegalArgumentException("brickUrlFactory must be defined.");
        }
        this.brickConfigurationStarter = brickConfigurationStarter;
        this.domain = domain;
        this.configurationStore = configurationStore;
        this.projectStore = projectStore;
        this.bootstrapConfigurationProvider = bootstrapConfigurationProvider;
        this.brickConfigurerProvider = brickConfigurerProvider;
        this.dnsManager = dnsManager;
        this.brickUrlFactory = brickUrlFactory;
    }

    @Override
    public BootstrapStackData bootstrapStack(String projectName, String stackName, StackType stackType) {
        if (!projectStore.projectNameIsValid(projectName)) {
            throw new IllegalArgumentException("project name " + projectName + " isn't valid.");
        }
        String loadBalancerHost = bootstrapConfigurationProvider.provideLoadBalancerHost(projectName, stackName);
        int sshPortEntrypoint = 0;
        if (stackType == StackType.BUILD) {
            sshPortEntrypoint = bootstrapConfigurationProvider.provideSshPortEntrypoint(projectName, stackName);
        }
        BootstrapStackData res = new BootstrapStackData(projectName, stackName, loadBalancerHost,
                sshPortEntrypoint);
        configurationStore.storeBootstrapStackData(res);
        return res;
    }

    @Override
    public Project start(ProjectConfiguration projectConfiguration) throws ProjectAlreadyExistException {
        if (projectConfiguration == null) {
            throw new IllegalArgumentException("projectConfiguration must be defined.");
        }
        if (CollectionUtils.isEmpty(projectConfiguration.getStackConfigurations())) {
            throw new IllegalArgumentException("Unable to create a project without stack.");
        }

        String projectName = projectConfiguration.getName();

        Set<DnsEntry> dnsEntries = new HashSet<>();
        List<BrickStartContext> contexts = new ArrayList<>();
        Set<Stack> stacks = new HashSet<>();
        for (StackConfiguration stackConfiguration : projectConfiguration.getStackConfigurations()) {
            String lbHost = stackConfiguration.getLoadBalancerHost();
            DnsEntry.Type dnsType = getDnsType(lbHost);
            for (BrickConfiguration brickConfiguration : stackConfiguration.getBrickConfigurations()) {
                Brick brick = brickConfiguration.getBrick();
                BrickType brickType = brick.getType();
                if (brickType.isRequiredHttpExposed()) {
                    String brickDomainName = brickUrlFactory.forgeUrl(projectConfiguration,
                            stackConfiguration.getName(), brickConfiguration);
                    dnsEntries.add(new DnsEntry(brickDomainName, dnsType, lbHost));
                }
                BrickStartContext context = new BrickStartContext(projectConfiguration, stackConfiguration,
                        brickConfiguration, domain, lbHost);
                contexts.add(context);
            }

            Stack stack = new Stack(stackConfiguration.getName(), stackConfiguration.getType(), new HashSet<>());
            stacks.add(stack);

        }
        dnsManager.createOrUpdateDnsEntries(dnsEntries);
        contexts.forEach(brickConfigurationStarter::start);
        Project project = new Project(projectConfiguration.getIdentifier(), projectName, new Date(), stacks);
        return project;
    }

    @Override
    public void addUsersToProject(ProjectConfiguration projectConfiguration, List<User> usersToAdd) {
        if (projectConfiguration == null) {
            throw new IllegalArgumentException("projectConfiguration must be defined.");
        }
        if (CollectionUtils.isEmpty(usersToAdd)) {
            throw new IllegalArgumentException("usersToAdd must be defined.");
        }

        projectConfiguration.getStackConfigurations().forEach(stackConfiguration -> {
            stackConfiguration.getBrickConfigurations().forEach(brickConfiguration -> {
                BrickConfigurer brickConfigurer = brickConfigurerProvider
                        .provideFromBrick(brickConfiguration.getBrick());
                String entrypoint = "http://" + brickUrlFactory.forgeUrl(projectConfiguration,
                        stackConfiguration.getName(), brickConfiguration);
                BrickConfigurerData brickConfigurerData = new BrickConfigurerData(projectConfiguration.getName(),
                        stackConfiguration.getName(), entrypoint, domain,
                        IteratorUtils.toList(projectConfiguration.getAdmins()),
                        IteratorUtils.toList(projectConfiguration.getUsers()));
                brickConfigurerData.getContext().putAll(brickConfiguration.getCustomData());
                try {
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Try to add users {} on entrypoint {}.",
                                org.apache.commons.lang.StringUtils.join(usersToAdd, ","), entrypoint);
                    }
                    brickConfigurer.addUsers(brickConfigurerData, usersToAdd);
                } catch (BrickConfigurationException e) {
                    LOGGER.error("An error occure while add users to brick " + brickConfiguration.getName() + "["
                            + entrypoint + "] on project " + projectConfiguration.getName() + ".", e);
                }
            });
        });

    }

    private static DnsEntry.Type getDnsType(String host) {
        assert StringUtils.isNotBlank(host) : "host must be defined";
        Matcher matcher = IP_PATTERN.matcher(host);
        return matcher.matches() ? DnsEntry.Type.A : DnsEntry.Type.CNAME;
    }
}