cloudapi: Add endpoints to clone aws images across regions

Support for creating multiple amis from a single compose. It uses the
AWSEC2* jobs to push images to new regions, and share them with new
accounts.

The compose it depends upon has to have succeeded.
This commit is contained in:
Sanne Raymaekers 2022-06-30 11:46:37 +02:00 committed by Ondřej Budai
parent 599829a3b8
commit d13347e1ca
8 changed files with 794 additions and 117 deletions

View file

@ -284,7 +284,8 @@ curl \
# Prepare a request to be sent to the composer API.
#
REQUEST_FILE="${WORKDIR}/request.json"
REQUEST_FILE="${WORKDIR}/compose_request.json"
IMG_COMPOSE_REQ_FILE="${WORKDIR}/img_compose_request.json"
ARCH=$(uname -m)
SSH_USER=
TEST_ID="$(uuidgen)"
@ -418,6 +419,64 @@ function waitForState() {
export UPLOAD_OPTIONS
}
function sendImgFromCompose() {
OUTPUT=$(mktemp)
HTTPSTATUS=$(curl \
--silent \
--show-error \
--cacert /etc/osbuild-composer/ca-crt.pem \
--key /etc/osbuild-composer/client-key.pem \
--cert /etc/osbuild-composer/client-crt.pem \
--header 'Content-Type: application/json' \
--request POST \
--data @"$1" \
--write-out '%{http_code}' \
--output "$OUTPUT" \
https://localhost/api/image-builder-composer/v2/composes/"$COMPOSE_ID"/clone)
test "$HTTPSTATUS" = "201"
IMG_ID=$(jq -r '.id' "$OUTPUT")
}
function waitForImgState() {
while true
do
OUTPUT=$(curl \
--silent \
--show-error \
--cacert /etc/osbuild-composer/ca-crt.pem \
--key /etc/osbuild-composer/client-key.pem \
--cert /etc/osbuild-composer/client-crt.pem \
"https://localhost/api/image-builder-composer/v2/clones/$IMG_ID")
IMG_UPLOAD_STATUS=$(echo "$OUTPUT" | jq -r '.status')
IMG_UPLOAD_OPTIONS=$(echo "$OUTPUT" | jq -r '.options')
case "$IMG_UPLOAD_STATUS" in
"success")
break
;;
# all valid status values for a compose which hasn't finished yet
"pending"|"running")
;;
# default undesired state
"failure")
echo "Image compose failed"
exit 1
;;
*)
echo "API returned unexpected image status value: '$IMG_UPLOAD_STATUS'"
exit 1
;;
esac
sleep 30
done
# export for use in subcases
export IMG_UPLOAD_OPTIONS
}
#
# Make sure that requesting a non existing paquet results in failure
#
@ -427,7 +486,6 @@ jq '.customizations.packages = [ "jesuisunpaquetquinexistepas" ]' "$REQUEST_FILE
sendCompose "$REQUEST_FILE2"
waitForState "failure"
# crashed/stopped/killed worker should result in a failed state
sendCompose "$REQUEST_FILE"
waitForState "building"
@ -449,6 +507,12 @@ fi
test "$UPLOAD_TYPE" = "$EXPECTED_UPLOAD_TYPE"
test $((INIT_COMPOSES+1)) = "$SUBS_COMPOSES"
if [ -s "$IMG_COMPOSE_REQ_FILE" ]; then
sendImgFromCompose "$IMG_COMPOSE_REQ_FILE"
waitForImgState
fi
#
# Verify the Cloud-provider specific upload_status options
#

View file

@ -13,12 +13,17 @@ function cleanup() {
AWS_INSTANCE_ID="${AWS_INSTANCE_ID:-}"
AMI_IMAGE_ID="${AMI_IMAGE_ID:-}"
AWS_SNAPSHOT_ID="${AWS_SNAPSHOT_ID:-}"
AMI_ID_2="${AMI_ID_2:-}"
SNAPSHOT_ID_2="${SNAPSHOT_ID_2:-}"
if [ -n "$AWS_CMD" ]; then
$AWS_CMD ec2 terminate-instances --instance-ids "$AWS_INSTANCE_ID"
$AWS_CMD ec2 deregister-image --image-id "$AMI_IMAGE_ID"
$AWS_CMD ec2 delete-snapshot --snapshot-id "$AWS_SNAPSHOT_ID"
$AWS_CMD ec2 delete-key-pair --key-name "key-for-$AMI_IMAGE_ID"
$AWS_CMD ec2 deregister-image --region "$REGION_2" --image-id "$AMI_2"
$AWS_CMD ec2 delete-snapshot --region "$REGION_2" --snapshot-id "$SNAPSHOT_ID_2"
fi
}
@ -68,6 +73,13 @@ function createReqFile() {
}
}
}
EOF
cat > "$IMG_COMPOSE_REQ_FILE" <<EOF
{
"region": "${AWS_REGION_2}",
"share_with_accounts": ["${AWS_API_TEST_SHARE_ACCOUNT_2}"]
}
EOF
}
@ -122,6 +134,38 @@ function verify() {
exit 1
fi
# Verify that the 2nd image from the same compose was copied and shared with existing and new account
AMI_ID_2=$(echo "$IMG_UPLOAD_OPTIONS" | jq -r .ami)
REGION_2=$(echo "$IMG_UPLOAD_OPTIONS" | jq -r .region)
$AWS_CMD ec2 describe-images --owners self --region "$REGION_2" --image-ids "$AMI_ID_2" \
> "$WORKDIR/ami2.json"
SNAPSHOT_ID_2=$(jq -r '.Images[].BlockDeviceMappings[].Ebs.SnapshotId' "$WORKDIR/ami2.json")
$AWS_CMD ec2 describe-snapshot-attribute --region "$REGION_2" --snapshot-id "$SNAPSHOT_ID_2" \
--attribute createVolumePermission > "$WORKDIR/snapshot-attributes2.json"
SHARED_ID_2=$(jq -r ".CreateVolumePermissions[] | select(.UserId==\"$AWS_API_TEST_SHARE_ACCOUNT\").UserId" "$WORKDIR/snapshot-attributes2.json")
if [ "$AWS_API_TEST_SHARE_ACCOUNT" != "$SHARED_ID_2" ]; then
echo "EC2 Snapshot wasn't shared with AWS_API_TEST_SHARE_ACCOUNT"
exit 1
fi
SHARED_ID_2=$(jq -r ".CreateVolumePermissions[] | select(.UserId==\"$AWS_API_TEST_SHARE_ACCOUNT_2\").UserId" "$WORKDIR/snapshot-attributes2.json")
if [ "$AWS_API_TEST_SHARE_ACCOUNT_2" != "$SHARED_ID_2" ]; then
echo "EC2 Snapshot wasn't shared with AWS_API_TEST_SHARE_ACCOUNT_2"
exit 1
fi
$AWS_CMD ec2 describe-image-attribute --attribute launchPermission --region "$REGION_2" --image-id "$AMI_ID_2" > "$WORKDIR/ami-attributes2.json"
SHARED_ID_2=$(jq -r ".LaunchPermissions[] | select(.UserId==\"$AWS_API_TEST_SHARE_ACCOUNT\").UserId" "$WORKDIR/ami-attributes2.json")
if [ "$AWS_API_TEST_SHARE_ACCOUNT" != "$SHARED_ID_2" ]; then
echo "EC2 ami wasn't shared with AWS_API_TEST_SHARE_ACCOUNT"
exit 1
fi
SHARED_ID_2=$(jq -r ".LaunchPermissions[] | select(.UserId==\"$AWS_API_TEST_SHARE_ACCOUNT_2\").UserId" "$WORKDIR/ami-attributes2.json")
if [ "$AWS_API_TEST_SHARE_ACCOUNT_2" != "$SHARED_ID_2" ]; then
echo "EC2 ami wasn't shared with AWS_API_TEST_SHARE_ACCOUNT_2"
exit 1
fi
# Create key-pair
$AWS_CMD ec2 create-key-pair --key-name "key-for-$AMI_IMAGE_ID" --query 'KeyMaterial' --output text > keypair.pem
chmod 400 ./keypair.pem