implemented aws.#Config and aws/cloudformation packages in stdlib
Signed-off-by: Sam Alba <sam.alba@gmail.com>
This commit is contained in:
parent
98a06c67d2
commit
64ab495c82
10
stdlib/aws/aws.cue
Normal file
10
stdlib/aws/aws.cue
Normal file
@ -0,0 +1,10 @@
|
||||
package aws
|
||||
|
||||
#Config: {
|
||||
// AWS region
|
||||
region: string
|
||||
// AWS access key
|
||||
accessKey: string // FIXME: should be a secret
|
||||
// AWS secret key
|
||||
secretKey: string // FIXME: should be a secret
|
||||
}
|
101
stdlib/aws/cloudformation/cloudformation.cue
Normal file
101
stdlib/aws/cloudformation/cloudformation.cue
Normal file
@ -0,0 +1,101 @@
|
||||
package cloudformation
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"dagger.io/dagger"
|
||||
"dagger.io/alpine"
|
||||
"dagger.io/aws"
|
||||
)
|
||||
|
||||
// AWS CloudFormation Stack
|
||||
#Stack: {
|
||||
|
||||
// AWS Config
|
||||
config: aws.#Config
|
||||
|
||||
// Source is the Cloudformation template (JSON/YAML string)
|
||||
source: string
|
||||
|
||||
// Stackname is the cloudformation stack
|
||||
stackName: string
|
||||
|
||||
// Stack parameters
|
||||
parameters: [string]: _
|
||||
|
||||
// Behavior when failure to create/update the Stack
|
||||
onFailure: *"DO_NOTHING" | "ROLLBACK" | "DELETE"
|
||||
|
||||
// Timeout for waiting for the stack to be created/updated (in minutes)
|
||||
timeout: *10 | uint
|
||||
|
||||
// Never update the stack if already exists
|
||||
neverUpdate: *false | bool
|
||||
|
||||
#files: {
|
||||
"/entrypoint.sh": #Code
|
||||
"/src/template.json": source
|
||||
if len(parameters) > 0 {
|
||||
"/src/parameters.json": json.Marshal(
|
||||
[ for key, val in parameters {
|
||||
ParameterKey: "\(key)"
|
||||
ParameterValue: "\(val)"
|
||||
}])
|
||||
"/src/parameters_overrides.json": json.Marshal([ for key, val in parameters {"\(key)=\(val)"}])
|
||||
}
|
||||
}
|
||||
|
||||
outputs: {
|
||||
[string]: string
|
||||
|
||||
#dagger: compute: [
|
||||
dagger.#Load & {
|
||||
from: alpine.#Image & {
|
||||
package: bash: "=5.1.0-r0"
|
||||
package: jq: "=1.6-r1"
|
||||
package: "aws-cli": "=1.18.177-r0"
|
||||
}
|
||||
},
|
||||
dagger.#Mkdir & {
|
||||
path: "/src"
|
||||
},
|
||||
for dest, content in #files {
|
||||
dagger.#WriteFile & {
|
||||
"dest": dest
|
||||
"content": content
|
||||
}
|
||||
},
|
||||
dagger.#Exec & {
|
||||
args: [
|
||||
"/bin/bash",
|
||||
"--noprofile",
|
||||
"--norc",
|
||||
"-eo",
|
||||
"pipefail",
|
||||
"/entrypoint.sh",
|
||||
]
|
||||
env: {
|
||||
AWS_CONFIG_FILE: "/cache/aws/config"
|
||||
AWS_ACCESS_KEY_ID: config.accessKey
|
||||
AWS_SECRET_ACCESS_KEY: config.secretKey
|
||||
AWS_DEFAULT_REGION: config.region
|
||||
AWS_REGION: config.region
|
||||
AWS_DEFAULT_OUTPUT: "json"
|
||||
AWS_PAGER: ""
|
||||
if neverUpdate {
|
||||
NEVER_UPDATE: "true"
|
||||
}
|
||||
STACK_NAME: stackName
|
||||
TIMEOUT: "\(timeout)"
|
||||
ON_FAILURE: onFailure
|
||||
}
|
||||
dir: "/src"
|
||||
mount: "/cache/aws": "cache"
|
||||
},
|
||||
dagger.#Export & {
|
||||
source: "/outputs.json"
|
||||
format: "json"
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
108
stdlib/aws/cloudformation/code.cue
Normal file
108
stdlib/aws/cloudformation/code.cue
Normal file
@ -0,0 +1,108 @@
|
||||
package cloudformation
|
||||
|
||||
#Code: #"""
|
||||
set +o pipefail
|
||||
|
||||
aws cloudformation validate-template --template-body file:///src/template.json
|
||||
parameters=""
|
||||
|
||||
function getOutputs() {
|
||||
aws cloudformation describe-stacks \
|
||||
--stack-name "$STACK_NAME" \
|
||||
--query 'Stacks[].Outputs' \
|
||||
--output json \
|
||||
| jq '.[] | map( { (.OutputKey|tostring): .OutputValue } ) | add' \
|
||||
> /outputs.json
|
||||
}
|
||||
|
||||
# Check if the stack exists
|
||||
aws cloudformation describe-stacks --stack-name "$STACK_NAME" 2>/dev/null || {
|
||||
if [ -f /src/parameters.json ]; then
|
||||
parameters="--parameters file:///src/parameters.json"
|
||||
cat /src/parameters.json
|
||||
fi
|
||||
|
||||
aws cloudformation create-stack \
|
||||
--stack-name "$STACK_NAME" \
|
||||
--template-body "file:///src/template.json" \
|
||||
--capabilities CAPABILITY_IAM \
|
||||
--on-failure "$ON_FAILURE" \
|
||||
--timeout-in-minutes "$TIMEOUT" \
|
||||
$parameters \
|
||||
|| {
|
||||
# Create failed, display errors
|
||||
aws cloudformation describe-stack-events \
|
||||
--stack-name "$STACK_NAME" \
|
||||
--max-items 10 \
|
||||
| >&2 jq '.StackEvents[] | select((.ResourceStatus | contains("FAILED")) or (.ResourceStatus | contains("ERROR"))) | ("===> ERROR: " + .LogicalResourceId + ": " + .ResourceStatusReason)'
|
||||
exit 1
|
||||
}
|
||||
|
||||
aws cloudformation wait stack-create-complete \
|
||||
--stack-name "$STACK_NAME"
|
||||
|
||||
getOutputs
|
||||
exit 0
|
||||
}
|
||||
|
||||
# In case there is an action already in progress, we wait for the corresponding action to complete
|
||||
wait_action=""
|
||||
stack_status=$(aws cloudformation describe-stacks --stack-name "$STACK_NAME" | jq -r '.Stacks[].StackStatus')
|
||||
case "$stack_status" in
|
||||
"CREATE_FAILED")
|
||||
echo "Deleting previous failed stack..."
|
||||
aws cloudformation delete-stack --stack-name "$STACK_NAME"
|
||||
aws cloudformation wait stack-delete-complete --stack-name "$STACK_NAME" || true
|
||||
;;
|
||||
"CREATE_IN_PROGRESS")
|
||||
echo "Stack create already in progress, waiting..."
|
||||
aws cloudformation wait stack-create-complete --stack-name "$STACK_NAME" || true
|
||||
;;
|
||||
"UPDATE_IN_PROGRESS")
|
||||
# Cancel update to avoid stacks stuck in deadlock (re-apply then works)
|
||||
echo "Stack update already in progress, waiting..."
|
||||
aws cloudformation cancel-update-stack --stack-name "$STACK_NAME" || true
|
||||
;;
|
||||
"ROLLBACK_IN_PROGRESS")
|
||||
echo "Stack rollback already in progress, waiting..."
|
||||
aws cloudformation wait stack-rollback-complete --stack-name "$STACK_NAME" || true
|
||||
;;
|
||||
"DELETE_IN_PROGRESS")
|
||||
echo "Stack delete already in progress, waiting..."
|
||||
aws cloudformation wait stack-delete-complete --stack-name "$STACK_NAME" || true
|
||||
;;
|
||||
"UPDATE_COMPLETE_CLEANUP_IN_PROGRESS")
|
||||
echo "Stack update almost completed, waiting..."
|
||||
aws cloudformation wait stack-update-complete --stack-name "$STACK_NAME" || true
|
||||
;;
|
||||
esac
|
||||
|
||||
[ -n "$NEVER_UPDATE" ] && {
|
||||
getOutputs
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Stack exists, trigger an update via `deploy`
|
||||
if [ -f /src/parameters_overrides.json ]; then
|
||||
parameters="--parameter-overrides file:///src/parameters_overrides.json"
|
||||
cat /src/parameters_overrides.json
|
||||
fi
|
||||
echo "Deploying stack $STACK_NAME"
|
||||
aws cloudformation deploy \
|
||||
--stack-name "$STACK_NAME" \
|
||||
--template-file "/src/template.json" \
|
||||
--capabilities CAPABILITY_IAM \
|
||||
--no-fail-on-empty-changeset \
|
||||
$parameters \
|
||||
|| {
|
||||
# Deploy failed, display errors
|
||||
echo "Failed to deploy stack $STACK_NAME"
|
||||
aws cloudformation describe-stack-events \
|
||||
--stack-name "$STACK_NAME" \
|
||||
--max-items 10 \
|
||||
| >&2 jq '.StackEvents[] | select((.ResourceStatus | contains("FAILED")) or (.ResourceStatus | contains("ERROR"))) | ("===> ERROR: " + .LogicalResourceId + ": " + .ResourceStatusReason)'
|
||||
exit 1
|
||||
}
|
||||
|
||||
getOutputs
|
||||
"""#
|
Reference in New Issue
Block a user