Jenkins pipeline - check if an ECS service exist

Viewed 1330

I'm using AWS ECS CLI within Jenkins pipeline to automate my CICD. What I'm trying to do is I want to create a service based upon the task definition if the service does not exist yet, if the service already exists I just want to update it instead. Here is the create-service cli command:

aws ecs create-service \
                --cluster $stg_cluster \
                --task-definition $task_def \
                --service-name $ecs_service \
                --desired-count 1 \
                --launch-type EC2 \
                --scheduling-strategy REPLICA \
                --load-balancers \"targetGroupArn=$target_group_arn,containerName=$container_name,containerPort=80\" \
                --deployment-configuration \"maximumPercent=200,minimumHealthyPercent=100\"    

It works fine for the first time but will fail at subsequent deployments because of this error:

An error occurred (InvalidParameterException) when calling the CreateService operation: Creation of service was not idempotent.

I believe I have to use the command update-service instead but not sure how to write ECS CLI command to check if an ECS service has already existed. One way I can think of is I can check the returned code from the create-service cli command see if it equals to 0 but again not sure how to retrieve it from the pipeline. Thanks for your help.

3 Answers

First you can run aws ecs describe-services to check if that service is already there and the state is ACTIVE. If it's active then you can run aws ecs update-service to update existing service. If it's not ACTIVE then you can run aws ecs create-service to create the service.

This is a sample code you can use to check if a service is already created and active:

aws ecs describe-services --cluster CLUSTER_NAME --services SERVIVE_NAME | jq --raw-output 'select(.services[].status != null ) | .services[].status'

and then use an if condition to run update-service or create-service.

This is my code in case anyone is interested. #Jenkinsfile pipeline

stage('Deploy')
{
   steps {
     ....
     script {
                int count = sh(script: """
                    aws ecs describe-services --cluster $ecs_cluster --services $ecs_service | jq '.services | length'
                """, 
                returnStdout: true).trim()

                echo "service count: $count"

                if (count > 0) {
                    //ECS service exists: update
                    echo "Updating ECS service $ecs_service..."
                    sh(script: """
                        aws ecs update-service \
                            --cluster $ecs_cluster \
                            --service $ecs_service \
                            --task-definition $task_def \
                    """)
                }
                else {
                    //ECS service does not exist: create new
                    echo "Creating new ECS service $ecs_service..."
                    
                    sh(script: """
                        aws ecs create-service \
                        --cluster $ecs_cluster \
                        --task-definition $task_def \
                        --service-name $ecs_service \
                        --desired-count 1 \
                        --launch-type EC2 \
                        --scheduling-strategy REPLICA \
                        --load-balancers \"targetGroupArn=${target_group_arn},containerName=$app_name,containerPort=80\" \
                        --deployment-configuration \"maximumPercent=200,minimumHealthyPercent=100\"
                    """)
                }                
            }  

   }
}

Use query parameter in aws cli :

#!/bin/bash
CLUSTER="test-cluster-name"
SERVICE="test-service-name"
echo "check ECS service exists"
status=$(aws ecs describe-services --cluster ${CLUSTER} --services ${SERVICE} --query 'failures[0].reason' --output text)

if [[ "${status}" == "MISSING" ]]; then
    echo "ecs service ${SERVICE} missing in ${CLUSTER}"
    exit 1
fi

same in jenkins pipline:

stage('Deploy')
{
   steps {
     ....
     script {
              string status = sh(script: """
                    aws ecs describe-services --cluster $ecs_cluster --services $ecs_service --query 'failures[0].reason' --output text
                """, 
                returnStdout: true).trim()
                echo "service status: $status" 
                if (status == 'MISSING') { 
                  echo "ecs service: $ecs_service does not exists in $ecs_cluster"
                  // put create service logic
                }
   }}}
Related