public override async Task <bool> ExecuteAsync() { try { var skipPush = this.GetBoolValueOrDefault(this.DeployTaskProperties.SkipImagePush, ECSDefinedCommandOptions.ARGUMENT_SKIP_IMAGE_PUSH, false).GetValueOrDefault(); var ecsContainer = this.GetStringValueOrDefault(this.TaskDefinitionProperties.ContainerName, ECSDefinedCommandOptions.ARGUMENT_CONTAINER_NAME, true); var ecsTaskDefinition = this.GetStringValueOrDefault(this.TaskDefinitionProperties.TaskDefinitionName, ECSDefinedCommandOptions.ARGUMENT_TD_NAME, true); this.PushDockerImageProperties.DockerImageTag = this.GetStringValueOrDefault(this.PushDockerImageProperties.DockerImageTag, ECSDefinedCommandOptions.ARGUMENT_DOCKER_TAG, true).ToLower(); if (!this.PushDockerImageProperties.DockerImageTag.Contains(":")) { this.PushDockerImageProperties.DockerImageTag += ":latest"; } if (skipPush) { this.PushDockerImageProperties.DockerImageTag = await ECSUtilities.ExpandImageTagIfNecessary(this.Logger, this.ECRClient, this.PushDockerImageProperties.DockerImageTag); } else { var pushCommand = new PushDockerImageCommand(this.Logger, this.WorkingDirectory, this.OriginalCommandLineArguments) { ConfigFile = this.ConfigFile, DisableInteractive = this.DisableInteractive, Credentials = this.Credentials, ECRClient = this.ECRClient, Profile = this.Profile, ProfileLocation = this.ProfileLocation, ProjectLocation = this.ProjectLocation, Region = this.Region, WorkingDirectory = this.WorkingDirectory, PushDockerImageProperties = this.PushDockerImageProperties, }; var success = await pushCommand.ExecuteAsync(); if (!success) { return(false); } this.PushDockerImageProperties.DockerImageTag = pushCommand.PushedImageUri; } var taskDefinitionArn = await ECSUtilities.CreateOrUpdateTaskDefinition(this.Logger, this.ECSClient, this, this.TaskDefinitionProperties, this.PushDockerImageProperties.DockerImageTag, IsFargateLaunch(this.ClusterProperties.LaunchType)); var ecsCluster = this.GetStringValueOrDefault(this.ClusterProperties.ECSCluster, ECSDefinedCommandOptions.ARGUMENT_ECS_CLUSTER, true); await ECSUtilities.EnsureClusterExistsAsync(this.Logger, this.ECSClient, ecsCluster); var taskCount = this.GetIntValueOrDefault(this.DeployTaskProperties.TaskCount, ECSDefinedCommandOptions.ARGUMENT_ECS_TASK_COUNT, false); if (!taskCount.HasValue) { taskCount = 1; } var taskGroup = this.GetStringValueOrDefault(this.DeployTaskProperties.TaskGroup, ECSDefinedCommandOptions.ARGUMENT_ECS_TASK_GROUP, false); var launchType = this.GetStringValueOrDefault(this.ClusterProperties.LaunchType, ECSDefinedCommandOptions.ARGUMENT_LAUNCH_TYPE, true); var runTaskRequest = new Amazon.ECS.Model.RunTaskRequest { Cluster = ecsCluster, TaskDefinition = taskDefinitionArn, Count = taskCount.Value, LaunchType = launchType }; if (IsFargateLaunch(this.ClusterProperties.LaunchType)) { var subnets = this.GetStringValuesOrDefault(this.ClusterProperties.SubnetIds, ECSDefinedCommandOptions.ARGUMENT_LAUNCH_SUBNETS, false); var securityGroups = this.GetStringValuesOrDefault(this.ClusterProperties.SecurityGroupIds, ECSDefinedCommandOptions.ARGUMENT_LAUNCH_SECURITYGROUPS, false); var networkConfiguration = new Amazon.ECS.Model.NetworkConfiguration(); await ECSUtilities.SetupAwsVpcNetworkConfigurationAsync(this, networkConfiguration); runTaskRequest.NetworkConfiguration = networkConfiguration; await this.AttemptToCreateServiceLinkRoleAsync(); } else { runTaskRequest.PlacementConstraints = ECSUtilities.ConvertPlacementConstraint(this.GetStringValuesOrDefault(this.DeployTaskProperties.PlacementConstraints, ECSDefinedCommandOptions.ARGUMENT_PLACEMENT_CONSTRAINTS, false)); runTaskRequest.PlacementStrategy = ECSUtilities.ConvertPlacementStrategy(this.GetStringValuesOrDefault(this.DeployTaskProperties.PlacementStrategy, ECSDefinedCommandOptions.ARGUMENT_PLACEMENT_STRATEGY, false)); } if (!string.IsNullOrEmpty(taskGroup)) { runTaskRequest.Group = taskGroup; } try { var response = await this.ECSClient.RunTaskAsync(runTaskRequest); this.Logger?.WriteLine($"Started {response.Tasks.Count} task:"); foreach (var task in response.Tasks) { this.Logger?.WriteLine($"\t{task.TaskArn}"); } } catch (Exception e) { throw new DockerToolsException("Error executing deploy-task: " + e.Message, DockerToolsException.ECSErrorCode.RunTaskFail); } if (this.GetBoolValueOrDefault(this.PersistConfigFile, CommonDefinedCommandOptions.ARGUMENT_PERSIST_CONFIG_FILE, false).GetValueOrDefault()) { this.SaveConfigFile(); } } catch (DockerToolsException e) { this.Logger?.WriteLine(e.Message); this.LastToolsException = e; return(false); } catch (Exception e) { this.Logger?.WriteLine($"Unknown error executing deploy-task: {e.Message}"); this.Logger?.WriteLine(e.StackTrace); return(false); } return(true); }
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); } }