Using DISTRO_CODE simplifies test case selection and allows to test different distro than the one test is running on. This is used to run tests for RHEL 9.0 on F33 or RHEL 8.4
654 lines
18 KiB
Bash
Executable file
654 lines
18 KiB
Bash
Executable file
#!/usr/bin/bash
|
|
|
|
#
|
|
# Test osbuild-composer's main API endpoint by building a sample image and
|
|
# uploading it to the appropriate cloud provider. The test currently supports
|
|
# AWS and GCP.
|
|
#
|
|
# This script sets `-x` and is meant to always be run like that. This is
|
|
# simpler than adding extensive error reporting, which would make this script
|
|
# considerably more complex. Also, the full trace this produces is very useful
|
|
# for the primary audience: developers of osbuild-composer looking at the log
|
|
# from a run on a remote continuous integration system.
|
|
#
|
|
|
|
set -euxo pipefail
|
|
|
|
#TODO: remove this once there is rhel9 support for necessary image types
|
|
if [[ $DISTRO_CODE == rhel_90 ]]; then
|
|
echo "Skipped"
|
|
exit 0
|
|
fi
|
|
|
|
#
|
|
# Provision the software under tet.
|
|
#
|
|
|
|
/usr/libexec/osbuild-composer-test/provision.sh
|
|
|
|
#
|
|
# Which cloud provider are we testing?
|
|
#
|
|
|
|
CLOUD_PROVIDER_AWS="aws"
|
|
CLOUD_PROVIDER_GCP="gcp"
|
|
CLOUD_PROVIDER_AZURE="azure"
|
|
|
|
CLOUD_PROVIDER=${1:-$CLOUD_PROVIDER_AWS}
|
|
|
|
case $CLOUD_PROVIDER in
|
|
"$CLOUD_PROVIDER_AWS")
|
|
echo "Testing AWS"
|
|
;;
|
|
"$CLOUD_PROVIDER_GCP")
|
|
echo "Testing Google Cloud Platform"
|
|
;;
|
|
"$CLOUD_PROVIDER_AZURE")
|
|
echo "Testing Azure"
|
|
;;
|
|
*)
|
|
echo "Unknown cloud provider '$CLOUD_PROVIDER'. Supported are '$CLOUD_PROVIDER_AWS', '$CLOUD_PROVIDER_GCP'"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
#
|
|
# Verify that this script is running in the right environment.
|
|
#
|
|
|
|
# Check that needed variables are set to access AWS.
|
|
function checkEnvAWS() {
|
|
printenv AWS_REGION AWS_BUCKET AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_API_TEST_SHARE_ACCOUNT > /dev/null
|
|
}
|
|
|
|
# Check that needed variables are set to access GCP.
|
|
function checkEnvGCP() {
|
|
printenv GOOGLE_APPLICATION_CREDENTIALS GCP_BUCKET GCP_REGION GCP_API_TEST_SHARE_ACCOUNT > /dev/null
|
|
}
|
|
|
|
# Check that needed variables are set to access Azure.
|
|
function checkEnvAzure() {
|
|
printenv AZURE_TENANT_ID AZURE_SUBSCRIPTION_ID AZURE_RESOURCE_GROUP AZURE_LOCATION AZURE_CLIENT_ID AZURE_CLIENT_SECRET > /dev/null
|
|
}
|
|
|
|
case $CLOUD_PROVIDER in
|
|
"$CLOUD_PROVIDER_AWS")
|
|
checkEnvAWS
|
|
;;
|
|
"$CLOUD_PROVIDER_GCP")
|
|
checkEnvGCP
|
|
;;
|
|
"$CLOUD_PROVIDER_AZURE")
|
|
checkEnvAzure
|
|
;;
|
|
esac
|
|
|
|
#
|
|
# Create a temporary directory and ensure it gets deleted when this script
|
|
# terminates in any way.
|
|
#
|
|
|
|
function cleanupAWS() {
|
|
# since this function can be called at any time, ensure that we don't expand unbound variables
|
|
AWS_CMD="${AWS_CMD:-}"
|
|
AWS_INSTANCE_ID="${AWS_INSTANCE_ID:-}"
|
|
AMI_IMAGE_ID="${AMI_IMAGE_ID:-}"
|
|
AWS_SNAPSHOT_ID="${AWS_SNAPSHOT_ID:-}"
|
|
|
|
if [ -n "$AWS_CMD" ]; then
|
|
set +e
|
|
$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"
|
|
set -e
|
|
fi
|
|
}
|
|
|
|
function cleanupGCP() {
|
|
# since this function can be called at any time, ensure that we don't expand unbound variables
|
|
GCP_CMD="${GCP_CMD:-}"
|
|
GCP_IMAGE_NAME="${GCP_IMAGE_NAME:-}"
|
|
GCP_INSTANCE_NAME="${GCP_INSTANCE_NAME:-}"
|
|
|
|
if [ -n "$GCP_CMD" ]; then
|
|
set +e
|
|
$GCP_CMD compute instances delete --zone="$GCP_REGION-a" "$GCP_INSTANCE_NAME"
|
|
$GCP_CMD compute images delete "$GCP_IMAGE_NAME"
|
|
set -e
|
|
fi
|
|
}
|
|
|
|
function cleanupAzure() {
|
|
# since this function can be called at any time, ensure that we don't expand unbound variables
|
|
AZURE_CMD="${AZURE_CMD:-}"
|
|
AZURE_IMAGE_NAME="${AZURE_IMAGE_NAME:-}"
|
|
|
|
# do not run clean-up if the image name is not yet defined
|
|
if [[ -n "$AZURE_CMD" && -n "$AZURE_IMAGE_NAME" ]]; then
|
|
set +e
|
|
$AZURE_CMD image delete --resource-group sharing-research --name "$AZURE_IMAGE_NAME"
|
|
|
|
# find a storage account by its tag
|
|
AZURE_STORAGE_ACCOUNT=$($AZURE_CMD resource list --tag imageBuilderStorageAccount=location="$AZURE_LOCATION" | jq -r .[0].name)
|
|
$AZURE_CMD storage blob delete --container-name imagebuilder --name "$AZURE_IMAGE_NAME".vhd --account-name "$AZURE_STORAGE_ACCOUNT"
|
|
set -e
|
|
fi
|
|
}
|
|
|
|
WORKDIR=$(mktemp -d)
|
|
function cleanup() {
|
|
case $CLOUD_PROVIDER in
|
|
"$CLOUD_PROVIDER_AWS")
|
|
cleanupAWS
|
|
;;
|
|
"$CLOUD_PROVIDER_GCP")
|
|
cleanupGCP
|
|
;;
|
|
"$CLOUD_PROVIDER_AZURE")
|
|
cleanupAzure
|
|
;;
|
|
esac
|
|
|
|
rm -rf "$WORKDIR"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
#
|
|
# Install the necessary cloud provider client tools
|
|
#
|
|
|
|
#
|
|
# Install the aws client from the upstream release, because it doesn't seem to
|
|
# be available as a RHEL package.
|
|
#
|
|
function installClientAWS() {
|
|
if ! hash aws; then
|
|
sudo dnf install -y awscli
|
|
aws --version
|
|
fi
|
|
|
|
AWS_CMD="aws --region $AWS_REGION --output json --color on"
|
|
}
|
|
|
|
#
|
|
# Install the gcp clients from the upstream release
|
|
#
|
|
function installClientGCP() {
|
|
if ! hash gcloud; then
|
|
sudo tee -a /etc/yum.repos.d/google-cloud-sdk.repo << EOM
|
|
[google-cloud-sdk]
|
|
name=Google Cloud SDK
|
|
baseurl=https://packages.cloud.google.com/yum/repos/cloud-sdk-el7-x86_64
|
|
enabled=1
|
|
gpgcheck=1
|
|
repo_gpgcheck=1
|
|
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
|
|
https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
|
|
EOM
|
|
fi
|
|
|
|
sudo dnf -y install google-cloud-sdk
|
|
GCP_CMD="gcloud --format=json --quiet"
|
|
$GCP_CMD --version
|
|
}
|
|
|
|
function installClientAzure() {
|
|
if ! hash az; then
|
|
# this installation method is taken from the official docs:
|
|
# https://docs.microsoft.com/cs-cz/cli/azure/install-azure-cli-linux?pivots=dnf
|
|
sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc
|
|
echo -e "[azure-cli]
|
|
name=Azure CLI
|
|
baseurl=https://packages.microsoft.com/yumrepos/azure-cli
|
|
enabled=1
|
|
gpgcheck=1
|
|
gpgkey=https://packages.microsoft.com/keys/microsoft.asc" | sudo tee /etc/yum.repos.d/azure-cli.repo
|
|
fi
|
|
|
|
sudo dnf install -y azure-cli
|
|
AZURE_CMD="az"
|
|
$AZURE_CMD version
|
|
}
|
|
|
|
case $CLOUD_PROVIDER in
|
|
"$CLOUD_PROVIDER_AWS")
|
|
installClientAWS
|
|
;;
|
|
"$CLOUD_PROVIDER_GCP")
|
|
installClientGCP
|
|
;;
|
|
"$CLOUD_PROVIDER_AZURE")
|
|
installClientAzure
|
|
;;
|
|
esac
|
|
|
|
#
|
|
# Make sure /openapi.json and /version endpoints return success
|
|
#
|
|
|
|
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/composer/v1/version | jq .
|
|
|
|
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/composer/v1/openapi.json | jq .
|
|
|
|
#
|
|
# Prepare a request to be sent to the composer API.
|
|
#
|
|
|
|
REQUEST_FILE="${WORKDIR}/request.json"
|
|
ARCH=$(uname -m)
|
|
SSH_USER=
|
|
|
|
# Generate a string, which can be used as a predictable resource name,
|
|
# especially when running the test in Jenkins where we may need to clean up
|
|
# resources in case the test unexpectedly fails or is canceled
|
|
JENKINS_HOME="${JENKINS_HOME:-}"
|
|
if [[ -n "$JENKINS_HOME" ]]; then
|
|
# in Jenkins, imitate GenerateCIArtifactName() from internal/test/helpers.go
|
|
TEST_ID="$DISTRO_CODE-$ARCH-$BRANCH_NAME-$BUILD_ID"
|
|
else
|
|
# if not running in Jenkins, generate ID not relying on specific env variables
|
|
TEST_ID=$(uuidgen);
|
|
fi
|
|
|
|
case $(set +x; . /etc/os-release; echo "$ID-$VERSION_ID") in
|
|
"rhel-8.4")
|
|
DISTRO="rhel-84"
|
|
SSH_USER="cloud-user"
|
|
;;
|
|
"rhel-8.2" | "rhel-8.3")
|
|
DISTRO="rhel-8"
|
|
SSH_USER="cloud-user"
|
|
;;
|
|
"fedora-32")
|
|
DISTRO="fedora-32"
|
|
SSH_USER="fedora"
|
|
;;
|
|
"fedora-33")
|
|
DISTRO="fedora-33"
|
|
SSH_USER="fedora"
|
|
;;
|
|
"centos-8")
|
|
DISTRO="centos-8"
|
|
SSH_USER="cloud-user"
|
|
;;
|
|
esac
|
|
|
|
function createReqFileAWS() {
|
|
AWS_SNAPSHOT_NAME=$(uuidgen)
|
|
|
|
cat > "$REQUEST_FILE" << EOF
|
|
{
|
|
"distribution": "$DISTRO",
|
|
"customizations": {
|
|
"packages": [
|
|
"postgresql"
|
|
]
|
|
},
|
|
"image_requests": [
|
|
{
|
|
"architecture": "$ARCH",
|
|
"image_type": "ami",
|
|
"repositories": $(jq ".\"$ARCH\"" /usr/share/tests/osbuild-composer/repositories/"$DISTRO".json),
|
|
"upload_request": {
|
|
"type": "aws",
|
|
"options": {
|
|
"region": "${AWS_REGION}",
|
|
"s3": {
|
|
"access_key_id": "${AWS_ACCESS_KEY_ID}",
|
|
"secret_access_key": "${AWS_SECRET_ACCESS_KEY}",
|
|
"bucket": "${AWS_BUCKET}"
|
|
},
|
|
"ec2": {
|
|
"access_key_id": "${AWS_ACCESS_KEY_ID}",
|
|
"secret_access_key": "${AWS_SECRET_ACCESS_KEY}",
|
|
"snapshot_name": "${AWS_SNAPSHOT_NAME}",
|
|
"share_with_accounts": ["${AWS_API_TEST_SHARE_ACCOUNT}"]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
EOF
|
|
}
|
|
|
|
function createReqFileGCP() {
|
|
# constrains for GCP resource IDs:
|
|
# - max 62 characters
|
|
# - must be a match of regex '[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?|[1-9][0-9]{0,19}'
|
|
#
|
|
# use sha224sum to get predictable 56 characters long testID without invalid characters
|
|
GCP_TEST_ID_HASH="$(echo -n "$TEST_ID" | sha224sum - | sed -E 's/([a-z0-9])\s+-/\1/')"
|
|
|
|
GCP_IMAGE_NAME="image-$GCP_TEST_ID_HASH"
|
|
|
|
cat > "$REQUEST_FILE" << EOF
|
|
{
|
|
"distribution": "$DISTRO",
|
|
"customizations": {
|
|
"packages": [
|
|
"postgresql"
|
|
]
|
|
},
|
|
"image_requests": [
|
|
{
|
|
"architecture": "$ARCH",
|
|
"image_type": "vhd",
|
|
"repositories": $(jq ".\"$ARCH\"" /usr/share/tests/osbuild-composer/repositories/"$DISTRO".json),
|
|
"upload_request": {
|
|
"type": "gcp",
|
|
"options": {
|
|
"bucket": "${GCP_BUCKET}",
|
|
"region": "${GCP_REGION}",
|
|
"image_name": "${GCP_IMAGE_NAME}",
|
|
"share_with_accounts": ["${GCP_API_TEST_SHARE_ACCOUNT}"]
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
EOF
|
|
}
|
|
|
|
function createReqFileAzure() {
|
|
AZURE_IMAGE_NAME="osbuild-composer-api-test-$(uuidgen)"
|
|
|
|
cat > "$REQUEST_FILE" << EOF
|
|
{
|
|
"distribution": "$DISTRO",
|
|
"image_requests": [
|
|
{
|
|
"architecture": "$ARCH",
|
|
"image_type": "vhd",
|
|
"repositories": $(jq ".\"$ARCH\"" /usr/share/tests/osbuild-composer/repositories/"$DISTRO".json),
|
|
"upload_request": {
|
|
"type": "azure",
|
|
"options": {
|
|
"tenant_id": "${AZURE_TENANT_ID}",
|
|
"subscription_id": "${AZURE_SUBSCRIPTION_ID}",
|
|
"resource_group": "${AZURE_RESOURCE_GROUP}",
|
|
"location": "${AZURE_LOCATION}",
|
|
"image_name": "${AZURE_IMAGE_NAME}"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
EOF
|
|
}
|
|
|
|
case $CLOUD_PROVIDER in
|
|
"$CLOUD_PROVIDER_AWS")
|
|
createReqFileAWS
|
|
;;
|
|
"$CLOUD_PROVIDER_GCP")
|
|
createReqFileGCP
|
|
;;
|
|
"$CLOUD_PROVIDER_AZURE")
|
|
createReqFileAzure
|
|
;;
|
|
esac
|
|
|
|
#
|
|
# Send the request and wait for the job to finish.
|
|
#
|
|
# Separate `curl` and `jq` commands here, because piping them together hides
|
|
# the server's response in case of an error.
|
|
#
|
|
|
|
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 \
|
|
--header 'Content-Type: application/json' \
|
|
--request POST \
|
|
--data @"$REQUEST_FILE" \
|
|
https://localhost/api/composer/v1/compose)
|
|
|
|
COMPOSE_ID=$(echo "$OUTPUT" | jq -r '.id')
|
|
|
|
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/composer/v1/compose/"$COMPOSE_ID")
|
|
|
|
COMPOSE_STATUS=$(echo "$OUTPUT" | jq -r '.image_status.status')
|
|
UPLOAD_STATUS=$(echo "$OUTPUT" | jq -r '.image_status.upload_status.status')
|
|
UPLOAD_TYPE=$(echo "$OUTPUT" | jq -r '.image_status.upload_status.type')
|
|
UPLOAD_OPTIONS=$(echo "$OUTPUT" | jq -r '.image_status.upload_status.options')
|
|
|
|
case "$COMPOSE_STATUS" in
|
|
# valid status values for compose which is not yet finished
|
|
"pending"|"building"|"uploading"|"registering")
|
|
;;
|
|
"success")
|
|
test "$UPLOAD_STATUS" = "success"
|
|
test "$UPLOAD_TYPE" = "$CLOUD_PROVIDER"
|
|
break
|
|
;;
|
|
"failure")
|
|
echo "Image compose failed"
|
|
exit 1
|
|
;;
|
|
*)
|
|
echo "API returned unexpected image_status.status value: '$COMPOSE_STATUS'"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
sleep 30
|
|
done
|
|
|
|
#
|
|
# Verify the Cloud-provider specific upload_status options
|
|
#
|
|
|
|
function checkUploadStatusOptionsAWS() {
|
|
local AMI
|
|
AMI=$(echo "$UPLOAD_OPTIONS" | jq -r '.ami')
|
|
local REGION
|
|
REGION=$(echo "$UPLOAD_OPTIONS" | jq -r '.region')
|
|
|
|
# AWS ID consist of resource identifier followed by a 17-character string
|
|
echo "$AMI" | grep -e 'ami-[[:alnum:]]\{17\}' -
|
|
test "$REGION" = "$AWS_REGION"
|
|
}
|
|
|
|
function checkUploadStatusOptionsGCP() {
|
|
GCP_PROJECT=$(jq -r '.project_id' "$GOOGLE_APPLICATION_CREDENTIALS")
|
|
|
|
local IMAGE_NAME
|
|
IMAGE_NAME=$(echo "$UPLOAD_OPTIONS" | jq -r '.image_name')
|
|
local PROJECT_ID
|
|
PROJECT_ID=$(echo "$UPLOAD_OPTIONS" | jq -r '.project_id')
|
|
|
|
test "$IMAGE_NAME" = "$GCP_IMAGE_NAME"
|
|
test "$PROJECT_ID" = "$GCP_PROJECT"
|
|
}
|
|
|
|
function checkUploadStatusOptionsAzure() {
|
|
local IMAGE_NAME
|
|
IMAGE_NAME=$(echo "$UPLOAD_OPTIONS" | jq -r '.image_name')
|
|
|
|
test "$IMAGE_NAME" = "$AZURE_IMAGE_NAME"
|
|
}
|
|
|
|
case $CLOUD_PROVIDER in
|
|
"$CLOUD_PROVIDER_AWS")
|
|
checkUploadStatusOptionsAWS
|
|
;;
|
|
"$CLOUD_PROVIDER_GCP")
|
|
checkUploadStatusOptionsGCP
|
|
;;
|
|
"$CLOUD_PROVIDER_AZURE")
|
|
checkUploadStatusOptionsAzure
|
|
;;
|
|
esac
|
|
|
|
#
|
|
# Verify the image landed in the appropriate cloud provider, and delete it.
|
|
#
|
|
|
|
# Reusable function, which waits for a given host to respond to SSH
|
|
function _instanceWaitSSH() {
|
|
local HOST="$1"
|
|
|
|
for LOOP_COUNTER in {0..30}; do
|
|
if ssh-keyscan "$HOST" > /dev/null 2>&1; then
|
|
echo "SSH is up!"
|
|
# ssh-keyscan "$PUBLIC_IP" | sudo tee -a /root/.ssh/known_hosts
|
|
break
|
|
fi
|
|
echo "Retrying in 5 seconds... $LOOP_COUNTER"
|
|
sleep 5
|
|
done
|
|
}
|
|
|
|
# Verify image in EC2 on AWS
|
|
function verifyInAWS() {
|
|
$AWS_CMD ec2 describe-images \
|
|
--owners self \
|
|
--filters Name=name,Values="$AWS_SNAPSHOT_NAME" \
|
|
> "$WORKDIR/ami.json"
|
|
|
|
AMI_IMAGE_ID=$(jq -r '.Images[].ImageId' "$WORKDIR/ami.json")
|
|
AWS_SNAPSHOT_ID=$(jq -r '.Images[].BlockDeviceMappings[].Ebs.SnapshotId' "$WORKDIR/ami.json")
|
|
SHARE_OK=1
|
|
|
|
# Verify that the ec2 snapshot was shared
|
|
$AWS_CMD ec2 describe-snapshot-attribute --snapshot-id "$AWS_SNAPSHOT_ID" --attribute createVolumePermission > "$WORKDIR/snapshot-attributes.json"
|
|
|
|
SHARED_ID=$(jq -r '.CreateVolumePermissions[0].UserId' "$WORKDIR/snapshot-attributes.json")
|
|
if [ "$AWS_API_TEST_SHARE_ACCOUNT" != "$SHARED_ID" ]; then
|
|
SHARE_OK=0
|
|
fi
|
|
|
|
# Verify that the ec2 ami was shared
|
|
$AWS_CMD ec2 describe-image-attribute --image-id "$AMI_IMAGE_ID" --attribute launchPermission > "$WORKDIR/ami-attributes.json"
|
|
|
|
SHARED_ID=$(jq -r '.LaunchPermissions[0].UserId' "$WORKDIR/ami-attributes.json")
|
|
if [ "$AWS_API_TEST_SHARE_ACCOUNT" != "$SHARED_ID" ]; then
|
|
SHARE_OK=0
|
|
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
|
|
|
|
# Create an instance based on the ami
|
|
$AWS_CMD ec2 run-instances --image-id "$AMI_IMAGE_ID" --count 1 --instance-type t2.micro --key-name "key-for-$AMI_IMAGE_ID" > "$WORKDIR/instances.json"
|
|
AWS_INSTANCE_ID=$(jq -r '.Instances[].InstanceId' "$WORKDIR/instances.json")
|
|
|
|
$AWS_CMD ec2 wait instance-running --instance-ids "$AWS_INSTANCE_ID"
|
|
|
|
$AWS_CMD ec2 describe-instances --instance-ids "$AWS_INSTANCE_ID" > "$WORKDIR/instances.json"
|
|
HOST=$(jq -r '.Reservations[].Instances[].PublicIpAddress' "$WORKDIR/instances.json")
|
|
|
|
echo "⏱ Waiting for AWS instance to respond to ssh"
|
|
_instanceWaitSSH "$HOST"
|
|
|
|
# Check if postgres is installed
|
|
ssh -oStrictHostKeyChecking=no -i ./keypair.pem "$SSH_USER"@"$HOST" rpm -q postgresql
|
|
|
|
if [ "$SHARE_OK" != 1 ]; then
|
|
echo "EC2 snapshot wasn't shared with the AWS_API_TEST_SHARE_ACCOUNT. 😢"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Verify image in Compute Node on GCP
|
|
function verifyInGCP() {
|
|
# Authenticate
|
|
$GCP_CMD auth activate-service-account --key-file "$GOOGLE_APPLICATION_CREDENTIALS"
|
|
# Extract and set the default project to be used for commands
|
|
GCP_PROJECT=$(jq -r '.project_id' "$GOOGLE_APPLICATION_CREDENTIALS")
|
|
$GCP_CMD config set project "$GCP_PROJECT"
|
|
|
|
# Verify that the image was shared
|
|
SHARE_OK=1
|
|
$GCP_CMD compute images get-iam-policy "$GCP_IMAGE_NAME" > "$WORKDIR/image-iam-policy.json"
|
|
SHARED_ACCOUNT=$(jq -r '.bindings[0].members[0]' "$WORKDIR/image-iam-policy.json")
|
|
SHARED_ROLE=$(jq -r '.bindings[0].role' "$WORKDIR/image-iam-policy.json")
|
|
if [ "$SHARED_ACCOUNT" != "$GCP_API_TEST_SHARE_ACCOUNT" ] || [ "$SHARED_ROLE" != "roles/compute.imageUser" ]; then
|
|
SHARE_OK=0
|
|
fi
|
|
|
|
if [ "$SHARE_OK" != 1 ]; then
|
|
echo "GCP image wasn't shared with the GCP_API_TEST_SHARE_ACCOUNT. 😢"
|
|
exit 1
|
|
fi
|
|
|
|
# Verify that the image boots and have customizations applied
|
|
# Create SSH keys to use
|
|
GCP_SSH_KEY="$WORKDIR/id_google_compute_engine"
|
|
ssh-keygen -t rsa -f "$GCP_SSH_KEY" -C "$SSH_USER" -N ""
|
|
GCP_SSH_METADATA_FILE="$WORKDIR/gcp-ssh-keys-metadata"
|
|
|
|
echo "${SSH_USER}:$(cat "$GCP_SSH_KEY".pub)" > "$GCP_SSH_METADATA_FILE"
|
|
|
|
# create the instance
|
|
# resource ID can have max 62 characters, the $GCP_TEST_ID_HASH contains 56 characters
|
|
GCP_INSTANCE_NAME="vm-$GCP_TEST_ID_HASH"
|
|
|
|
$GCP_CMD compute instances create "$GCP_INSTANCE_NAME" \
|
|
--zone="$GCP_REGION-a" \
|
|
--image-project="$GCP_PROJECT" \
|
|
--image="$GCP_IMAGE_NAME" \
|
|
--metadata-from-file=ssh-keys="$GCP_SSH_METADATA_FILE"
|
|
HOST=$($GCP_CMD compute instances describe "$GCP_INSTANCE_NAME" --zone="$GCP_REGION-a" --format='get(networkInterfaces[0].accessConfigs[0].natIP)')
|
|
|
|
echo "⏱ Waiting for GCP instance to respond to ssh"
|
|
_instanceWaitSSH "$HOST"
|
|
|
|
# Check if postgres is installed
|
|
ssh -oStrictHostKeyChecking=no -i "$GCP_SSH_KEY" "$SSH_USER"@"$HOST" rpm -q postgresql
|
|
}
|
|
|
|
# Verify image in Azure
|
|
function verifyInAzure() {
|
|
set +x
|
|
$AZURE_CMD login --service-principal --username "${AZURE_CLIENT_ID}" --password "${AZURE_CLIENT_SECRET}" --tenant "${AZURE_TENANT_ID}"
|
|
set -x
|
|
|
|
# verify that the image exists
|
|
$AZURE_CMD image show --resource-group "${AZURE_RESOURCE_GROUP}" --name "${AZURE_IMAGE_NAME}"
|
|
|
|
# Boot testing is currently blocked due to
|
|
# https://github.com/Azure/azure-cli/issues/17123
|
|
# Without this issue fixed or worked around, I'm not able to delete the disk
|
|
# attached to the VM.
|
|
}
|
|
|
|
case $CLOUD_PROVIDER in
|
|
"$CLOUD_PROVIDER_AWS")
|
|
verifyInAWS
|
|
;;
|
|
"$CLOUD_PROVIDER_GCP")
|
|
verifyInGCP
|
|
;;
|
|
"$CLOUD_PROVIDER_AZURE")
|
|
verifyInAzure
|
|
;;
|
|
esac
|
|
|
|
exit 0
|