Skip to content

Commit

Permalink
capacity providers (#211)
Browse files Browse the repository at this point in the history
* capacity providers

* capacity providers

* capacity providers

* capacity providers

* PR cmments

* added assumedRoleArn
  • Loading branch information
chathsuom authored Jan 29, 2021
1 parent e1e324d commit a225334
Show file tree
Hide file tree
Showing 11 changed files with 213 additions and 13 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ TaskRole:
Resource: "*"
- Action:
- "ecs:ListContainerInstances"
- "ecs:DescribeClusters"
Effect: Allow
Resource:
- !Sub "arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:cluster/<clusterName>"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,8 @@ TaskDefinition registerTemplate(final String cloudName, final ECSTaskTemplate te

if (template.isFargate()) {
request
.withRequiresCompatibilities(template.getLaunchType())
.withNetworkMode("awsvpc")
.withRequiresCompatibilities(LaunchType.FARGATE.toString())
.withNetworkMode(NetworkMode.Awsvpc.toString())
.withMemory(String.valueOf(template.getMemoryConstraint()))
.withCpu(String.valueOf(template.getCpu()));
}
Expand Down Expand Up @@ -439,7 +439,6 @@ RunTaskResult runEcsTask(final ECSSlave agent, final ECSTaskTemplate template, S

RunTaskRequest req = new RunTaskRequest()
.withTaskDefinition(taskDefinition.getTaskDefinitionArn())
.withLaunchType(LaunchType.fromValue(template.getLaunchType()))
.withOverrides(new TaskOverride()
.withContainerOverrides(new ContainerOverride()
.withName(agentContainerName)
Expand All @@ -448,8 +447,13 @@ RunTaskResult runEcsTask(final ECSSlave agent, final ECSTaskTemplate template, S
.withEnvironment(envNodeSecret)))
.withPlacementStrategy(template.getPlacementStrategyEntries())
.withCluster(clusterArn);

if (template.getLaunchType() != null && template.getLaunchType().equals("FARGATE")) {
if ( ! template.getDefaultCapacityProvider() && template.getCapacityProviderStrategies() == null ) {
req.withLaunchType(LaunchType.fromValue(template.getLaunchType()));
}
if ( ! template.getDefaultCapacityProvider() && template.getCapacityProviderStrategies() != null ) {
req.withCapacityProviderStrategy(template.getCapacityProviderStrategyEntries());
}
if (template.isFargate()) {
req.withPlatformVersion(template.getPlatformVersion());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@

package com.cloudbees.jenkins.plugins.amazonecs;

import com.amazonaws.services.ecs.AmazonECS;
import com.amazonaws.services.ecs.model.AwsVpcConfiguration;
import com.amazonaws.services.ecs.model.ContainerDefinition;
import com.amazonaws.services.ecs.model.HostEntry;
import com.amazonaws.services.ecs.model.HostVolumeProperties;
import com.amazonaws.services.ecs.model.KeyValuePair;
import com.amazonaws.services.ecs.model.LaunchType;
import com.amazonaws.services.ecs.model.CapacityProviderStrategyItem;
import com.amazonaws.services.ecs.model.LinuxParameters;
import com.amazonaws.services.ecs.model.MountPoint;
import com.amazonaws.services.ecs.model.NetworkMode;
Expand All @@ -40,8 +42,12 @@
import com.amazonaws.services.ecs.model.RegisterTaskDefinitionRequest;
import com.amazonaws.services.ecs.model.RepositoryCredentials;
import com.amazonaws.services.ecs.model.Volume;
import com.amazonaws.services.ecs.model.DescribeClustersRequest;
import com.amazonaws.services.ecs.model.DescribeClustersResult;
import com.amazonaws.services.ecs.model.Cluster;
import static com.google.common.base.Strings.isNullOrEmpty;
import hudson.Extension;
import hudson.RelativePath;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import hudson.model.Label;
Expand Down Expand Up @@ -71,6 +77,7 @@
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.Collections;

/**
* @author <a href="mailto:[email protected]">Nicolas De Loof</a>
Expand Down Expand Up @@ -238,6 +245,12 @@ public int getMemoryConstraint() {
*/
private final String launchType;

/**
* Use default capacity provider will omit launch types and capacity strategies
*
*/
private boolean defaultCapacityProvider;

/**
* Task network mode
*/
Expand Down Expand Up @@ -269,7 +282,7 @@ public int getMemoryConstraint() {
private List<ExtraHostEntry> extraHosts;
private List<PortMappingEntry> portMappings;
private List<PlacementStrategyEntry> placementStrategies;

private List<CapacityProviderStrategyEntry> capacityProviderStrategies;


/**
Expand Down Expand Up @@ -301,7 +314,9 @@ public ECSTaskTemplate(String templateName,
@Nullable String dynamicTaskDefinitionOverride,
String image,
@Nullable final String repositoryCredentials,
String launchType,
@Nullable String launchType,
boolean defaultCapacityProvider,
@Nullable List<CapacityProviderStrategyEntry> capacityProviderStrategies,
String networkMode,
@Nullable String remoteFSRoot,
boolean uniqueRemoteFSRoot,
Expand Down Expand Up @@ -349,6 +364,8 @@ public ECSTaskTemplate(String templateName,
this.memoryReservation = memoryReservation;
this.cpu = cpu;
this.launchType = launchType;
this.defaultCapacityProvider = defaultCapacityProvider;
this.capacityProviderStrategies = capacityProviderStrategies;
this.networkMode = networkMode;
this.subnets = subnets;
this.securityGroups = securityGroups;
Expand Down Expand Up @@ -425,6 +442,15 @@ public void setDnsSearchDomains(String dnsSearchDomains) {
}

public boolean isFargate() {
if (!this.defaultCapacityProvider && this.capacityProviderStrategies != null && ! this.capacityProviderStrategies.isEmpty()) {
for (CapacityProviderStrategyEntry capacityProviderStrategy : this.capacityProviderStrategies) {
String provider = capacityProviderStrategy.provider;
if (provider.contains(LaunchType.FARGATE.toString())) {
return true;
}
}
return false;
}
return StringUtils.trimToNull(this.launchType) != null && launchType.equals(LaunchType.FARGATE.toString());
}

Expand Down Expand Up @@ -489,6 +515,10 @@ public boolean getAssignPublicIp() {
return assignPublicIp;
}

public boolean getDefaultCapacityProvider() {
return defaultCapacityProvider;
}

public String getDnsSearchDomains() {
return dnsSearchDomains;
}
Expand Down Expand Up @@ -613,6 +643,10 @@ public List<PlacementStrategyEntry> getPlacementStrategies() {
return placementStrategies;
}

public List<CapacityProviderStrategyEntry> getCapacityProviderStrategies() {
return capacityProviderStrategies;
}

/**
* This merge does not take an into consideration the child intentionally setting empty values for parameters like "entrypoint" - in fact
* it's not uncommon to override the entrypoint of a container and set it to blank so you can use your own entrypoint as part of the command.
Expand All @@ -631,6 +665,7 @@ public ECSTaskTemplate merge(ECSTaskTemplate parent) {
String image = isNullOrEmpty(this.image) ? parent.getImage() : this.image;
String repositoryCredentials = isNullOrEmpty(this.repositoryCredentials) ? parent.getRepositoryCredentials() : this.repositoryCredentials;
String launchType = isNullOrEmpty(this.launchType) ? parent.getLaunchType() : this.launchType;
boolean defaultCapacityProvider = this.defaultCapacityProvider ? this.defaultCapacityProvider : parent.getDefaultCapacityProvider();
String networkMode = isNullOrEmpty(this.networkMode) ? parent.getNetworkMode() : this.networkMode;
String remoteFSRoot = isNullOrEmpty(this.remoteFSRoot) ? parent.getRemoteFSRoot() : this.remoteFSRoot;

Expand Down Expand Up @@ -660,6 +695,7 @@ public ECSTaskTemplate merge(ECSTaskTemplate parent) {
List<MountPointEntry> mountPoints = isEmpty(this.mountPoints) ? parent.getMountPoints() : this.mountPoints;
List<PortMappingEntry> portMappings = isEmpty(this.portMappings) ? parent.getPortMappings() : this.portMappings;
List<PlacementStrategyEntry> placementStrategies = isEmpty(this.placementStrategies) ? parent.getPlacementStrategies() : this.placementStrategies;
List<CapacityProviderStrategyEntry> capacityProviderStrategies = isEmpty(this.capacityProviderStrategies) ? parent.getCapacityProviderStrategies() : this.capacityProviderStrategies;

String executionRole = isNullOrEmpty(this.executionRole) ? parent.getExecutionRole() : this.executionRole;
String taskrole = isNullOrEmpty(this.taskrole) ? parent.getTaskrole() : this.taskrole;
Expand All @@ -671,6 +707,8 @@ public ECSTaskTemplate merge(ECSTaskTemplate parent) {
image,
repositoryCredentials,
launchType,
defaultCapacityProvider,
capacityProviderStrategies,
networkMode,
remoteFSRoot,
uniqueRemoteFSRoot,
Expand Down Expand Up @@ -802,6 +840,22 @@ Collection<PlacementStrategy> getPlacementStrategyEntries() {
return placements;
}

Collection<CapacityProviderStrategyItem> getCapacityProviderStrategyEntries() {
if (null == capacityProviderStrategies || capacityProviderStrategies.isEmpty())
return null;
Collection<CapacityProviderStrategyItem> stragies = new ArrayList<CapacityProviderStrategyItem>();
for (CapacityProviderStrategyEntry capacityProviderStrategy : this.capacityProviderStrategies) {
String provider = capacityProviderStrategy.provider;
int base = capacityProviderStrategy.base;
int weight = capacityProviderStrategy.weight;

stragies.add(new CapacityProviderStrategyItem().withCapacityProvider(provider)
.withWeight(weight)
.withBase(base));
}
return stragies;
}

public static class EnvironmentEntry extends AbstractDescribableImpl<EnvironmentEntry> implements Serializable {
private static final long serialVersionUID = 4195862080979262875L;
public String name, value;
Expand Down Expand Up @@ -957,6 +1011,57 @@ public FormValidation doCheckField(@QueryParameter("field") String field, @Query
}
}

public static class CapacityProviderStrategyEntry extends AbstractDescribableImpl<CapacityProviderStrategyEntry> implements Serializable {
//private static final long serialVersionUID = 4195862080979262875L;
public String provider;
public int base, weight;

@DataBoundConstructor
public CapacityProviderStrategyEntry(String provider, int base, int weight) {
this.base = base;
this.weight = weight;
this.provider = provider;
}

@Override
public String toString() {
return "CapacityProviderStrategyEntry{" + provider + "base: " + base + "weight: " + weight + "}";
}

@Extension
public static class DescriptorImpl extends Descriptor<CapacityProviderStrategyEntry> {
public ListBoxModel doFillProviderItems(
@RelativePath("../..") @QueryParameter String credentialsId,
@RelativePath("../..") @QueryParameter String assumedRoleArn,
@RelativePath("../..") @QueryParameter String regionName,
@RelativePath("../..") @QueryParameter String cluster
){
ECSService ecsService = new ECSService(credentialsId, assumedRoleArn, regionName);
final AmazonECS client = ecsService.getAmazonECSClient();
final List<Cluster> allClusters = new ArrayList<Cluster>();
DescribeClustersResult result = client.describeClusters(new DescribeClustersRequest().withClusters(cluster));
allClusters.addAll(result.getClusters());
final ListBoxModel options = new ListBoxModel();
for ( Cluster c : allClusters) {
List<String> item = c.getCapacityProviders();
Collections.sort(item);
for (String provider : item) {
options.add(provider);
}
}
return options;
}
@Override
public String getDisplayName() {
return "CapacityProviderStrategyEntry";
}

public FormValidation doCheckField(@QueryParameter("base") int base, @QueryParameter("weight") int weight, @QueryParameter("provider") String provider) throws IOException, ServletException {
return FormValidation.ok();
}
}
}

public Set<LabelAtom> getLabelSet() {
return Label.parse(label);
}
Expand Down Expand Up @@ -1142,6 +1247,12 @@ public boolean equals(Object o) {
if (launchType != null ? !launchType.equals(that.launchType) : that.launchType != null) {
return false;
}
if (defaultCapacityProvider != that.defaultCapacityProvider) {
return false;
}
if (capacityProviderStrategies != null ? !capacityProviderStrategies.equals(that.capacityProviderStrategies) : that.capacityProviderStrategies != null) {
return false;
}
if (networkMode != null ? !networkMode.equals(that.networkMode) : that.networkMode != null) {
return false;
}
Expand Down Expand Up @@ -1192,6 +1303,8 @@ public int hashCode() {
result = 31 * result + (jvmArgs != null ? jvmArgs.hashCode() : 0);
result = 31 * result + (mountPoints != null ? mountPoints.hashCode() : 0);
result = 31 * result + (launchType != null ? launchType.hashCode() : 0);
result = 31 * result + (defaultCapacityProvider ? 1 : 0);
result = 31 * result + (capacityProviderStrategies != null ? capacityProviderStrategies.hashCode() : 0);
result = 31 * result + (networkMode != null ? networkMode.hashCode() : 0);
result = 31 * result + (privileged ? 1 : 0);
result = 31 * result + (uniqueRemoteFSRoot ? 1 : 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.cloudbees.jenkins.plugins.amazonecs.ECSTaskTemplate.MountPointEntry;
import com.cloudbees.jenkins.plugins.amazonecs.ECSTaskTemplate.PortMappingEntry;
import com.cloudbees.jenkins.plugins.amazonecs.ECSTaskTemplate.PlacementStrategyEntry;
import com.cloudbees.jenkins.plugins.amazonecs.ECSTaskTemplate.CapacityProviderStrategyEntry;
import com.google.common.collect.ImmutableSet;
import hudson.model.Run;
import java.util.logging.Level;
Expand All @@ -50,6 +51,7 @@ public class ECSTaskTemplateStep extends Step implements Serializable {
private String repositoryCredentials;
private String image;
private String launchType;
private boolean defaultCapacityProvider;
private String networkMode;
private String remoteFSRoot;
private boolean uniqueRemoteFSRoot;
Expand All @@ -73,6 +75,7 @@ public class ECSTaskTemplateStep extends Step implements Serializable {
private List<MountPointEntry> mountPoints;
private List<PortMappingEntry> portMappings;
private List<PlacementStrategyEntry> placementStrategies;
private List<CapacityProviderStrategyEntry> capacityProviderStrategies;

private List<String> overrides;

Expand Down Expand Up @@ -235,6 +238,15 @@ public boolean getAssignPublicIp() {
return assignPublicIp;
}

@DataBoundSetter
public void setDefaultCapacityProvider(boolean defaultCapacityProvider) {
this.defaultCapacityProvider = defaultCapacityProvider;
}

public boolean getDefaultCapacityProvider() {
return defaultCapacityProvider;
}

@DataBoundSetter
public void setPrivileged(boolean privileged) {
this.privileged = privileged;
Expand Down Expand Up @@ -343,6 +355,16 @@ public void setPlacementStrategies(List<PlacementStrategyEntry> placementStrateg
this.placementStrategies = placementStrategies;
}

public List<CapacityProviderStrategyEntry> getCapacityProviderStrategies() {
return capacityProviderStrategies;
}

@DataBoundSetter
public void setCapacityProviderStrategy(List<CapacityProviderStrategyEntry> capacityProviderStrategies) {
this.capacityProviderStrategies = capacityProviderStrategies;
}


@DataBoundSetter
public void setOverrides(List<String> overrides) {
this.overrides = overrides;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public boolean start() throws Exception {
step.getImage(),
step.getRepositoryCredentials(),
step.getLaunchType(),
step.getDefaultCapacityProvider(),
step.getCapacityProviderStrategies(),
step.getNetworkMode(),
step.getRemoteFSRoot(),
step.getUniqueRemoteFSRoot(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,30 @@
<f:entry name="launchType" title="${%Launch type}" field="launchType">
<f:select />
</f:entry>
<f:entry title="${%Default Capacity Provider}" field="defaultCapacityProvider" description="Use Default Capacity Provider. This will ignore Capacity provider strategy and use launch type value to set require capabilities">
<f:checkbox />
</f:entry>
<f:entry field="capacityProviderStrategies" title="${%Capacity provider strategy}">
<f:repeatable field="capacityProviderStrategies">
<table width="100%">
<f:entry field="base" title="${%Base}">
<f:textbox default="0"/>
</f:entry>
<f:entry field="weight" title="${%Weight}">
<f:textbox default="0"/>
</f:entry>
<f:entry name="provider" title="${%Provider}" field="provider">
<f:select />
</f:entry>

<f:entry>
<div align="right">
<f:repeatableDeleteButton />
</div>
</f:entry>
</table>
</f:repeatable>
</f:entry>
<f:entry name="networkMode" title="${%Network mode}" field="networkMode">
<f:select />
</f:entry>
Expand Down
Loading

0 comments on commit a225334

Please sign in to comment.