/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * 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: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.api.environment.server; import org.eclipse.che.api.agent.server.AgentRegistry; import org.eclipse.che.api.agent.server.exception.AgentException; import org.eclipse.che.api.agent.server.impl.AgentSorter; import org.eclipse.che.api.agent.shared.model.Agent; import org.eclipse.che.api.agent.shared.model.AgentKey; import org.eclipse.che.api.core.model.workspace.Environment; import org.eclipse.che.api.core.model.workspace.ExtendedMachine; import org.eclipse.che.api.core.model.workspace.ServerConf2; import org.eclipse.che.api.environment.server.model.CheServiceImpl; import org.eclipse.che.api.environment.server.model.CheServicesEnvironmentImpl; import org.eclipse.che.commons.annotation.Nullable; import org.slf4j.Logger; import javax.inject.Inject; import java.util.HashMap; import java.util.Map; import static com.google.common.base.Strings.isNullOrEmpty; import static java.lang.String.format; import static org.eclipse.che.api.environment.server.AgentConfigApplier.PROPERTIES.ENVIRONMENT; import static org.slf4j.LoggerFactory.getLogger; /** * Applies docker specific properties of the agents to {@link CheServiceImpl} or {@link CheServicesEnvironmentImpl}. * * </p> * Dependencies between agents are respected. * This class must be called before machines represented by {@link CheServiceImpl} is started, * otherwise changing configuration has no effect. * </br> * The list of supported properties are: * <li>environment</li> * * The {@code environment} property contains command separated environment variables to set * respecting the following format: "name=value". * * @see Agent#getProperties() * @see CheServiceImpl#getEnvironment() * @see CheServiceImpl#getPorts() * @see CheServiceImpl#getLabels() * * @author Anatolii Bazko * @author Alexander Garagatyi */ public class AgentConfigApplier { private static final Logger LOG = getLogger(AgentConfigApplier.class); private final AgentSorter sorter; private final AgentRegistry agentRegistry; @Inject public AgentConfigApplier(AgentSorter sorter, AgentRegistry agentRegistry) { this.sorter = sorter; this.agentRegistry = agentRegistry; } /** * Applies docker specific properties to an environment of machines. * * @param envConfig * environment config with the list of agents that should be injected into machine * @param internalEnv * affected environment of machines * @throws AgentException * if any error occurs */ public void apply(Environment envConfig, CheServicesEnvironmentImpl internalEnv) throws AgentException { for (Map.Entry<String, ? extends ExtendedMachine> machineEntry : envConfig.getMachines() .entrySet()) { String machineName = machineEntry.getKey(); ExtendedMachine machineConf = machineEntry.getValue(); CheServiceImpl internalMachine = internalEnv.getServices().get(machineName); apply(machineConf, internalMachine); } } /** * Applies docker specific properties to a machine. * * @param machineConf * machine config with the list of agents that should be injected into machine * @param machine * affected machine * @throws AgentException * if any error occurs */ public void apply(@Nullable ExtendedMachine machineConf, CheServiceImpl machine) throws AgentException { if (machineConf != null) { for (AgentKey agentKey : sorter.sort(machineConf.getAgents())) { Agent agent = agentRegistry.getAgent(agentKey); addEnv(machine, agent.getProperties()); addExposedPorts(machine, agent.getServers()); addLabels(machine, agent.getServers()); } } } private void addLabels(CheServiceImpl service, Map<String, ? extends ServerConf2> servers) { for (Map.Entry<String, ? extends ServerConf2> entry : servers.entrySet()) { String ref = entry.getKey(); ServerConf2 conf = entry.getValue(); service.getLabels().put("che:server:" + conf.getPort() + ":protocol", conf.getProtocol()); service.getLabels().put("che:server:" + conf.getPort() + ":ref", ref); String path = conf.getProperties().get("path"); if (!isNullOrEmpty(path)) { service.getLabels().put("che:server:" + conf.getPort() + ":path", path); } } } private void addEnv(CheServiceImpl service, Map<String, String> properties) { String environment = properties.get(ENVIRONMENT.toString()); if (isNullOrEmpty(environment)) { return; } Map<String, String> newEnv = new HashMap<>(); if (service.getEnvironment() != null) { newEnv.putAll(service.getEnvironment()); } for (String env : environment.split(",")) { String[] items = env.split("="); if (items.length != 2) { LOG.warn(format("Illegal environment variable '%s' format", env)); continue; } String var = items[0]; String name = items[1]; newEnv.put(var, name); } service.setEnvironment(newEnv); } private void addExposedPorts(CheServiceImpl service, Map<String, ? extends ServerConf2> servers) { for (ServerConf2 server : servers.values()) { service.getExpose().add(server.getPort()); } } public enum PROPERTIES { ENVIRONMENT("environment"); private final String value; PROPERTIES(String value) { this.value = value; } @Override public String toString() { return value; } } }