/*******************************************************************************
* 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.plugin.docker.machine.local;
import com.google.common.base.Strings;
import org.eclipse.che.api.core.util.SystemInfo;
import org.eclipse.che.api.environment.server.AgentConfigApplier;
import org.eclipse.che.api.environment.server.DefaultInfrastructureProvisioner;
import org.eclipse.che.api.environment.server.exception.EnvironmentException;
import org.eclipse.che.api.environment.server.model.CheServiceImpl;
import org.eclipse.che.api.environment.server.model.CheServicesEnvironmentImpl;
import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
import org.eclipse.che.api.workspace.server.model.impl.ExtendedMachineImpl;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.commons.lang.os.WindowsPathEscaper;
import org.eclipse.che.inject.CheBootstrap;
import org.eclipse.che.plugin.docker.machine.ext.provider.DockerExtConfBindingProvider;
import org.eclipse.che.plugin.docker.machine.ext.provider.ExecAgentVolumeProvider;
import org.eclipse.che.plugin.docker.machine.ext.provider.TerminalVolumeProvider;
import org.eclipse.che.plugin.docker.machine.ext.provider.WsAgentVolumeProvider;
import org.eclipse.che.plugin.docker.machine.node.WorkspaceFolderPathProvider;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import static java.lang.String.format;
import static org.eclipse.che.api.workspace.shared.Utils.getDevMachineName;
/**
* Infrastructure provisioner that uses volumes for workspaces projects storing because it relies on local Che usage.
*
* @author Alexander Garagatyi
*/
public class LocalCheInfrastructureProvisioner extends DefaultInfrastructureProvisioner {
private final WorkspaceFolderPathProvider workspaceFolderPathProvider;
private final WindowsPathEscaper pathEscaper;
private final String projectFolderPath;
private final WsAgentVolumeProvider wsAgentVolumeProvider;
private final DockerExtConfBindingProvider dockerExtConfBindingProvider;
private final TerminalVolumeProvider terminalVolumeProvider;
private final ExecAgentVolumeProvider execVolumeProvider;
private final String projectsVolumeOptions;
@Inject
public LocalCheInfrastructureProvisioner(AgentConfigApplier agentConfigApplier,
WorkspaceFolderPathProvider workspaceFolderPathProvider,
WindowsPathEscaper pathEscaper,
@Named("che.workspace.projects.storage") String projectFolderPath,
@Nullable @Named("che.docker.volumes_projects_options") String projectsVolumeOptions,
WsAgentVolumeProvider wsAgentVolumeProvider,
DockerExtConfBindingProvider dockerExtConfBindingProvider,
TerminalVolumeProvider terminalVolumeProvider,
ExecAgentVolumeProvider execAgentVolumeProvider) {
super(agentConfigApplier);
this.workspaceFolderPathProvider = workspaceFolderPathProvider;
this.pathEscaper = pathEscaper;
this.projectFolderPath = projectFolderPath;
this.wsAgentVolumeProvider = wsAgentVolumeProvider;
this.dockerExtConfBindingProvider = dockerExtConfBindingProvider;
this.terminalVolumeProvider = terminalVolumeProvider;
this.execVolumeProvider = execAgentVolumeProvider;
if (!Strings.isNullOrEmpty(projectsVolumeOptions)) {
this.projectsVolumeOptions = ":" + projectsVolumeOptions;
} else {
this.projectsVolumeOptions = "";
}
}
@Override
public void provision(EnvironmentImpl envConfig, CheServicesEnvironmentImpl internalEnv)
throws EnvironmentException {
String devMachineName = getDevMachineName(envConfig);
if (devMachineName == null) {
throw new EnvironmentException("ws-machine is not found on agents applying");
}
CheServiceImpl devMachine = internalEnv.getServices().get(devMachineName);
for (CheServiceImpl machine : internalEnv.getServices().values()) {
ArrayList<String> volumes = new ArrayList<>(machine.getVolumes());
volumes.add(terminalVolumeProvider.get());
volumes.add(execVolumeProvider.get());
machine.setVolumes(volumes);
}
// add bind-mount volume for projects in a workspace
String projectFolderVolume;
try {
projectFolderVolume = format("%s:%s%s",
workspaceFolderPathProvider.getPath(internalEnv.getWorkspaceId()),
projectFolderPath, projectsVolumeOptions);
} catch (IOException e) {
throw new EnvironmentException("Error occurred on resolving path to files of workspace " +
internalEnv.getWorkspaceId());
}
List<String> devMachineVolumes = devMachine.getVolumes();
devMachineVolumes.add(SystemInfo.isWindows() ? pathEscaper.escapePath(projectFolderVolume)
: projectFolderVolume);
// add volume with ws-agent archive
devMachineVolumes.add(wsAgentVolumeProvider.get());
// add volume and variable to setup ws-agent configuration
String dockerExtConfVolume = dockerExtConfBindingProvider.get();
if (dockerExtConfVolume != null) {
devMachineVolumes.add(dockerExtConfVolume);
}
HashMap<String, String> environmentVars = new HashMap<>(devMachine.getEnvironment());
environmentVars.put(CheBootstrap.CHE_LOCAL_CONF_DIR, DockerExtConfBindingProvider.EXT_CHE_LOCAL_CONF_DIR);
devMachine.setEnvironment(environmentVars);
// apply basic infra (e.g. agents)
super.provision(envConfig, internalEnv);
}
@Override
public void provision(ExtendedMachineImpl machineConfig, CheServiceImpl internalMachine)
throws EnvironmentException {
List<String> volumes = internalMachine.getVolumes();
volumes.add(terminalVolumeProvider.get());
volumes.add(execVolumeProvider.get());
super.provision(machineConfig, internalMachine);
}
}