in src/Amazon.ECS.Tools/Commands/DeployServiceCommand.cs [160:292]
private async Task CreateOrUpdateService(string ecsCluster, string ecsService, string taskDefinitionArn, string ecsContainer)
{
try
{
var describeServiceResponse = await this.ECSClient.DescribeServicesAsync(new DescribeServicesRequest
{
Cluster = ecsCluster,
Services = new List<string> { ecsService }
});
var desiredCount = this.GetIntValueOrDefault(this.DeployServiceProperties.DesiredCount, ECSDefinedCommandOptions.ARGUMENT_ECS_DESIRED_COUNT, false);
var deploymentMaximumPercent = this.GetIntValueOrDefault(this.DeployServiceProperties.DeploymentMaximumPercent, ECSDefinedCommandOptions.ARGUMENT_DEPLOYMENT_MAXIMUM_PERCENT, false);
var deploymentMinimumHealthyPercent = this.GetIntValueOrDefault(this.DeployServiceProperties.DeploymentMinimumHealthyPercent, ECSDefinedCommandOptions.ARGUMENT_DEPLOYMENT_MINIMUM_HEALTHY_PERCENT, false);
var launchType = this.GetStringValueOrDefault(this.ClusterProperties.LaunchType, ECSDefinedCommandOptions.ARGUMENT_LAUNCH_TYPE, true);
NetworkConfiguration networkConfiguration = null;
if (IsFargateLaunch(this.ClusterProperties.LaunchType))
{
if (describeServiceResponse.Services.Count != 0)
networkConfiguration = describeServiceResponse.Services[0].NetworkConfiguration;
else
{
networkConfiguration = new NetworkConfiguration();
}
await ECSUtilities.SetupAwsVpcNetworkConfigurationAsync(this, networkConfiguration);
}
DeploymentConfiguration deploymentConfiguration = null;
if (deploymentMaximumPercent.HasValue || deploymentMinimumHealthyPercent.HasValue)
{
deploymentConfiguration = new DeploymentConfiguration();
if (deploymentMaximumPercent.HasValue)
deploymentConfiguration.MaximumPercent = deploymentMaximumPercent.Value;
if (deploymentMinimumHealthyPercent.HasValue)
deploymentConfiguration.MinimumHealthyPercent = deploymentMinimumHealthyPercent.Value;
}
if (describeServiceResponse.Services.Count == 0 || describeServiceResponse.Services[0].Status == "INACTIVE")
{
this.Logger?.WriteLine($"Creating new service: {ecsService}");
var request = new CreateServiceRequest
{
ClientToken = Guid.NewGuid().ToString(),
Cluster = ecsCluster,
ServiceName = ecsService,
TaskDefinition = taskDefinitionArn,
DesiredCount = desiredCount.HasValue ? desiredCount.Value : 1,
DeploymentConfiguration = deploymentConfiguration,
LaunchType = launchType,
NetworkConfiguration = networkConfiguration
};
if(IsFargateLaunch(this.ClusterProperties.LaunchType))
{
await this.AttemptToCreateServiceLinkRoleAsync();
}
else
{
request.PlacementConstraints = ECSUtilities.ConvertPlacementConstraint(this.GetStringValuesOrDefault(this.DeployServiceProperties.PlacementConstraints, ECSDefinedCommandOptions.ARGUMENT_PLACEMENT_CONSTRAINTS, false));
request.PlacementStrategy = ECSUtilities.ConvertPlacementStrategy(this.GetStringValuesOrDefault(this.DeployServiceProperties.PlacementStrategy, ECSDefinedCommandOptions.ARGUMENT_PLACEMENT_STRATEGY, false));
}
var elbTargetGroup = this.GetStringValueOrDefault(this.DeployServiceProperties.ELBTargetGroup, ECSDefinedCommandOptions.ARGUMENT_ELB_TARGET_GROUP_ARN, false);
if (!this.OverrideIgnoreTargetGroup && !string.IsNullOrWhiteSpace(elbTargetGroup))
{
if(!IsFargateLaunch(this.ClusterProperties.LaunchType))
{
request.Role = this.GetStringValueOrDefault(this.DeployServiceProperties.ELBServiceRole, ECSDefinedCommandOptions.ARGUMENT_ELB_SERVICE_ROLE, false);
}
var port = this.GetIntValueOrDefault(this.DeployServiceProperties.ELBContainerPort, ECSDefinedCommandOptions.ARGUMENT_ELB_CONTAINER_PORT, false);
if (!port.HasValue)
port = 80;
request.LoadBalancers.Add(new LoadBalancer
{
TargetGroupArn = elbTargetGroup,
ContainerName = ecsContainer,
ContainerPort = port.Value
});
}
try
{
await this.ECSClient.CreateServiceAsync(request);
}
catch(Amazon.ECS.Model.InvalidParameterException e)
{
if (e.Message.StartsWith("The target group") && !string.IsNullOrEmpty(elbTargetGroup) && string.IsNullOrEmpty(this.DeployServiceProperties.ELBTargetGroup))
{
request.LoadBalancers.Clear();
request.Role = null;
var defaultFile = string.IsNullOrEmpty(this.ConfigFile) ? ECSToolsDefaults.DEFAULT_FILE_NAME : this.ConfigFile;
this.Logger?.WriteLine($"Warning: ELB Target Group ARN specified in config file {defaultFile} does not exist.");
await this.ECSClient.CreateServiceAsync(request);
}
else
{
throw;
}
}
}
else
{
this.Logger?.WriteLine($"Updating new service: {ecsService}");
var updateRequest = new UpdateServiceRequest
{
Cluster = ecsCluster,
Service = ecsService,
TaskDefinition = taskDefinitionArn,
DeploymentConfiguration = deploymentConfiguration,
NetworkConfiguration = networkConfiguration
};
if(desiredCount.HasValue)
{
updateRequest.DesiredCount = desiredCount.Value;
}
await this.ECSClient.UpdateServiceAsync(updateRequest);
}
}
catch (DockerToolsException)
{
throw;
}
catch (Exception e)
{
throw new DockerToolsException($"Error updating ECS service {ecsService} on cluster {ecsCluster}: {e.Message}", DockerToolsException.ECSErrorCode.FailedToUpdateService);
}
}