feat: Enhance stack deployment process in Jenkins pipeline with improved payload handling and validation
This commit is contained in:
@@ -58,45 +58,97 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage('Deploy to Portainer') {
|
stage('Prepare compose payload') {
|
||||||
|
steps {
|
||||||
|
sh '''
|
||||||
|
base64 -w 0 docker-compose.prod.yml > compose-content.b64
|
||||||
|
echo "Compose payload prepared"
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Fetch Portainer stacks') {
|
||||||
steps {
|
steps {
|
||||||
withCredentials([string(credentialsId: 'portainer-token', variable: 'PORTAINER_TOKEN')]) {
|
withCredentials([string(credentialsId: 'portainer-token', variable: 'PORTAINER_TOKEN')]) {
|
||||||
sh '''
|
sh '''
|
||||||
COMPOSE_CONTENT=$(base64 -w 0 docker-compose.prod.yml)
|
curl -s -X GET "''' + env.PORTAINER_URL + '''/api/stacks" \
|
||||||
|
-H "X-API-Key: $PORTAINER_TOKEN" > portainer-stacks.json
|
||||||
# Get the list of stacks
|
echo "Portainer stacks fetched"
|
||||||
STACKS=$(curl -s -X GET "''' + env.PORTAINER_URL + '''/api/stacks" \
|
|
||||||
-H "X-API-Key: $PORTAINER_TOKEN")
|
|
||||||
|
|
||||||
# Check whether the stack already exists
|
|
||||||
STACK_ID=$(echo "$STACKS" | jq -r '.[] | select(.Name == "''' + params.STACK_NAME + '''") | .Id')
|
|
||||||
|
|
||||||
if [ -n "$STACK_ID" ]; then
|
|
||||||
echo "Existing stack found (ID: $STACK_ID), updating..."
|
|
||||||
RESPONSE=$(curl -s -X PUT "''' + env.PORTAINER_URL + '''/api/stacks/$STACK_ID?endpointId=''' + env.PORTAINER_ENV_ID + '''" \
|
|
||||||
-H "X-API-Key: $PORTAINER_TOKEN" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{\"stackFileContent\": \"$COMPOSE_CONTENT\", \"prune\": true, \"pullImage\": true}")
|
|
||||||
else
|
|
||||||
echo "Creating stack ''' + params.STACK_NAME + '''..."
|
|
||||||
RESPONSE=$(curl -s -X POST "''' + env.PORTAINER_URL + '''/api/stacks/create/standalone/string?endpointId=''' + env.PORTAINER_ENV_ID + '''" \
|
|
||||||
-H "X-API-Key: $PORTAINER_TOKEN" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{\"name\": \"''' + params.STACK_NAME + '''\", \"stackFileContent\": \"$COMPOSE_CONTENT\"}")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check whether the response contains an error
|
|
||||||
if echo "$RESPONSE" | jq -e '.message' > /dev/null 2>&1; then
|
|
||||||
echo "Portainer error: $(echo $RESPONSE | jq -r '.message')"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Stack deployed successfully"
|
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stage('Resolve target stack') {
|
||||||
|
steps {
|
||||||
|
script {
|
||||||
|
env.STACK_ID = sh(
|
||||||
|
script: "jq -r '.[] | select(.Name == \"${params.STACK_NAME}\") | .Id' portainer-stacks.json | head -n 1",
|
||||||
|
returnStdout: true
|
||||||
|
).trim()
|
||||||
|
|
||||||
|
if (env.STACK_ID) {
|
||||||
|
echo "Existing stack found (ID: ${env.STACK_ID})"
|
||||||
|
} else {
|
||||||
|
echo "Stack does not exist and will be created"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Update existing stack') {
|
||||||
|
when {
|
||||||
|
expression { return env.STACK_ID?.trim() }
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
withCredentials([string(credentialsId: 'portainer-token', variable: 'PORTAINER_TOKEN')]) {
|
||||||
|
sh '''
|
||||||
|
COMPOSE_CONTENT=$(cat compose-content.b64)
|
||||||
|
|
||||||
|
curl -s -X PUT "''' + env.PORTAINER_URL + '''/api/stacks/$STACK_ID?endpointId=''' + env.PORTAINER_ENV_ID + '''" \
|
||||||
|
-H "X-API-Key: $PORTAINER_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"stackFileContent\": \"$COMPOSE_CONTENT\", \"prune\": true, \"pullImage\": true}" > portainer-response.json
|
||||||
|
|
||||||
|
echo "Stack updated"
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Create new stack') {
|
||||||
|
when {
|
||||||
|
expression { return !env.STACK_ID?.trim() }
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
withCredentials([string(credentialsId: 'portainer-token', variable: 'PORTAINER_TOKEN')]) {
|
||||||
|
sh '''
|
||||||
|
COMPOSE_CONTENT=$(cat compose-content.b64)
|
||||||
|
|
||||||
|
curl -s -X POST "''' + env.PORTAINER_URL + '''/api/stacks/create/standalone/string?endpointId=''' + env.PORTAINER_ENV_ID + '''" \
|
||||||
|
-H "X-API-Key: $PORTAINER_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"name\": \"''' + params.STACK_NAME + '''\", \"stackFileContent\": \"$COMPOSE_CONTENT\"}" > portainer-response.json
|
||||||
|
|
||||||
|
echo "Stack created"
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Validate Portainer response') {
|
||||||
|
steps {
|
||||||
|
sh '''
|
||||||
|
if jq -e '.message' portainer-response.json > /dev/null 2>&1; then
|
||||||
|
echo "Portainer error: $(jq -r '.message' portainer-response.json)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Stack deployed successfully"
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
post {
|
post {
|
||||||
|
|||||||
Reference in New Issue
Block a user