package com.mesosphere.sdk.specification; import com.mesosphere.sdk.offer.Constants; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.mesos.Protos; import org.apache.mesos.Protos.DiscoveryInfo; import java.util.Collection; import java.util.Collections; import java.util.List; /** * This class represents a single port, with associated environment name. */ public class PortSpec extends DefaultResourceSpec { private final String envKey; private final String portName; private final DiscoveryInfo.Visibility visibility; private final Collection<String> networkNames; private final List<RangeSpec> ranges; @JsonCreator protected PortSpec( @JsonProperty("value") Protos.Value value, @JsonProperty("role") String role, @JsonProperty("pre-reserved-role") String preReservedRole, @JsonProperty("principal") String principal, @JsonProperty("env-key") String envKey, @JsonProperty("port-name") String portName, @JsonProperty("visibility") DiscoveryInfo.Visibility visibility, @JsonProperty("network-names") Collection<String> networkNames, @JsonProperty("ranges") List<RangeSpec> ranges) { super(Constants.PORTS_RESOURCE_TYPE, value, role, preReservedRole, principal); this.envKey = envKey; this.portName = portName; this.visibility = visibility; this.networkNames = networkNames; this.ranges = ranges; } public PortSpec(Builder builder) { this( builder.value, builder.role, builder.preReservedRole, builder.principal, builder.envKey, builder.portName, builder.visibility, builder.networkNames, builder.ranges); validatePort(); } public static Builder newBuilder() { return new Builder(); } public static Builder newBuilder(PortSpec copy) { Builder builder = new Builder(); builder.envKey(copy.getEnvKey()) .portName(copy.getPortName()) .visibility(copy.getVisibility()) .networkNames(copy.getNetworkNames()) .ranges(copy.getRanges()) .value(copy.getValue()) .role(copy.getRole()) .preReservedRole(copy.getPreReservedRole()) .principal(copy.getPrincipal()); return builder; } /** * Returns a copy of the provided {@link PortSpec} which has been updated to have the provided {@code value}. */ @JsonIgnore public static PortSpec withValue(PortSpec portSpec, Protos.Value value) { return new PortSpec( value, portSpec.getRole(), portSpec.getPreReservedRole(), portSpec.getPrincipal(), portSpec.getEnvKey(), portSpec.getPortName(), portSpec.getVisibility(), portSpec.getNetworkNames(), portSpec.getRanges()); } protected void validatePort() { validateResource(); ValidationUtils.nonEmpty(this, "portName", portName); ValidationUtils.nonNull(this, "visibility", visibility); } @JsonProperty("port-name") public String getPortName() { return portName; } @JsonProperty("visibility") public DiscoveryInfo.Visibility getVisibility() { return visibility; } @JsonProperty("network-names") public Collection<String> getNetworkNames() { return networkNames; } @JsonProperty("env-key") public String getEnvKey() { return envKey; } @JsonProperty("ranges") public List<RangeSpec> getRanges() { return ranges; } @JsonIgnore public long getPort() { return getValue().getRanges().getRange(0).getBegin(); } @Override public String toString() { return String.format("%s, port-name: %s, network-names: %s, env-key: %s, visibility: %s, " + "ranges %s", super.toString(), getPortName(), getNetworkNames(), getEnvKey(), getVisibility(), getRanges()); } @Override public boolean equals(Object o) { return EqualsBuilder.reflectionEquals(this, o); } @Override public int hashCode() { return HashCodeBuilder.reflectionHashCode(this); } /** * {@link PortSpec} builder static inner class. */ public static class Builder extends DefaultResourceSpec.Builder { protected String envKey; protected String portName; protected DiscoveryInfo.Visibility visibility; protected Collection<String> networkNames; protected List<RangeSpec> ranges = Collections.emptyList(); protected Builder() { } public Builder envKey(String envKey) { this.envKey = envKey; return this; } public Builder portName(String portName) { this.portName = portName; return this; } public Builder visibility(DiscoveryInfo.Visibility visibility) { this.visibility = visibility; return this; } public Builder networkNames(Collection<String> networkNames) { this.networkNames = networkNames; return this; } public Builder ranges(List<RangeSpec> ranges) { this.ranges = ranges; return this; } public PortSpec build() { return new PortSpec(this); } } }