Skip to content

Commit

Permalink
SingularityMesosTaskBuilder: honor mesos containerizer, network port …
Browse files Browse the repository at this point in the history
…mapping, volumes
  • Loading branch information
Steven Schlansker committed Jan 4, 2018
1 parent 5c3f0aa commit 7a77fb0
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public SingularityContainerInfo(
@JsonProperty("volumes") Optional<List<SingularityVolume>> volumes,
@JsonProperty("docker") Optional<SingularityDockerInfo> docker,
@JsonProperty("mesos") Optional<SingularityMesosInfo> mesos,
@JsonProperty("network_infos") Optional<List<SingularityNetworkInfo>> networkInfos) {
@JsonProperty("networkInfos") Optional<List<SingularityNetworkInfo>> networkInfos) {
this.type = type;
this.volumes = volumes;
this.docker = docker;
Expand Down Expand Up @@ -56,7 +56,6 @@ public Optional<SingularityMesosInfo> getMesos() {
return mesos;
}

@JsonProperty("network_infos")
@ApiModelProperty(required=false, value="Mesos container network configuration")
public Optional<List<SingularityNetworkInfo>> getNetworkInfos() {
return networkInfos;
Expand Down Expand Up @@ -90,7 +89,7 @@ public String toString() {
", volumes=" + volumes +
", docker=" + docker +
", mesos=" + mesos +
", network_infos=" + networkInfos +
", networkInfos=" + networkInfos +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
package com.hubspot.mesos;

import java.util.Collections;
import java.util.Map;
import java.util.Objects;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.MoreObjects;
import com.google.common.base.Optional;
import com.wordnik.swagger.annotations.ApiModelProperty;

public class SingularityDockerVolume {
private final Optional<String> driver, name;
private final Map<String, Object> driverOptions;
private final Map<String, String> driverOptions;

@JsonCreator
public SingularityDockerVolume(
@JsonProperty("driver") Optional<String> driver,
@JsonProperty("name") Optional<String> name,
@JsonProperty("driver_options") Map<String, Object> driverOptions)
@JsonProperty("driverOptions") Map<String, String> driverOptions)
{
this.driver = driver;
this.name = name;
this.driverOptions = driverOptions;
this.driverOptions = MoreObjects.firstNonNull(driverOptions, Collections.emptyMap());
}

@ApiModelProperty(required=false, value="Docker volume driver name")
Expand All @@ -33,9 +35,8 @@ public Optional<String> getName() {
return name;
}

@JsonProperty("driver_options")
@ApiModelProperty(required=false, value="Volume driver options")
public Map<String, Object> getDriverOptions() {
public Map<String, String> getDriverOptions() {
return driverOptions;
}

Expand Down Expand Up @@ -63,7 +64,7 @@ public String toString() {
return "SingularityDockerVolume{" +
"driver='" + driver + '\'' +
", name=" + name +
", driver_options=" + driverOptions +
", driverOptions=" + driverOptions +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class SingularityNetworkInfo {
@JsonCreator
public SingularityNetworkInfo(@JsonProperty("name") Optional<String> name,
@JsonProperty("groups") Optional<List<String>> groups,
@JsonProperty("port_mappings") Optional<List<SingularityPortMapping>> portMappings) {
@JsonProperty("portMappings") Optional<List<SingularityPortMapping>> portMappings) {
this.name = name;
this.groups = groups;
this.portMappings = portMappings;
Expand Down Expand Up @@ -61,7 +61,7 @@ public String toString() {
return "SingularityNetworkInfo{" +
"name='" + name + '\'' +
", groups=" + groups +
", port_mappings=" + portMappings +
", portMappings=" + portMappings +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,19 @@ public class SingularityPortMapping {
private final Optional<String> protocol;

@JsonCreator
public SingularityPortMapping(@JsonProperty("host_port") int hostPort,
@JsonProperty("container_port") int containerPort,
public SingularityPortMapping(@JsonProperty("hostPort") int hostPort,
@JsonProperty("containerPort") int containerPort,
@JsonProperty("protocol") Optional<String> protocol) {
this.hostPort = hostPort;
this.containerPort = containerPort;
this.protocol = protocol;
}

@JsonProperty("host_port")
@ApiModelProperty(required=true, value="the port to map from on the host network interface")
public int getHostPort() {
return hostPort;
}

@JsonProperty("container_port")
@ApiModelProperty(required=true, value="the port to map to on the container network interface")
public int getContainerPort() {
return containerPort;
Expand Down Expand Up @@ -59,8 +57,8 @@ public int hashCode() {
@Override
public String toString() {
return "SingularityPortMapping{" +
"host_port='" + hostPort + '\'' +
", container_port=" + containerPort +
"hostPort='" + hostPort + '\'' +
", containerPort=" + containerPort +
", protocol=" + protocol +
'}';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class SingularityVolumeSource {
@JsonCreator
public SingularityVolumeSource(
@JsonProperty("type") SingularityVolumeSourceType type,
@JsonProperty("docker_volume") Optional<SingularityDockerVolume> dockerVolume) {
@JsonProperty("dockerVolume") Optional<SingularityDockerVolume> dockerVolume) {
this.type = MoreObjects.firstNonNull(type, SingularityVolumeSourceType.UNKNOWN);
this.dockerVolume = dockerVolume;
}
Expand All @@ -26,7 +26,6 @@ public SingularityVolumeSourceType getType() {
}

@ApiModelProperty(required=false, value="Docker source volume spec")
@JsonProperty("docker_volume")
public Optional<SingularityDockerVolume> getDockerVolume() {
return dockerVolume;
}
Expand All @@ -53,7 +52,7 @@ public int hashCode() {
public String toString() {
return "SingularityVolumeSource{" +
"type='" + type + '\'' +
", docker_volume=" + dockerVolume +
", dockerVolume=" + dockerVolume +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,18 @@
import org.apache.mesos.v1.Protos.CommandInfo.URI;
import org.apache.mesos.v1.Protos.ContainerInfo;
import org.apache.mesos.v1.Protos.ContainerInfo.DockerInfo;
import org.apache.mesos.v1.Protos.ContainerInfo.MesosInfo;
import org.apache.mesos.v1.Protos.Environment;
import org.apache.mesos.v1.Protos.Environment.Variable;
import org.apache.mesos.v1.Protos.ExecutorID;
import org.apache.mesos.v1.Protos.ExecutorInfo;
import org.apache.mesos.v1.Protos.Image;
import org.apache.mesos.v1.Protos.Label;
import org.apache.mesos.v1.Protos.Labels;
import org.apache.mesos.v1.Protos.Labels.Builder;
import org.apache.mesos.v1.Protos.NetworkInfo;
import org.apache.mesos.v1.Protos.Parameter;
import org.apache.mesos.v1.Protos.Parameters;
import org.apache.mesos.v1.Protos.Resource;
import org.apache.mesos.v1.Protos.TaskID;
import org.apache.mesos.v1.Protos.TaskInfo;
Expand All @@ -33,30 +37,39 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.primitives.Ints;
import com.google.inject.Inject;
import com.google.protobuf.ByteString;
import com.hubspot.deploy.ExecutorDataBuilder;
import com.hubspot.singularity.helpers.MesosProtosUtils;
import com.hubspot.singularity.helpers.MesosUtils;
import com.hubspot.mesos.Resources;
import com.hubspot.mesos.SingularityAppcImage;
import com.hubspot.mesos.SingularityContainerInfo;
import com.hubspot.mesos.SingularityDockerImage;
import com.hubspot.mesos.SingularityDockerInfo;
import com.hubspot.mesos.SingularityDockerNetworkType;
import com.hubspot.mesos.SingularityDockerParameter;
import com.hubspot.mesos.SingularityDockerPortMapping;
import com.hubspot.mesos.SingularityDockerVolume;
import com.hubspot.mesos.SingularityMesosArtifact;
import com.hubspot.singularity.helpers.SingularityMesosTaskHolder;
import com.hubspot.mesos.SingularityMesosImage;
import com.hubspot.mesos.SingularityMesosInfo;
import com.hubspot.mesos.SingularityMesosTaskLabel;
import com.hubspot.mesos.SingularityNetworkInfo;
import com.hubspot.mesos.SingularityPortMapping;
import com.hubspot.mesos.SingularityVolume;
import com.hubspot.mesos.SingularityVolumeSource;
import com.hubspot.singularity.SingularityS3UploaderFile;
import com.hubspot.singularity.SingularityTask;
import com.hubspot.singularity.SingularityTaskExecutorData;
import com.hubspot.singularity.SingularityTaskId;
import com.hubspot.singularity.SingularityTaskRequest;
import com.hubspot.singularity.config.SingularityConfiguration;
import com.hubspot.singularity.data.ExecutorIdGenerator;
import com.hubspot.singularity.helpers.MesosProtosUtils;
import com.hubspot.singularity.helpers.MesosUtils;
import com.hubspot.singularity.helpers.SingularityMesosTaskHolder;

@Singleton
class SingularityMesosTaskBuilder {
Expand Down Expand Up @@ -343,12 +356,114 @@ private void prepareContainerInfo(final SingularityOfferHolder offerHolder, fina
} else {
volumeBuilder.setMode(Volume.Mode.RO);
}
if (volumeInfo.getSource().isPresent()) {
final Volume.Source.Builder sourceBuilder = Volume.Source.newBuilder();
final SingularityVolumeSource source = volumeInfo.getSource().get();
sourceBuilder.setType(Volume.Source.Type.valueOf(source.getType().toString()));
if (source.getDockerVolume().isPresent()) {
final Volume.Source.DockerVolume.Builder dockerVolumeBuilder = Volume.Source.DockerVolume.newBuilder();
final SingularityDockerVolume dockerVolume = source.getDockerVolume().get();
if (dockerVolume.getDriver().isPresent()) {
dockerVolumeBuilder.setDriver(dockerVolume.getDriver().get());
}
if (dockerVolume.getName().isPresent()) {
dockerVolumeBuilder.setName(dockerVolume.getName().get());
}
if (!dockerVolume.getDriverOptions().isEmpty()) {
final Parameters.Builder parameters = Parameters.newBuilder();
for (Entry<String, String> option : dockerVolume.getDriverOptions().entrySet()) {
parameters.addParameter(Parameter.newBuilder().setKey(option.getKey()).setValue(option.getValue()).build());
}
dockerVolumeBuilder.setDriverOptions(parameters.build());
}
sourceBuilder.setDockerVolume(dockerVolumeBuilder.build());
}
volumeBuilder.setSource(sourceBuilder.build());
}
containerBuilder.addVolumes(volumeBuilder);
}

prepareMesosInfo(containerBuilder, containerInfo);

prepareNetworkInfos(containerBuilder, containerInfo, ports);

bldr.setContainer(containerBuilder);
}

private void prepareMesosInfo(ContainerInfo.Builder containerBuilder, final SingularityContainerInfo containerInfo) {
if (!containerInfo.getMesos().isPresent()) {
return;
}
final MesosInfo.Builder builder = MesosInfo.newBuilder();
final SingularityMesosInfo mesos = containerInfo.getMesos().get();
if (mesos.getImage().isPresent()) {
final SingularityMesosImage image = mesos.getImage().get();
final Image.Builder imageBuilder = Image.newBuilder();

imageBuilder.setType(Image.Type.valueOf(image.getType().toString()));
if (image.getAppc().isPresent()) {
final SingularityAppcImage appc = image.getAppc().get();
final Image.Appc.Builder appcBuilder = Image.Appc.newBuilder();
appcBuilder.setName(appc.getName());
if (appc.getId().isPresent()) {
appcBuilder.setId(appc.getId().get());
}
imageBuilder.setAppc(appcBuilder.build());
}

if (image.getDocker().isPresent()) {
final SingularityDockerImage docker = image.getDocker().get();
final Image.Docker.Builder dockerBuilder = Image.Docker.newBuilder();
dockerBuilder.setName(docker.getName());
imageBuilder.setDocker(dockerBuilder.build());
}

builder.setImage(imageBuilder.build());
}
containerBuilder.setMesos(builder.build());
}

private void prepareNetworkInfos(ContainerInfo.Builder containerBuilder, final SingularityContainerInfo containerInfo, final Optional<long[]> ports) {
for (SingularityNetworkInfo netInfo : containerInfo.getNetworkInfos().or(Collections.emptyList())) {
final NetworkInfo.Builder netBuilder = NetworkInfo.newBuilder();
if (netInfo.getName().isPresent()) {
netBuilder.setName(netInfo.getName().get());
}
for (String group : netInfo.getGroups().or(Collections.emptyList())) {
netBuilder.addGroups(group);
}
for (SingularityPortMapping mapping : netInfo.getPortMappings().or(defaultPortMappingFor(ports))) {
final NetworkInfo.PortMapping.Builder portBuilder = NetworkInfo.PortMapping.newBuilder();
final int hostPort = mapping.getHostPort();
final int containerPort = mapping.getContainerPort();
final long[] offerPorts = ports.or(new long[0]);
portBuilder.setHostPort(hostPort < offerPorts.length ? (int) offerPorts[hostPort] : hostPort);
portBuilder.setContainerPort(containerPort < offerPorts.length ? (int) offerPorts[containerPort] : containerPort);
if (mapping.getProtocol().isPresent()) {
portBuilder.setProtocol(mapping.getProtocol().get());
}
netBuilder.addPortMappings(portBuilder.build());
}
containerBuilder.addNetworkInfos(netBuilder.build());
}
}

private Supplier<List<SingularityPortMapping>> defaultPortMappingFor(Optional<long[]> ports) {
return new Supplier<List<SingularityPortMapping>>() {
@Override
public List<SingularityPortMapping> get() {
final long[] portArray = ports.or(new long[0]);
final List<SingularityPortMapping> mappings = new ArrayList<>(portArray.length);
for (long port : portArray) {
final int p = (int) port;
mappings.add(new SingularityPortMapping(p, p, Optional.of("tcp")));
mappings.add(new SingularityPortMapping(p, p, Optional.of("udp")));
}
return mappings;
}
};
}

private List<Resource> buildMesosResources(final Resources resources, Optional<String> role) {
ImmutableList.Builder<Resource> builder = ImmutableList.builder();

Expand Down
Loading

0 comments on commit 7a77fb0

Please sign in to comment.