name: Constellation create description: Create a new Constellation cluster using latest OS image. inputs: workerNodesCount: description: "Number of worker nodes to spawn." required: true controlNodesCount: description: "Number of control-plane nodes to spawn." required: true cloudProvider: description: "Either 'gcp' or 'azure'." required: true machineType: description: "Machine type of VM to spawn." required: false osImage: description: "OS image to use. The default value 'debug-latest' will select the latest available debug image." required: true isDebugImage: description: "Is OS img a debug img?" required: true kubernetesVersion: description: "Kubernetes version to create the cluster from." required: false # # GCP specific inputs # gcpProject: description: "The GCP project to deploy Constellation in." required: false gcpClusterServiceAccountKey: description: "The GCP Service account to use inside the created Constellation cluster." required: false # # Azure specific inputs # azureSubscription: description: "The Azure subscription ID to deploy Constellation in." required: false azureTenant: description: "The Azure tenant ID to deploy Constellation in." required: false azureClientID: description: "The Azure client ID of the application registration created for Constellation." required: false azureClientSecret: description: "The Azure client secret value of the used secret." required: false azureUserAssignedIdentity: description: "The Azure user assigned identity to use for Constellation." required: false azureResourceGroup: description: "The Azure resource group to use for Constellation cluster" required: false outputs: kubeconfig: description: "The kubeconfig for the cluster." value: ${{ steps.constellation-init.outputs.KUBECONFIG }} runs: using: "composite" steps: - name: Constellation config generate shell: bash run: | constellation config generate ${{ inputs.cloudProvider }} yq eval -i \ "(.provider | select(. | has(\"azure\")).azure.subscription) = \"${{ inputs.azureSubscription }}\" | (.provider | select(. | has(\"azure\")).azure.tenant) = \"${{ inputs.azureTenant }}\" | (.provider | select(. | has(\"azure\")).azure.location) = \"North Europe\" | (.provider | select(. | has(\"azure\")).azure.userAssignedIdentity) = \"${{ inputs.azureUserAssignedIdentity }}\" | (.provider | select(. | has(\"azure\")).azure.resourceGroup) = \"${{ inputs.azureResourceGroup }}\" | (.provider | select(. | has(\"azure\")).azure.appClientID) = \"${{ inputs.azureClientID }}\" | (.provider | select(. | has(\"azure\")).azure.clientSecretValue) = \"${{ inputs.azureClientSecret }}\" | (.provider | select(. | has(\"azure\")).azure.enforcedMeasurements) = [15]" \ constellation-conf.yaml yq eval -i \ "(.provider | select(. | has(\"gcp\")).gcp.project) = \"${{ inputs.gcpProject }}\" | (.provider | select(. | has(\"gcp\")).gcp.region) = \"europe-west3\" | (.provider | select(. | has(\"gcp\")).gcp.zone) = \"europe-west3-b\" | (.provider | select(. | has(\"gcp\")).gcp.enforcedMeasurements) = [15] | (.provider | select(. | has(\"gcp\")).gcp.serviceAccountKeyPath) = \"serviceAccountKey.json\"" \ constellation-conf.yaml yq eval -i \ "(.provider | select(. | has(\"aws\")).aws.region) = \"eu-central-1\" | (.provider | select(. | has(\"aws\")).aws.zone) = \"eu-central-1a\" | (.provider | select(. | has(\"aws\")).aws.iamProfileControlPlane) = \"e2e_test_control_plane_instance_profile\" | (.provider | select(. | has(\"aws\")).aws.iamProfileWorkerNodes) = \"e2e_test_worker_node_instance_profile\" | (.provider | select(. | has(\"aws\")).aws.enforcedMeasurements) = [15]" \ constellation-conf.yaml if [ ${{ inputs.kubernetesVersion != '' }} = true ]; then yq eval -i "(.kubernetesVersion) = ${{ inputs.kubernetesVersion }}" constellation-conf.yaml fi - name: Set image shell: bash env: CSP: ${{ inputs.cloudProvider }} run: | case $CSP in azure) if [ "${{ inputs.osImage == 'debug-latest' }}" = true ] then IMAGE_DEFINITION=$(az sig image-definition list --resource-group constellation-images --gallery-name Constellation_Debug_CVM --query "[].name" -o tsv | sort --version-sort | tail -n 1) AZURE_IMAGE=$(az sig image-version list --resource-group constellation-images --gallery-name Constellation_Debug_CVM --gallery-image-definition ${IMAGE_DEFINITION} --query "sort_by([], &publishingProfile.publishedDate)[].id" -o table | tail -n 1) else AZURE_IMAGE=${{ inputs.osImage }} fi yq eval -i "(.provider.azure.image) = \"${AZURE_IMAGE}\"" constellation-conf.yaml ;; gcp) if [ "${{ inputs.osImage == 'debug-latest' }}" = true ] then GCP_IMAGE_NAME=$(gcloud compute images list --project constellation-images --filter="name ~ constellation-\d{10} AND family~constellation-debug-v\d+-\d+-\d+" --sort-by=creationTimestamp --format="table(name)" | tail -n 1) GCP_IMAGE="projects/constellation-images/global/images/${GCP_IMAGE_NAME}" else GCP_IMAGE=${{ inputs.osImage }} fi yq eval -i "(.provider.gcp.image) = \"${GCP_IMAGE}\"" constellation-conf.yaml ;; aws) if [ "${{ inputs.osImage == 'debug-latest' }}" = true ] then AWS_IMAGE=$(aws ec2 describe-images --owners 795746500882 --region eu-central-1 --filters "Name=name,Values=constellation-debug-v*" --query "sort_by(Images, &CreationDate)[].ImageId" | jq -r '.[-1]') else AWS_IMAGE=${{ inputs.osImage }} fi yq eval -i "(.provider.aws.image) = \"${AWS_IMAGE}\"" constellation-conf.yaml ;; esac - name: Set instanceType if: ${{ inputs.machineType && inputs.machineType != 'default' }} shell: bash run: | yq eval -i "(.provider | select(. | has(\"azure\")).azure.instanceType) = \"${{ inputs.machineType }}\"" constellation-conf.yaml yq eval -i "(.provider | select(. | has(\"gcp\")).gcp.instanceType) = \"${{ inputs.machineType }}\"" constellation-conf.yaml yq eval -i "(.provider | select(. | has(\"aws\")).aws.instanceType) = \"${{ inputs.machineType }}\"" constellation-conf.yaml - name: Create serviceAccountKey.json if: ${{ inputs.cloudProvider == 'gcp' }} shell: bash env: GCP_CLUSTER_SERVICE_ACCOUNT_KEY: ${{ inputs.gcpClusterServiceAccountKey }} run: | echo "$GCP_CLUSTER_SERVICE_ACCOUNT_KEY" > serviceAccountKey.json - name: Enable debugCluster flag if: ${{ inputs.isDebugImage == 'true' }} shell: bash run: | yq eval -i '(.debugCluster) = true' constellation-conf.yaml - name: Constellation create shell: bash run: | echo "Creating cluster using config:" cat constellation-conf.yaml constellation create -c ${{ inputs.controlNodesCount }} -w ${{ inputs.workerNodesCount }} --name e2e-test -y - name: Cdbg deploy if: ${{ inputs.isDebugImage == 'true' }} shell: bash run: | echo "::group::cdbg deploy" chmod +x $GITHUB_WORKSPACE/build/cdbg cdbg deploy --bootstrapper $GITHUB_WORKSPACE/build/bootstrapper echo "::endgroup::" - name: Constellation init id: constellation-init shell: bash run: | constellation init echo "KUBECONFIG=$(pwd)/constellation-admin.conf" >> $GITHUB_OUTPUT - name: Wait for nodes to join and become ready shell: bash env: KUBECONFIG: "${{ steps.constellation-init.outputs.KUBECONFIG }}" JOINTIMEOUT: "1200" # 20 minutes timeout for all nodes to join run: | echo "::group::Wait for nodes" NODES_COUNT=$((${{ inputs.controlNodesCount }} + ${{ inputs.workerNodesCount }})) JOINWAIT=0 until [ "$(kubectl get nodes -o json | jq '.items | length')" == "${NODES_COUNT}" ] || [ $JOINWAIT -gt $JOINTIMEOUT ]; do echo "$(kubectl get nodes -o json | jq '.items | length')/"${NODES_COUNT}" nodes have joined.. waiting.." JOINWAIT=$((JOINWAIT+30)) sleep 30 done if [ $JOINWAIT -gt $JOINTIMEOUT ]; then echo "Timed out waiting for nodes to join" exit 1 fi echo "$(kubectl get nodes -o json | jq '.items | length')/"${NODES_COUNT}" nodes have joined" kubectl wait --for=condition=ready --all nodes --timeout=10m echo "::endgroup::" - name: Download boot logs if: ${{ always() }} continue-on-error: true shell: bash env: CSP: ${{ inputs.cloudProvider }} run: | echo "::group::Download boot logs" case $CSP in azure) AZURE_RESOURCE_GROUP=$(yq eval ".provider.azure.resourceGroup" constellation-conf.yaml) ./.github/actions/constellation_create/az-logs.sh ${AZURE_RESOURCE_GROUP} ;; gcp) ./.github/actions/constellation_create/gcp-logs.sh ;; aws) ./.github/actions/constellation_create/aws-logs.sh eu-central-1 ;; esac echo "::endgroup::" - name: Upload boot logs if: ${{ always() && !env.ACT }} uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # tag=v3.1.1 with: name: serial-logs path: "*.log"