diff --git a/.github/workflows/component-test.yaml b/.github/workflows/component-test.yaml new file mode 100644 index 00000000..3df1f97d --- /dev/null +++ b/.github/workflows/component-test.yaml @@ -0,0 +1,74 @@ +# File: .github/workflows/docker-go-build.yml +name: gitops-runtime-helm + +on: + push: + branches: + - main + paths-ignore: + - "*.md" + - charts/** + pull_request: + branches: + - main + paths-ignore: + - "*.md" + - charts/** + +jobs: + component-test: + runs-on: ubuntu-latest + + env: + DOCKER_CLI_EXPERIMENTAL: enabled + # Enable BuildKit + DOCKER_BUILDKIT: 1 + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v3 + - name: Set up kubectl + uses: azure/setup-kubectl@v3 + with: + version: 'v1.29.0' + - name: Install K3d + run: | + curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash + k3d --version + + - name: Create K3d cluster + run: | + k3d cluster create test-cluster --wait + kubectl get nodes + + - name: install kuttl + run: | + mkdir -p ./bin + curl -L https://github.com/kudobuilder/kuttl/releases/download/v0.22.0/kubectl-kuttl_0.22.0_linux_x86_64 -o ./bin/kuttl; + + chmod +x ./bin/kuttl; + - name: Install jq + run: | + sudo apt-get update + sudo apt-get install -y jq + - name: install helm + run: | + curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 + + chmod 700 get_helm.sh + + ./get_helm.sh + helm repo add gitea-charts https://dl.gitea.com/charts/ + helm repo add mockserver https://www.mock-server.com + + + - name: Run KUTTL tests + run: | + cd tests/component-tests && ./../../bin/kuttl test --parallel 1 --start-kind=false --namespace e2e-test --config startup.yaml \ No newline at end of file diff --git a/.gitignore b/.gitignore index 682a42a7..d7f3bd74 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,11 @@ output values-dev* dry-run.yaml .debug +bin +# Test +cmd/__debug_* +/test/component-tests/setup/simple-app +/test/component-tests/setup/codefresh-isc +**/test/component-tests/setup/values/runtime.values.yaml +**/test/component-tests/promotion/01-gitCommit/commit.json +**/test/component-tests/kubeconfig \ No newline at end of file diff --git a/tests/component-tests/promotion/00-dragAndDrop/00-assert.yaml b/tests/component-tests/promotion/00-dragAndDrop/00-assert.yaml new file mode 100644 index 00000000..191a20bc --- /dev/null +++ b/tests/component-tests/promotion/00-dragAndDrop/00-assert.yaml @@ -0,0 +1,27 @@ +# ----------------------------------------------------------------------------- +# 00-assert.yaml - KUTTL TestAssert for drag-and-drop workflow status +# +# This TestAssert script checks the status of the workflow created by the +# drag-and-drop test in the Codefresh GitOps Operator component tests. +# +# Usage: +# This assertion is executed as part of the KUTTL test suite. +# +# Steps performed: +# - Queries the workflow status for the specific release. +# - Asserts that the workflow status is 'Succeeded'. +# ----------------------------------------------------------------------------- +--- +apiVersion: kuttl.dev/v1beta1 +commands: + - script: > + STATUS="$(kubectl get workflow -n codefresh -l codefresh.io/release=682051c15f0ea1658a3eed78 -o jsonpath="{.items[*].status.phase}")" + + if [ $STATUS = 'Succeeded' ]; then + echo "workflow status for release '682051c15f0ea1658a3eed78' has succeeded" + else + echo "workflow status ($STATUS) for release '682051c15f0ea1658a3eed78' should be succeeded" + exit 1 + fi +kind: TestAssert +timeout: 240 \ No newline at end of file diff --git a/tests/component-tests/promotion/00-dragAndDrop/00-drag-and-drop-task.yaml b/tests/component-tests/promotion/00-dragAndDrop/00-drag-and-drop-task.yaml new file mode 100644 index 00000000..5d905edc --- /dev/null +++ b/tests/component-tests/promotion/00-dragAndDrop/00-drag-and-drop-task.yaml @@ -0,0 +1,18 @@ +# ----------------------------------------------------------------------------- +# 00-drag-and-drop-task.yaml - KUTTL TestStep for drag-and-drop mock setup +# +# This TestStep runs the dragAndDrop.sh script to load drag-and-drop mock +# expectations into Mockserver for the Codefresh GitOps Operator component tests. +# +# Usage: +# This step is executed as part of the KUTTL test suite. +# +# Steps performed: +# - Executes the dragAndDrop.sh script to configure Mockserver. +# ----------------------------------------------------------------------------- +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: ./dragAndDrop.sh +timeout: 30 \ No newline at end of file diff --git a/tests/component-tests/promotion/00-dragAndDrop/dragAndDrop.json b/tests/component-tests/promotion/00-dragAndDrop/dragAndDrop.json new file mode 100755 index 00000000..adc4be00 --- /dev/null +++ b/tests/component-tests/promotion/00-dragAndDrop/dragAndDrop.json @@ -0,0 +1,86 @@ +[ + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\nquery productReleaseTasks {\n\tproductReleaseTasks {\n\t\ttype\n\t\tlabels\n\t\tcommitInfo {\n\t\t\tsha\n\t\t\tcommitter\n\t\t\tdate\n\t\t\tmessage\n\t\t}\n\t\tappNamespace\n\t\tappName\n\t\trepoUrl\n\t\tbranch\n\t\tpath\n\t\tpostActionOnly\n\t\tpreAction\n\t\tactionUrl\n\t\tactionBody\n\t\tpostAction\n\t\tworkflowNamespace\n\t\tworkflowName\n\t}\n}", + "variables": {} + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "productReleaseTasks": [ + { + "type": "CreateProductReleaseTask", + "labels": { + "codefresh.io/product": "simple", + "codefresh.io/env": "prod", + "codefresh.io/release": "682051c15f0ea1658a3eed78", + "codefresh.io/promotion-flow": "", + "codefresh.io/app-name": "simple-prod", + "codefresh.io/app-namespace": "codefresh", + "codefresh.io/release-name": "3ab912d13" + }, + "commitInfo": null, + "appNamespace": "codefresh", + "appName": "simple-prod", + "repoUrl": "http://gitea-http.gitea:3000/test-owner/simple-app.git", + "branch": "HEAD", + "path": ".", + "postActionOnly": false, + "preAction": null, + "actionUrl": "/api/graphql", + "actionBody": "{\"query\":\"\\n mutation commitFiles($args: CommitFilesArgs!) {\\n commitFiles(args: $args) {\\n COMMIT_SHA: sha\\n sha\\n message\\n date\\n committer {\\n name\\n email\\n }\\n }\\n }\\n\",\"variables\":{\"args\":{\"msg\":\"promote codefresh/simple-dev to codefresh/simple-prod\",\"description\":\"\",\"files\":[{\"path\":\"values.yaml\",\"revision\":\"f238c105280eaf3a045d261f2caa1e423d8b4473\",\"data\":\"# Default values for simple-app.\\n# This is a YAML-formatted file.\\n# Declare variables to be passed into your templates.\\n\\nreplicaCount: 1\\n\\nimage:\\n repository: wang/alpine-go-echo-server\\n # sed -i -e \\\"s/^\\\\( tag:\\\\).*/\\\\1 $CI_COMMIT_SHA/\\\" ops/values.yaml\\n tag: 0.1\\n pullPolicy: IfNotPresent\\n\\nimagePullSecrets: []\\nnameOverride: \\\"\\\"\\nfullnameOverride: \\\"\\\"\\ncomponents:\\n - test1\\napp:\\n name: my-app-name\\n command:\\n - \\\"/app/echo-server\\\"\\n port: 3000\\n ## Enabled 'ports' If additional ports are needed\\n # ports:\\n # - name: port2\\n # containerPort: 3002\\n # protocol: TCP\\n # - name: port3\\n # containerPort: 3003\\n # protocol: UDP\\n config:\\n test_env: \\\"This is test value\\\"\\n secrets: false # To enable secretRef, you need create a secret named as RELEASE-NAME-secrets\\n # livenessProbe:\\n # httpGet:\\n # path: /\\n # port: http\\n # readinessProbe:\\n # httpGet:\\n # path: /\\n # port: http\\n volumeMounts: []\\n # - name: demo-data\\n # mountPath: /mnt/data\\n # readonly: true\\n\\nsidecar:\\n name: my-app-name-sidecar\\n enabled: false\\n image:\\n tag: 0.1\\n repository: wang/alpine-go-echo-server\\n pullPolicy: IfNotPresent\\n port: 3001\\n command:\\n - \\\"/app/echo-server\\\"\\n volumeMounts: []\\n resources:\\n limits:\\n cpu: 100m\\n memory: 128Mi\\n\\n\\nvolumes: []\\n # - name: demo-data\\n # secret:\\n # secretName: demo-secrets\\n\\nserviceAccount:\\n # Specifies whether a service account should be created\\n create: true\\n # Annotations to add to the service account\\n annotations: {}\\n # The name of the service account to use.\\n # If not set and create is true, a name is generated using the fullname template\\n name:\\n\\npodSecurityContext: {}\\n # fsGroup: 2000\\n\\nsecurityContext: {}\\n # capabilities:\\n # drop:\\n # - ALL\\n # readOnlyRootFilesystem: true\\n # runAsNonRoot: true\\n # runAsUser: 1000\\n\\nservice:\\n enabled: true\\n type: ClusterIP\\n port: 80\\n ## Enable 'ports', if additional ports are needed\\n # ports:\\n # - name: port2\\n # port: 3002\\n # targetPort: port2\\n # protocol: TCP\\n # - name: port3\\n # port: 3003\\n # targetPort: port3\\n # protocol: UDP\\n\\ningress:\\n enabled: false\\n annotations: {}\\n # kubernetes.io/ingress.class: nginx\\n # kubernetes.io/tls-acme: \\\"true\\\"\\n # cert-manager.io/cluster-issuer: letsencrypt-production\\n hosts:\\n - host: chart-example.local\\n paths: []\\n # - /\\n # - /index.html\\n tls: []\\n # - secretName: chart-example-tls\\n # hosts:\\n # - chart-example.local\\n\\nresources: {}\\n # We usually recommend not to specify default resources and to leave this as a conscious\\n # choice for the user. This also increases chances charts run on environments with little\\n # resources, such as Minikube. If you do want to specify resources, uncomment the following\\n # lines, adjust them as necessary, and remove the curly braces after 'resources:'.\\n # limits:\\n # cpu: 100m\\n # memory: 128Mi\\n # requests:\\n # cpu: 100m\\n # memory: 128Mi\\n\\nnodeSelector: {}\\n\\ntolerations: []\\n\\naffinity: {}\\n\"}],\"repo\":\"test-owner/simple-app\",\"branchName\":\"HEAD\",\"force\":true}}}", + "postAction": null, + "workflowNamespace": null, + "workflowName": null + } + ] + } + } + }, + "times": { + "remainingTimes": 1, + "unlimited": false + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\nquery productReleaseRunHooksTasks {\n\tproductReleaseRunHooksTasks {\n\t\ttype\n\t\tlabels\n\t\tworkflowTemplateName\n\t\tworkflowNamespace\n\t\tworkflowName\n\t\tparameters\n\t}\n}", + "variables": {} + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "productReleaseRunHooksTasks": [] + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\nquery productReleaseCommitStatuses {\n\tproductReleaseCommitStatuses {\n\t\tsha\n\t\trepoURL\n\t\tstatus\n\t\tdescription\n\t\tcontext\n\t\ttargetUrl\n\t}\n}", + "variables": {} + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "productReleaseCommitStatuses": [] + } + } + } + } +] diff --git a/tests/component-tests/promotion/00-dragAndDrop/dragAndDrop.sh b/tests/component-tests/promotion/00-dragAndDrop/dragAndDrop.sh new file mode 100755 index 00000000..0969b619 --- /dev/null +++ b/tests/component-tests/promotion/00-dragAndDrop/dragAndDrop.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# ----------------------------------------------------------------------------- +# dragAndDrop.sh - Loads drag-and-drop mock expectations for component tests +# +# This script loads mock expectations into the Mockserver for drag-and-drop +# scenarios in the Codefresh GitOps Operator component test suite. +# +# Usage: +# ./dragAndDrop.sh +# +# Steps performed: +# - Waits briefly to ensure Mockserver is ready. +# - Loads drag-and-drop mock expectations from dragAndDrop.json. +# ----------------------------------------------------------------------------- +sleep 2 +curl -i -X PUT http://127.0.0.1:1080/mockserver/expectation --data-binary "@./dragAndDrop.json" diff --git a/tests/component-tests/promotion/01-git-commit/00-app-sync.json b/tests/component-tests/promotion/01-git-commit/00-app-sync.json new file mode 100755 index 00000000..690f4010 --- /dev/null +++ b/tests/component-tests/promotion/01-git-commit/00-app-sync.json @@ -0,0 +1,159 @@ +[ + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\nquery productReleaseTasks {\n\tproductReleaseTasks {\n\t\ttype\n\t\tlabels\n\t\tcommitInfo {\n\t\t\tsha\n\t\t\tcommitter\n\t\t\tdate\n\t\t\tmessage\n\t\t}\n\t\tappNamespace\n\t\tappName\n\t\trepoUrl\n\t\tbranch\n\t\tpath\n\t\tpostActionOnly\n\t\tpreAction\n\t\tactionUrl\n\t\tactionBody\n\t\tpostAction\n\t\tworkflowNamespace\n\t\tworkflowName\n\t}\n}", + "variables": {} + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "productReleaseTasks": [ + { + "type": "CreateProductReleaseTask", + "labels": { + "codefresh.io/app-name": "simple-dev", + "codefresh.io/app-namespace": "codefresh", + "codefresh.io/env": "dev", + "codefresh.io/product": "simple", + "codefresh.io/promotion-flow": "stam", + "codefresh.io/release": "684040897b3903d3764e1f73", + "codefresh.io/release-name": "50575377c" + }, + "appNamespace": "codefresh", + "appName": "simple-dev", + "repoUrl": "http://gitea-http.gitea:3000/test-owner/simple-app.git", + "branch": "dev", + "path": ".", + "postActionOnly": true, + "commitInfo": { + "sha": "source-commit-sha", + "committer": "testowner ", + "date": "2025-05-12T05:49:00Z", + "message": "Update values.yaml" + }, + "actionUrl": "", + "actionBody": "" + } + ] + } + } + }, + "times": { + "remainingTimes": 1, + "unlimited": false + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\nquery productReleaseRunHooksTasks {\n\tproductReleaseRunHooksTasks {\n\t\ttype\n\t\tlabels\n\t\tworkflowTemplateName\n\t\tworkflowNamespace\n\t\tworkflowName\n\t\tparameters\n\t}\n}", + "variables": {} + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "productReleaseRunHooksTasks": [] + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\nquery productReleaseCommitStatuses {\n\tproductReleaseCommitStatuses {\n\t\tsha\n\t\trepoURL\n\t\tstatus\n\t\tdescription\n\t\tcontext\n\t\ttargetUrl\n\t}\n}", + "variables": {} + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "productReleaseCommitStatuses": [] + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "type": "REGEX", + "regex": ".*createProductRelease.*" + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "labels": { + "aaa": "bbb" + } + } + } + }, + "times": { + "remainingTimes": 1, + "unlimited": false + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "type": "REGEX", + "regex": ".*PromotionData.*" + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "srcApp": { + "metadata": { + "name": "simple-dev", + "cluster": "https://kubernetes.default.svc", + "namespace": "codefresh" + }, + "specSource": { + "repoURL": "http://gitea-http.gitea:3000/test-owner/simple-app.git", + "targetRevision": "dev", + "path": "." + } + }, + "destApp": { + "metadata": { + "name": "simple-prod", + "cluster": "https://kubernetes.default.svc", + "namespace": "codefresh" + }, + "specSource": { + "repoURL": "http://gitea-http.gitea:3000/test-owner/simple-app.git", + "targetRevision": "HEAD", + "path": "." + } + }, + "promotionTemplate": { + "promotion": [], + "versionSource": { + "file": "", + "jsonPath": "" + } + } + } + } + } + } +] \ No newline at end of file diff --git a/tests/component-tests/promotion/01-git-commit/00-app-sync.sh b/tests/component-tests/promotion/01-git-commit/00-app-sync.sh new file mode 100755 index 00000000..017df1c1 --- /dev/null +++ b/tests/component-tests/promotion/01-git-commit/00-app-sync.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# ----------------------------------------------------------------------------- +# 00-app-sync.sh - Updates app values and loads sync mock expectations +# +# This script is used in the Codefresh GitOps Operator component test suite to: +# - Update the 'values.yaml' file in the simple-app repository. +# - Commit and push the changes to the repository. +# - Update mock expectation JSON files with the latest commit SHA. +# - Load the updated mock expectations into Mockserver. +# +# Usage: +# ./00-app-sync.sh +# +# Steps performed: +# - Updates the image tag in values.yaml from '0.1' to 'latest'. +# - Commits and pushes the change to the simple-app repository. +# - Retrieves the latest commit SHA. +# - Updates the mock JSON files with the new commit SHA. +# - Loads the updated expectations into Mockserver. +# ----------------------------------------------------------------------------- +sleep 2 +OS_TYPE=$(uname) +cd ../../setup/simple-app +if [ "$OS_TYPE" = "Linux" ]; then + sed -i 's/0.1/latest/g' values.yaml +else + sed -i '' 's/0.1/latest/g' values.yaml +fi +git add --a +git commit -m "update values.yaml" +git push + +srcCommitSha=$(git rev-parse HEAD) +## update commit sha for dev app +if [ "$OS_TYPE" = "Linux" ]; then + sed -i "s/source-commit-sha/$srcCommitSha/g" ../../promotion/01-git-commit/00-app-sync.json +## update commit sha for prod app + sed -i "s/source-commit-sha/$srcCommitSha/g" ../../promotion/01-git-commit/01-app-promote.json +else + sed -i '' "s/source-commit-sha/$srcCommitSha/g" ../../promotion/01-git-commit/00-app-sync.json +## update commit sha for prod app + sed -i '' "s/source-commit-sha/$srcCommitSha/g" ../../promotion/01-git-commit/01-app-promote.json +fi + +sleep 5 +curl -i -X PUT http://127.0.0.1:1080/mockserver/expectation --data-binary "@../../promotion/01-git-commit/00-app-sync.json" diff --git a/tests/component-tests/promotion/01-git-commit/00-app-sync.yaml b/tests/component-tests/promotion/01-git-commit/00-app-sync.yaml new file mode 100644 index 00000000..c5bf50cc --- /dev/null +++ b/tests/component-tests/promotion/01-git-commit/00-app-sync.yaml @@ -0,0 +1,19 @@ +# ----------------------------------------------------------------------------- +# 00-app-sync.yaml - KUTTL TestStep for app sync and mock update +# +# This TestStep runs the 00-app-sync.sh script to update the simple-app +# repository and load updated sync mock expectations into Mockserver for the +# Codefresh GitOps Operator component tests. +# +# Usage: +# This step is executed as part of the KUTTL test suite. +# +# Steps performed: +# - Executes the 00-app-sync.sh script to update the app and mocks. +# ----------------------------------------------------------------------------- +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: ./00-app-sync.sh +timeout: 30 \ No newline at end of file diff --git a/tests/component-tests/promotion/01-git-commit/00-assert.yaml b/tests/component-tests/promotion/01-git-commit/00-assert.yaml new file mode 100644 index 00000000..81fb3f2c --- /dev/null +++ b/tests/component-tests/promotion/01-git-commit/00-assert.yaml @@ -0,0 +1,27 @@ +# ----------------------------------------------------------------------------- +# 00-assert.yaml - KUTTL TestAssert for git-commit workflow status +# +# This TestAssert script checks the status of the workflow created by the +# git-commit test in the Codefresh GitOps Operator component tests. +# +# Usage: +# This assertion is executed as part of the KUTTL test suite. +# +# Steps performed: +# - Queries the workflow status for the specific release. +# - Asserts that the workflow status is 'Succeeded'. +# ----------------------------------------------------------------------------- +--- +apiVersion: kuttl.dev/v1beta1 +commands: + - script: > + STATUS="$(kubectl get workflow -n codefresh -l codefresh.io/release=684040897b3903d3764e1f73 -o jsonpath="{.items[*].status.phase}")" + + if [ $STATUS = 'Succeeded' ]; then + echo "workflow status for release '684040897b3903d3764e1f73' has succeeded" + else + echo "workflow status ($STATUS) for release '684040897b3903d3764e1f73' should be succeeded" + exit 1 + fi +kind: TestAssert +timeout: 240 \ No newline at end of file diff --git a/tests/component-tests/promotion/01-git-commit/01-app-promote.json b/tests/component-tests/promotion/01-git-commit/01-app-promote.json new file mode 100755 index 00000000..275beeba --- /dev/null +++ b/tests/component-tests/promotion/01-git-commit/01-app-promote.json @@ -0,0 +1,163 @@ +[ + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\nquery productReleaseTasks {\n\tproductReleaseTasks {\n\t\ttype\n\t\tlabels\n\t\tcommitInfo {\n\t\t\tsha\n\t\t\tcommitter\n\t\t\tdate\n\t\t\tmessage\n\t\t}\n\t\tappNamespace\n\t\tappName\n\t\trepoUrl\n\t\tbranch\n\t\tpath\n\t\tpostActionOnly\n\t\tpreAction\n\t\tactionUrl\n\t\tactionBody\n\t\tpostAction\n\t\tworkflowNamespace\n\t\tworkflowName\n\t}\n}", + "variables": {} + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "productReleaseTasks": [ + { + "type": "CreateProductReleaseTask", + "labels": { + "codefresh.io/product": "simple", + "codefresh.io/env": "prod", + "codefresh.io/release": "68218f613623801deee005c0", + "codefresh.io/promotion-flow": "test", + "codefresh.io/app-name": "simple-prod", + "codefresh.io/app-namespace": "codefresh", + "codefresh.io/release-name": "f8646c7d0" + }, + "commitInfo": { + "sha": "source-commit-sha", + "committer": "testowner ", + "date": "2025-05-12T05:49:00Z", + "message": "Update values.yaml" + }, + "appNamespace": "codefresh", + "appName": "simple-prod", + "repoUrl": "http://gitea-http.gitea:3000/test-owner/simple-app.git", + "branch": "master", + "path": ".", + "postActionOnly": false, + "preAction": null, + "actionUrl": "/api/promotions/commit", + "actionBody": "{\"srcAppId\":{\"runtime\":\"test-runtime\",\"namespace\":\"codefresh\",\"name\":\"simple-dev\"},\"srcAppCommitSha\":\"source-commit-sha\",\"destAppId\":{\"runtime\":\"test-runtime\",\"namespace\":\"codefresh\",\"name\":\"simple-prod\"},\"message\":\"promoting codefresh/simple-dev to codefresh/simple-prod\"}", + "postAction": null, + "workflowNamespace": null, + "workflowName": null + } + ] + } + } + }, + "times": { + "remainingTimes": 1, + "unlimited": false + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\nquery productReleaseRunHooksTasks {\n\tproductReleaseRunHooksTasks {\n\t\ttype\n\t\tlabels\n\t\tworkflowTemplateName\n\t\tworkflowNamespace\n\t\tworkflowName\n\t\tparameters\n\t}\n}", + "variables": {} + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "productReleaseRunHooksTasks": [] + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\nquery productReleaseCommitStatuses {\n\tproductReleaseCommitStatuses {\n\t\tsha\n\t\trepoURL\n\t\tstatus\n\t\tdescription\n\t\tcontext\n\t\ttargetUrl\n\t}\n}", + "variables": {} + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "productReleaseCommitStatuses": [] + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "type": "REGEX", + "regex": ".*createProductRelease.*" + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "labels": { + "aaa": "bbb" + } + } + } + }, + "times": { + "remainingTimes": 1, + "unlimited": false + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "type": "REGEX", + "regex": ".*PromotionData.*" + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "srcApp": { + "metadata": { + "name": "simple-dev", + "cluster": "https://kubernetes.default.svc", + "namespace": "codefresh" + }, + "specSource": { + "repoURL": "http://gitea-http.gitea:3000/test-owner/simple-app.git", + "targetRevision": "dev", + "path": "." + } + }, + "destApp": { + "metadata": { + "name": "simple-prod", + "cluster": "https://kubernetes.default.svc", + "namespace": "codefresh" + }, + "specSource": { + "repoURL": "http://gitea-http.gitea:3000/test-owner/simple-app.git", + "targetRevision": "HEAD", + "path": "." + } + }, + "promotionTemplate": { + "promotion": [], + "versionSource": { + "file": "", + "jsonPath": "" + } + } + } + } + } + } +] \ No newline at end of file diff --git a/tests/component-tests/promotion/01-git-commit/01-app-promote.sh b/tests/component-tests/promotion/01-git-commit/01-app-promote.sh new file mode 100755 index 00000000..630f7e98 --- /dev/null +++ b/tests/component-tests/promotion/01-git-commit/01-app-promote.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# ----------------------------------------------------------------------------- +# 01-app-promote.sh - Loads app promotion mock expectations for component tests +# +# This script loads mock expectations into the Mockserver for the app promotion +# scenario in the Codefresh GitOps Operator component test suite. +# +# Usage: +# ./01-app-promote.sh +# +# Steps performed: +# - Loads the app promotion mock expectations from 01-app-promote.json into Mockserver. +# ----------------------------------------------------------------------------- +curl -i -X PUT http://127.0.0.1:1080/mockserver/expectation --data-binary "@../../promotion/01-git-commit/01-app-promote.json" diff --git a/tests/component-tests/promotion/01-git-commit/01-app-promote.yaml b/tests/component-tests/promotion/01-git-commit/01-app-promote.yaml new file mode 100644 index 00000000..1ef245b1 --- /dev/null +++ b/tests/component-tests/promotion/01-git-commit/01-app-promote.yaml @@ -0,0 +1,18 @@ +# ----------------------------------------------------------------------------- +# 01-app-promote.yaml - KUTTL TestStep for app promotion mock setup +# +# This TestStep runs the 01-app-promote.sh script to load app promotion mock +# expectations into Mockserver for the Codefresh GitOps Operator component tests. +# +# Usage: +# This step is executed as part of the KUTTL test suite. +# +# Steps performed: +# - Executes the 01-app-promote.sh script to configure Mockserver with promotion mocks. +# ----------------------------------------------------------------------------- +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: ./01-app-promote.sh +timeout: 30 \ No newline at end of file diff --git a/tests/component-tests/promotion/01-git-commit/01-assert.yaml b/tests/component-tests/promotion/01-git-commit/01-assert.yaml new file mode 100644 index 00000000..ac925951 --- /dev/null +++ b/tests/component-tests/promotion/01-git-commit/01-assert.yaml @@ -0,0 +1,27 @@ +# ----------------------------------------------------------------------------- +# 01-assert.yaml - KUTTL TestAssert for app promotion workflow status +# +# This TestAssert script checks the status of the workflow created by the +# app promotion test in the Codefresh GitOps Operator component tests. +# +# Usage: +# This assertion is executed as part of the KUTTL test suite. +# +# Steps performed: +# - Queries the workflow status for the specific release. +# - Asserts that the workflow status is 'Succeeded'. +# ----------------------------------------------------------------------------- +--- +apiVersion: kuttl.dev/v1beta1 +commands: + - script: > + STATUS="$(kubectl get workflow -n codefresh -l codefresh.io/release=68218f613623801deee005c0 -o jsonpath="{.items[*].status.phase}")" + + if [ $STATUS = 'Succeeded' ]; then + echo "workflow status for release '68218f613623801deee005c0' has succeeded" + else + echo "workflow status ($STATUS) for release '68218f613623801deee005c0' should be succeeded" + exit 1 + fi +kind: TestAssert +timeout: 240 \ No newline at end of file diff --git a/tests/component-tests/setup/fixture/applications/simple-dev.yaml b/tests/component-tests/setup/fixture/applications/simple-dev.yaml new file mode 100644 index 00000000..c2acaf27 --- /dev/null +++ b/tests/component-tests/setup/fixture/applications/simple-dev.yaml @@ -0,0 +1,32 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: simple-dev + namespace: codefresh + finalizers: + - resources-finalizer.argocd.argoproj.io/foreground + annotations: + codefresh.io/product: simple-app +spec: + project: default + destination: + name: in-cluster + namespace: dev + source: + path: . + repoURL: http://gitea-http.gitea:3000/test-owner/simple-app.git + targetRevision: dev + syncPolicy: + automated: + prune: true + selfHeal: true + allowEmpty: true + syncOptions: + - PrunePropagationPolicy=foreground + - Replace=false + - PruneLast=false + - Validate=true + - CreateNamespace=true + - ApplyOutOfSyncOnly=false + - ServerSideApply=true + - RespectIgnoreDifferences=false \ No newline at end of file diff --git a/tests/component-tests/setup/fixture/applications/simple-prod.yaml b/tests/component-tests/setup/fixture/applications/simple-prod.yaml new file mode 100644 index 00000000..3e72fbaf --- /dev/null +++ b/tests/component-tests/setup/fixture/applications/simple-prod.yaml @@ -0,0 +1,32 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: simple-prod + namespace: codefresh + finalizers: + - resources-finalizer.argocd.argoproj.io/foreground + annotations: + codefresh.io/product: simple-app +spec: + project: default + destination: + name: in-cluster + namespace: prod + source: + path: . + repoURL: http://gitea-http.gitea:3000/test-owner/simple-app.git + targetRevision: HEAD + syncPolicy: + automated: + prune: true + selfHeal: true + allowEmpty: true + syncOptions: + - PrunePropagationPolicy=foreground + - Replace=false + - PruneLast=false + - Validate=true + - CreateNamespace=true + - ApplyOutOfSyncOnly=false + - ServerSideApply=true + - RespectIgnoreDifferences=false \ No newline at end of file diff --git a/tests/component-tests/setup/fixture/codefresh-isc/README.md b/tests/component-tests/setup/fixture/codefresh-isc/README.md new file mode 100644 index 00000000..a00d6d8f --- /dev/null +++ b/tests/component-tests/setup/fixture/codefresh-isc/README.md @@ -0,0 +1,2 @@ +# codefresh-isc +Codefresh Internal Shared Configurations diff --git a/tests/component-tests/setup/fixture/codefresh-isc/git-sources/my-runtime/default/README.md b/tests/component-tests/setup/fixture/codefresh-isc/git-sources/my-runtime/default/README.md new file mode 100644 index 00000000..324dee18 --- /dev/null +++ b/tests/component-tests/setup/fixture/codefresh-isc/git-sources/my-runtime/default/README.md @@ -0,0 +1,22 @@ +# codefresh-runtime-applications + +This repository was created as part of the default Git Source added to your Codefresh Runtime. + +Git Sources are how The Codefresh GitOps Platform syncs Kubernetes Resource Definitions from Git to your Clusters. + +### Resources Definitions that should be stored in this Git Source +- CD + - Argo CD Applications + - Argo CD Projects + - Argo CD Application Sets +- Pipelines + - Workflow Templates + - Cluster Templates + - Sensors + - Event Sources + +### Application resources should not be stored in a Git Source, such as: +- Deployments +- Services +- Secrets +- Roles diff --git a/tests/component-tests/setup/fixture/codefresh-isc/resources/DUMMY b/tests/component-tests/setup/fixture/codefresh-isc/resources/DUMMY new file mode 100644 index 00000000..e69de29b diff --git a/tests/component-tests/setup/fixture/codefresh-isc/resources/test-runtime/image-source.yaml b/tests/component-tests/setup/fixture/codefresh-isc/resources/test-runtime/image-source.yaml new file mode 100644 index 00000000..24362fa9 --- /dev/null +++ b/tests/component-tests/setup/fixture/codefresh-isc/resources/test-runtime/image-source.yaml @@ -0,0 +1,27 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: image-source + labels: + codefresh.io/entity: 'git-source' + codefresh.io/internal: 'false' + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: cf-git-sources + sources: + - repoURL: https://github.com/test-owner/main-source.git + path: . + targetRevision: HEAD + directory: + include: '*' + exclude: '' + recurse: true + destination: + namespace: codefresh + server: https://kubernetes.default.svc + syncPolicy: + automated: + allowEmpty: true + prune: true + selfHeal: true diff --git a/tests/component-tests/setup/fixture/codefresh-isc/resources/test-runtime/old-source.yaml b/tests/component-tests/setup/fixture/codefresh-isc/resources/test-runtime/old-source.yaml new file mode 100644 index 00000000..e4d4cf0c --- /dev/null +++ b/tests/component-tests/setup/fixture/codefresh-isc/resources/test-runtime/old-source.yaml @@ -0,0 +1,27 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: old-source + labels: + codefresh.io/entity: 'git-source' + codefresh.io/internal: 'false' + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: cf-git-sources + sources: + - repoURL: https://github.com/test-owner/main-source.git + path: . + targetRevision: main + directory: + include: '*' + exclude: '' + recurse: true + destination: + namespace: codefresh + server: https://kubernetes.default.svc + syncPolicy: + automated: + allowEmpty: true + prune: true + selfHeal: true diff --git a/tests/component-tests/setup/fixture/codefresh-isc/runtimes/test-runtime/in-cluster.yaml b/tests/component-tests/setup/fixture/codefresh-isc/runtimes/test-runtime/in-cluster.yaml new file mode 100644 index 00000000..5c8df76a --- /dev/null +++ b/tests/component-tests/setup/fixture/codefresh-isc/runtimes/test-runtime/in-cluster.yaml @@ -0,0 +1,29 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + finalizers: + - resources-finalizer.argocd.argoproj.io + labels: + codefresh.io/entity: internal-config + codefresh.io/internal: 'true' + name: in-cluster +spec: + destination: + namespace: codefresh + server: https://kubernetes.default.svc + project: default + source: + directory: + include: >- + {all-runtimes-all-clusters/**/*.yaml,all-runtimes-all-clusters/*.yaml,configurations/**/*.yaml,control-planes/**/*.yaml,control-planes/*.yaml,test-runtime/image-source.yaml,test-runtime/old-source.yaml,runtimes/test-runtime/**/*.yaml,runtimes/test-runtime/*.yaml} + recurse: true + path: resources + repoURL: http://gitea-http.gitea:3000/test-owner/codefresh-isc.git + targetRevision: HEAD + syncPolicy: + automated: + allowEmpty: true + prune: true + selfHeal: true + syncOptions: + - allowEmpty=true diff --git a/tests/component-tests/setup/fixture/payloads/create-repo-isc.json b/tests/component-tests/setup/fixture/payloads/create-repo-isc.json new file mode 100644 index 00000000..a83457e0 --- /dev/null +++ b/tests/component-tests/setup/fixture/payloads/create-repo-isc.json @@ -0,0 +1,6 @@ +{ + "name": "codefresh-isc", + "description": "Created via API", + "private": false, + "auto_init": true +} \ No newline at end of file diff --git a/tests/component-tests/setup/fixture/payloads/create-repo-simple-app.json b/tests/component-tests/setup/fixture/payloads/create-repo-simple-app.json new file mode 100644 index 00000000..ffce7741 --- /dev/null +++ b/tests/component-tests/setup/fixture/payloads/create-repo-simple-app.json @@ -0,0 +1,6 @@ +{ + "name": "simple-app", + "description": "Created via API", + "private": false, + "auto_init": true +} \ No newline at end of file diff --git a/tests/component-tests/setup/fixture/payloads/create-user-token.json b/tests/component-tests/setup/fixture/payloads/create-user-token.json new file mode 100644 index 00000000..c30b830b --- /dev/null +++ b/tests/component-tests/setup/fixture/payloads/create-user-token.json @@ -0,0 +1,13 @@ +{ + "name": "write_token", + "scopes": [ + "write:activitypub", + "write:issue", + "write:misc", + "write:notification", + "write:organization", + "write:package", + "write:repository", + "write:user" + ] +} \ No newline at end of file diff --git a/tests/component-tests/setup/fixture/payloads/create-user.json b/tests/component-tests/setup/fixture/payloads/create-user.json new file mode 100644 index 00000000..cfaacb41 --- /dev/null +++ b/tests/component-tests/setup/fixture/payloads/create-user.json @@ -0,0 +1,9 @@ +{ + "email": "test.owner@gmail.com", + "full_name": "New User", + "login_name": "test-owner", + "username": "test-owner", + "password": "password", + "must_change_password": false, + "send_notify": true +} \ No newline at end of file diff --git a/tests/component-tests/setup/fixture/simple-app/Chart.yaml b/tests/component-tests/setup/fixture/simple-app/Chart.yaml new file mode 100644 index 00000000..93120133 --- /dev/null +++ b/tests/component-tests/setup/fixture/simple-app/Chart.yaml @@ -0,0 +1,21 @@ +apiVersion: v2 +name: simple-app +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: 1.16.2 diff --git a/tests/component-tests/setup/fixture/simple-app/README.md b/tests/component-tests/setup/fixture/simple-app/README.md new file mode 100644 index 00000000..9886567b --- /dev/null +++ b/tests/component-tests/setup/fixture/simple-app/README.md @@ -0,0 +1,55 @@ +# simple-app + +![Version: 0.1.1](https://img.shields.io/badge/Version-0.1.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.16.2](https://img.shields.io/badge/AppVersion-1.16.2-informational?style=flat-square) + +A Helm chart for Kubernetes + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| app.command[0] | string | `"/app/echo-server"` | | +| app.config.test_env | string | `"This is test value"` | | +| app.name | string | `"my-app-name"` | | +| app.port | int | `3000` | | +| app.secrets | bool | `false` | | +| app.volumeMounts | list | `[]` | | +| components[0] | string | `"test1"` | | +| fullnameOverride | string | `""` | | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"wang/alpine-go-echo-server"` | | +| image.tag | string | `"latest"` | | +| imagePullSecrets | list | `[]` | | +| ingress.annotations | object | `{}` | | +| ingress.enabled | bool | `false` | | +| ingress.hosts[0].host | string | `"chart-example.local"` | | +| ingress.hosts[0].paths | list | `[]` | | +| ingress.tls | list | `[]` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podSecurityContext | object | `{}` | | +| replicaCount | int | `1` | | +| resources | object | `{}` | | +| securityContext | object | `{}` | | +| service.enabled | bool | `true` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `nil` | | +| sidecar.command[0] | string | `"/app/echo-server"` | | +| sidecar.enabled | bool | `false` | | +| sidecar.image.pullPolicy | string | `"IfNotPresent"` | | +| sidecar.image.repository | string | `"wang/alpine-go-echo-server"` | | +| sidecar.image.tag | float | `0.1` | | +| sidecar.name | string | `"my-app-name-sidecar"` | | +| sidecar.port | int | `3001` | | +| sidecar.resources.limits.cpu | string | `"100m"` | | +| sidecar.resources.limits.memory | string | `"128Mi"` | | +| sidecar.volumeMounts | list | `[]` | | +| tolerations | list | `[]` | | +| volumes | list | `[]` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.12.0](https://github.com/norwoodj/helm-docs/releases/v1.12.0) diff --git a/tests/component-tests/setup/fixture/simple-app/create-regcred.sh b/tests/component-tests/setup/fixture/simple-app/create-regcred.sh new file mode 100644 index 00000000..841c9559 --- /dev/null +++ b/tests/component-tests/setup/fixture/simple-app/create-regcred.sh @@ -0,0 +1 @@ +kubectl create secret docker-registry regcred-demo --docker-server= --docker-username= --docker-password= --docker-email= \ No newline at end of file diff --git a/tests/component-tests/setup/fixture/simple-app/create-secrets.sh b/tests/component-tests/setup/fixture/simple-app/create-secrets.sh new file mode 100755 index 00000000..517b390f --- /dev/null +++ b/tests/component-tests/setup/fixture/simple-app/create-secrets.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +set -ex + +if [ $# -eq 3 ]; then + SECRETS_FILE=$1 + SECRETS_NAMESPACE=$2 + SECRETS_NAME=$3 +else + echo "Usage: $0 " + exit 1 +fi + +kubectl create secret generic $SECRETS_NAME -n $SECRETS_NAMESPACE --from-env-file=$SECRETS_FILE --dry-run -o json > $SECRETS_FILE.json + +kubeseal <$SECRETS_FILE.json >$SECRETS_FILE-secret.json + +rm $SECRETS_FILE.json \ No newline at end of file diff --git a/tests/component-tests/setup/fixture/simple-app/package.sh b/tests/component-tests/setup/fixture/simple-app/package.sh new file mode 100755 index 00000000..ae8b2b1b --- /dev/null +++ b/tests/component-tests/setup/fixture/simple-app/package.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +set -ex + +VERSION=$(grep -e ^version Chart.yaml | cut -d' ' -f 2) + +if [ -z "$(git status --porcelain)" ]; then + helm package . + git checkout 0.1.2 + helm package . + git checkout 0.1.1 + helm package . + git rev-parse --verify --quiet gh-pages && git branch --quiet -D -f gh-pages + git checkout --orphan gh-pages + git reset + helm repo index . --url https://tendant.github.io/simple-app + git add index.yaml simple-app-0.1.1.tgz simple-app-0.1.2.tgz simple-app-$VERSION.tgz + git commit -am "Update release" + git clean -df + git push -f origin gh-pages + git checkout master +else + echo "There is uncommitted change! Exiting without releasing." + exit 1 +fi \ No newline at end of file diff --git a/tests/component-tests/setup/fixture/simple-app/templates/NOTES.txt b/tests/component-tests/setup/fixture/simple-app/templates/NOTES.txt new file mode 100644 index 00000000..34ca7caf --- /dev/null +++ b/tests/component-tests/setup/fixture/simple-app/templates/NOTES.txt @@ -0,0 +1,21 @@ +1. Get the application URL by running these commands to: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "simple-app.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "simple-app.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "simple-app.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "simple-app.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/tests/component-tests/setup/fixture/simple-app/templates/_helpers.tpl b/tests/component-tests/setup/fixture/simple-app/templates/_helpers.tpl new file mode 100644 index 00000000..5f14e2fb --- /dev/null +++ b/tests/component-tests/setup/fixture/simple-app/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "simple-app.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "simple-app.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Values.app.name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "simple-app.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "simple-app.labels" -}} +helm.sh/chart: {{ include "simple-app.chart" . }} +{{ include "simple-app.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "simple-app.selectorLabels" -}} +app.kubernetes.io/name: {{ include "simple-app.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "simple-app.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "simple-app.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/tests/component-tests/setup/fixture/simple-app/templates/configmap.yaml b/tests/component-tests/setup/fixture/simple-app/templates/configmap.yaml new file mode 100644 index 00000000..6cbc290d --- /dev/null +++ b/tests/component-tests/setup/fixture/simple-app/templates/configmap.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-configmap +data: + {{- range $key, $value := .Values.app.config }} + {{ $key | upper }}: "{{ $value }}" + {{- end }} diff --git a/tests/component-tests/setup/fixture/simple-app/templates/deployment.yaml b/tests/component-tests/setup/fixture/simple-app/templates/deployment.yaml new file mode 100644 index 00000000..758b1260 --- /dev/null +++ b/tests/component-tests/setup/fixture/simple-app/templates/deployment.yaml @@ -0,0 +1,110 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "simple-app.fullname" . }} + labels: + {{- include "simple-app.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "simple-app.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + labels: + {{- include "simple-app.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "simple-app.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + envFrom: + - configMapRef: + name: {{ .Release.Name }}-configmap + {{- if .Values.app.secrets }} + - secretRef: + name: {{ .Release.Name }}-secrets + {{- end }} + {{- if .Values.app.command }} + command: + {{- toYaml .Values.app.command | nindent 12 }} + {{- end }} + {{- if .Values.service.enabled }} + ports: + {{- if .Values.app.port }} + - name: http + containerPort: {{ .Values.app.port }} + protocol: TCP + {{- end }} + {{- if .Values.app.ports }} + {{- toYaml .Values.app.ports | nindent 12 }} + {{- end }} + {{- if .Values.app.livenessProbe }} + livenessProbe: + {{- toYaml .Values.app.livenessProbe | nindent 12}} + {{- else }} + livenessProbe: + httpGet: + path: / + port: http + {{- end }} + {{- if .Values.app.readinessProbe }} + readinessProbe: + {{- toYaml .Values.app.readinessProbe | nindent 12}} + {{- else }} + readinessProbe: + httpGet: + path: / + port: http + {{- end }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- if .Values.app.volumeMounts }} + volumeMounts: + {{- toYaml .Values.app.volumeMounts | nindent 12 }} + {{- end }} + {{- if .Values.sidecar.enabled }} + - name: {{ .Values.sidecar.name }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + imagePullPolicy: {{ .Values.sidecar.image.pullPolicy }} + command: + {{- toYaml .Values.sidecar.command | nindent 12 }} + ports: + - name: sidecar-port + containerPort: {{ .Values.sidecar.port }} + protocol: TCP + {{- if .Values.sidecar.volumeMounts }} + volumeMounts: + {{- toYaml .Values.sidecar.volumeMounts | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.sidecar.resources | nindent 12 }} + {{- end }} + {{- if .Values.volumes }} + volumes: + {{- toYaml .Values.volumes | nindent 8}} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/tests/component-tests/setup/fixture/simple-app/templates/ingress.yaml b/tests/component-tests/setup/fixture/simple-app/templates/ingress.yaml new file mode 100644 index 00000000..822333dd --- /dev/null +++ b/tests/component-tests/setup/fixture/simple-app/templates/ingress.yaml @@ -0,0 +1,46 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "simple-app.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress" -}} +apiVersion: networking.k8s.io/v1 +{{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "simple-app.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ . }} + pathType: Prefix + backend: + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- end }} + {{- end }} +{{- end }} diff --git a/tests/component-tests/setup/fixture/simple-app/templates/service.yaml b/tests/component-tests/setup/fixture/simple-app/templates/service.yaml new file mode 100644 index 00000000..def7ae99 --- /dev/null +++ b/tests/component-tests/setup/fixture/simple-app/templates/service.yaml @@ -0,0 +1,22 @@ +{{- if .Values.service.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "simple-app.fullname" . }} + labels: + {{- include "simple-app.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + {{- if .Values.service.port }} + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + {{- end }} + {{- if .Values.service.ports }} + {{- toYaml .Values.service.ports | nindent 4 }} + {{- end }} + selector: + {{- include "simple-app.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/tests/component-tests/setup/fixture/simple-app/templates/serviceaccount.yaml b/tests/component-tests/setup/fixture/simple-app/templates/serviceaccount.yaml new file mode 100644 index 00000000..a45ec628 --- /dev/null +++ b/tests/component-tests/setup/fixture/simple-app/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "simple-app.serviceAccountName" . }} + labels: + {{- include "simple-app.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end -}} diff --git a/tests/component-tests/setup/fixture/simple-app/templates/tests/test-connection.yaml b/tests/component-tests/setup/fixture/simple-app/templates/tests/test-connection.yaml new file mode 100644 index 00000000..aa906a82 --- /dev/null +++ b/tests/component-tests/setup/fixture/simple-app/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "simple-app.fullname" . }}-test-connection" + labels: + {{- include "simple-app.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test-success +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "simple-app.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/tests/component-tests/setup/fixture/simple-app/values.yaml b/tests/component-tests/setup/fixture/simple-app/values.yaml new file mode 100644 index 00000000..c5ca6345 --- /dev/null +++ b/tests/component-tests/setup/fixture/simple-app/values.yaml @@ -0,0 +1,126 @@ +# Default values for simple-app. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 +image: + repository: wang/alpine-go-echo-server + # sed -i -e "s/^\( tag:\).*/\1 $CI_COMMIT_SHA/" ops/values.yaml + tag: latest + pullPolicy: IfNotPresent +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" +components: + - test1 +app: + name: my-app-name + command: + - "/app/echo-server" + port: 3000 + ## Enabled 'ports' If additional ports are needed + # ports: + # - name: port2 + # containerPort: 3002 + # protocol: TCP + # - name: port3 + # containerPort: 3003 + # protocol: UDP + config: + test_env: "This is test value" + secrets: false # To enable secretRef, you need create a secret named as RELEASE-NAME-secrets + # livenessProbe: + # httpGet: + # path: / + # port: http + # readinessProbe: + # httpGet: + # path: / + # port: http + volumeMounts: [] + # - name: demo-data + # mountPath: /mnt/data + # readonly: true +sidecar: + name: my-app-name-sidecar + enabled: false + image: + tag: 0.1 + repository: wang/alpine-go-echo-server + pullPolicy: IfNotPresent + port: 3001 + command: + - "/app/echo-server" + volumeMounts: [] + resources: + limits: + cpu: 100m + memory: 128Mi +volumes: [] +# - name: demo-data +# secret: +# secretName: demo-secrets + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: +podSecurityContext: {} +# fsGroup: 2000 + +securityContext: {} +# capabilities: +# drop: +# - ALL +# readOnlyRootFilesystem: true +# runAsNonRoot: true +# runAsUser: 1000 + +service: + enabled: true + type: ClusterIP + port: 80 + ## Enable 'ports', if additional ports are needed + # ports: + # - name: port2 + # port: 3002 + # targetPort: port2 + # protocol: TCP + # - name: port3 + # port: 3003 + # targetPort: port3 + # protocol: UDP +ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # cert-manager.io/cluster-issuer: letsencrypt-production + hosts: + - host: chart-example.local + paths: [] + # - / + # - /index.html + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local +resources: {} +# We usually recommend not to specify default resources and to leave this as a conscious +# choice for the user. This also increases chances charts run on environments with little +# resources, such as Minikube. If you do want to specify resources, uncomment the following +# lines, adjust them as necessary, and remove the curly braces after 'resources:'. +# limits: +# cpu: 100m +# memory: 128Mi +# requests: +# cpu: 100m +# memory: 128Mi + +nodeSelector: {} +tolerations: [] +affinity: {} diff --git a/tests/component-tests/setup/mocks/gitea-mocks.json b/tests/component-tests/setup/mocks/gitea-mocks.json new file mode 100644 index 00000000..a221502d --- /dev/null +++ b/tests/component-tests/setup/mocks/gitea-mocks.json @@ -0,0 +1,44 @@ +[ + { + "httpRequest": { + "method": "GET", + "path": "/api/v3/repos/test-owner/simple-app" + }, + "httpResponse": { + "statusCode": 200, + "body": { + "id": "1234", + "clone_url": "http://gitea-http.gitea:3000/test-owner/simple-app.git", + "default_branch": "main" + } + } + }, + { + "httpRequest": { + "method": "GET", + "path": "/api/v3/repos/test-owner/codefresh-isc" + }, + "httpResponse": { + "statusCode": 200, + "body": { + "id": "1234", + "clone_url": "http://gitea-http.gitea:3000/test-owner/codefresh-isc.git", + "default_branch": "main" + } + } + }, + { + "httpRequest": { + "method": "GET", + "path": "/api/v3/user" + }, + "httpResponse": { + "statusCode": 200, + "body": { + "id": "1234", + "login": "test-owner", + "email": "test.owner@gmail.com" + } + } + } +] \ No newline at end of file diff --git a/tests/component-tests/setup/mocks/platform-mocks.json b/tests/component-tests/setup/mocks/platform-mocks.json new file mode 100644 index 00000000..26b4da51 --- /dev/null +++ b/tests/component-tests/setup/mocks/platform-mocks.json @@ -0,0 +1,366 @@ +[ + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\n mutation CreateRuntime($installationArgs: RuntimeInstallationArgs!) {\n createRuntime(installationArgs: $installationArgs) {\n newAccessToken\n }\n }\n", + "variables": { + "installationArgs": { + "runtimeName": "test-runtime", + "runtimeNamespace": "codefresh", + "componentNames": [], + "isExternalArgoCd": false, + "chartVersion": "0.19.0", + "cluster": "https://kubernetes.default.svc", + "ingressClass": "nginx", + "ingressController": "nginx", + "ingressHost": "http://host.docker.internal:8080", + "installationType": "HELM", + "managed": false, + "runtimeVersion": "0.1.71" + } + } + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "createRuntime": { + "newAccessToken": "aaaaaaaaaaaaaaa.bbbbbbbbbbbbbbb" + } + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "type": "REGEX", + "regex": "\\{\\s*\"query\"\\s*:\\s*\".*saveSealingKey.*\",\\s*\"variables\"\\s*:\\s*\\{\\s*\"privateKey\"\\s*:\\s*\".*\"\\s*\\}\\s*\\}" + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "saveSealingKey": "68161a545a284d2ec56e9d1a" + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\n query {\n productComponentsList(filters: { hasPendingPullRequests: true }) {\n id\n pendingPullRequests {\n repo\n id\n }\n }\n }\n" + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "productComponentsList": [] + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\n query Applications($pagination: SlicePaginationArgs!, $filters: ApplicationsFilterArgs) {\n response: applications(pagination: $pagination, filters: $filters) {\n edges {\n node {\n metadata {\n name\n namespace\n runtime\n account\n }\n }\n }\n }\n }\n", + "variables": { + "filters": { + "inactive": true, + "includeComponents": true + }, + "pagination": { + "first": 50 + } + } + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "response": { + "edges": [], + "pageInfo": { + "startCursor": null, + "endCursor": null, + "hasNextPage": false, + "hasPrevPage": false + } + } + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "type": "JSON_SCHEMA", + "jsonSchema": { + "type": "object", + "properties": { + "query": { + "type": "string", + "pattern": "query getSealingKey\\(\\$id: String!\\) \\{[\\s\\S]*getSealingKey" + }, + "variables": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "required": [ + "id" + ] + } + }, + "required": [ + "query", + "variables" + ] + } + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "getSealingKey": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKSndJQkFBS0NBZ0VBb3dYZTFUaldIR1dQQS9zV3FnSmVJSDc5VytBbEdENWJUNkoxanZOVGoyenRSZ2pXClVTeTdZMDNSRGdjZkdNQlRQUzBDdWkxNWlSTUhCNjR3UzNZTEk1eEllOENOY0l2K0taK2RsZ1kyWEE3SVJwREIKZVFabGNwaTdjamcvSEZDbnZiWW5tb0Nja0hJdEpnZHd0Nkl5OFA2Qm0yMVVNUjVXR1VzOXlhTDU5Y28zMVFuTApUeVh5Y1BWOTI0QTdLZkVzdEo4R3F2S0VtUVZFdnFIdFcyeEtkOXNTUDg5ZXpvK3g2WExKaGFVZ002U1JtMzczCndVcjh5d21kOTlrQ0lJVXRjVmRPOTdSZHkzRkpPeUswVmQzb0lMNWZVaXZkV2pQTnFjQjFxSUdCQ3VnbkVFS1IKdTE3TUx2bEtRRkQwKzZ6VGJUSG9iL0pZN0NzMXVXUlBFZGNtOWhWc2lCQTYwN2FIejlCOEtyUnhKT041c2NkZAorc0lnRVlBWjIxZllkVjArVnhYQm9xa3hwYWd1bHExMTd5ZWl5K2FNcmh3VkRyWkx2Tjh0YmtyaitVemhIcThTCjNaYWROdWE4MkRQdzFvSzhnMThPRGVWbVIzcUtuT3hmaUtJWm1kNXhGRzJiUFdCUWtkbUExdkphZGtWdnh5U0YKakJyM1NVREIzNjZ6TERHOElSbzQrWkM5c2dSanlaL2FqTTNkaWhEOFFkU1pBai9oRmZ5Q3FkRjZYWCt3Yk1PRgpDOWhQZDZVa2pFSEZNRHBkNm5MRi9GTENaY2xZSEg3WTMxK3ZsUEE5c3l3eGpLTDlyRmNielhVV3c2RTdnMmN3Cnh4cnpXYkRkT0xtMUpLRjY5NU5EcllNQS8zMjlaVmJOMDZXV0JwTHhkbVlHRU9OWllkRHhWVVJKelVNQ0F3RUEKQVFLQ0FnQW16MVQzU2VxZkpBWmlHanFSQ3JOQjVUbUh6OXJFNU1OME4rYm91MERmV2owNmVRd2NreHVoVG50QQpiYTJYaE9ITUpKVUxvWnZYYURJNlA5dTdlMFMzbTVNZDh2ODVGZnJTQ2UvSU1YNXJlQkZ4eXpCa0VZUEJQbDhSCm1CWmVOVTFadXEyKytITk5hQUVibHBYZEFiNUM1VFFSdm50V25qUTlIVTUrWEZCSmxYU3BRUVdudUE3NW1WZjMKRTVZQ0xDcEtiYmwycFBtd1BETGJkMDA4Z0pGUjYxTnk0WGxlajVMNVVweHJOcDV0N1BYRklQcjJoMVdiT0pUawoxa0xOWHljc1htNnNSY0kybHFlcWJsNmtPb255a1orN3ZqbWFLYzhDWkpFZUpvYUVCRFNZaUdDTlRNb3JQS25TCm1mTllueEpPWXAxRldWcVdEc3RoY1dIcGkyRDR2MkdYaTQ0UnZ2UE1kME9EVDdrVFlFWFc0YlFsQURlVkZjUDIKcjcrOGJDWWZFd0dReG9xRVpsbjdnb0ZsbGd5RVl0RmcyMGRSR2pKVzFxVDI4b21CU0UvMHI4d3lvaGxJQ25XVgowWVJrS01ld1M1VjdXUndnVzNjL3pOa0M5c082VlhZSm82UmRVUWgyVFpDRHROcUZOUmk5ZHIvTnNFcG0zb0ZmCkJUNVRUSW5YQWM5RTJXOVBFUEVic2Z5Y3BacThJcFNuSnNKck9qbW9taTBmalBoMDBvbFYvVVVXdWZ5UDBibzkKcEh3L2tMR3JrOGFzNmlIdE5ITyt6eTl0TEhtcWhKbFY1aEU0azJjNUs0Q1Nqbnh4WlBZTFVkTldMV1NvM2NSbwovMmtvVUhacjRhVWhmVmMxTXFrY2pNZ1RUeEhNNnFxTGRDQXF1dGNqOU1pemJVV0pZUUtDQVFFQTBRQVExMVJvCm1qUGlaZjU5VG1oWHJrOWduSkJGWjJpMk1JdXlBVitFZHc5SFJWRVR6ZjY2S0hHZDFudzJjTGYxaWVVOXRrRzAKeHRHdlFGc1Y1SXRaVzhOMDhjemRQTXNEd0tGNmN1bFJBemhFU2ZxQ3BLek5xaDQ0MFNGaWlqSURYR0hxMTJ6bwplRGNhZjVkL0ZmS1daMUx4c1JFMlhRMFl3Lyt1U1" + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\n query GitSources($pagination: SlicePaginationArgs, $project: String, $runtime: String) {\n response: gitSources(pagination: $pagination, project: $project, runtime: $runtime) {\n edges {\n node {\n metadata {\n account\n runtime\n group\n version\n kind\n name\n namespace\n }\n self {\n repoURL\n path\n revision\n }\n permissions {\n userId\n read\n write\n }\n }\n }\n pageInfo {\n startCursor\n endCursor\n hasNextPage\n hasPrevPage\n }\n }\n }\n", + "variables": { + "runtime": "test-runtime" + } + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "response": { + "edges": [], + "pageInfo": { + "startCursor": null, + "endCursor": null, + "hasNextPage": false, + "hasPrevPage": false + } + } + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\n query me {\n me {\n runtimeName\n activeAccount {\n id\n name\n gitProvider\n gitApiUrl\n sharedConfigRepo\n }\n }\n }\n" + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "me": { + "runtimeName": "test-runtime", + "activeAccount": { + "id": "6791f6184c56bd51c65784a2", + "name": "local", + "gitProvider": "GITHUB", + "gitApiUrl": "http://mockserver.mockserver:1080", + "sharedConfigRepo": "http://gitea-http.gitea:3000/test-owner/codefresh-isc" + } + } + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\n query Runtime($name: String!) {\n runtime(name: $name) {\n metadata {\n account\n namespace\n }\n installationStatus\n installationType\n ingressHost\n runtimeVersion\n }\n }\n", + "variables": { + "name": "test-runtime" + } + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "runtime": { + "metadata": { + "account": "6791f6184c56bd51c65784a2", + "namespace": "codefresh" + }, + "installationStatus": "IN_PROGRESS", + "installationType": "HELM", + "ingressHost": "http://host.docker.internal:8080", + "runtimeVersion": "0.1.71" + } + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "type": "REGEX", + "regex": "\\{\\s*\"query\"\\s*:\\s*\".*shouldBeImplicitConfigurationRuntime.*\"\\s*\\}" + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "shouldBeImplicitConfigurationRuntime": false + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "type": "REGEX", + "regex": "\\{\\s*\"query\"\\s*:\\s*\".*updateRuntimeClusters.*\",\\s*\"variables\"\\s*:\\s*\\{\\s*\"clusters\"\\s*:\\s*\\[.*\\]\\s*\\}\\s*\\}" + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "runtime": { + "metadata": { + "account": "6791f6184c56bd51c65784a2", + "namespace": "codefresh" + }, + "installationStatus": "COMPLETED", + "installationType": "HELM", + "ingressHost": "http://host.docker.internal:8080", + "runtimeVersion": "0.1.71" + } + } + } + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/api/argo-runtime", + "body": { + "name": "test-runtime" + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "token": "example-runtime-token" + } + } + }, + { + "httpRequest": { + "method": "GET", + "path": "/api/argo-runtime/test-runtime/storeKey" + }, + "httpResponse": { + "statusCode": 200, + "body": { + "storeKey": "example-runtime-token" + } + } + }, + { + "httpRequest": { + "method": "GET", + "path": "/api/ping" + }, + "httpResponse": { + "statusCode": 200 + } + }, + { + "httpRequest": { + "method": "POST", + "path": "/2.0/api/graphql", + "body": { + "query": "\\n query PromotionData(\\n $srcRuntime: String!\\n $srcNamespace: String!\\n $srcName: String!\\n $destRuntime: String!\\n $destNamespace: String!\\n $destName: String!\\n ) {\\n srcApp: application(runtime: $srcRuntime, namespace: $srcNamespace, name: $srcName) {\\n metadata {\\n name\\n cluster\\n namespace\\n }\\n specSource {\\n repoURL\\n targetRevision\\n path\\n }\\n }\\n destApp: application(runtime: $destRuntime, namespace: $destNamespace, name: $destName) {\\n metadata {\\n name\\n cluster\\n namespace\\n }\\n specSource {\\n repoURL\\n targetRevision\\n path\\n }\\n }\\n promotionTemplate(runtime: $destRuntime, namespace: $destNamespace, name: $destName) {\\n promotion {\\n glob\\n jsonPaths\\n }\\n versionSource {\\n file\\n jsonPath\\n }\\n }\\n }\\n", + "variables": { + "srcRuntime": "test-runtime", + "srcNamespace": "codefresh", + "srcName": "simple-dev", + "destRuntime": "test-runtime", + "destNamespace": "codefresh", + "destName": "simple-prod" + } + } + }, + "httpResponse": { + "statusCode": 200, + "body": { + "data": { + "srcApp": { + "metadata": { + "name": "simple-dev", + "cluster": "https://kubernetes.default.svc", + "namespace": "codefresh" + }, + "specSource": { + "repoURL": "http://gitea-http.gitea:3000/test-owner/simple-app.git", + "targetRevision": "dev", + "path": "." + } + }, + "destApp": { + "metadata": { + "name": "simple-prod", + "cluster": "https://kubernetes.default.svc", + "namespace": "codefresh" + }, + "specSource": { + "repoURL": "http://gitea-http.gitea:3000/test-owner/simple-app.git", + "targetRevision": "HEAD", + "path": "." + } + }, + "promotionTemplate": { + "promotion": [], + "versionSource": { + "file": "", + "jsonPath": "" + } + } + } + } + } + } +] diff --git a/tests/component-tests/setup/scripts/cleanup.sh b/tests/component-tests/setup/scripts/cleanup.sh new file mode 100755 index 00000000..e23f9574 --- /dev/null +++ b/tests/component-tests/setup/scripts/cleanup.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# ----------------------------------------------------------------------------- +# cleanup.sh - Cleans up test repositories and restores test fixture files +# +# This script is used in the Codefresh GitOps Operator component test suite to: +# - Remove cloned test repositories. +# - Restore the runtime values and mock expectation JSON files to their original state. +# +# Usage: +# ./cleanup.sh +# +# Steps performed: +# - Deletes the codefresh-isc and simple-app directories. +# - Restores runtime.values.yaml and mock JSON files to their initial state using git. +# ----------------------------------------------------------------------------- +rm -rf ./test/component-tests/setup/codefresh-isc +rm -rf ./test/component-tests/setup/simple-app +git restore ./test/component-tests/setup/values/runtime.values.yaml +git restore ./test/component-tests/promotion/01-git-commit/00-app-sync.json +git restore ./test/component-tests/promotion/01-git-commit/01-app-promote.json \ No newline at end of file diff --git a/tests/component-tests/setup/scripts/helm-deps.sh b/tests/component-tests/setup/scripts/helm-deps.sh new file mode 100755 index 00000000..3e9f3c74 --- /dev/null +++ b/tests/component-tests/setup/scripts/helm-deps.sh @@ -0,0 +1,4 @@ +#!/bin/bash +cd ../../charts/gitops-runtime +helm dependency update +cd ../../ \ No newline at end of file diff --git a/tests/component-tests/setup/scripts/init-gitea.sh b/tests/component-tests/setup/scripts/init-gitea.sh new file mode 100755 index 00000000..ca7b9925 --- /dev/null +++ b/tests/component-tests/setup/scripts/init-gitea.sh @@ -0,0 +1,99 @@ +#!/bin/bash +#----------------------------------------------------------------------------- +# init-gitea.sh - Initializes Gitea server and repositories for component tests +# +# This script automates the setup of a Gitea test environment for the Codefresh +# GitOps Operator component test suite. It creates a test user, generates a user +# token, updates the runtime values file with the token, creates test repositories, +# and pushes initial commits and branches. +# +# Usage: +# ./init-gitea.sh +# +# Steps performed: +# - Port-forwards the Gitea service to localhost:3000. +# - Creates a test user via the Gitea API. +# - Generates a user token and updates runtime.values.yaml. +# - Creates 'isc' and 'simple-app' repositories. +# - Clones, configures, and pushes initial commits to the repositories. +# - Creates a 'dev' branch in the simple-app repository and updates values. +# ----------------------------------------------------------------------------- +OS_TYPE=$(uname) +kubectl --namespace gitea port-forward svc/gitea-http 3000:3000 & +sleep 3 +## create repo owner +response=$(curl --location 'http://127.0.0.1:3000/api/v1/admin/users' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Basic Z2l0ZWFfYWRtaW46cjhzQThDUEhEOSFidDZk' \ +--data-binary "@./setup/fixture/payloads/create-user.json") + +owner=$(echo "$response" | jq -r '.login') + +## create user token +response=$(curl --location "http://127.0.0.1:3000/api/v1/users/$owner/tokens" \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Basic dGVzdC1vd25lcjpwYXNzd29yZA==' \ +--data-binary "@./setup/fixture/payloads/create-user-token.json") + +token=$(echo "$response" | jq -r '.sha1') +echo "token: $token" +echo "owner: $pwd" +pwd +if [ "$OS_TYPE" = "Linux" ]; then + sed -i "s/gitea-token/$token/g" ./setup/values/runtime.values.yaml +else + sed -i '' "s/gitea-token/$token/g" ./setup/values/runtime.values.yaml +fi + +## create isc repo +curl --location 'http://127.0.0.1:3000/api/v1/user/repos' \ +--header 'Content-Type: application/json' \ +--header "Authorization: Bearer $token" \ +--data-binary "@./setup/fixture/payloads/create-repo-isc.json" + +## create simple app repo +curl --location 'http://127.0.0.1:3000/api/v1/user/repos' \ +--header 'Content-Type: application/json' \ +--header "Authorization: Bearer $token" \ +--data-binary "@./setup/fixture/payloads/create-repo-simple-app.json" + +## clone simple-app repo and push initial commit +cd ./setup +git clone http://127.0.0.1:3000/$owner/simple-app.git +cd simple-app +git config user.name "test-owner" +git config user.email "test.owner@gmail.com" + +git remote set-url origin http://$owner:$token@127.0.0.1:3000/$owner/simple-app.git +cp -R ./../fixture/simple-app/* . +git add --a +git commit -m "Initial commit" +git push + +## create dev branch +git checkout -b dev +git config user.name "test-owner" +git config user.email "test.owner@gmail.com" +if [ "$OS_TYPE" = "Linux" ]; then + sed -i 's/latest/0.1/g' values.yaml +else + sed -i '' 's/latest/0.1/g' values.yaml +fi +git add --a +git commit -m "update values.yaml" +git push --set-upstream origin dev +cd .. + +## clone codefresh-isc repo and push initial commit +git clone http://127.0.0.1:3000/$owner/codefresh-isc.git +cd codefresh-isc +git remote set-url origin http://$owner:$token@127.0.0.1:3000/$owner/codefresh-isc.git +cp -R ./../fixture/codefresh-isc/* . +git add --a +git commit -m "Initial commit" +git push +cd .. + + + + diff --git a/tests/component-tests/setup/scripts/init-platform.sh b/tests/component-tests/setup/scripts/init-platform.sh new file mode 100755 index 00000000..ff06ae00 --- /dev/null +++ b/tests/component-tests/setup/scripts/init-platform.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# ----------------------------------------------------------------------------- +# init-platform.sh - Initializes platform mocks for component tests +# +# This script sets up mock expectations in the Mockserver for platform and Gitea +# endpoints. It port-forwards the Mockserver service, then loads mock +# expectations from JSON files to simulate platform and Gitea API responses. +# +# Usage: +# ./init-platform.sh +# +# Steps performed: +# - Port-forwards the Mockserver service to localhost:1080. +# - Loads platform and Gitea mock expectations into Mockserver. +# ----------------------------------------------------------------------------- +sleep 2 +kubectl -n mockserver port-forward svc/mockserver 1080:1080 & +sleep 2 +curl -i -X PUT http://127.0.0.1:1080/mockserver/expectation --data-binary "@./setup/mocks/platform-mocks.json" +curl -i -X PUT http://127.0.0.1:1080/mockserver/expectation --data-binary "@./setup/mocks/gitea-mocks.json" diff --git a/tests/component-tests/setup/scripts/init.sh b/tests/component-tests/setup/scripts/init.sh new file mode 100755 index 00000000..f2c67a70 --- /dev/null +++ b/tests/component-tests/setup/scripts/init.sh @@ -0,0 +1,6 @@ +#!/bin/bash +## This script sets up the environment gitea +./setup/scripts/init-gitea.sh + +## This script sets up the environment mockserver +./setup/scripts/init-platform.sh \ No newline at end of file diff --git a/tests/component-tests/setup/values/gitea.values.yaml b/tests/component-tests/setup/values/gitea.values.yaml new file mode 100644 index 00000000..4629621e --- /dev/null +++ b/tests/component-tests/setup/values/gitea.values.yaml @@ -0,0 +1,16 @@ +# ----------------------------------------------------------------------------- +# gitea.values.yaml - Custom Helm values for Gitea in component tests +# +# This file provides custom configuration for deploying Gitea as part of the +# Codefresh GitOps Operator component test suite. It disables the use of +# Redis and PostgreSQL HA, and enables a single PostgreSQL instance. +# +# These values are used by the Helm install command in the test suite to +# ensure a minimal and reliable Gitea setup for testing purposes. +# ----------------------------------------------------------------------------- +redis-cluster: + enabled: false +postgresql-ha: + enabled: false +postgresql: + enabled: true diff --git a/tests/component-tests/setup/values/runtime.values.yaml b/tests/component-tests/setup/values/runtime.values.yaml new file mode 100644 index 00000000..316ebe80 --- /dev/null +++ b/tests/component-tests/setup/values/runtime.values.yaml @@ -0,0 +1,51 @@ +# ----------------------------------------------------------------------------- +# runtime.values.yaml - Custom Helm values for Codefresh GitOps Runtime in component tests +# +# This file provides configuration for deploying the Codefresh GitOps Runtime +# as part of the component test suite. It sets up mock endpoints, disables +# certain features for testing, and configures runtime and networking options +# to ensure a controlled and reproducible test environment. +# +# Key configurations: +# - Sets mock Codefresh and ingress URLs. +# - Disables tunnel client and ingress. +# - Configures internal router and app-proxy for test networking. +# - Sets a unique runtime name and disables validation steps. +# - Uses a test-specific image tag for the gitops-operator. +# +# These values are used by the Helm install command in the test suite. +# ----------------------------------------------------------------------------- +global: + codefresh: + url: "http://mockserver.mockserver:1080" + userToken: + token: "aaaaaaaaaaaaaaa.bbbbbbbbbbbbbbb" + # required if your user has access to multiple accounts + accountId: "6791f6184c56bd51c65784a2" + runtime: + # optional - remove if you have an existing configuration runtime + isConfigurationRuntime: true + name: "test-runtime" # this should be unique to your account + cluster: https://kubernetes.default.svc + codefreshHosted: false + ingressUrl: http://host.docker.internal:8080 # important! + ingress: + enabled: false # important! + gitCredentials: + password: + value: "gitea-token" # optional (you can add it in the ui) +installer: + skipValidation: true + skipUsageValidation: true + +tunnel-client: + enabled: false #important! + +internal-router: + service: + type: NodePort # important + nodePort: 31243 # important - this port matches kind config port above + +app-proxy: + config: + cors: "http://mockserver.mockserver:1080" diff --git a/tests/component-tests/startup.yaml b/tests/component-tests/startup.yaml new file mode 100644 index 00000000..69deeb37 --- /dev/null +++ b/tests/component-tests/startup.yaml @@ -0,0 +1,42 @@ +# ----------------------------------------------------------------------------- +# startup.yaml - KUTTL TestSuite for Codefresh GitOps Operator Component Tests +# +# This TestSuite automates the setup of required services and environments for +# component-level testing of the Codefresh GitOps Operator. It uses Helm and +# kubectl commands to install dependencies, wait for readiness, and patch +# deployments as needed. +# +# Steps performed: +# - Installs Mockserver and waits for it to become available. +# - Installs Gitea with custom values and waits for readiness. +# - Runs initialization scripts in the background. +# - Installs the Codefresh GitOps Runtime via Helm. +# - Patches the gitops-operator deployment to inject the NAMESPACE env var. +# - Waits for cap-app-proxy and gitops-operator deployments to be available. +# - Creates 'dev' and 'prod' namespaces. +# - Applies application fixtures for testing. +# +# Test directories and timeouts are configured at the end of the file. +# ----------------------------------------------------------------------------- +apiVersion: kuttl.dev/v1beta1 +kind: TestSuite +commands: + - command: helm upgrade --install --namespace mockserver --create-namespace --version 5.14.0 --set="service.type=ClusterIP" mockserver mockserver/mockserver + - command: kubectl -n mockserver wait --for=condition=available --timeout=120s deployment/mockserver + - command: helm install gitea gitea-charts/gitea --values ./setup/values/gitea.values.yaml -n gitea --create-namespace + - command: kubectl -n gitea wait --for=condition=available --timeout=180s deployment/gitea + - script: ./setup/scripts/init.sh + background: true + - command: sleep 3 + - command: ./setup/scripts/helm-deps.sh + - command: helm upgrade --install cf-gitops-runtime ../../charts/gitops-runtime --create-namespace --namespace codefresh -f ./setup/values/runtime.values.yaml + - command: > + kubectl patch deployment gitops-operator -n codefresh --type=json -p='[{"op": "add", "path": "/spec/template/spec/containers/0/env/-", "value": {"name": "NAMESPACE", "valueFrom": {"fieldRef": {"fieldPath": "metadata.namespace"}}}}]' + - command: kubectl -n codefresh wait --for=condition=available --timeout=400s deployment/cap-app-proxy + - command: kubectl -n codefresh wait --for=condition=available --timeout=180s deployment/gitops-operator + - command: kubectl create namespace dev + - command: kubectl create namespace prod + - command: kubectl apply -f ./setup/fixture/applications +testDirs: + - promotion +timeout: 300 \ No newline at end of file