diff --git a/test/cases/api/azure.sh b/test/cases/api/azure.sh index 76be691b8..263cc253d 100644 --- a/test/cases/api/azure.sh +++ b/test/cases/api/azure.sh @@ -109,11 +109,16 @@ function checkUploadStatusOptions() { test "$IMAGE_NAME" = "$AZURE_IMAGE_NAME" } -# Verify image in Azure -function verify() { +# Log into Azure +function cloud_login() { set +x $AZURE_CMD login --service-principal --username "${V2_AZURE_CLIENT_ID}" --password "${V2_AZURE_CLIENT_SECRET}" --tenant "${AZURE_TENANT_ID}" set -x +} + +# Verify image in Azure +function verify() { + cloud_login # verify that the image exists and tag it $AZURE_CMD image show --resource-group "${AZURE_RESOURCE_GROUP}" --name "${AZURE_IMAGE_NAME}" diff --git a/test/cases/api/common/aws.sh b/test/cases/api/common/aws.sh index 14c315e54..7037056b3 100644 --- a/test/cases/api/common/aws.sh +++ b/test/cases/api/common/aws.sh @@ -31,3 +31,10 @@ function installClient() { fi $GOVC_CMD version } + +# Log into AWS +# AWS does not need explicit login, but define this function for the sake of +# consistency to allow calling scripts to not care about cloud differences +function cloud_login() { + true +} diff --git a/test/cases/api/gcp.sh b/test/cases/api/gcp.sh index 267b8159c..d88877c8a 100644 --- a/test/cases/api/gcp.sh +++ b/test/cases/api/gcp.sh @@ -101,14 +101,18 @@ function checkUploadStatusOptions() { test "$PROJECT_ID" = "$GCP_PROJECT" } - -# Verify image in Compute Engine on GCP -function verify() { +# Log into GCP +function cloud_login() { # 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 image in Compute Engine on GCP +function verify() { + cloud_login # Add "gitlab-ci-test" label to the image $GCP_CMD compute images add-labels "$GCP_IMAGE_NAME" --labels=gitlab-ci-test=true diff --git a/test/cases/koji.sh b/test/cases/koji.sh index 887fe73c4..1c3fa1049 100755 --- a/test/cases/koji.sh +++ b/test/cases/koji.sh @@ -16,6 +16,89 @@ if [ "${NIGHTLY:=false}" == "true" ]; then exit 0 fi +# +# Cloud provider / target names +# + +CLOUD_PROVIDER_AWS="aws" +CLOUD_PROVIDER_GCP="gcp" +CLOUD_PROVIDER_AZURE="azure" + +# +# Test types +# +# Tests Koji compose via cloudapi +TEST_TYPE_CLOUDAPI="cloudapi" +# Tests Koji compose via cloudapi with upload to a cloud target +TEST_TYPE_CLOUD_UPLOAD="cloud-upload" + +# test Koji compose via cloudapi without upload to cloud by default +TEST_TYPE="${1:-$TEST_TYPE_CLOUDAPI}" + +# +# Cloud upload - check environment and prepare it +# +if [[ "$TEST_TYPE" == "$TEST_TYPE_CLOUD_UPLOAD" ]]; then + if [[ $# -ne 3 ]]; then + echo "Usage: $0 cloud-upload TARGET IMAGE_TYPE" + exit 1 + fi + + CLOUD_PROVIDER="${2}" + IMAGE_TYPE="${3}" + + greenprint "Using Cloud Provider / Target ${CLOUD_PROVIDER} for Image Type ${IMAGE_TYPE}" + + # Load a correct test runner. + # Each one must define following methods: + # - checkEnv + # - cleanup + # - installClient + case $CLOUD_PROVIDER in + "$CLOUD_PROVIDER_AWS") + source /usr/libexec/tests/osbuild-composer/api/aws.sh + ;; + "$CLOUD_PROVIDER_GCP") + source /usr/libexec/tests/osbuild-composer/api/gcp.sh + ;; + "$CLOUD_PROVIDER_AZURE") + source /usr/libexec/tests/osbuild-composer/api/azure.sh + ;; + *) + echo "Unknown cloud provider: ${CLOUD_PROVIDER}" + exit 1 + esac + + # Verify that this script is running in the right environment. + checkEnv + + # Container image used for cloud provider CLI tools + export CONTAINER_IMAGE_CLOUD_TOOLS="quay.io/osbuild/cloud-tools:latest" + + if which podman 2>/dev/null >&2; then + export CONTAINER_RUNTIME=podman + elif which docker 2>/dev/null >&2; then + export CONTAINER_RUNTIME=docker + else + echo No container runtime found, install podman or docker. + exit 1 + fi + + WORKDIR=$(mktemp -d) + export WORKDIR + function cleanups() { + greenprint "Script execution stopped or finished - Cleaning up" + set +eu + cleanup + sudo rm -rf "$WORKDIR" + set -eu + } + trap cleanups EXIT + + # install appropriate cloud environment client tool + installClient +fi + # Provision the software under test. /usr/libexec/osbuild-composer-test/provision.sh @@ -51,13 +134,73 @@ koji --server=http://localhost:8080/kojihub --user kojiadmin --password kojipass # Always build the latest RHEL - that suits the koji API usecase the most. if [[ "$DISTRO_CODE" == rhel-8* ]]; then - DISTRO_CODE=rhel-87 + DISTRO_CODE=rhel-87 elif [[ "$DISTRO_CODE" == rhel-9* ]]; then - DISTRO_CODE=rhel-91 + DISTRO_CODE=rhel-91 fi -greenprint "Pushing compose to Koji (/api/image-builder-comoser/v2/" -sudo /usr/libexec/osbuild-composer-test/koji-compose.py "$DISTRO_CODE" "${ARCH}" +case ${TEST_TYPE} in + "$TEST_TYPE_CLOUDAPI") + greenprint "Pushing compose to Koji (/api/image-builder-comoser/v2/)" + COMPOSE_ID="$(sudo /usr/libexec/osbuild-composer-test/koji-compose.py "${DISTRO_CODE}" "${ARCH}")" + ;; + "$TEST_TYPE_CLOUD_UPLOAD") + greenprint "Pushing compose to Koji (/api/image-builder-comoser/v2/) with cloud upload target" + COMPOSE_ID="$(sudo -E /usr/libexec/osbuild-composer-test/koji-compose.py "${DISTRO_CODE}" "${ARCH}" "${CLOUD_PROVIDER}" "${IMAGE_TYPE}")" + ;; + *) + echo "Unknown test type: ${TEST_TYPE}" + exit 1 +esac + +if [[ "$TEST_TYPE" == "$TEST_TYPE_CLOUD_UPLOAD" ]]; then + greenprint "Verify that image was uploaded to the cloud provider" + + COMPOSE_STATUS=$(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/composes/${COMPOSE_ID}") + UPLOAD_OPTIONS=$(echo "${COMPOSE_STATUS}" | jq -r '.image_status.upload_status.options') + + # Authenticate with the appropriate cloud + cloud_login + + case $CLOUD_PROVIDER in + "$CLOUD_PROVIDER_AWS") + AMI_IMAGE_ID=$(echo "${UPLOAD_OPTIONS}" | jq -r '.ami') + $AWS_CMD ec2 describe-images \ + --owners self \ + --filters Name=image-id,Values="${AMI_IMAGE_ID}" \ + > "${WORKDIR}/ami.json" + # extract the snapshot ID for the purpose of cleanup + AWS_SNAPSHOT_ID=$(jq -r '.Images[].BlockDeviceMappings[].Ebs.SnapshotId' "$WORKDIR/ami.json") + export AWS_SNAPSHOT_ID + if [[ $(jq '.Images | length' "${WORKDIR}/ami.json") -ne 1 ]]; then + echo "${AMI_IMAGE_ID} image not found in AWS" + exit 1 + fi + ;; + "$CLOUD_PROVIDER_GCP") + GCP_IMAGE_NAME=$(echo "${UPLOAD_OPTIONS}" | jq -r '.image_name') + # The command exits with non-zero value if the image does not exist + $GCP_CMD compute images describe "${GCP_IMAGE_NAME}" + ;; + "$CLOUD_PROVIDER_AZURE") + AZURE_IMAGE_NAME=$(echo "${UPLOAD_OPTIONS}" | jq -r '.image_name') + # The command exits with non-zero value if the image does not exist + $AZURE_CMD image show --resource-group "${AZURE_RESOURCE_GROUP}" --name "${AZURE_IMAGE_NAME}" + ;; + *) + echo "Unknown cloud provider: ${CLOUD_PROVIDER}" + exit 1 + esac + + # if we got here, the image must have been found + greenprint "Image was SUCCESSFULLY found in the respective cloud provider environment!" +fi greenprint "Show Koji task" koji --server=http://localhost:8080/kojihub taskinfo 1