Support deployments in Kubernetes/OpenShift recipes
Add support of deployments in Kubernetes and OpenShift recipes.
Important changes:
- Since a (Kubernetes|OpenShift)Environment now can contain *both* pods
and deployments simultaneously, we need to:
- Introduce a wrapper class, PodData, which stores spec and metadata
for either a pod or deployment, allowing provisioners to look in one
place for specs that need to be modified
- Disallow modifying the results of KubernetesEnvironment.getPods()
directly, as this would ignore any deployments in the environment
- Add method KubernetesEnvironment.getDeployments(), to obtain
deployment objects directly when needed.
- Modify workspace start process to start all deployments in environment
as well as all pods.
Note: In an effort to keep the changes in this PR readable, nothing is
done to fix broken tests due to the changes above. This commit will not
compile unless test compilation is skipped. The next commit fixes tests.
Signed-off-by: Angel Misevski <amisevsk@redhat.com>
6.19.x
parent
902ddc02fd
commit
9dfc0b6654
|
|
@ -21,14 +21,18 @@ import io.fabric8.kubernetes.api.model.ConfigMap;
|
|||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import io.fabric8.kubernetes.api.model.PodTemplateSpec;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.api.model.Service;
|
||||
import io.fabric8.kubernetes.api.model.apps.Deployment;
|
||||
import io.fabric8.kubernetes.api.model.extensions.Ingress;
|
||||
import io.fabric8.kubernetes.client.Watcher.Action;
|
||||
import io.opentracing.Span;
|
||||
import io.opentracing.Tracer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -642,12 +646,14 @@ public class KubernetesInternalRuntime<E extends KubernetesEnvironment>
|
|||
// namespace.pods().watch(new AbnormalStopHandler());
|
||||
namespace.deployments().watchEvents(new MachineLogsPublisher());
|
||||
if (unrecoverableEventListenerFactory.isConfigured()) {
|
||||
Map<String, Pod> pods = getContext().getEnvironment().getPods();
|
||||
Set<String> toWatch = new HashSet<>();
|
||||
KubernetesEnvironment environment = getContext().getEnvironment();
|
||||
toWatch.addAll(environment.getPodsCopy().keySet());
|
||||
toWatch.addAll(environment.getDeploymentsCopy().keySet());
|
||||
namespace
|
||||
.deployments()
|
||||
.watchEvents(
|
||||
unrecoverableEventListenerFactory.create(
|
||||
pods.keySet(), this::handleUnrecoverableEvent));
|
||||
unrecoverableEventListenerFactory.create(toWatch, this::handleUnrecoverableEvent));
|
||||
}
|
||||
|
||||
final KubernetesServerResolver serverResolver =
|
||||
|
|
@ -713,39 +719,57 @@ public class KubernetesInternalRuntime<E extends KubernetesEnvironment>
|
|||
final Map<String, InternalMachineConfig> machineConfigs = environment.getMachines();
|
||||
final String workspaceId = getContext().getIdentity().getWorkspaceId();
|
||||
LOG.debug("Begin pods creation for workspace '{}'", workspaceId);
|
||||
for (Pod toCreate : environment.getPods().values()) {
|
||||
startTracingContainersStartup(toCreate);
|
||||
for (Pod toCreate : environment.getPodsCopy().values()) {
|
||||
startTracingContainersStartup(toCreate.getSpec(), toCreate.getMetadata());
|
||||
ObjectMeta toCreateMeta = toCreate.getMetadata();
|
||||
final Pod createdPod = namespace.deployments().deploy(toCreate);
|
||||
LOG.debug(
|
||||
"Creating pod '{}' in workspace '{}'", toCreate.getMetadata().getName(), workspaceId);
|
||||
final ObjectMeta podMetadata = createdPod.getMetadata();
|
||||
for (Container container : createdPod.getSpec().getContainers()) {
|
||||
String machineName = Names.machineName(toCreate, container);
|
||||
|
||||
LOG.debug("Creating machine '{}' in workspace '{}'", machineName, workspaceId);
|
||||
machines.put(
|
||||
getContext().getIdentity(),
|
||||
new KubernetesMachineImpl(
|
||||
workspaceId,
|
||||
machineName,
|
||||
podMetadata.getName(),
|
||||
container.getName(),
|
||||
MachineStatus.STARTING,
|
||||
machineConfigs.get(machineName).getAttributes(),
|
||||
serverResolver.resolve(machineName)));
|
||||
eventPublisher.sendStartingEvent(machineName, getContext().getIdentity());
|
||||
}
|
||||
LOG.debug("Creating pod '{}' in workspace '{}'", toCreateMeta.getName(), workspaceId);
|
||||
startMachines(createdPod, toCreateMeta, machineConfigs, serverResolver);
|
||||
}
|
||||
for (Deployment toCreate : environment.getDeploymentsCopy().values()) {
|
||||
PodTemplateSpec template = toCreate.getSpec().getTemplate();
|
||||
startTracingContainersStartup(template.getSpec(), template.getMetadata());
|
||||
ObjectMeta toCreateMeta = toCreate.getMetadata();
|
||||
final Pod createdPod = namespace.deployments().deploy(toCreate);
|
||||
LOG.debug("Creating deployment '{}' in workspace '{}'", toCreateMeta.getName(), workspaceId);
|
||||
startMachines(createdPod, toCreateMeta, machineConfigs, serverResolver);
|
||||
}
|
||||
LOG.debug("Pods creation finished in workspace '{}'", workspaceId);
|
||||
}
|
||||
|
||||
private void startTracingContainersStartup(Pod pod) {
|
||||
/** Puts createdPod in the {@code machines} map and sends the starting event for this machine */
|
||||
public void startMachines(
|
||||
Pod createdPod,
|
||||
ObjectMeta toCreateMeta,
|
||||
Map<String, InternalMachineConfig> machineConfigs,
|
||||
KubernetesServerResolver serverResolver)
|
||||
throws InfrastructureException {
|
||||
final String workspaceId = getContext().getIdentity().getWorkspaceId();
|
||||
for (Container container : createdPod.getSpec().getContainers()) {
|
||||
String machineName = Names.machineName(toCreateMeta, container);
|
||||
|
||||
LOG.debug("Creating machine '{}' in workspace '{}'", machineName, workspaceId);
|
||||
machines.put(
|
||||
getContext().getIdentity(),
|
||||
new KubernetesMachineImpl(
|
||||
workspaceId,
|
||||
machineName,
|
||||
createdPod.getMetadata().getName(),
|
||||
container.getName(),
|
||||
MachineStatus.STARTING,
|
||||
machineConfigs.get(machineName).getAttributes(),
|
||||
serverResolver.resolve(machineName)));
|
||||
eventPublisher.sendStartingEvent(machineName, getContext().getIdentity());
|
||||
}
|
||||
}
|
||||
|
||||
private void startTracingContainersStartup(PodSpec podSpec, ObjectMeta podMeta) {
|
||||
if (tracer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Container container : pod.getSpec().getContainers()) {
|
||||
String machineName = Names.machineName(pod, container);
|
||||
for (Container container : podSpec.getContainers()) {
|
||||
String machineName = Names.machineName(podMeta, container);
|
||||
|
||||
machineStartupTraces.put(
|
||||
machineName,
|
||||
|
|
|
|||
|
|
@ -16,9 +16,11 @@ import static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.CHE_
|
|||
import static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.MACHINE_NAME_ANNOTATION_FMT;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import java.util.Map;
|
||||
import org.eclipse.che.commons.lang.NameGenerator;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
|
||||
/**
|
||||
* Helps to work with Kubernetes objects names.
|
||||
|
|
@ -45,7 +47,15 @@ public class Names {
|
|||
* </pre>
|
||||
*/
|
||||
public static String machineName(Pod pod, Container container) {
|
||||
final Map<String, String> annotations = pod.getMetadata().getAnnotations();
|
||||
return machineName(pod.getMetadata(), container);
|
||||
}
|
||||
|
||||
public static String machineName(PodData podData, Container container) {
|
||||
return machineName(podData.getMetadata(), container);
|
||||
}
|
||||
|
||||
public static String machineName(ObjectMeta podMeta, Container container) {
|
||||
final Map<String, String> annotations = podMeta.getAnnotations();
|
||||
final String machineName;
|
||||
final String containerName = container.getName();
|
||||
if (annotations != null
|
||||
|
|
@ -55,11 +65,11 @@ public class Names {
|
|||
}
|
||||
|
||||
final String originalPodName;
|
||||
final Map<String, String> labels = pod.getMetadata().getLabels();
|
||||
final Map<String, String> labels = podMeta.getLabels();
|
||||
if (labels != null && (originalPodName = labels.get(CHE_ORIGINAL_NAME_LABEL)) != null) {
|
||||
return originalPodName + '/' + containerName;
|
||||
}
|
||||
return pod.getMetadata().getName() + '/' + containerName;
|
||||
return podMeta.getName() + '/' + containerName;
|
||||
}
|
||||
|
||||
/** Return pod name that will be unique for a whole namespace. */
|
||||
|
|
|
|||
|
|
@ -11,11 +11,16 @@
|
|||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.kubernetes.environment;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.fabric8.kubernetes.api.model.ConfigMap;
|
||||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import io.fabric8.kubernetes.api.model.PodTemplateSpec;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.api.model.Service;
|
||||
import io.fabric8.kubernetes.api.model.apps.Deployment;
|
||||
import io.fabric8.kubernetes.api.model.extensions.Ingress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -37,6 +42,14 @@ public class KubernetesEnvironment extends InternalEnvironment {
|
|||
public static final String TYPE = "kubernetes";
|
||||
|
||||
private final Map<String, Pod> pods;
|
||||
private final Map<String, Deployment> deployments;
|
||||
/**
|
||||
* Stores abstracted spec and meta from either a deployment or pod.
|
||||
*
|
||||
* <p>{@link PodData}
|
||||
*/
|
||||
private final Map<String, PodData> podData;
|
||||
|
||||
private final Map<String, Service> services;
|
||||
private final Map<String, Ingress> ingresses;
|
||||
private final Map<String, PersistentVolumeClaim> persistentVolumeClaims;
|
||||
|
|
@ -61,7 +74,9 @@ public class KubernetesEnvironment extends InternalEnvironment {
|
|||
public KubernetesEnvironment(KubernetesEnvironment k8sEnv) {
|
||||
this(
|
||||
k8sEnv,
|
||||
k8sEnv.getPods(),
|
||||
k8sEnv.getPodsCopy(),
|
||||
k8sEnv.getDeploymentsCopy(),
|
||||
k8sEnv.getPodData(),
|
||||
k8sEnv.getServices(),
|
||||
k8sEnv.getIngresses(),
|
||||
k8sEnv.getPersistentVolumeClaims(),
|
||||
|
|
@ -72,6 +87,8 @@ public class KubernetesEnvironment extends InternalEnvironment {
|
|||
protected KubernetesEnvironment(
|
||||
InternalEnvironment internalEnvironment,
|
||||
Map<String, Pod> pods,
|
||||
Map<String, Deployment> deployments,
|
||||
Map<String, PodData> podData,
|
||||
Map<String, Service> services,
|
||||
Map<String, Ingress> ingresses,
|
||||
Map<String, PersistentVolumeClaim> persistentVolumeClaims,
|
||||
|
|
@ -80,6 +97,8 @@ public class KubernetesEnvironment extends InternalEnvironment {
|
|||
super(internalEnvironment);
|
||||
setType(TYPE);
|
||||
this.pods = pods;
|
||||
this.deployments = deployments;
|
||||
this.podData = podData;
|
||||
this.services = services;
|
||||
this.ingresses = ingresses;
|
||||
this.persistentVolumeClaims = persistentVolumeClaims;
|
||||
|
|
@ -92,6 +111,8 @@ public class KubernetesEnvironment extends InternalEnvironment {
|
|||
Map<String, InternalMachineConfig> machines,
|
||||
List<Warning> warnings,
|
||||
Map<String, Pod> pods,
|
||||
Map<String, Deployment> deployments,
|
||||
Map<String, PodData> podData,
|
||||
Map<String, Service> services,
|
||||
Map<String, Ingress> ingresses,
|
||||
Map<String, PersistentVolumeClaim> persistentVolumeClaims,
|
||||
|
|
@ -100,6 +121,8 @@ public class KubernetesEnvironment extends InternalEnvironment {
|
|||
super(internalRecipe, machines, warnings);
|
||||
setType(TYPE);
|
||||
this.pods = pods;
|
||||
this.deployments = deployments;
|
||||
this.podData = podData;
|
||||
this.services = services;
|
||||
this.ingresses = ingresses;
|
||||
this.persistentVolumeClaims = persistentVolumeClaims;
|
||||
|
|
@ -112,9 +135,43 @@ public class KubernetesEnvironment extends InternalEnvironment {
|
|||
return (KubernetesEnvironment) super.setType(type);
|
||||
}
|
||||
|
||||
/** Returns pods that should be created when environment starts. */
|
||||
public Map<String, Pod> getPods() {
|
||||
return pods;
|
||||
/**
|
||||
* Returns pods that should be created when environment starts.
|
||||
*
|
||||
* <p>Note: This map <b>should not</b> be changed, as it will only return pods and not
|
||||
* deployments. If objects in the map need to be changed, see {@link #getPodData()}
|
||||
*/
|
||||
public Map<String, Pod> getPodsCopy() {
|
||||
return ImmutableMap.copyOf(pods);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns deployments that should be created when environment starts.
|
||||
*
|
||||
* <p>Note: This map <b>should not</b> be changed. If objects in the map need to be changed, see
|
||||
* {@link #getPodData()}
|
||||
*/
|
||||
public Map<String, Deployment> getDeploymentsCopy() {
|
||||
return ImmutableMap.copyOf(deployments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link PodData} representing the metadata and pod spec of objects (pods or deployments)
|
||||
* that should be created when environment starts. The data returned by this method represents all
|
||||
* deployment and pod objects that form the workspace, and should be used when provisioning or
|
||||
* performing any action that needs to see every object in the environment.
|
||||
*/
|
||||
public Map<String, PodData> getPodData() {
|
||||
return ImmutableMap.copyOf(podData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a pod to the current environment. This method is necessary as the map returned by {@link
|
||||
* #getPodsCopy()} is a copy. This method also adds the relevant data to {@link #getPodData()}.
|
||||
*/
|
||||
public void addPod(String key, Pod pod) {
|
||||
pods.put(key, pod);
|
||||
podData.put(key, new PodData(pod.getSpec(), pod.getMetadata()));
|
||||
}
|
||||
|
||||
/** Returns services that should be created when environment starts. */
|
||||
|
|
@ -146,6 +203,8 @@ public class KubernetesEnvironment extends InternalEnvironment {
|
|||
protected final InternalEnvironment internalEnvironment;
|
||||
|
||||
protected final Map<String, Pod> pods = new HashMap<>();
|
||||
protected final Map<String, Deployment> deployments = new HashMap<>();
|
||||
protected final Map<String, PodData> podData = new HashMap<>();
|
||||
protected final Map<String, Service> services = new HashMap<>();
|
||||
protected final Map<String, Ingress> ingresses = new HashMap<>();
|
||||
protected final Map<String, PersistentVolumeClaim> pvcs = new HashMap<>();
|
||||
|
|
@ -183,6 +242,25 @@ public class KubernetesEnvironment extends InternalEnvironment {
|
|||
|
||||
public Builder setPods(Map<String, Pod> pods) {
|
||||
this.pods.putAll(pods);
|
||||
pods.entrySet()
|
||||
.forEach(
|
||||
e -> {
|
||||
Pod pod = e.getValue();
|
||||
podData.put(e.getKey(), new PodData(pod.getSpec(), pod.getMetadata()));
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDeployments(Map<String, Deployment> deployments) {
|
||||
this.deployments.putAll(deployments);
|
||||
deployments
|
||||
.entrySet()
|
||||
.forEach(
|
||||
e -> {
|
||||
PodTemplateSpec podTemplate = e.getValue().getSpec().getTemplate();
|
||||
podData.put(
|
||||
e.getKey(), new PodData(podTemplate.getSpec(), podTemplate.getMetadata()));
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -218,7 +296,49 @@ public class KubernetesEnvironment extends InternalEnvironment {
|
|||
|
||||
public KubernetesEnvironment build() {
|
||||
return new KubernetesEnvironment(
|
||||
internalEnvironment, pods, services, ingresses, pvcs, secrets, configMaps);
|
||||
internalEnvironment,
|
||||
pods,
|
||||
deployments,
|
||||
podData,
|
||||
services,
|
||||
ingresses,
|
||||
pvcs,
|
||||
secrets,
|
||||
configMaps);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstraction of pod, since deployments store pod spec and meta within a PodSpecTemplate instead
|
||||
* of a pod object. This class allows us to use one class to support passing of the relevant parts
|
||||
* of a pod or deployment when it comes to provisioning.
|
||||
*
|
||||
* <p>The methods for accessing metadata and spec are identical to that of the Pod class (i.e.
|
||||
* {@code getSpec()} and {@code getMetadata()}
|
||||
*/
|
||||
public static class PodData {
|
||||
private PodSpec podSpec;
|
||||
private ObjectMeta podMeta;
|
||||
|
||||
public PodData(PodSpec podSpec, ObjectMeta podMeta) {
|
||||
this.podSpec = podSpec;
|
||||
this.podMeta = podMeta;
|
||||
}
|
||||
|
||||
public PodSpec getSpec() {
|
||||
return podSpec;
|
||||
}
|
||||
|
||||
public void setSpec(PodSpec podSpec) {
|
||||
this.podSpec = podSpec;
|
||||
}
|
||||
|
||||
public ObjectMeta getMetadata() {
|
||||
return podMeta;
|
||||
}
|
||||
|
||||
public void setMetadata(ObjectMeta podMeta) {
|
||||
this.podMeta = podMeta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
|
|||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.api.model.Service;
|
||||
import io.fabric8.kubernetes.api.model.apps.Deployment;
|
||||
import io.fabric8.kubernetes.api.model.extensions.Ingress;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -100,6 +101,7 @@ public class KubernetesEnvironmentFactory
|
|||
clientFactory.create().lists().load(new ByteArrayInputStream(content.getBytes())).get();
|
||||
|
||||
Map<String, Pod> pods = new HashMap<>();
|
||||
Map<String, Deployment> deployments = new HashMap<>();
|
||||
Map<String, Service> services = new HashMap<>();
|
||||
boolean isAnyIngressPresent = false;
|
||||
boolean isAnyPVCPresent = false;
|
||||
|
|
@ -109,6 +111,9 @@ public class KubernetesEnvironmentFactory
|
|||
if (object instanceof Pod) {
|
||||
Pod pod = (Pod) object;
|
||||
pods.put(pod.getMetadata().getName(), pod);
|
||||
} else if (object instanceof Deployment) {
|
||||
Deployment deployment = (Deployment) object;
|
||||
deployments.put(deployment.getMetadata().getName(), deployment);
|
||||
} else if (object instanceof Service) {
|
||||
Service service = (Service) object;
|
||||
services.put(service.getMetadata().getName(), service);
|
||||
|
|
@ -158,6 +163,7 @@ public class KubernetesEnvironmentFactory
|
|||
.setMachines(machines)
|
||||
.setWarnings(warnings)
|
||||
.setPods(pods)
|
||||
.setDeployments(deployments)
|
||||
.setServices(services)
|
||||
.setIngresses(new HashMap<>())
|
||||
.setPersistentVolumeClaims(new HashMap<>())
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@ import static java.lang.String.format;
|
|||
|
||||
import com.google.common.base.Joiner;
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.eclipse.che.api.core.ValidationException;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.Names;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
|
||||
/**
|
||||
* Validates {@link KubernetesEnvironment}.
|
||||
|
|
@ -35,10 +35,10 @@ public class KubernetesEnvironmentValidator {
|
|||
* @throws ValidationException if the specified {@link KubernetesEnvironment} is invalid
|
||||
*/
|
||||
public void validate(KubernetesEnvironment env) throws ValidationException {
|
||||
checkArgument(!env.getPods().isEmpty(), "Environment should contain at least 1 pod");
|
||||
checkArgument(!env.getPodData().isEmpty(), "Environment should contain at least 1 pod");
|
||||
|
||||
Set<String> missingMachines = new HashSet<>(env.getMachines().keySet());
|
||||
for (Pod pod : env.getPods().values()) {
|
||||
for (PodData pod : env.getPodData().values()) {
|
||||
if (pod.getSpec() != null && pod.getSpec().getContainers() != null) {
|
||||
for (Container container : pod.getSpec().getContainers()) {
|
||||
missingMachines.remove(Names.machineName(pod, container));
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import io.fabric8.kubernetes.api.model.OwnerReference;
|
|||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import io.fabric8.kubernetes.api.model.apps.Deployment;
|
||||
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
|
||||
import io.fabric8.kubernetes.api.model.apps.DoneableDeployment;
|
||||
import io.fabric8.kubernetes.client.KubernetesClientException;
|
||||
import io.fabric8.kubernetes.client.Watch;
|
||||
|
|
@ -125,38 +126,59 @@ public class KubernetesDeployments {
|
|||
putLabel(pod, CHE_WORKSPACE_ID_LABEL, workspaceId);
|
||||
|
||||
ObjectMeta metadata = pod.getMetadata();
|
||||
// Note: metadata.name will be changed as for pods it is set by the deployment.
|
||||
String originalName = metadata.getName();
|
||||
putLabel(pod, CHE_DEPLOYMENT_NAME_LABEL, originalName);
|
||||
|
||||
PodSpec podSpec = pod.getSpec();
|
||||
podSpec.setRestartPolicy("Always"); // Only allowable value
|
||||
|
||||
Deployment deployment =
|
||||
new DeploymentBuilder()
|
||||
.withMetadata(metadata)
|
||||
.withNewSpec()
|
||||
.withNewSelector()
|
||||
.withMatchLabels(metadata.getLabels())
|
||||
.endSelector()
|
||||
.withReplicas(1)
|
||||
.withNewTemplate()
|
||||
.withMetadata(metadata)
|
||||
.withSpec(podSpec)
|
||||
.endTemplate()
|
||||
.endSpec()
|
||||
.build();
|
||||
return createDeployment(deployment, workspaceId);
|
||||
}
|
||||
|
||||
public Pod deploy(Deployment deployment) throws InfrastructureException {
|
||||
ObjectMeta podMeta = deployment.getSpec().getTemplate().getMetadata();
|
||||
putLabel(podMeta, CHE_WORKSPACE_ID_LABEL, workspaceId);
|
||||
putLabel(podMeta, CHE_DEPLOYMENT_NAME_LABEL, deployment.getMetadata().getName());
|
||||
putLabel(deployment.getMetadata(), CHE_WORKSPACE_ID_LABEL, workspaceId);
|
||||
// Match condition for a deployment is an AND of all labels
|
||||
deployment.getSpec().getSelector().setMatchLabels(podMeta.getLabels());
|
||||
// Avoid accidental setting of multiple replicas
|
||||
deployment.getSpec().setReplicas(1);
|
||||
|
||||
PodSpec podSpec = deployment.getSpec().getTemplate().getSpec();
|
||||
podSpec.setRestartPolicy("Always"); // Only allowable value
|
||||
|
||||
return createDeployment(deployment, workspaceId);
|
||||
}
|
||||
|
||||
private Pod createDeployment(Deployment deployment, String workspaceId)
|
||||
throws InfrastructureException {
|
||||
final String deploymentName = deployment.getMetadata().getName();
|
||||
final CompletableFuture<Pod> createFuture = new CompletableFuture<>();
|
||||
final Watch createWatch =
|
||||
clientFactory
|
||||
.create(workspaceId)
|
||||
.pods()
|
||||
.inNamespace(namespace)
|
||||
.watch(new CreateWatcher(createFuture, workspaceId, originalName));
|
||||
.watch(new CreateWatcher(createFuture, workspaceId, deploymentName));
|
||||
try {
|
||||
clientFactory
|
||||
.create(workspaceId)
|
||||
.apps()
|
||||
.deployments()
|
||||
.inNamespace(namespace)
|
||||
.createNew()
|
||||
.withMetadata(metadata)
|
||||
.withNewSpec()
|
||||
.withNewSelector()
|
||||
.withMatchLabels(metadata.getLabels())
|
||||
.endSelector()
|
||||
.withReplicas(1)
|
||||
.withNewTemplate()
|
||||
.withMetadata(metadata)
|
||||
.withSpec(podSpec)
|
||||
.endTemplate()
|
||||
.endSpec()
|
||||
.done();
|
||||
.create(deployment);
|
||||
return createFuture.get(POD_CREATION_TIMEOUT_MIN, TimeUnit.MINUTES);
|
||||
} catch (KubernetesClientException e) {
|
||||
throw new KubernetesInfrastructureException(e);
|
||||
|
|
@ -165,17 +187,17 @@ public class KubernetesDeployments {
|
|||
throw new InfrastructureException(
|
||||
String.format(
|
||||
"Interrupted while waiting for Pod creation. -id: %s -message: %s",
|
||||
metadata.getName(), e.getMessage()));
|
||||
deploymentName, e.getMessage()));
|
||||
} catch (ExecutionException e) {
|
||||
throw new InfrastructureException(
|
||||
String.format(
|
||||
"Error occured while waiting for Pod creation. -id: %s -message: %s",
|
||||
metadata.getName(), e.getCause().getMessage()));
|
||||
deploymentName, e.getCause().getMessage()));
|
||||
} catch (TimeoutException e) {
|
||||
throw new InfrastructureException(
|
||||
String.format(
|
||||
"Pod creation timeout exceeded. -id: %s -message: %s",
|
||||
metadata.getName(), e.getMessage()));
|
||||
deploymentName, e.getMessage()));
|
||||
} finally {
|
||||
createWatch.close();
|
||||
}
|
||||
|
|
@ -894,19 +916,20 @@ public class KubernetesDeployments {
|
|||
|
||||
private final CompletableFuture<Pod> future;
|
||||
private final String workspaceId;
|
||||
private final String originalName;
|
||||
private final String deploymentName;
|
||||
|
||||
private CreateWatcher(CompletableFuture<Pod> future, String workspaceId, String originalName) {
|
||||
private CreateWatcher(
|
||||
CompletableFuture<Pod> future, String workspaceId, String deploymentName) {
|
||||
this.future = future;
|
||||
this.workspaceId = workspaceId;
|
||||
this.originalName = originalName;
|
||||
this.deploymentName = deploymentName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventReceived(Action action, Pod resource) {
|
||||
Map<String, String> labels = resource.getMetadata().getLabels();
|
||||
if (workspaceId.equals(labels.get(CHE_WORKSPACE_ID_LABEL))
|
||||
&& originalName.equals(labels.get(CHE_DEPLOYMENT_NAME_LABEL))) {
|
||||
&& deploymentName.equals(labels.get(CHE_DEPLOYMENT_NAME_LABEL))) {
|
||||
future.complete(resource);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import io.fabric8.kubernetes.api.model.VolumeMount;
|
|||
import io.fabric8.kubernetes.api.model.VolumeMountBuilder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
|
||||
/**
|
||||
* Helps to work with Kubernetes objects.
|
||||
|
|
@ -45,6 +46,20 @@ public class KubernetesObjectUtil {
|
|||
target.setMetadata(metadata = new ObjectMeta());
|
||||
}
|
||||
|
||||
putLabel(target.getMetadata(), key, value);
|
||||
}
|
||||
|
||||
public static void putLabel(PodData target, String key, String value) {
|
||||
ObjectMeta metadata = target.getMetadata();
|
||||
|
||||
if (metadata == null) {
|
||||
target.setMetadata(metadata = new ObjectMeta());
|
||||
}
|
||||
|
||||
putLabel(metadata, key, value);
|
||||
}
|
||||
|
||||
public static void putLabel(ObjectMeta metadata, String key, String value) {
|
||||
Map<String, String> labels = metadata.getLabels();
|
||||
if (labels == null) {
|
||||
metadata.setLabels(labels = new HashMap<>());
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import static org.eclipse.che.workspace.infrastructure.kubernetes.provision.Logs
|
|||
import com.google.inject.Inject;
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
|
@ -40,6 +39,7 @@ import org.eclipse.che.commons.annotation.Traced;
|
|||
import org.eclipse.che.commons.tracing.TracingTags;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.Names;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespace;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespaceFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesPersistentVolumeClaims;
|
||||
|
|
@ -128,7 +128,7 @@ public class CommonPVCStrategy implements WorkspaceVolumesStrategy {
|
|||
String commonPVCName = getCommonPVCName(identity);
|
||||
final PersistentVolumeClaim pvc = newPVC(commonPVCName, pvcAccessMode, pvcQuantity);
|
||||
k8sEnv.getPersistentVolumeClaims().put(commonPVCName, pvc);
|
||||
for (Pod pod : k8sEnv.getPods().values()) {
|
||||
for (PodData pod : k8sEnv.getPodData().values()) {
|
||||
PodSpec podSpec = pod.getSpec();
|
||||
List<Container> containers = new ArrayList<>();
|
||||
containers.addAll(podSpec.getContainers());
|
||||
|
|
@ -198,7 +198,7 @@ public class CommonPVCStrategy implements WorkspaceVolumesStrategy {
|
|||
String pvcName,
|
||||
String workspaceId,
|
||||
Set<String> subPaths,
|
||||
Pod pod,
|
||||
PodData pod,
|
||||
Container container,
|
||||
Map<String, Volume> volumes) {
|
||||
if (volumes.isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.Kube
|
|||
import static org.eclipse.che.workspace.infrastructure.kubernetes.provision.LogsVolumeMachineProvisioner.LOGS_VOLUME_NAME;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import io.fabric8.kubernetes.api.model.VolumeBuilder;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -29,6 +28,7 @@ import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
|||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.Names;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ public class EphemeralWorkspaceAdapter {
|
|||
public void provision(KubernetesEnvironment k8sEnv, RuntimeIdentity identity)
|
||||
throws InfrastructureException {
|
||||
LOG.debug("Provisioning PVC strategy for workspace '{}'", identity.getWorkspaceId());
|
||||
for (Pod pod : k8sEnv.getPods().values()) {
|
||||
for (PodData pod : k8sEnv.getPodData().values()) {
|
||||
PodSpec podSpec = pod.getSpec();
|
||||
|
||||
// To ensure same volumes get mounted correctly in different containers, we need to track
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ public class PVCSubPathHelper {
|
|||
final String podName = jobName + '-' + workspaceId;
|
||||
final String[] command = buildCommand(commandBase, arguments);
|
||||
final Pod pod = newPod(podName, command);
|
||||
securityContextProvisioner.provision(pod);
|
||||
securityContextProvisioner.provision(pod.getSpec());
|
||||
|
||||
KubernetesDeployments deployments = null;
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import com.google.common.collect.ImmutableMap;
|
|||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
|
@ -41,6 +40,7 @@ import org.eclipse.che.commons.annotation.Traced;
|
|||
import org.eclipse.che.commons.tracing.TracingTags;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.Names;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespaceFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesPersistentVolumeClaims;
|
||||
import org.slf4j.Logger;
|
||||
|
|
@ -115,7 +115,7 @@ public class UniqueWorkspacePVCStrategy implements WorkspaceVolumesStrategy {
|
|||
.create(workspaceId)
|
||||
.persistentVolumeClaims()
|
||||
.getByLabel(CHE_WORKSPACE_ID_LABEL, workspaceId));
|
||||
for (Pod pod : k8sEnv.getPods().values()) {
|
||||
for (PodData pod : k8sEnv.getPodData().values()) {
|
||||
final PodSpec podSpec = pod.getSpec();
|
||||
List<Container> containers = new ArrayList<>();
|
||||
containers.addAll(podSpec.getContainers());
|
||||
|
|
@ -158,7 +158,7 @@ public class UniqueWorkspacePVCStrategy implements WorkspaceVolumesStrategy {
|
|||
String workspaceId,
|
||||
Map<String, PersistentVolumeClaim> provisionedClaims,
|
||||
Map<String, PersistentVolumeClaim> existingVolumeName2PVC,
|
||||
Pod pod,
|
||||
PodData pod,
|
||||
Container container,
|
||||
Map<String, Volume> volumes)
|
||||
throws InfrastructureException {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import com.google.common.annotations.VisibleForTesting;
|
|||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.inject.Inject;
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.SecretBuilder;
|
||||
import io.fabric8.kubernetes.api.model.SecretVolumeSourceBuilder;
|
||||
import io.fabric8.kubernetes.api.model.Volume;
|
||||
|
|
@ -30,6 +29,7 @@ import javax.inject.Singleton;
|
|||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
|
||||
/**
|
||||
* Mount configured self-signed certificate as file in each workspace machines if configured.
|
||||
|
|
@ -81,7 +81,7 @@ public class CertificateProvisioner implements ConfigurationProvisioner<Kubernet
|
|||
.withStringData(ImmutableMap.of(CA_CERT_FILE, certificate))
|
||||
.build());
|
||||
|
||||
for (Pod pod : k8sEnv.getPods().values()) {
|
||||
for (PodData pod : k8sEnv.getPodData().values()) {
|
||||
Optional<Volume> certVolume =
|
||||
pod.getSpec()
|
||||
.getVolumes()
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import com.google.gson.Gson;
|
|||
import com.google.gson.stream.JsonWriter;
|
||||
import io.fabric8.kubernetes.api.model.LocalObjectReference;
|
||||
import io.fabric8.kubernetes.api.model.LocalObjectReferenceBuilder;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.api.model.SecretBuilder;
|
||||
import java.io.IOException;
|
||||
|
|
@ -93,7 +93,10 @@ public class ImagePullSecretProvisioner implements ConfigurationProvisioner<Kube
|
|||
|
||||
k8sEnv.getSecrets().put(secret.getMetadata().getName(), secret);
|
||||
|
||||
k8sEnv.getPods().values().forEach(p -> addImagePullSecret(secret.getMetadata().getName(), p));
|
||||
k8sEnv
|
||||
.getPodData()
|
||||
.values()
|
||||
.forEach(p -> addImagePullSecret(secret.getMetadata().getName(), p.getSpec()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -160,13 +163,12 @@ public class ImagePullSecretProvisioner implements ConfigurationProvisioner<Kube
|
|||
}
|
||||
}
|
||||
|
||||
private void addImagePullSecret(String secretName, Pod pod) {
|
||||
List<LocalObjectReference> imagePullSecrets = pod.getSpec().getImagePullSecrets();
|
||||
pod.getSpec()
|
||||
.setImagePullSecrets(
|
||||
ImmutableList.<LocalObjectReference>builder()
|
||||
.add(new LocalObjectReferenceBuilder().withName(secretName).build())
|
||||
.addAll(imagePullSecrets)
|
||||
.build());
|
||||
private void addImagePullSecret(String secretName, PodSpec podSpec) {
|
||||
List<LocalObjectReference> imagePullSecrets = podSpec.getImagePullSecrets();
|
||||
podSpec.setImagePullSecrets(
|
||||
ImmutableList.<LocalObjectReference>builder()
|
||||
.add(new LocalObjectReferenceBuilder().withName(secretName).build())
|
||||
.addAll(imagePullSecrets)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import static java.util.stream.Collectors.toList;
|
|||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
|
@ -37,6 +36,7 @@ import org.eclipse.che.commons.lang.Pair;
|
|||
import org.eclipse.che.commons.tracing.TracingTags;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.Names;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
|
||||
/**
|
||||
* Fixes installers servers ports if conflicts are present.
|
||||
|
|
@ -76,7 +76,7 @@ public class InstallerServersPortProvisioner implements ConfigurationProvisioner
|
|||
|
||||
TracingTags.WORKSPACE_ID.set(identity::getWorkspaceId);
|
||||
|
||||
for (Pod pod : k8sEnv.getPods().values()) {
|
||||
for (PodData pod : k8sEnv.getPodData().values()) {
|
||||
// it is needed to detect conflicts between all containers in a pod
|
||||
// because they use the same ports
|
||||
List<InternalMachineConfig> podMachines =
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.kubernetes.provision;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
|
|
@ -19,6 +19,7 @@ import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
|||
import org.eclipse.che.commons.annotation.Traced;
|
||||
import org.eclipse.che.commons.tracing.TracingTags;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
|
||||
/**
|
||||
* Adds grace termination period to workspace pods.
|
||||
|
|
@ -45,8 +46,8 @@ public class PodTerminationGracePeriodProvisioner implements ConfigurationProvis
|
|||
|
||||
TracingTags.WORKSPACE_ID.set(identity::getWorkspaceId);
|
||||
|
||||
for (Pod pod : k8sEnv.getPods().values()) {
|
||||
if (!isTerminationGracePeriodSet(pod)) {
|
||||
for (PodData pod : k8sEnv.getPodData().values()) {
|
||||
if (!isTerminationGracePeriodSet(pod.getSpec())) {
|
||||
pod.getSpec().setTerminationGracePeriodSeconds(graceTerminationPeriodSec);
|
||||
}
|
||||
}
|
||||
|
|
@ -57,7 +58,7 @@ public class PodTerminationGracePeriodProvisioner implements ConfigurationProvis
|
|||
* @return true if 'terminationGracePeriodSeconds' have been explicitly set in Kubernetes /
|
||||
* OpenShift recipe, false otherwise
|
||||
*/
|
||||
private boolean isTerminationGracePeriodSet(final Pod pod) {
|
||||
return pod.getSpec().getTerminationGracePeriodSeconds() != null;
|
||||
private boolean isTerminationGracePeriodSet(final PodSpec podSpec) {
|
||||
return podSpec.getTerminationGracePeriodSeconds() != null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
package org.eclipse.che.workspace.infrastructure.kubernetes.provision;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.EnvVar;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
|
|
@ -22,6 +21,7 @@ import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
|||
import org.eclipse.che.commons.annotation.Traced;
|
||||
import org.eclipse.che.commons.tracing.TracingTags;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
|
||||
/**
|
||||
* Add proxy configuration to pod containers
|
||||
|
|
@ -60,7 +60,7 @@ public class ProxySettingsProvisioner implements ConfigurationProvisioner {
|
|||
TracingTags.WORKSPACE_ID.set(identity::getWorkspaceId);
|
||||
|
||||
if (!proxyEnvVars.isEmpty()) {
|
||||
for (Pod pod : k8sEnv.getPods().values()) {
|
||||
for (PodData pod : k8sEnv.getPodData().values()) {
|
||||
pod.getSpec()
|
||||
.getContainers()
|
||||
.forEach(
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.kubernetes.provision;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSecurityContextBuilder;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
|
|
@ -38,13 +38,12 @@ public class SecurityContextProvisioner implements ConfigurationProvisioner<Kube
|
|||
public void provision(KubernetesEnvironment k8sEnv, RuntimeIdentity identity)
|
||||
throws InfrastructureException {
|
||||
if (runAsUser != null) {
|
||||
k8sEnv.getPods().values().forEach(this::provision);
|
||||
k8sEnv.getPodData().values().forEach(p -> provision(p.getSpec()));
|
||||
}
|
||||
}
|
||||
|
||||
public void provision(Pod pod) {
|
||||
pod.getSpec()
|
||||
.setSecurityContext(
|
||||
new PodSecurityContextBuilder().withRunAsUser(runAsUser).withFsGroup(fsGroup).build());
|
||||
public void provision(PodSpec podSpec) {
|
||||
podSpec.setSecurityContext(
|
||||
new PodSecurityContextBuilder().withRunAsUser(runAsUser).withFsGroup(fsGroup).build());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ package org.eclipse.che.workspace.infrastructure.kubernetes.provision;
|
|||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
|
@ -23,6 +22,7 @@ import org.eclipse.che.commons.annotation.Nullable;
|
|||
import org.eclipse.che.commons.annotation.Traced;
|
||||
import org.eclipse.che.commons.tracing.TracingTags;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
|
||||
/**
|
||||
* Sets the service account to workspace pods if configured.
|
||||
|
|
@ -51,7 +51,7 @@ public class ServiceAccountProvisioner implements ConfigurationProvisioner {
|
|||
TracingTags.WORKSPACE_ID.set(identity::getWorkspaceId);
|
||||
|
||||
if (!isNullOrEmpty(serviceAccount)) {
|
||||
for (Pod pod : k8sEnv.getPods().values()) {
|
||||
for (PodData pod : k8sEnv.getPodData().values()) {
|
||||
pod.getSpec().setServiceAccountName(serviceAccount);
|
||||
pod.getSpec().setAutomountServiceAccountToken(true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ package org.eclipse.che.workspace.infrastructure.kubernetes.provision;
|
|||
import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesObjectUtil.putLabel;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.extensions.Ingress;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.inject.Singleton;
|
||||
|
|
@ -26,6 +26,7 @@ import org.eclipse.che.commons.tracing.TracingTags;
|
|||
import org.eclipse.che.workspace.infrastructure.kubernetes.Constants;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.Names;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
|
||||
/**
|
||||
* Makes names of Kubernetes pods and ingresses unique whole namespace by {@link Names}.
|
||||
|
|
@ -48,15 +49,14 @@ public class UniqueNamesProvisioner<T extends KubernetesEnvironment>
|
|||
|
||||
TracingTags.WORKSPACE_ID.set(workspaceId);
|
||||
|
||||
final Set<Pod> pods = new HashSet<>(k8sEnv.getPods().values());
|
||||
k8sEnv.getPods().clear();
|
||||
for (Pod pod : pods) {
|
||||
final Collection<PodData> podData = k8sEnv.getPodData().values();
|
||||
for (PodData pod : podData) {
|
||||
final ObjectMeta podMeta = pod.getMetadata();
|
||||
putLabel(pod, Constants.CHE_ORIGINAL_NAME_LABEL, podMeta.getName());
|
||||
putLabel(podMeta, Constants.CHE_ORIGINAL_NAME_LABEL, podMeta.getName());
|
||||
final String podName = Names.uniquePodName(podMeta.getName(), workspaceId);
|
||||
podMeta.setName(podName);
|
||||
k8sEnv.getPods().put(podName, pod);
|
||||
}
|
||||
|
||||
final Set<Ingress> ingresses = new HashSet<>(k8sEnv.getIngresses().values());
|
||||
k8sEnv.getIngresses().clear();
|
||||
for (Ingress ingress : ingresses) {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ package org.eclipse.che.workspace.infrastructure.kubernetes.provision.env;
|
|||
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.EnvVar;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import javax.inject.Singleton;
|
||||
import org.eclipse.che.api.core.model.workspace.config.MachineConfig;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
|
|
@ -23,6 +22,7 @@ import org.eclipse.che.commons.annotation.Traced;
|
|||
import org.eclipse.che.commons.tracing.TracingTags;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.Names;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.provision.ConfigurationProvisioner;
|
||||
|
||||
/**
|
||||
|
|
@ -39,7 +39,7 @@ public class EnvVarsConverter implements ConfigurationProvisioner {
|
|||
|
||||
TracingTags.WORKSPACE_ID.set(identity::getWorkspaceId);
|
||||
|
||||
for (Pod pod : k8sEnv.getPods().values()) {
|
||||
for (PodData pod : k8sEnv.getPodData().values()) {
|
||||
for (Container container : pod.getSpec().getContainers()) {
|
||||
String machineName = Names.machineName(pod, container);
|
||||
InternalMachineConfig machineConf = k8sEnv.getMachines().get(machineName);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMO
|
|||
import static org.eclipse.che.workspace.infrastructure.kubernetes.Names.machineName;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
|
|
@ -26,6 +25,7 @@ import org.eclipse.che.api.workspace.server.spi.environment.MemoryAttributeProvi
|
|||
import org.eclipse.che.commons.annotation.Traced;
|
||||
import org.eclipse.che.commons.tracing.TracingTags;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.provision.ConfigurationProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.util.Containers;
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ public class RamLimitRequestProvisioner implements ConfigurationProvisioner {
|
|||
TracingTags.WORKSPACE_ID.set(identity::getWorkspaceId);
|
||||
|
||||
final Map<String, InternalMachineConfig> machines = k8sEnv.getMachines();
|
||||
for (Pod pod : k8sEnv.getPods().values()) {
|
||||
for (PodData pod : k8sEnv.getPodData().values()) {
|
||||
for (Container container : pod.getSpec().getContainers()) {
|
||||
InternalMachineConfig machineConfig = machines.get(machineName(pod, container));
|
||||
memoryAttributeProvisioner.provision(
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ package org.eclipse.che.workspace.infrastructure.kubernetes.provision.restartpol
|
|||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.WarningImpl;
|
||||
|
|
@ -22,6 +21,7 @@ import org.eclipse.che.commons.annotation.Traced;
|
|||
import org.eclipse.che.commons.tracing.TracingTags;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.Warnings;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.provision.ConfigurationProvisioner;
|
||||
|
||||
/**
|
||||
|
|
@ -40,7 +40,7 @@ public class RestartPolicyRewriter implements ConfigurationProvisioner {
|
|||
|
||||
TracingTags.WORKSPACE_ID.set(identity::getWorkspaceId);
|
||||
|
||||
for (Pod podConfig : k8sEnv.getPods().values()) {
|
||||
for (PodData podConfig : k8sEnv.getPodData().values()) {
|
||||
final String podName = podConfig.getMetadata().getName();
|
||||
final PodSpec podSpec = podConfig.getSpec();
|
||||
rewriteRestartPolicy(podSpec, podName, k8sEnv);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
package org.eclipse.che.workspace.infrastructure.kubernetes.provision.server;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
|
|
@ -25,6 +24,7 @@ import org.eclipse.che.commons.annotation.Traced;
|
|||
import org.eclipse.che.commons.tracing.TracingTags;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.Names;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.provision.ConfigurationProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.KubernetesServerExposer;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ExternalServerExposerStrategy;
|
||||
|
|
@ -64,7 +64,7 @@ public class ServersConverter<T extends KubernetesEnvironment>
|
|||
SecureServerExposer<T> secureServerExposer =
|
||||
secureServerExposerFactoryProvider.get(k8sEnv).create(identity);
|
||||
|
||||
for (Pod podConfig : k8sEnv.getPods().values()) {
|
||||
for (PodData podConfig : k8sEnv.getPodData().values()) {
|
||||
final PodSpec podSpec = podConfig.getSpec();
|
||||
for (Container containerConfig : podSpec.getContainers()) {
|
||||
String machineName = Names.machineName(podConfig, containerConfig);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.CHE_
|
|||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.ContainerPort;
|
||||
import io.fabric8.kubernetes.api.model.ContainerPortBuilder;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.Service;
|
||||
import io.fabric8.kubernetes.api.model.ServicePort;
|
||||
import io.fabric8.kubernetes.api.model.ServicePortBuilder;
|
||||
|
|
@ -38,6 +37,7 @@ import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
|||
import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.Constants;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.provision.UniqueNamesProvisioner;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ExternalServerExposerStrategy;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.SecureServerExposer;
|
||||
|
|
@ -107,14 +107,14 @@ public class KubernetesServerExposer<T extends KubernetesEnvironment> {
|
|||
private final SecureServerExposer<T> secureServerExposer;
|
||||
private final String machineName;
|
||||
private final Container container;
|
||||
private final Pod pod;
|
||||
private final PodData pod;
|
||||
private final T k8sEnv;
|
||||
|
||||
public KubernetesServerExposer(
|
||||
ExternalServerExposerStrategy<T> externalServerExposer,
|
||||
SecureServerExposer<T> secureServerExposer,
|
||||
String machineName,
|
||||
Pod pod,
|
||||
PodData pod,
|
||||
Container container,
|
||||
T k8sEnv) {
|
||||
this.externalServerExposer = externalServerExposer;
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ public class JwtProxyProvisioner {
|
|||
private void ensureJwtProxyInjected(KubernetesEnvironment k8sEnv) throws InfrastructureException {
|
||||
if (!k8sEnv.getMachines().containsKey(JWT_PROXY_MACHINE_NAME)) {
|
||||
k8sEnv.getMachines().put(JWT_PROXY_MACHINE_NAME, createJwtProxyMachine());
|
||||
k8sEnv.getPods().put(JWT_PROXY_POD_NAME, createJwtProxyPod());
|
||||
k8sEnv.addPod(JWT_PROXY_POD_NAME, createJwtProxyPod());
|
||||
|
||||
KeyPair keyPair;
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ package org.eclipse.che.workspace.infrastructure.kubernetes.wsplugins;
|
|||
import com.google.common.annotations.Beta;
|
||||
import com.google.inject.Inject;
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -25,6 +24,7 @@ import org.eclipse.che.api.workspace.server.spi.environment.InternalMachineConfi
|
|||
import org.eclipse.che.api.workspace.server.wsplugins.model.PluginMeta;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.Names;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.wsplugins.brokerphases.BrokerEnvironmentFactory;
|
||||
|
||||
/**
|
||||
|
|
@ -58,18 +58,18 @@ public class KubernetesBrokerInitContainerApplier<E extends KubernetesEnvironmen
|
|||
E brokerEnvironment =
|
||||
brokerEnvironmentFactory.create(pluginsMeta, runtimeID, new BrokersResult());
|
||||
|
||||
Map<String, Pod> workspacePods = workspaceEnvironment.getPods();
|
||||
Map<String, PodData> workspacePods = workspaceEnvironment.getPodData();
|
||||
if (workspacePods.size() != 1) {
|
||||
throw new InfrastructureException(
|
||||
"Che plugins tooling configuration can be applied to a workspace with one pod only.");
|
||||
}
|
||||
Pod workspacePod = workspacePods.values().iterator().next();
|
||||
PodData workspacePod = workspacePods.values().iterator().next();
|
||||
|
||||
Map<String, Pod> brokerPods = brokerEnvironment.getPods();
|
||||
Map<String, PodData> brokerPods = brokerEnvironment.getPodData();
|
||||
if (brokerPods.size() != 1) {
|
||||
throw new InfrastructureException("Broker environment must have only one Pod.");
|
||||
}
|
||||
Pod brokerPod = brokerPods.values().iterator().next();
|
||||
PodData brokerPod = brokerPods.values().iterator().next();
|
||||
|
||||
// Add broker machines to workspace environment so that the init containers can be provisioned.
|
||||
List<Container> brokerContainers = brokerPod.getSpec().getContainers();
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ import org.eclipse.che.api.workspace.server.wsplugins.model.Command;
|
|||
import org.eclipse.che.workspace.infrastructure.kubernetes.Names;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.Warnings;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
|
||||
/**
|
||||
* Applies Che plugins tooling configuration to a kubernetes internal runtime object.
|
||||
|
|
@ -84,10 +85,11 @@ public class KubernetesPluginsToolingApplier implements ChePluginsApplier {
|
|||
|
||||
KubernetesEnvironment kubernetesEnvironment = (KubernetesEnvironment) internalEnvironment;
|
||||
|
||||
Map<String, Pod> pods = kubernetesEnvironment.getPods();
|
||||
Map<String, PodData> pods = kubernetesEnvironment.getPodData();
|
||||
switch (pods.size()) {
|
||||
case 0:
|
||||
addToolingPod(kubernetesEnvironment);
|
||||
pods = kubernetesEnvironment.getPodData();
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
|
|
@ -95,7 +97,7 @@ public class KubernetesPluginsToolingApplier implements ChePluginsApplier {
|
|||
throw new InfrastructureException(
|
||||
"Che plugins tooling configuration can be applied to a workspace with one pod only");
|
||||
}
|
||||
Pod pod = pods.values().iterator().next();
|
||||
PodData pod = pods.values().iterator().next();
|
||||
|
||||
CommandsResolver commandsResolver = new CommandsResolver(kubernetesEnvironment);
|
||||
for (ChePlugin chePlugin : chePlugins) {
|
||||
|
|
@ -125,7 +127,7 @@ public class KubernetesPluginsToolingApplier implements ChePluginsApplier {
|
|||
.endSpec()
|
||||
.build();
|
||||
|
||||
kubernetesEnvironment.getPods().put(CHE_WORKSPACE_POD, pod);
|
||||
kubernetesEnvironment.addPod(CHE_WORKSPACE_POD, pod);
|
||||
}
|
||||
|
||||
private void populateWorkspaceEnvVars(
|
||||
|
|
@ -133,7 +135,7 @@ public class KubernetesPluginsToolingApplier implements ChePluginsApplier {
|
|||
|
||||
List<EnvVar> workspaceEnv = toK8sEnvVars(chePlugin.getWorkspaceEnv());
|
||||
kubernetesEnvironment
|
||||
.getPods()
|
||||
.getPodData()
|
||||
.values()
|
||||
.stream()
|
||||
.flatMap(pod -> pod.getSpec().getContainers().stream())
|
||||
|
|
@ -161,7 +163,7 @@ public class KubernetesPluginsToolingApplier implements ChePluginsApplier {
|
|||
* @throws InfrastructureException when any error occurs
|
||||
*/
|
||||
private void addSidecar(
|
||||
Pod pod,
|
||||
PodData pod,
|
||||
CheContainer container,
|
||||
ChePlugin chePlugin,
|
||||
KubernetesEnvironment kubernetesEnvironment,
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ public class DeployBroker extends BrokerPhase {
|
|||
namespace.configMaps().create(configMap);
|
||||
}
|
||||
|
||||
Pod pluginBrokerPod = getPluginBrokerPod(brokerEnvironment.getPods());
|
||||
Pod pluginBrokerPod = getPluginBrokerPod(brokerEnvironment.getPodsCopy());
|
||||
|
||||
if (factory.isConfigured()) {
|
||||
UnrecoverablePodEventListener unrecoverableEventListener =
|
||||
|
|
|
|||
|
|
@ -45,10 +45,15 @@ import io.fabric8.kubernetes.api.model.KubernetesList;
|
|||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodBuilder;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import io.fabric8.kubernetes.api.model.PodTemplateSpec;
|
||||
import io.fabric8.kubernetes.api.model.PodTemplateSpecBuilder;
|
||||
import io.fabric8.kubernetes.api.model.Quantity;
|
||||
import io.fabric8.kubernetes.api.model.ResourceRequirements;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.api.model.apps.Deployment;
|
||||
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
|
||||
import io.fabric8.kubernetes.api.model.extensions.Ingress;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.client.dsl.KubernetesListMixedOperation;
|
||||
|
|
@ -176,6 +181,116 @@ public class KubernetesEnvironmentFactoryTest {
|
|||
new WarningImpl(CONFIG_MAP_IGNORED_WARNING_CODE, CONFIG_MAP_IGNORED_WARNING_MESSAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addPodsWhenRecipeContainsThem() throws Exception {
|
||||
Pod pod =
|
||||
new PodBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("pod-test")
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.endSpec()
|
||||
.build();
|
||||
|
||||
final List<HasMetadata> recipeObjects = singletonList(pod);
|
||||
when(validatedObjects.getItems()).thenReturn(recipeObjects);
|
||||
|
||||
final KubernetesEnvironment parsed =
|
||||
k8sEnvironmentFactory.doCreate(internalRecipe, emptyMap(), emptyList());
|
||||
|
||||
assertEquals(parsed.getPodsCopy().size(), 1);
|
||||
assertEquals(
|
||||
parsed.getPodsCopy().values().iterator().next().getMetadata().getName(),
|
||||
pod.getMetadata().getName());
|
||||
assertEquals(parsed.getPodData().size(), 1);
|
||||
assertEquals(
|
||||
parsed.getPodData().values().iterator().next().getMetadata().getName(),
|
||||
pod.getMetadata().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addDeploymentsWhenRecipeContainsThem() throws Exception {
|
||||
PodTemplateSpec podTemplate =
|
||||
new PodTemplateSpecBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("deployment-pod")
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.endSpec()
|
||||
.build();
|
||||
Deployment deployment =
|
||||
new DeploymentBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("deployment-test")
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.withTemplate(podTemplate)
|
||||
.endSpec()
|
||||
.build();
|
||||
|
||||
final List<HasMetadata> recipeObjects = singletonList(deployment);
|
||||
when(validatedObjects.getItems()).thenReturn(recipeObjects);
|
||||
|
||||
final KubernetesEnvironment parsed =
|
||||
k8sEnvironmentFactory.doCreate(internalRecipe, emptyMap(), emptyList());
|
||||
|
||||
assertEquals(parsed.getDeploymentsCopy().size(), 1);
|
||||
assertEquals(
|
||||
parsed.getDeploymentsCopy().values().iterator().next().getMetadata().getName(),
|
||||
deployment.getMetadata().getName());
|
||||
assertEquals(parsed.getPodData().size(), 1);
|
||||
assertEquals(
|
||||
parsed.getPodData().values().iterator().next().getMetadata().getName(),
|
||||
podTemplate.getMetadata().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bothPodsAndDeploymentsIncludedInPodData() throws Exception {
|
||||
PodTemplateSpec podTemplate =
|
||||
new PodTemplateSpecBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("deployment-pod")
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.endSpec()
|
||||
.build();
|
||||
Deployment deployment =
|
||||
new DeploymentBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("deployment-test")
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.withTemplate(podTemplate)
|
||||
.endSpec()
|
||||
.build();
|
||||
Pod pod =
|
||||
new PodBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("bare-pod")
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.endSpec()
|
||||
.build();
|
||||
final List<HasMetadata> recipeObjects = asList(deployment, pod);
|
||||
when(validatedObjects.getItems()).thenReturn(recipeObjects);
|
||||
|
||||
final KubernetesEnvironment parsed =
|
||||
k8sEnvironmentFactory.doCreate(internalRecipe, emptyMap(), emptyList());
|
||||
|
||||
assertEquals(parsed.getPodData().size(), 2);
|
||||
assertTrue(
|
||||
parsed
|
||||
.getPodData()
|
||||
.values()
|
||||
.stream()
|
||||
.allMatch(
|
||||
podData -> {
|
||||
String name = podData.getMetadata().getName();
|
||||
return name.equals(podTemplate.getMetadata().getName())
|
||||
|| name.equals(pod.getMetadata().getName());
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProvisionRamAttributesIsInvoked() throws Exception {
|
||||
final long firstMachineRamLimit = 3072;
|
||||
|
|
|
|||
|
|
@ -13,14 +13,13 @@ package org.eclipse.che.workspace.infrastructure.openshift;
|
|||
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import io.fabric8.kubernetes.api.model.ConfigMap;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.api.model.Service;
|
||||
import io.fabric8.openshift.api.model.Route;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
|
@ -123,10 +122,12 @@ public class OpenShiftInternalRuntime extends KubernetesInternalRuntime<OpenShif
|
|||
|
||||
project.deployments().watchEvents(new MachineLogsPublisher());
|
||||
if (unrecoverablePodEventListenerFactory.isConfigured()) {
|
||||
Map<String, Pod> pods = getContext().getEnvironment().getPods();
|
||||
Set<String> toWatch = new HashSet<>();
|
||||
OpenShiftEnvironment environment = getContext().getEnvironment();
|
||||
toWatch.addAll(environment.getPodsCopy().keySet());
|
||||
toWatch.addAll(environment.getDeploymentsCopy().keySet());
|
||||
UnrecoverablePodEventListener handler =
|
||||
unrecoverablePodEventListenerFactory.create(
|
||||
pods.keySet(), this::handleUnrecoverableEvent);
|
||||
unrecoverablePodEventListenerFactory.create(toWatch, this::handleUnrecoverableEvent);
|
||||
project.deployments().watchEvents(handler);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,10 @@ package org.eclipse.che.workspace.infrastructure.openshift.environment;
|
|||
import io.fabric8.kubernetes.api.model.ConfigMap;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodTemplateSpec;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.api.model.Service;
|
||||
import io.fabric8.kubernetes.api.model.apps.Deployment;
|
||||
import io.fabric8.kubernetes.api.model.extensions.Ingress;
|
||||
import io.fabric8.openshift.api.model.Route;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -27,6 +29,7 @@ import org.eclipse.che.api.workspace.server.spi.environment.InternalMachineConfi
|
|||
import org.eclipse.che.api.workspace.server.spi.environment.InternalRecipe;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.Builder;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData;
|
||||
|
||||
/**
|
||||
* Holds objects of OpenShift environment.
|
||||
|
|
@ -63,13 +66,24 @@ public class OpenShiftEnvironment extends KubernetesEnvironment {
|
|||
public OpenShiftEnvironment(
|
||||
InternalEnvironment internalEnvironment,
|
||||
Map<String, Pod> pods,
|
||||
Map<String, Deployment> deployments,
|
||||
Map<String, PodData> podData,
|
||||
Map<String, Service> services,
|
||||
Map<String, Ingress> ingresses,
|
||||
Map<String, PersistentVolumeClaim> pvcs,
|
||||
Map<String, Secret> secrets,
|
||||
Map<String, ConfigMap> configMaps,
|
||||
Map<String, Route> routes) {
|
||||
super(internalEnvironment, pods, services, ingresses, pvcs, secrets, configMaps);
|
||||
super(
|
||||
internalEnvironment,
|
||||
pods,
|
||||
deployments,
|
||||
podData,
|
||||
services,
|
||||
ingresses,
|
||||
pvcs,
|
||||
secrets,
|
||||
configMaps);
|
||||
setType(TYPE);
|
||||
this.routes = routes;
|
||||
}
|
||||
|
|
@ -79,13 +93,26 @@ public class OpenShiftEnvironment extends KubernetesEnvironment {
|
|||
Map<String, InternalMachineConfig> machines,
|
||||
List<Warning> warnings,
|
||||
Map<String, Pod> pods,
|
||||
Map<String, Deployment> deployments,
|
||||
Map<String, PodData> podData,
|
||||
Map<String, Service> services,
|
||||
Map<String, Ingress> ingresses,
|
||||
Map<String, PersistentVolumeClaim> pvcs,
|
||||
Map<String, Secret> secrets,
|
||||
Map<String, ConfigMap> configMaps,
|
||||
Map<String, Route> routes) {
|
||||
super(internalRecipe, machines, warnings, pods, services, ingresses, pvcs, secrets, configMaps);
|
||||
super(
|
||||
internalRecipe,
|
||||
machines,
|
||||
warnings,
|
||||
pods,
|
||||
deployments,
|
||||
podData,
|
||||
services,
|
||||
ingresses,
|
||||
pvcs,
|
||||
secrets,
|
||||
configMaps);
|
||||
setType(TYPE);
|
||||
this.routes = routes;
|
||||
}
|
||||
|
|
@ -130,6 +157,26 @@ public class OpenShiftEnvironment extends KubernetesEnvironment {
|
|||
@Override
|
||||
public Builder setPods(Map<String, Pod> pods) {
|
||||
this.pods.putAll(pods);
|
||||
pods.entrySet()
|
||||
.forEach(
|
||||
e -> {
|
||||
Pod pod = e.getValue();
|
||||
podData.put(e.getKey(), new PodData(pod.getSpec(), pod.getMetadata()));
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder setDeployments(Map<String, Deployment> deployments) {
|
||||
this.deployments.putAll(deployments);
|
||||
deployments
|
||||
.entrySet()
|
||||
.forEach(
|
||||
e -> {
|
||||
PodTemplateSpec podTemplate = e.getValue().getSpec().getTemplate();
|
||||
podData.put(
|
||||
e.getKey(), new PodData(podTemplate.getSpec(), podTemplate.getMetadata()));
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -176,7 +223,16 @@ public class OpenShiftEnvironment extends KubernetesEnvironment {
|
|||
|
||||
public OpenShiftEnvironment build() {
|
||||
return new OpenShiftEnvironment(
|
||||
internalEnvironment, pods, services, ingresses, pvcs, secrets, configMaps, routes);
|
||||
internalEnvironment,
|
||||
pods,
|
||||
deployments,
|
||||
podData,
|
||||
services,
|
||||
ingresses,
|
||||
pvcs,
|
||||
secrets,
|
||||
configMaps,
|
||||
routes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
|
|||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.api.model.Service;
|
||||
import io.fabric8.kubernetes.api.model.apps.Deployment;
|
||||
import io.fabric8.openshift.api.model.DeploymentConfig;
|
||||
import io.fabric8.openshift.api.model.Route;
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
|
@ -101,6 +102,7 @@ public class OpenShiftEnvironmentFactory extends InternalEnvironmentFactory<Open
|
|||
clientFactory.create().lists().load(new ByteArrayInputStream(content.getBytes())).get();
|
||||
|
||||
Map<String, Pod> pods = new HashMap<>();
|
||||
Map<String, Deployment> deployments = new HashMap<>();
|
||||
Map<String, Service> services = new HashMap<>();
|
||||
boolean isAnyRoutePresent = false;
|
||||
boolean isAnyPVCPresent = false;
|
||||
|
|
@ -112,6 +114,9 @@ public class OpenShiftEnvironmentFactory extends InternalEnvironmentFactory<Open
|
|||
} else if (object instanceof Pod) {
|
||||
Pod pod = (Pod) object;
|
||||
pods.put(pod.getMetadata().getName(), pod);
|
||||
} else if (object instanceof Deployment) {
|
||||
Deployment deployment = (Deployment) object;
|
||||
deployments.put(deployment.getMetadata().getName(), deployment);
|
||||
} else if (object instanceof Service) {
|
||||
Service service = (Service) object;
|
||||
services.put(service.getMetadata().getName(), service);
|
||||
|
|
@ -161,6 +166,7 @@ public class OpenShiftEnvironmentFactory extends InternalEnvironmentFactory<Open
|
|||
.setMachines(machines)
|
||||
.setWarnings(warnings)
|
||||
.setPods(pods)
|
||||
.setDeployments(deployments)
|
||||
.setServices(services)
|
||||
.setPersistentVolumeClaims(new HashMap<>())
|
||||
.setSecrets(new HashMap<>())
|
||||
|
|
|
|||
|
|
@ -44,10 +44,15 @@ import io.fabric8.kubernetes.api.model.KubernetesList;
|
|||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodBuilder;
|
||||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import io.fabric8.kubernetes.api.model.PodTemplateSpec;
|
||||
import io.fabric8.kubernetes.api.model.PodTemplateSpecBuilder;
|
||||
import io.fabric8.kubernetes.api.model.Quantity;
|
||||
import io.fabric8.kubernetes.api.model.ResourceRequirements;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.api.model.apps.Deployment;
|
||||
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
|
||||
import io.fabric8.kubernetes.client.dsl.KubernetesListMixedOperation;
|
||||
import io.fabric8.kubernetes.client.dsl.RecreateFromServerGettable;
|
||||
import io.fabric8.openshift.api.model.Route;
|
||||
|
|
@ -175,6 +180,116 @@ public class OpenShiftEnvironmentFactoryTest {
|
|||
new WarningImpl(CONFIG_MAP_IGNORED_WARNING_CODE, CONFIG_MAP_IGNORED_WARNING_MESSAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addPodsWhenRecipeContainsThem() throws Exception {
|
||||
Pod pod =
|
||||
new PodBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("pod-test")
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.endSpec()
|
||||
.build();
|
||||
|
||||
final List<HasMetadata> recipeObjects = singletonList(pod);
|
||||
when(validatedObjects.getItems()).thenReturn(recipeObjects);
|
||||
|
||||
final KubernetesEnvironment parsed =
|
||||
osEnvironmentFactory.doCreate(internalRecipe, emptyMap(), emptyList());
|
||||
|
||||
assertEquals(parsed.getPodsCopy().size(), 1);
|
||||
assertEquals(
|
||||
parsed.getPodsCopy().values().iterator().next().getMetadata().getName(),
|
||||
pod.getMetadata().getName());
|
||||
assertEquals(parsed.getPodData().size(), 1);
|
||||
assertEquals(
|
||||
parsed.getPodData().values().iterator().next().getMetadata().getName(),
|
||||
pod.getMetadata().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addDeploymentsWhenRecipeContainsThem() throws Exception {
|
||||
PodTemplateSpec podTemplate =
|
||||
new PodTemplateSpecBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("deployment-pod")
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.endSpec()
|
||||
.build();
|
||||
Deployment deployment =
|
||||
new DeploymentBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("deployment-test")
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.withTemplate(podTemplate)
|
||||
.endSpec()
|
||||
.build();
|
||||
|
||||
final List<HasMetadata> recipeObjects = singletonList(deployment);
|
||||
when(validatedObjects.getItems()).thenReturn(recipeObjects);
|
||||
|
||||
final KubernetesEnvironment parsed =
|
||||
osEnvironmentFactory.doCreate(internalRecipe, emptyMap(), emptyList());
|
||||
|
||||
assertEquals(parsed.getDeploymentsCopy().size(), 1);
|
||||
assertEquals(
|
||||
parsed.getDeploymentsCopy().values().iterator().next().getMetadata().getName(),
|
||||
deployment.getMetadata().getName());
|
||||
assertEquals(parsed.getPodData().size(), 1);
|
||||
assertEquals(
|
||||
parsed.getPodData().values().iterator().next().getMetadata().getName(),
|
||||
podTemplate.getMetadata().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bothPodsAndDeploymentsIncludedInPodData() throws Exception {
|
||||
PodTemplateSpec podTemplate =
|
||||
new PodTemplateSpecBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("deployment-pod")
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.endSpec()
|
||||
.build();
|
||||
Deployment deployment =
|
||||
new DeploymentBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("deployment-test")
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.withTemplate(podTemplate)
|
||||
.endSpec()
|
||||
.build();
|
||||
Pod pod =
|
||||
new PodBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("bare-pod")
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.endSpec()
|
||||
.build();
|
||||
final List<HasMetadata> recipeObjects = asList(deployment, pod);
|
||||
when(validatedObjects.getItems()).thenReturn(recipeObjects);
|
||||
|
||||
final KubernetesEnvironment parsed =
|
||||
osEnvironmentFactory.doCreate(internalRecipe, emptyMap(), emptyList());
|
||||
|
||||
assertEquals(parsed.getPodData().size(), 2);
|
||||
assertTrue(
|
||||
parsed
|
||||
.getPodData()
|
||||
.values()
|
||||
.stream()
|
||||
.allMatch(
|
||||
podData -> {
|
||||
String name = podData.getMetadata().getName();
|
||||
return name.equals(podTemplate.getMetadata().getName())
|
||||
|| name.equals(pod.getMetadata().getName());
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProvisionRamAttributesIsInvoked() throws Exception {
|
||||
final long firstMachineRamLimit = 3072 * BYTES_IN_MB;
|
||||
|
|
|
|||
Loading…
Reference in New Issue