diff --git a/.github/actions/create-kind-cluster/action.yaml b/.github/actions/create-kind-cluster/action.yaml index c12797b35c4..c8e7d3d90b8 100644 --- a/.github/actions/create-kind-cluster/action.yaml +++ b/.github/actions/create-kind-cluster/action.yaml @@ -2,6 +2,14 @@ name: "Create a KinD cluster" description: | Create a KinD cluster. inputs: + secure: + description: "Whether the KinD cluster should be created with a secure local registry configuration" + required: false + default: "false" + temp-cert-dir: + description: "The temporary directory where the certificates are stored" + required: false + default: "" kind-version: description: "The version of KinD to install" required: false @@ -12,15 +20,15 @@ inputs: default: "false" registry-name: description: "The name of the local registry" - required: false + required: true default: "radius-registry" registry-server: description: "The server name for the local registry" - required: false + required: true default: "localhost" registry-port: description: "The port for the local registry" - required: false + required: true default: "5000" runs: using: "composite" @@ -35,15 +43,56 @@ runs: if: ${{ inputs.with-local-registry == 'false' }} shell: bash run: | + # https://kind.sigs.k8s.io/docs/user/local-registry/ cat </dev/null || mktemp -d -t 'temp_cert_dir') + echo "TEMP_CERT_DIR=$temp_cert_dir" >> $GITHUB_OUTPUT + - name: Create certificates for local registry if: ${{ inputs.secure == 'true' }} shell: bash @@ -54,11 +67,9 @@ runs: echo "$CFG" } - # Create a temporary directory to store the certificates - temp_cert_dir=$(mktemp -d 2>/dev/null || mktemp -d -t 'temp_cert_dir') - echo "TEMP_CERT_DIR=$temp_cert_dir" >> $GITHUB_ENV + TEMP_CERT_DIR=${{ steps.create-temp-cert-dir.outputs.TEMP_CERT_DIR }} - pushd $temp_cert_dir + pushd $TEMP_CERT_DIR # Create the directory for the certificates mkdir -p certs/${{ inputs.registry-server }} @@ -79,6 +90,7 @@ runs: if: ${{ inputs.secure == 'true' }} shell: bash run: | + TEMP_CERT_DIR=${{ steps.create-temp-cert-dir.outputs.TEMP_CERT_DIR }} sudo apt install ca-certificates sudo cp $TEMP_CERT_DIR/certs/${{ inputs.registry-server }}/client.crt /usr/local/share/ca-certificates/${{ inputs.registry-server }}.crt sudo cp $TEMP_CERT_DIR/certs/${{ inputs.registry-server }}/client.crt /usr/local/share/ca-certificates/${{ inputs.registry-name }}.crt @@ -88,6 +100,7 @@ runs: if: ${{ inputs.secure == 'true' }} shell: bash run: | + TEMP_CERT_DIR=${{ steps.create-temp-cert-dir.outputs.TEMP_CERT_DIR }} echo "==== Create secure Docker registry" docker run -d \ -p ${{ inputs.registry-port }}:5000 \ diff --git a/.github/actions/download-pr-data-artifact/action.yaml b/.github/actions/download-pr-data-artifact/action.yaml index 04b0258adb1..009a1ba34af 100644 --- a/.github/actions/download-pr-data-artifact/action.yaml +++ b/.github/actions/download-pr-data-artifact/action.yaml @@ -29,7 +29,7 @@ runs: }); let fs = require('fs'); fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/pr_number.zip`, Buffer.from(download.data)); - - name: 'Unzip artifact' + - name: "Unzip artifact" shell: bash run: unzip pr_number.zip - name: Set PR number diff --git a/.github/workflows/functional-test-cloud.yaml b/.github/workflows/functional-test-cloud.yaml index 71a8e0aa05f..bc81a5a0fc9 100644 --- a/.github/workflows/functional-test-cloud.yaml +++ b/.github/workflows/functional-test-cloud.yaml @@ -25,6 +25,11 @@ permissions: on: # Enable manual trigger workflow_dispatch: + inputs: + branch: + description: "Branch to run the workflow on" + required: true + default: "main" schedule: # Run every 4 hours on weekdays. - cron: "30 0,4,8,12,16,20 * * 1-5" @@ -110,23 +115,34 @@ jobs: with: app_id: ${{ env.FUNCTIONAL_TEST_APP_ID }} private_key: ${{ secrets.FUNCTIONAL_TEST_APP_PRIVATE_KEY }} + - name: Set up checkout target (scheduled) - if: github.event_name == 'schedule' + if: github.event_name == 'schedule' || github.event_name == 'repository_dispatch' run: | echo "CHECKOUT_REPO=${{ github.repository }}" >> $GITHUB_ENV echo "CHECKOUT_REF=refs/heads/main" >> $GITHUB_ENV + - name: Set up checkout target (pull_request) if: github.event_name == 'pull_request' run: | echo "CHECKOUT_REPO=${{ github.repository }}" >> $GITHUB_ENV echo "CHECKOUT_REF=${{ github.ref }}" >> $GITHUB_ENV echo "PR_NUMBER=${{ github.event.pull_request.number }}" >> $GITHUB_ENV - - name: Use custom actions + + - name: Set up checkout target (workflow_dispatch) + if: github.event_name == 'workflow_dispatch' + run: | + echo "CHECKOUT_REPO=${{ github.repository }}" >> $GITHUB_ENV + echo "CHECKOUT_REF=refs/heads/${{ github.event.inputs.branch }}" >> $GITHUB_ENV + + - name: Check out code uses: actions/checkout@v4 + - name: "Download PR data artifacts" if: github.event_name == 'workflow_run' uses: ./.github/actions/download-pr-data-artifact id: get-pr-number + - name: "Set PR context (workflow_run)" if: github.event_name == 'workflow_run' uses: actions/github-script@v7 @@ -140,6 +156,7 @@ jobs: `CHECKOUT_REPO=${payload.head_repository.full_name}\n`+ `CHECKOUT_REF=${payload.head_sha}\n` + `PR_NUMBER=${{ steps.get-pr-number.outputs.pr_number }}\n`); + - name: Set DE image and tag (repository_dispatch from de-functional-test) if: github.event_name == 'repository_dispatch' uses: actions/github-script@v7 @@ -157,15 +174,18 @@ jobs: `CHECKOUT_REF=refs/heads/main` ); } + - name: Check out code uses: actions/checkout@v4 with: repository: ${{ env.CHECKOUT_REPO }} ref: ${{ env.CHECKOUT_REF }} + - name: Set up Go ${{ env.GOVER }} uses: actions/setup-go@v5 with: go-version: ${{ env.GOVER }} + - name: Generate ID for release id: gen-id run: | @@ -187,6 +207,7 @@ jobs: echo "PR_NUMBER=${{ env.PR_NUMBER }}" >> $GITHUB_OUTPUT echo "DE_IMAGE=${{ env.DE_IMAGE }}" >> $GITHUB_OUTPUT echo "DE_TAG=${{ env.DE_TAG }}" >> $GITHUB_OUTPUT + - uses: marocchino/sticky-pull-request-comment@v2 if: env.PR_NUMBER != '' continue-on-error: true @@ -226,12 +247,14 @@ jobs: ## Test Status + - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + - uses: marocchino/sticky-pull-request-comment@v2 if: env.PR_NUMBER != '' continue-on-error: true @@ -242,18 +265,21 @@ jobs: append: true message: | :hourglass: Building Radius and pushing container images for functional tests... + - name: Build and Push container images run: | make build && make docker-build && make docker-push env: DOCKER_REGISTRY: ${{ env.CONTAINER_REGISTRY }} DOCKER_TAG_VERSION: ${{ env.REL_VERSION }} + - name: Upload CLI binary uses: actions/upload-artifact@v4 with: name: ${{ steps.gen-id.outputs.RAD_CLI_ARTIFACT_NAME }} path: | ./dist/linux_amd64/release/rad + - uses: marocchino/sticky-pull-request-comment@v2 if: success() && env.PR_NUMBER != '' continue-on-error: true @@ -264,6 +290,7 @@ jobs: append: true message: | :white_check_mark: Container images build succeeded + - uses: marocchino/sticky-pull-request-comment@v2 if: failure() && env.PR_NUMBER != '' continue-on-error: true @@ -274,6 +301,7 @@ jobs: append: true message: | :x: Container images build failed + - uses: marocchino/sticky-pull-request-comment@v2 if: env.PR_NUMBER != '' continue-on-error: true @@ -284,6 +312,7 @@ jobs: append: true message: | :hourglass: Publishing Bicep Recipes for functional tests... + - name: Publish Bicep Test Recipes run: | mkdir ./bin @@ -297,6 +326,7 @@ jobs: env: BICEP_RECIPE_REGISTRY: ${{ env.BICEP_RECIPE_REGISTRY }} BICEP_RECIPE_TAG_VERSION: ${{ env.REL_VERSION }} + - uses: marocchino/sticky-pull-request-comment@v2 if: success() && env.PR_NUMBER != '' continue-on-error: true @@ -307,6 +337,7 @@ jobs: append: true message: | :white_check_mark: Recipe publishing succeeded + - uses: marocchino/sticky-pull-request-comment@v2 if: failure() && env.PR_NUMBER != '' continue-on-error: true @@ -317,6 +348,7 @@ jobs: append: true message: | :x: Test recipe publishing failed + tests: name: Run ${{ matrix.name }} functional tests needs: build @@ -324,12 +356,8 @@ jobs: strategy: fail-fast: true matrix: - os: [ubuntu-latest] - name: [corerp-cloud, ucp-cloud] - include: - # datastorerp functional tests need the larger VM. - - os: ubuntu-latest-m - name: datastoresrp-cloud + os: [ubuntu-latest-m] + name: [corerp-cloud, ucp-cloud, datastoresrp-cloud] runs-on: ${{ matrix.os }} env: UNIQUE_ID: ${{ needs.build.outputs.UNIQUE_ID }} @@ -349,6 +377,7 @@ jobs: with: app_id: ${{ env.FUNCTIONAL_TEST_APP_ID }} private_key: ${{ secrets.FUNCTIONAL_TEST_APP_PRIVATE_KEY }} + - uses: LouisBrunner/checks-action@v2.0.0 if: always() with: @@ -358,27 +387,32 @@ jobs: repo: ${{ github.repository }} sha: ${{ env.CHECKOUT_REF }} details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - - name: Checkout + + - name: Checkout Radius repository uses: actions/checkout@v4 with: repository: ${{ env.CHECKOUT_REPO }} ref: ${{ env.CHECKOUT_REF }} - - name: Checkout samples repo + + - name: Checkout Samples repository uses: actions/checkout@v4 if: matrix.name == 'samples' with: repository: radius-project/samples ref: refs/heads/edge path: samples + - name: Set up Go ${{ env.GOVER }} uses: actions/setup-go@v5 with: go-version: ${{ env.GOVER }} + - name: Get Go Cache path id: go-cache-paths run: | echo "go-build=$(go env GOCACHE)" >> $GITHUB_OUTPUT echo "go-mod=$(go env GOMODCACHE)" >> $GITHUB_OUTPUT + - uses: actions/cache@v4 with: path: | @@ -387,17 +421,20 @@ jobs: key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-go- + - name: Download rad CLI uses: actions/download-artifact@v4 with: name: ${{ env.RAD_CLI_ARTIFACT_NAME }} path: bin + - name: Login to Azure uses: azure/login@v2 with: client-id: ${{ secrets.AZURE_SP_TESTS_APPID }} tenant-id: ${{ secrets.AZURE_SP_TESTS_TENANTID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTIONID_TESTS }} + - uses: marocchino/sticky-pull-request-comment@v2 continue-on-error: true with: @@ -407,6 +444,7 @@ jobs: append: true message: | :hourglass: Starting ${{ matrix.name }} functional tests... + - name: Create azure resource group - ${{ env.AZURE_TEST_RESOURCE_GROUP }} run: | current_time=$(date +%s) @@ -418,9 +456,11 @@ jobs: while [ $(az group exists --name $RESOURCE_GROUP) = false ]; do sleep 2; done env: RESOURCE_GROUP: ${{ env.AZURE_TEST_RESOURCE_GROUP }} + - uses: azure/setup-helm@v4 with: version: ${{ env.HELM_VER }} + - name: Create KinD cluster run: | curl -sSLo "kind" "https://github.com/kubernetes-sigs/kind/releases/download/${{ env.KIND_VER }}/kind-linux-amd64" @@ -462,24 +502,29 @@ jobs: extraArgs: service-account-private-key-file: /etc/kubernetes/pki/sa.key EOF + - name: Install dapr into cluster run: | wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | /bin/bash -s ${{ env.DAPR_VER }} dapr init -k --wait --timeout 600 --runtime-version ${{ env.DAPR_VER }} --dashboard-version ${{ env.DAPR_DASHBOARD_VER }} + - name: Install Azure Keyvault CSI driver chart run: | helm repo add csi-secrets-store-provider-azure https://azure.github.io/secrets-store-csi-driver-provider-azure/charts helm install csi csi-secrets-store-provider-azure/csi-secrets-store-provider-azure --version ${{ env.AZURE_KEYVAULT_CSI_DRIVER_VER }} + - name: Install azure workload identity webhook chart run: | helm repo add azure-workload-identity https://azure.github.io/azure-workload-identity/charts helm install workload-identity-webhook azure-workload-identity/workload-identity-webhook --namespace radius-default --create-namespace --version ${{ env.AZURE_WORKLOAD_IDENTITY_WEBHOOK_VER }} --set azureTenantID=${{ secrets.AZURE_SP_TESTS_TENANTID }} + - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Download Bicep run: | chmod +x ./bin/rad @@ -487,9 +532,11 @@ jobs: which rad || { echo "cannot find rad"; exit 1; } rad bicep download rad version + - name: Install gotestsum (test reporting tool) run: | go install gotest.tools/gotestsum@v${{ env.GOTESTSUM_VER }} + - uses: marocchino/sticky-pull-request-comment@v2 if: failure() && env.PR_NUMBER != '' continue-on-error: true @@ -500,6 +547,7 @@ jobs: append: true message: | :x: Test tool installation for ${{ matrix.name }} failed. Please check [the logs](${{ env.ACTION_LINK }}) for more details + - name: Install Radius run: | export PATH=$GITHUB_WORKSPACE/bin:$PATH @@ -530,6 +578,7 @@ jobs: rad env update kind-radius --aws-region ${{ env.AWS_REGION }} --aws-account-id ${{ secrets.FUNCTEST_AWS_ACCOUNT_ID }} rad credential register aws \ --access-key-id ${{ secrets.FUNCTEST_AWS_ACCESS_KEY_ID }} --secret-access-key ${{ secrets.FUNCTEST_AWS_SECRET_ACCESS_KEY }} + - uses: marocchino/sticky-pull-request-comment@v2 if: failure() && env.PR_NUMBER != '' continue-on-error: true @@ -540,9 +589,11 @@ jobs: append: true message: | :x: Failed to install Radius for ${{ matrix.name }} functional test. Please check [the logs](${{ env.ACTION_LINK }}) for more details + - name: Publish Terraform test recipes run: | make publish-test-terraform-recipes + - name: Run functional tests run: | # Ensure rad cli is in path before running tests. @@ -579,6 +630,7 @@ jobs: BICEP_RECIPE_TAG_VERSION: ${{ env.BICEP_RECIPE_TAG_VERSION }} GH_TOKEN: ${{ steps.get_installation_token.outputs.token }} GOTESTSUM_OPTS: "--junitfile ./dist/functional_test/results.xml" + - name: Process Functional Test Results uses: ./.github/actions/process-test-results # In case of failure, upload functional_test_results to artifacts so that they are not erased by subsequent runs. @@ -587,10 +639,7 @@ jobs: test_group_name: "Functional Tests - ${{ matrix.name }}" artifact_name: "functional_test_results_${{ matrix.name }}" result_directory: "dist/functional_test/" - - uses: azure/setup-kubectl@v4 - if: always() - with: - version: ${{ env.KUBECTL_VER }} + - name: Collect Pod details if: always() run: | @@ -600,12 +649,14 @@ jobs: kubectl get pods -A >> $POD_STATE_LOG_FILENAME echo "kubectl describe pods -A" >> $POD_STATE_LOG_FILENAME kubectl describe pods -A >> $POD_STATE_LOG_FILENAME + - name: Upload container logs if: always() uses: actions/upload-artifact@v4 with: name: ${{ matrix.name }}_container_logs path: ./${{ env.RADIUS_CONTAINER_LOG_BASE }} + - name: Get Terraform recipe publishing logs if: always() run: | @@ -621,6 +672,7 @@ jobs: echo "Pod logs saved to recipes/pod-logs/" # Get kubernetes events and save to file kubectl get events -n $namespace > recipes/pod-logs/events.txt + - name: Upload Terraform recipe publishing logs uses: actions/upload-artifact@v4 if: always() @@ -628,6 +680,7 @@ jobs: name: ${{ matrix.name }}_recipes-pod-logs path: recipes/pod-logs if-no-files-found: error + - uses: marocchino/sticky-pull-request-comment@v2 if: success() && env.PR_NUMBER != '' continue-on-error: true @@ -638,6 +691,7 @@ jobs: append: true message: | :white_check_mark: ${{ matrix.name }} functional tests succeeded + - uses: marocchino/sticky-pull-request-comment@v2 if: failure() && env.PR_NUMBER != '' continue-on-error: true @@ -648,6 +702,7 @@ jobs: append: true message: | :x: ${{ matrix.name }} functional test failed. Please check [the logs](${{ env.ACTION_LINK }}) for more details + - uses: marocchino/sticky-pull-request-comment@v2 if: cancelled() && env.PR_NUMBER != '' continue-on-error: true @@ -658,6 +713,7 @@ jobs: append: true message: | :x: ${{ matrix.name }} functional test cancelled. Please check [the logs](${{ env.ACTION_LINK }}) for more details + - name: Delete azure resource group - ${{ env.AZURE_TEST_RESOURCE_GROUP }} if: always() run: | @@ -666,6 +722,7 @@ jobs: --subscription ${{ secrets.AZURE_SUBSCRIPTIONID_TESTS }} \ --name ${{ env.AZURE_TEST_RESOURCE_GROUP }} \ --yes --verbose + report-test-results: name: Report test results needs: [build, tests] @@ -680,6 +737,7 @@ jobs: with: app_id: ${{ env.FUNCTIONAL_TEST_APP_ID }} private_key: ${{ secrets.FUNCTIONAL_TEST_APP_PRIVATE_KEY }} + - name: Get tests job status id: get_test_status run: | @@ -700,6 +758,7 @@ jobs: done echo "Test Status: $TEST_STATUS" echo "test_status=$TEST_STATUS" >> $GITHUB_OUTPUT + - uses: LouisBrunner/checks-action@v2.0.0 if: always() with: @@ -712,6 +771,7 @@ jobs: output: | {"summary":"Functional Test run completed. See links for more information.","title":"Functional Test Run"} details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + report-failure: name: Report test failure needs: [build, tests] @@ -740,6 +800,7 @@ jobs: } } return failureCount; + - name: Create failure issue for failing scheduled run uses: actions/github-script@v7 # Only create an issue if there are (env.ISSUE_CREATE_THRESHOLD) failures of the recent tests. diff --git a/.github/workflows/functional-test-noncloud.yaml b/.github/workflows/functional-test-noncloud.yaml index 854f9814334..2fd8e98e732 100644 --- a/.github/workflows/functional-test-noncloud.yaml +++ b/.github/workflows/functional-test-noncloud.yaml @@ -25,6 +25,11 @@ permissions: on: # Enable manual trigger workflow_dispatch: + inputs: + branch: + description: "Branch to run the workflow on" + required: true + default: "main" schedule: # Run every 4 hours on weekdays. - cron: "30 0,4,8,12,16,20 * * 1-5" @@ -33,12 +38,6 @@ on: # Dispatch on external events repository_dispatch: types: [de-functional-test] - push: - branches: - - main - - release/* - tags: - - v* pull_request: branches: - main @@ -112,12 +111,6 @@ jobs: ); } - - name: Check out code - uses: actions/checkout@v4 - with: - repository: ${{ env.CHECKOUT_REPO }} - ref: ${{ env.CHECKOUT_REF }} - - name: Generate ID for release id: gen-id run: | @@ -160,7 +153,7 @@ jobs: DE_TAG: ${{ needs.build.outputs.DE_TAG }} steps: - name: Set up checkout target (scheduled) - if: github.event_name == 'schedule' + if: github.event_name == 'schedule' || github.event_name == 'repository_dispatch' run: | echo "CHECKOUT_REPO=${{ github.repository }}" >> $GITHUB_ENV echo "CHECKOUT_REF=refs/heads/main" >> $GITHUB_ENV @@ -172,7 +165,13 @@ jobs: echo "CHECKOUT_REF=${{ github.ref }}" >> $GITHUB_ENV echo "PR_NUMBER=${{ github.event.pull_request.number }}" >> $GITHUB_ENV - - name: Use custom actions + - name: Set up checkout target (workflow_dispatch) + if: github.event_name == 'workflow_dispatch' + run: | + echo "CHECKOUT_REPO=${{ github.repository }}" >> $GITHUB_ENV + echo "CHECKOUT_REF=refs/heads/${{ github.event.inputs.branch }}" >> $GITHUB_ENV + + - name: Check out code uses: actions/checkout@v4 - name: Checkout samples repo @@ -207,6 +206,7 @@ jobs: ${{ runner.os }}-go- - name: Create a secure local registry + id: create-local-registry uses: ./.github/actions/create-local-registry with: secure: "true" @@ -238,6 +238,8 @@ jobs: - name: Create a KinD cluster with a local registry uses: ./.github/actions/create-kind-cluster with: + secure: "true" + temp-cert-dir: ${{ steps.create-local-registry.outputs.temp-cert-dir }} kind-version: ${{ env.KIND_VER }} with-local-registry: "true" registry-name: ${{ env.LOCAL_REGISTRY_NAME }} @@ -268,14 +270,19 @@ jobs: echo "Radius release not found. Proceeding with installation." fi + RAD_COMMAND="rad install kubernetes \ + --chart ${{ env.RADIUS_CHART_LOCATION }} \ + --set rp.image=${{ env.LOCAL_REGISTRY_NAME }}:${{ env.LOCAL_REGISTRY_PORT }}/applications-rp,rp.tag=${{ env.REL_VERSION }} \ + --set controller.image=${{ env.LOCAL_REGISTRY_NAME }}:${{ env.LOCAL_REGISTRY_PORT }}/controller,controller.tag=${{ env.REL_VERSION }} \ + --set ucp.image=${{ env.LOCAL_REGISTRY_NAME }}:${{ env.LOCAL_REGISTRY_PORT }}/ucpd,ucp.tag=${{ env.REL_VERSION }} \ + --set de.image=${{ env.DE_IMAGE }},de.tag=${{ env.DE_TAG }}" + + if [ "${{ env.USE_CERT_FILE }}" = "true" ]; then + RAD_COMMAND="$RAD_COMMAND --set-file global.rootCA.cert=$TEMP_CERT_DIR/certs/${{ env.LOCAL_REGISTRY_SERVER }}/client.crt" + fi + echo "*** Installing Radius to Kubernetes ***" - rad install kubernetes \ - --chart ${{ env.RADIUS_CHART_LOCATION }} \ - --set rp.image=${{ env.LOCAL_REGISTRY_NAME }}:${{ env.LOCAL_REGISTRY_PORT }}/applications-rp,rp.tag=${{ env.REL_VERSION }} \ - --set controller.image=${{ env.LOCAL_REGISTRY_NAME }}:${{ env.LOCAL_REGISTRY_PORT }}/controller,controller.tag=${{ env.REL_VERSION }} \ - --set ucp.image=${{ env.LOCAL_REGISTRY_NAME }}:${{ env.LOCAL_REGISTRY_PORT }}/ucpd,ucp.tag=${{ env.REL_VERSION }} \ - --set de.image=${{ env.DE_IMAGE }},de.tag=${{ env.DE_TAG }} \ - --set-file global.rootCA.cert=$TEMP_CERT_DIR/certs/${{ env.LOCAL_REGISTRY_SERVER }}/client.crt + eval $RAD_COMMAND echo "*** Create workspace, group and environment for test ***" rad workspace create kubernetes @@ -285,6 +292,9 @@ jobs: # The functional test is designed to use default namespace. So you must create the environment for default namespace. rad env create kind-radius --namespace default rad env switch kind-radius + env: + USE_CERT_FILE: "true" + TEMP_CERT_DIR: ${{ steps.create-local-registry.outputs.temp-cert-dir }} - name: Publish Terraform test recipes run: | @@ -298,7 +308,8 @@ jobs: env: BICEP_RECIPE_REGISTRY: "${{ env.LOCAL_REGISTRY_SERVER }}:${{ env.LOCAL_REGISTRY_PORT }}" BICEP_RECIPE_TAG_VERSION: ${{ env.REL_VERSION }} - SSL_CERT_FILE: $TEMP_CERT_DIR/certs/${{ env.LOCAL_REGISTRY_SERVER }}/client.crt + TEMP_CERT_DIR: ${{ steps.create-local-registry.outputs.temp-cert-dir }} + SSL_CERT_FILE: ${{ steps.create-local-registry.outputs.temp-cert-dir }}/certs/${{ env.LOCAL_REGISTRY_SERVER }}/client.crt - name: Run functional tests run: | @@ -330,11 +341,6 @@ jobs: artifact_name: "functional_test_results_${{ matrix.name }}" result_directory: "dist/functional_test/" - - uses: azure/setup-kubectl@v4 - if: always() - with: - version: ${{ env.KUBECTL_VER }} - - name: Collect detailed Radius logs and events id: radius-logs-events if: always() diff --git a/.github/workflows/functional-tests-approval.yaml b/.github/workflows/functional-tests-approval.yaml index 2e8b6bfb116..50b022b40d4 100644 --- a/.github/workflows/functional-tests-approval.yaml +++ b/.github/workflows/functional-tests-approval.yaml @@ -1,4 +1,4 @@ -name: 'Approve Functional Tests' +name: "Approve Functional Tests" on: pull_request: branches: @@ -7,11 +7,12 @@ on: - release/* jobs: approve-functional-tests-run: - name: 'Approve Functional Tests' + name: "Approve Functional Tests" runs-on: ubuntu-latest environment: functional-tests steps: - - name: Use custom actions - uses: actions/checkout@v4 - - name: Save PR number - uses: ./.github/actions/save-pr-as-artifact + - name: Checkout Radius repository + uses: actions/checkout@v4 + + - name: Save PR number + uses: ./.github/actions/save-pr-as-artifact diff --git a/test/functional-portable/datastoresrp/cloud/resources/mongodb_test.go b/test/functional-portable/datastoresrp/cloud/resources/mongodb_test.go deleted file mode 100644 index b176975655b..00000000000 --- a/test/functional-portable/datastoresrp/cloud/resources/mongodb_test.go +++ /dev/null @@ -1,72 +0,0 @@ -/* -Copyright 2023 The Radius Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package resource_test - -import ( - "testing" - - "github.com/radius-project/radius/test/rp" - "github.com/radius-project/radius/test/step" - "github.com/radius-project/radius/test/testutil" - "github.com/radius-project/radius/test/validation" -) - -// Test_MongoDB_Recipe validates: -// the creation of a mongoDB from a recipe that uses an Azure resource -func Test_MongoDB_Recipe(t *testing.T) { - template := "testdata/datastoresrp-resources-mongodb-recipe.bicep" - name := "dsrp-resources-mongodb-recipe" - appNamespace := "dsrp-resources-mongodb-recipe-app" - - test := rp.NewRPTest(t, name, []rp.TestStep{ - { - Executor: step.NewDeployExecutor(template, testutil.GetMagpieImage(), testutil.GetBicepRecipeRegistry(), testutil.GetBicepRecipeVersion()), - RPResources: &validation.RPResourceSet{ - Resources: []validation.RPResource{ - { - Name: "dsrp-resources-mongodb-recipe-env", - Type: validation.EnvironmentsResource, - }, - { - Name: "dsrp-resources-mongodb-recipe", - Type: validation.ApplicationsResource, - App: name, - }, - { - Name: "mongodb-app-ctnr", - Type: validation.ContainersResource, - App: name, - }, - { - Name: "mongodb-db", - Type: validation.MongoDatabasesResource, - App: name, - }, - }, - }, - K8sObjects: &validation.K8sObjectSet{ - Namespaces: map[string][]validation.K8sObject{ - appNamespace: { - validation.NewK8sPodForResource(name, "mongodb-app-ctnr").ValidateLabels(false), - }, - }, - }, - }, - }) - - test.Test(t) -} diff --git a/test/functional-portable/datastoresrp/cloud/resources/redis_test.go b/test/functional-portable/datastoresrp/cloud/resources/redis_test.go deleted file mode 100644 index ffeb6b8eb51..00000000000 --- a/test/functional-portable/datastoresrp/cloud/resources/redis_test.go +++ /dev/null @@ -1,101 +0,0 @@ -/* -Copyright 2023 The Radius Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package resource_test - -import ( - "context" - "strings" - "testing" - - "github.com/radius-project/radius/test/rp" - "github.com/radius-project/radius/test/step" - "github.com/radius-project/radius/test/testutil" - "github.com/radius-project/radius/test/validation" - "github.com/stretchr/testify/require" -) - -func Test_Redis_Recipe(t *testing.T) { - template := "testdata/datastoresrp-resources-redis-recipe.bicep" - name := "dsrp-resources-redis-recipe" - - test := rp.NewRPTest(t, name, []rp.TestStep{ - { - Executor: step.NewDeployExecutor(template, testutil.GetBicepRecipeRegistry(), testutil.GetBicepRecipeVersion()), - RPResources: &validation.RPResourceSet{ - Resources: []validation.RPResource{ - { - Name: "dsrp-resources-env-recipe-env", - Type: validation.EnvironmentsResource, - }, - { - Name: name, - Type: validation.ApplicationsResource, - }, - { - Name: "rds-recipe", - Type: validation.RedisCachesResource, - App: name, - }, - }, - }, - SkipObjectValidation: true, - PostStepVerify: func(ctx context.Context, t *testing.T, test rp.RPTest) { - redis, err := test.Options.ManagementClient.GetResource(ctx, "Applications.Datastores/redisCaches", "rds-recipe") - require.NoError(t, err) - require.NotNil(t, redis) - status := redis.Properties["status"].(map[string]any) - recipe := status["recipe"].(map[string]interface{}) - require.Equal(t, "bicep", recipe["templateKind"].(string)) - templatePath := strings.Split(recipe["templatePath"].(string), ":")[0] - require.Equal(t, "ghcr.io/radius-project/dev/test/testrecipes/test-bicep-recipes/redis-recipe-value-backed", templatePath) - }, - }, - }) - - test.Test(t) -} - -func Test_Redis_DefaultRecipe(t *testing.T) { - template := "testdata/datastoresrp-resources-redis-default-recipe.bicep" - name := "dsrp-resources-redis-default-recipe" - - test := rp.NewRPTest(t, name, []rp.TestStep{ - { - Executor: step.NewDeployExecutor(template, testutil.GetBicepRecipeRegistry(), testutil.GetBicepRecipeVersion()), - RPResources: &validation.RPResourceSet{ - Resources: []validation.RPResource{ - { - Name: "dsrp-resources-env-default-recipe-env", - Type: validation.EnvironmentsResource, - }, - { - Name: name, - Type: validation.ApplicationsResource, - }, - { - Name: "rds-default-recipe", - Type: validation.RedisCachesResource, - App: name, - }, - }, - }, - SkipObjectValidation: true, - }, - }) - - test.Test(t) -} diff --git a/test/functional-portable/datastoresrp/cloud/resources/testdata/datastoresrp-resources-microsoft-sql.bicep b/test/functional-portable/datastoresrp/cloud/resources/testdata/datastoresrp-resources-microsoft-sql.bicep index 2cc83b1dde8..75ef07e1f90 100644 --- a/test/functional-portable/datastoresrp/cloud/resources/testdata/datastoresrp-resources-microsoft-sql.bicep +++ b/test/functional-portable/datastoresrp/cloud/resources/testdata/datastoresrp-resources-microsoft-sql.bicep @@ -64,14 +64,14 @@ resource db 'Applications.Datastores/sqlDatabases@2023-10-01-preview' = { application: app.id environment: environment resourceProvisioning: 'manual' - resources:[ + resources: [ { - id:mssqlresourceid + id: mssqlresourceid } ] database: database server: server - port:1433 + port: 1433 username: adminUsername secrets: { password: adminPassword diff --git a/test/functional-portable/datastoresrp/noncloud/resources/mongodb_test.go b/test/functional-portable/datastoresrp/noncloud/resources/mongodb_test.go index cd9c8d67c42..d399e0bdd48 100644 --- a/test/functional-portable/datastoresrp/noncloud/resources/mongodb_test.go +++ b/test/functional-portable/datastoresrp/noncloud/resources/mongodb_test.go @@ -70,3 +70,47 @@ func Test_MongoDB_Manual(t *testing.T) { test.Test(t) } + +func Test_MongoDB_Recipe(t *testing.T) { + template := "testdata/datastoresrp-resources-mongodb-recipe.bicep" + name := "dsrp-resources-mongodb-recipe" + appNamespace := "dsrp-resources-mongodb-recipe-app" + + test := rp.NewRPTest(t, name, []rp.TestStep{ + { + Executor: step.NewDeployExecutor(template, testutil.GetMagpieImage(), testutil.GetBicepRecipeRegistry(), testutil.GetBicepRecipeVersion()), + RPResources: &validation.RPResourceSet{ + Resources: []validation.RPResource{ + { + Name: "dsrp-resources-mongodb-recipe-env", + Type: validation.EnvironmentsResource, + }, + { + Name: "dsrp-resources-mongodb-recipe", + Type: validation.ApplicationsResource, + App: name, + }, + { + Name: "mongodb-app-ctnr", + Type: validation.ContainersResource, + App: name, + }, + { + Name: "mongodb-db", + Type: validation.MongoDatabasesResource, + App: name, + }, + }, + }, + K8sObjects: &validation.K8sObjectSet{ + Namespaces: map[string][]validation.K8sObject{ + appNamespace: { + validation.NewK8sPodForResource(name, "mongodb-app-ctnr").ValidateLabels(false), + }, + }, + }, + }, + }) + + test.Test(t) +} diff --git a/test/functional-portable/datastoresrp/noncloud/resources/redis_test.go b/test/functional-portable/datastoresrp/noncloud/resources/redis_test.go index 4f672d25308..070188ef75d 100644 --- a/test/functional-portable/datastoresrp/noncloud/resources/redis_test.go +++ b/test/functional-portable/datastoresrp/noncloud/resources/redis_test.go @@ -17,12 +17,15 @@ limitations under the License. package resource_test import ( + "context" + "strings" "testing" "github.com/radius-project/radius/test/rp" "github.com/radius-project/radius/test/step" "github.com/radius-project/radius/test/testutil" "github.com/radius-project/radius/test/validation" + "github.com/stretchr/testify/require" ) func Test_Redis_Manual(t *testing.T) { @@ -69,3 +72,75 @@ func Test_Redis_Manual(t *testing.T) { test.Test(t) } + +func Test_Redis_Recipe(t *testing.T) { + template := "testdata/datastoresrp-resources-redis-recipe.bicep" + name := "dsrp-resources-redis-recipe" + + test := rp.NewRPTest(t, name, []rp.TestStep{ + { + Executor: step.NewDeployExecutor(template, testutil.GetBicepRecipeRegistry(), testutil.GetBicepRecipeVersion()), + RPResources: &validation.RPResourceSet{ + Resources: []validation.RPResource{ + { + Name: "dsrp-resources-env-recipe-env", + Type: validation.EnvironmentsResource, + }, + { + Name: name, + Type: validation.ApplicationsResource, + }, + { + Name: "rds-recipe", + Type: validation.RedisCachesResource, + App: name, + }, + }, + }, + SkipObjectValidation: true, + PostStepVerify: func(ctx context.Context, t *testing.T, test rp.RPTest) { + redis, err := test.Options.ManagementClient.GetResource(ctx, "Applications.Datastores/redisCaches", "rds-recipe") + require.NoError(t, err) + require.NotNil(t, redis) + status := redis.Properties["status"].(map[string]any) + recipe := status["recipe"].(map[string]interface{}) + require.Equal(t, "bicep", recipe["templateKind"].(string)) + templatePath := strings.Split(recipe["templatePath"].(string), ":")[0] + require.Equal(t, "radius-registry:5000/dev/test/testrecipes/test-bicep-recipes/redis-recipe-value-backed", templatePath) + }, + }, + }) + + test.Test(t) +} + +func Test_Redis_DefaultRecipe(t *testing.T) { + template := "testdata/datastoresrp-resources-redis-default-recipe.bicep" + name := "dsrp-resources-redis-default-recipe" + + test := rp.NewRPTest(t, name, []rp.TestStep{ + { + Executor: step.NewDeployExecutor(template, testutil.GetBicepRecipeRegistry(), testutil.GetBicepRecipeVersion()), + RPResources: &validation.RPResourceSet{ + Resources: []validation.RPResource{ + { + Name: "dsrp-resources-env-default-recipe-env", + Type: validation.EnvironmentsResource, + }, + { + Name: name, + Type: validation.ApplicationsResource, + }, + { + Name: "rds-default-recipe", + Type: validation.RedisCachesResource, + App: name, + }, + }, + }, + SkipObjectValidation: true, + }, + }) + + test.Test(t) +} diff --git a/test/functional-portable/datastoresrp/cloud/resources/testdata/datastoresrp-resources-mongodb-recipe.bicep b/test/functional-portable/datastoresrp/noncloud/resources/testdata/datastoresrp-resources-mongodb-recipe.bicep similarity index 89% rename from test/functional-portable/datastoresrp/cloud/resources/testdata/datastoresrp-resources-mongodb-recipe.bicep rename to test/functional-portable/datastoresrp/noncloud/resources/testdata/datastoresrp-resources-mongodb-recipe.bicep index 8495e68ef45..0cf26a0aca0 100644 --- a/test/functional-portable/datastoresrp/cloud/resources/testdata/datastoresrp-resources-mongodb-recipe.bicep +++ b/test/functional-portable/datastoresrp/noncloud/resources/testdata/datastoresrp-resources-mongodb-recipe.bicep @@ -1,9 +1,5 @@ import radius as radius -param rg string = resourceGroup().name - -param sub string = subscription().subscriptionId - param registry string param version string @@ -19,11 +15,6 @@ resource env 'Applications.Core/environments@2023-10-01-preview' = { resourceId: 'self' namespace: 'dsrp-resources-mongodb-recipe-env' } - providers: { - azure: { - scope: '/subscriptions/${sub}/resourceGroups/${rg}' - } - } recipes: { 'Applications.Datastores/mongoDatabases': { mongoazure: { diff --git a/test/functional-portable/datastoresrp/cloud/resources/testdata/datastoresrp-resources-redis-default-recipe.bicep b/test/functional-portable/datastoresrp/noncloud/resources/testdata/datastoresrp-resources-redis-default-recipe.bicep similarity index 91% rename from test/functional-portable/datastoresrp/cloud/resources/testdata/datastoresrp-resources-redis-default-recipe.bicep rename to test/functional-portable/datastoresrp/noncloud/resources/testdata/datastoresrp-resources-redis-default-recipe.bicep index 81fed908782..ea374b04768 100644 --- a/test/functional-portable/datastoresrp/cloud/resources/testdata/datastoresrp-resources-redis-default-recipe.bicep +++ b/test/functional-portable/datastoresrp/noncloud/resources/testdata/datastoresrp-resources-redis-default-recipe.bicep @@ -1,7 +1,5 @@ import radius as radius -param scope string = resourceGroup().id - param registry string param version string @@ -15,11 +13,6 @@ resource env 'Applications.Core/environments@2023-10-01-preview' = { resourceId: 'self' namespace: 'dsrp-resources-env-default-recipe-env' } - providers: { - azure: { - scope: scope - } - } recipes: { 'Applications.Datastores/redisCaches': { default: { diff --git a/test/functional-portable/datastoresrp/cloud/resources/testdata/datastoresrp-resources-redis-recipe.bicep b/test/functional-portable/datastoresrp/noncloud/resources/testdata/datastoresrp-resources-redis-recipe.bicep similarity index 91% rename from test/functional-portable/datastoresrp/cloud/resources/testdata/datastoresrp-resources-redis-recipe.bicep rename to test/functional-portable/datastoresrp/noncloud/resources/testdata/datastoresrp-resources-redis-recipe.bicep index a97261e63f7..730bca5f957 100644 --- a/test/functional-portable/datastoresrp/cloud/resources/testdata/datastoresrp-resources-redis-recipe.bicep +++ b/test/functional-portable/datastoresrp/noncloud/resources/testdata/datastoresrp-resources-redis-recipe.bicep @@ -1,7 +1,5 @@ import radius as radius -param scope string = resourceGroup().id - param registry string param version string @@ -15,11 +13,6 @@ resource env 'Applications.Core/environments@2023-10-01-preview' = { resourceId: 'self' namespace: 'dsrp-resources-env-recipe-env' } - providers: { - azure: { - scope: scope - } - } recipes: { 'Applications.Datastores/redisCaches': { rediscache: { diff --git a/test/testutil/testutil.go b/test/testutil/testutil.go index e09c62a8a4c..f5a5d32f0d9 100644 --- a/test/testutil/testutil.go +++ b/test/testutil/testutil.go @@ -69,16 +69,16 @@ func GetOIDCIssuer() string { // SetDefault sets the default Docker registry and image tag if they are not already set in the environment. func SetDefault() (string, string) { - defaultDockerReg := os.Getenv("DOCKER_REGISTRY") + dockerRegistry := os.Getenv("DOCKER_REGISTRY") imageTag := os.Getenv("REL_VERSION") - if defaultDockerReg == "" { - defaultDockerReg = "ghcr.io/radius-project" + if dockerRegistry == "" { + dockerRegistry = "ghcr.io/radius-project" } if imageTag == "" { imageTag = "latest" } - return defaultDockerReg, imageTag + return dockerRegistry, imageTag } type ProxyMetadata struct { @@ -335,3 +335,13 @@ func GetCreationTimestamp() string { func GenerateS3BucketName() string { return "radiusfunctionaltestbucket-" + uuid.New().String() } + +// GetDockerRegistry returns the Docker registry from the environment variable DOCKER_REGISTRY or the default value +// "ghcr.io/radius-project". +func GetDockerRegistry() string { + regName := os.Getenv("DOCKER_REGISTRY") + if regName == "" { + return "ghcr.io/radius-project" + } + return regName +}