Skip to content

Commit

Permalink
Replace RuntimeInfrastructure#estimate with InternalEnvironmentFactory
Browse files Browse the repository at this point in the history
It is done for decoupling runtime from environment configuration
  • Loading branch information
Gennady Azarenkov authored and sleshchenko committed Nov 20, 2017
1 parent 4b560ce commit eb90e43
Show file tree
Hide file tree
Showing 36 changed files with 757 additions and 647 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,18 @@
import java.util.Map;
import java.util.Set;
import org.eclipse.che.api.core.ValidationException;
import org.eclipse.che.api.core.model.workspace.config.Environment;
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.installer.server.InstallerRegistry;
import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
import org.eclipse.che.api.workspace.server.spi.RecipeRetriever;
import org.eclipse.che.api.workspace.server.spi.RuntimeInfrastructure;
import org.eclipse.che.api.workspace.server.spi.normalization.ServersNormalizer;
import org.eclipse.che.api.workspace.server.spi.provision.InternalEnvironmentProvisioner;
import org.eclipse.che.workspace.infrastructure.docker.container.ContainersStartStrategy;
import org.eclipse.che.workspace.infrastructure.docker.container.DockerContainers;
import org.eclipse.che.workspace.infrastructure.docker.environment.DockerConfigSourceSpecificEnvironmentParser;
import org.eclipse.che.workspace.infrastructure.docker.environment.EnvironmentNormalizer;
import org.eclipse.che.workspace.infrastructure.docker.environment.EnvironmentParser;
import org.eclipse.che.workspace.infrastructure.docker.environment.EnvironmentValidator;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerimage.DockerImageEnvironmentParser;
import org.eclipse.che.workspace.infrastructure.docker.environment.compose.ComposeInternalEnvironment;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerfile.DockerfileInternalEnvironment;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerimage.DockerimageInternalEnvironment;
import org.eclipse.che.workspace.infrastructure.docker.model.DockerEnvironment;

/**
Expand All @@ -42,8 +36,7 @@
* @author Alexander Garagatyi
*/
public class DockerRuntimeInfrastructure extends RuntimeInfrastructure {
private final EnvironmentValidator dockerEnvironmentValidator;
private final EnvironmentParser dockerEnvironmentParser;

private final ContainersStartStrategy startStrategy;
private final InfrastructureProvisioner infrastructureProvisioner;
private final EnvironmentNormalizer environmentNormalizer;
Expand All @@ -52,29 +45,14 @@ public class DockerRuntimeInfrastructure extends RuntimeInfrastructure {

@Inject
public DockerRuntimeInfrastructure(
EnvironmentParser dockerEnvironmentParser,
EnvironmentValidator dockerEnvironmentValidator,
ContainersStartStrategy startStrategy,
InfrastructureProvisioner infrastructureProvisioner,
EnvironmentNormalizer environmentNormalizer,
Map<String, DockerConfigSourceSpecificEnvironmentParser> environmentParsers,
DockerRuntimeContextFactory contextFactory,
DockerContainers containers,
EventService eventService,
InstallerRegistry installerRegistry,
RecipeRetriever recipeRetriever,
Set<InternalEnvironmentProvisioner> internalEnvironmentProvisioners,
ServersNormalizer serversNormalizer) {
super(
"docker",
environmentParsers.keySet(),
eventService,
installerRegistry,
recipeRetriever,
internalEnvironmentProvisioners,
serversNormalizer);
this.dockerEnvironmentValidator = dockerEnvironmentValidator;
this.dockerEnvironmentParser = dockerEnvironmentParser;
EventService eventService) {
super("docker", environmentParsers.keySet(), eventService);
this.startStrategy = startStrategy;
this.infrastructureProvisioner = infrastructureProvisioner;
this.environmentNormalizer = environmentNormalizer;
Expand All @@ -83,39 +61,24 @@ public DockerRuntimeInfrastructure(
}

@Override
public InternalEnvironment estimate(Environment environment)
public DockerRuntimeContext prepare(RuntimeIdentity identity, InternalEnvironment environment)
throws ValidationException, InfrastructureException {
// workaround that in dockerimage environment image is in location field instead of content
if (DockerImageEnvironmentParser.TYPE.equals(environment.getRecipe().getType())
&& environment.getRecipe().getLocation() != null) {
// move image from location to content
EnvironmentImpl envCopy = new EnvironmentImpl(environment);
envCopy.getRecipe().setContent(environment.getRecipe().getLocation());
envCopy.getRecipe().setLocation(null);
return super.estimate(envCopy);
}
return super.estimate(environment);
}

@Override
public void internalEstimate(InternalEnvironment environment)
throws ValidationException, InfrastructureException {
DockerEnvironment dockerEnvironment = dockerEnvironmentParser.parse(environment);
dockerEnvironmentValidator.validate(environment, dockerEnvironment);
// check that order can be resolved
startStrategy.order(dockerEnvironment);
// TODO add an actual estimation of what is missing in the environment
// memory
// machines
}

@Override
protected DockerRuntimeContext internalPrepare(
RuntimeIdentity identity, InternalEnvironment environment)
throws ValidationException, InfrastructureException {

DockerEnvironment dockerEnvironment = dockerEnvironmentParser.parse(environment);
dockerEnvironmentValidator.validate(environment, dockerEnvironment);
DockerEnvironment dockerEnvironment;
String type = environment.getRecipe().getType();
switch (type) {
case "dockerfile":
dockerEnvironment = ((DockerfileInternalEnvironment) environment).getDockerEnvironment();
break;
case "dockerimage":
dockerEnvironment = ((DockerimageInternalEnvironment) environment).getDockerEnvironment();
break;
case "compose":
dockerEnvironment = ((ComposeInternalEnvironment) environment).getComposeEnvironment();
break;
default:
throw new InfrastructureException("Recipe type is not allowed " + type);
}

// modify environment with everything needed to use docker machines on particular (cloud)
// infrastructure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,20 @@

import com.google.inject.AbstractModule;
import com.google.inject.multibindings.MapBinder;
import org.eclipse.che.workspace.infrastructure.docker.environment.compose.ComposeEnvironmentParser;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerfile.DockerfileEnvironmentParser;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerimage.DockerImageEnvironmentParser;
import org.eclipse.che.api.workspace.server.spi.InternalEnvironmentFactory;
import org.eclipse.che.workspace.infrastructure.docker.environment.compose.ComposeInternalEnvironmentFactory;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerfile.DockerfileInternalEnvironmentFactory;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerimage.DockerimageInternalEnvironmentFactory;

/** @author Alexander Garagatyi */
public class DockerEnvironmentTypeModule extends AbstractModule {
@Override
protected void configure() {
// Environment type
MapBinder<String, DockerConfigSourceSpecificEnvironmentParser> envParserMapBinder =
MapBinder.newMapBinder(
binder(), String.class, DockerConfigSourceSpecificEnvironmentParser.class);
envParserMapBinder.addBinding("compose").to(ComposeEnvironmentParser.class);
envParserMapBinder
.addBinding(DockerfileEnvironmentParser.TYPE)
.to(DockerfileEnvironmentParser.class);
envParserMapBinder
.addBinding(DockerImageEnvironmentParser.TYPE)
.to(DockerImageEnvironmentParser.class);
MapBinder<String, InternalEnvironmentFactory> environmentFactories =
MapBinder.newMapBinder(binder(), String.class, InternalEnvironmentFactory.class);
environmentFactories.addBinding(ComposeInternalEnvironmentFactory.TYPE).to(ComposeInternalEnvironmentFactory.class);
environmentFactories.addBinding(DockerfileInternalEnvironmentFactory.TYPE).to(DockerfileInternalEnvironmentFactory.class);
environmentFactories.addBinding(DockerimageInternalEnvironmentFactory.TYPE).to(DockerimageInternalEnvironmentFactory.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
import org.eclipse.che.api.workspace.server.WsAgentMachineFinderUtil;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
import org.eclipse.che.api.workspace.server.spi.InternalMachineConfig;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.workspace.infrastructure.docker.model.DockerContainerConfig;
Expand Down Expand Up @@ -67,18 +66,18 @@ public class EnvironmentValidator {
private static final Pattern VOLUME_FROM_PATTERN =
Pattern.compile("^(?<containerName>" + MACHINE_NAME_REGEXP + ")(:(ro|rw))?$");

public void validate(InternalEnvironment env, DockerEnvironment dockerEnvironment)
public void validate(
Map<String, InternalMachineConfig> machines, DockerEnvironment dockerEnvironment)
throws ValidationException, InfrastructureException {
checkArgument(
dockerEnvironment.getContainers() != null && !dockerEnvironment.getContainers().isEmpty(),
"Environment should contain at least 1 container");

checkArgument(
env.getMachines() != null && !env.getMachines().isEmpty(),
"Environment should contain at least 1 machine");
machines != null && !machines.isEmpty(), "Environment should contain at least 1 machine");

List<String> missingContainers =
env.getMachines()
machines
.keySet()
.stream()
.filter(machineName -> !dockerEnvironment.getContainers().containsKey(machineName))
Expand All @@ -89,7 +88,7 @@ public void validate(InternalEnvironment env, DockerEnvironment dockerEnvironmen
Joiner.on(", ").join(missingContainers));

List<String> machinesWithWsagentServer =
env.getMachines()
machines
.entrySet()
.stream()
.filter(
Expand All @@ -111,7 +110,7 @@ public void validate(InternalEnvironment env, DockerEnvironment dockerEnvironmen
for (Map.Entry<String, DockerContainerConfig> entry :
dockerEnvironment.getContainers().entrySet()) {
validateMachine(
entry.getKey(), env.getMachines().get(entry.getKey()), entry.getValue(), containersNames);
entry.getKey(), machines.get(entry.getKey()), entry.getValue(), containersNames);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2012-2017 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.workspace.infrastructure.docker.environment.compose;

import java.util.List;
import java.util.Map;
import org.eclipse.che.api.core.ValidationException;
import org.eclipse.che.api.core.model.workspace.Warning;
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
import org.eclipse.che.api.workspace.server.spi.InternalMachineConfig;
import org.eclipse.che.api.workspace.server.spi.InternalRecipe;
import org.eclipse.che.workspace.infrastructure.docker.model.DockerEnvironment;

/**
* @author Alexander Garagatyi
* @author Alexander Andrienko
*/
public class ComposeInternalEnvironment extends InternalEnvironment {

private final DockerEnvironment composeEnvironment;

public ComposeInternalEnvironment(
Map<String, InternalMachineConfig> machines,
InternalRecipe recipe,
List<Warning> warnings,
DockerEnvironment composeEnvironment)
throws ValidationException {
super(machines, recipe, warnings);
this.composeEnvironment = composeEnvironment;
}

public DockerEnvironment getComposeEnvironment() {
return composeEnvironment;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,42 +12,52 @@

import static org.eclipse.che.workspace.infrastructure.docker.ArgumentsValidator.checkNotNull;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.eclipse.che.api.core.ValidationException;
import org.eclipse.che.api.core.model.workspace.config.Environment;
import org.eclipse.che.api.core.model.workspace.Warning;
import org.eclipse.che.api.installer.server.InstallerRegistry;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
import org.eclipse.che.api.workspace.server.spi.InternalEnvironmentFactory;
import org.eclipse.che.api.workspace.server.spi.InternalMachineConfig;
import org.eclipse.che.api.workspace.server.spi.InternalRecipe;
import org.eclipse.che.workspace.infrastructure.docker.environment.DockerConfigSourceSpecificEnvironmentParser;
import org.eclipse.che.api.workspace.server.spi.RecipeRetriever;
import org.eclipse.che.workspace.infrastructure.docker.environment.compose.model.ComposeEnvironment;
import org.eclipse.che.workspace.infrastructure.docker.environment.compose.model.ComposeService;
import org.eclipse.che.workspace.infrastructure.docker.model.DockerBuildContext;
import org.eclipse.che.workspace.infrastructure.docker.model.DockerContainerConfig;
import org.eclipse.che.workspace.infrastructure.docker.model.DockerEnvironment;

/**
* Converters compose file to {@link ComposeEnvironment} and vise versa or converters compose {@link
* Environment} to {@link DockerEnvironment}.
*
* @author Alexander Garagatyi
* @author Alexander Andrienko
*/
public class ComposeEnvironmentParser implements DockerConfigSourceSpecificEnvironmentParser {
public class ComposeInternalEnvironmentFactory extends InternalEnvironmentFactory {

public static final String TYPE = "compose";
private static final ObjectMapper YAML_PARSER = new ObjectMapper(new YAMLFactory());

@Inject
public ComposeInternalEnvironmentFactory(
InstallerRegistry installerRegistry, RecipeRetriever recipeRetriever) {
super(installerRegistry, recipeRetriever);
}

@Override
public DockerEnvironment parse(InternalEnvironment environment) throws ValidationException {
checkNotNull(environment, "Environment should not be null");
InternalRecipe recipe = environment.getRecipe();
checkNotNull(environment.getRecipe(), "Environment recipe should not be null");
ComposeEnvironment composeEnvironment = parse(recipe.getContent(), recipe.getContentType());
return asDockerEnvironment(composeEnvironment);
protected InternalEnvironment create(
Map<String, InternalMachineConfig> machines, InternalRecipe recipe, List<Warning> warnings)
throws InfrastructureException, ValidationException {
DockerEnvironment dockerEnvironment =
asDockerEnvironment(parse(recipe.getContent(), recipe.getContentType()));

return new ComposeInternalEnvironment(machines, recipe, warnings, dockerEnvironment);
}

/**
Expand Down Expand Up @@ -83,22 +93,6 @@ ComposeEnvironment parse(String recipeContent, String contentType) throws Valida
return composeEnvironment;
}

/**
* Converts Docker Compose environment model into YAML file.
*
* @param composeEnvironment Docker Compose environment model file
* @throws ValidationException when argument is null or conversion to YAML fails
*/
public String toYaml(ComposeEnvironment composeEnvironment) throws ValidationException {
checkNotNull(composeEnvironment, "Compose environment should not be null");

try {
return YAML_PARSER.writeValueAsString(composeEnvironment);
} catch (JsonProcessingException e) {
throw new ValidationException(e.getLocalizedMessage(), e);
}
}

private DockerEnvironment asDockerEnvironment(ComposeEnvironment composeEnvironment) {
Map<String, DockerContainerConfig> containers =
Maps.newHashMapWithExpectedSize(composeEnvironment.getServices().size());
Expand Down
Loading

0 comments on commit eb90e43

Please sign in to comment.