diff --git a/.github/workflows/ephemeral.yml b/.github/workflows/ephemeral.yml index d5c459f..5c1997f 100644 --- a/.github/workflows/ephemeral.yml +++ b/.github/workflows/ephemeral.yml @@ -4,274 +4,17 @@ on: pull_request: types: [opened, synchronize, reopened, closed] -env: - REGISTRY: registry.fullstack.pw - IMAGE_NAME: library/cks-backend - VAULT_ADDR: https://vault.fullstack.pw - permissions: contents: write pull-requests: write jobs: - manage-environment: - runs-on: self-hosted - outputs: - dns_name: ${{ steps.cluster-info.outputs.dns_name }} - cluster_name: ${{ steps.cluster-info.outputs.cluster_name }} - deployment_status: ${{ steps.deployment-status.outputs.status }} - steps: - - name: Set cluster info - id: cluster-info - run: | - CLUSTER_NAME="pr-${{ github.event.repository.name }}-${{ github.event.pull_request.number }}" - DNS_NAME="pr-${{ github.event.pull_request.number }}-${{ github.event.repository.name }}.ephemeral.fullstack.pw" - echo "cluster_name=$CLUSTER_NAME" >> $GITHUB_OUTPUT - echo "dns_name=$DNS_NAME" >> $GITHUB_OUTPUT - - - name: Checkout app code - if: github.event.action != 'closed' - uses: actions/checkout@v4 - - - name: Checkout infra repo - uses: actions/checkout@v4 - with: - repository: fullstack-pw/infra - token: ${{ secrets.RUNNER }} - path: infra - - - name: Check if cluster exists - id: check-cluster - run: | - CLUSTER_NAME="${{ steps.cluster-info.outputs.cluster_name }}" - if kubectl get cluster "$CLUSTER_NAME" -n "$CLUSTER_NAME" --context tools --kubeconfig /home/runner/.kube/config &>/dev/null; then - echo "exists=true" >> $GITHUB_OUTPUT - echo "Cluster $CLUSTER_NAME already exists" - else - echo "exists=false" >> $GITHUB_OUTPUT - echo "Cluster $CLUSTER_NAME does not exist" - fi - - # ==================== CREATE/UPDATE ENVIRONMENT ==================== - - name: Check IP pool capacity - if: github.event.action != 'closed' && steps.check-cluster.outputs.exists == 'false' - run: | - cd infra - AVAILABLE=$(./clusters/scripts/ip_pool_manager.sh check-capacity) - CAPACITY_RESULT=$? - echo "Capacity available: $AVAILABLE slots free" - if [ "$CAPACITY_RESULT" -ne 0 ]; then - echo "::error::IP pool exhausted. All 5 ephemeral cluster slots are in use (10 IPs / 2 per cluster). Please close old PRs." - exit 1 - fi - - - name: Allocate IP from pool - if: github.event.action != 'closed' && steps.check-cluster.outputs.exists == 'false' - id: allocate - run: | - cd infra - CLUSTER_NAME="${{ steps.cluster-info.outputs.cluster_name }}" - CLUSTER_IP=$(./clusters/scripts/ip_pool_manager.sh allocate "$CLUSTER_NAME") - - # Calculate node IP (VIP + 1) - each cluster needs 2 IPs - IP_LAST_OCTET=$(echo "$CLUSTER_IP" | cut -d'.' -f4) - NODE_IP_LAST_OCTET=$((IP_LAST_OCTET + 1)) - NODE_IP="192.168.1.${NODE_IP_LAST_OCTET}" - - echo "ip=$CLUSTER_IP" >> $GITHUB_OUTPUT - echo "node_ip=$NODE_IP" >> $GITHUB_OUTPUT - echo "Allocated control plane VIP: $CLUSTER_IP" - echo "Node IP: $NODE_IP" - - - name: Render Cluster API manifest - if: github.event.action != 'closed' && steps.check-cluster.outputs.exists == 'false' - run: | - cd infra - export CLUSTER_NAME="${{ steps.cluster-info.outputs.cluster_name }}" - export CLUSTER_IP="${{ steps.allocate.outputs.ip }}" - export NODE_IP="${{ steps.allocate.outputs.node_ip }}" - export PR_NUMBER="${{ github.event.pull_request.number }}" - export REPOSITORY="${{ github.event.repository.name }}" - envsubst < ephemeral-clusters/cluster-api/k3s-cluster.yaml.tpl > /tmp/cluster.yaml - cat /tmp/cluster.yaml - - - name: Create cluster via Cluster API - if: github.event.action != 'closed' && steps.check-cluster.outputs.exists == 'false' - run: | - kubectl apply -f /tmp/cluster.yaml --context tools --kubeconfig /home/runner/.kube/config - - - name: Copy Proxmox credentials to namespace - if: github.event.action != 'closed' && steps.check-cluster.outputs.exists == 'false' - run: | - CLUSTER_NAME="${{ steps.cluster-info.outputs.cluster_name }}" - kubectl --context tools --kubeconfig /home/runner/.kube/config \ - get secret proxmox-credentials -n k3s-test -o json | \ - jq 'del(.metadata.namespace,.metadata.uid,.metadata.resourceVersion,.metadata.creationTimestamp,.metadata.ownerReferences,.metadata.finalizers)' | \ - kubectl --context tools --kubeconfig /home/runner/.kube/config apply -n "$CLUSTER_NAME" -f - || \ - echo "Warning: Could not copy proxmox-credentials (may already exist)" - - - name: Wait for cluster available - if: github.event.action != 'closed' && steps.check-cluster.outputs.exists == 'false' - run: | - CLUSTER_NAME="${{ steps.cluster-info.outputs.cluster_name }}" - echo "Waiting for cluster $CLUSTER_NAME to be available..." - kubectl wait --for=condition=Available \ - cluster/$CLUSTER_NAME \ - -n $CLUSTER_NAME \ - --timeout=5m --context tools --kubeconfig /home/runner/.kube/config - - - name: Extract kubeconfig - if: github.event.action != 'closed' && steps.check-cluster.outputs.exists == 'false' - run: | - CLUSTER_NAME="${{ steps.cluster-info.outputs.cluster_name }}" - kubectl get secret ${CLUSTER_NAME}-kubeconfig \ - -n $CLUSTER_NAME \ - -o jsonpath='{.data.value}' --context tools --kubeconfig /home/runner/.kube/config | base64 -d > /tmp/kubeconfig - - # Rename context to match workspace name for OpenTofu - ORIGINAL_CONTEXT=$(kubectl --kubeconfig /tmp/kubeconfig config current-context) - kubectl --kubeconfig /tmp/kubeconfig config rename-context "$ORIGINAL_CONTEXT" "$CLUSTER_NAME" - kubectl --kubeconfig /tmp/kubeconfig config use-context "$CLUSTER_NAME" - - - name: Apply ephemeral infrastructure with OpenTofu - if: github.event.action != 'closed' && steps.check-cluster.outputs.exists == 'false' - env: - KUBECONFIG: /tmp/kubeconfig - run: | - cd infra - make ephemeral-init - make ephemeral-apply WORKSPACE=${{ steps.cluster-info.outputs.cluster_name }} MINIMAL=true - - # ==================== BUILD AND DEPLOY (PR opened/updated) ==================== - - - name: Build and push Docker image - id: build - if: github.event.action != 'closed' - run: | - IMAGE_TAG="pr-${{ github.event.pull_request.number }}-${{ github.sha }}" - docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${IMAGE_TAG} . - echo "${HARBOR_KEY}" | docker login ${{ env.REGISTRY }} -u admin --password-stdin - docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${IMAGE_TAG} - echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT - - - name: Extract kubeconfig - if: github.event.action != 'closed' - run: | - CLUSTER_NAME="${{ steps.cluster-info.outputs.cluster_name }}" - kubectl get secret ${CLUSTER_NAME}-kubeconfig \ - -n $CLUSTER_NAME \ - -o jsonpath='{.data.value}' --context tools --kubeconfig /home/runner/.kube/config | base64 -d > /tmp/kubeconfig - - # Rename context to match workspace name for OpenTofu - ORIGINAL_CONTEXT=$(kubectl --kubeconfig /tmp/kubeconfig config current-context) - kubectl --kubeconfig /tmp/kubeconfig config rename-context "$ORIGINAL_CONTEXT" "$CLUSTER_NAME" - kubectl --kubeconfig /tmp/kubeconfig config use-context "$CLUSTER_NAME" - - - name: Deploy to ephemeral cluster - if: github.event.action != 'closed' - env: - KUBECONFIG: /tmp/kubeconfig - run: | - DNS_NAME="${{ steps.cluster-info.outputs.dns_name }}" - IMAGE_TAG="${{ steps.build.outputs.image_tag }}" - - # Render manifests with updated image tag and DNS hostname - kubectl kustomize kustomize/overlays/ephemeral \ - | sed "s|${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:pr-will-be-replaced|${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${IMAGE_TAG}|" \ - | sed "s|dev.api.cks.fullstack.pw|${DNS_NAME}|g" \ - | kubectl apply -f - - - # Wait for deployment rollout - kubectl rollout status deployment/${{ github.event.repository.name }} \ - -n default --timeout=5m - - - name: Set deployment status - id: deployment-status - if: github.event.action != 'closed' - run: echo "status=success" >> $GITHUB_OUTPUT - - - name: Post deployment info - if: github.event.action != 'closed' && steps.check-cluster.outputs.exists == 'false' - uses: actions/github-script@v7 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const dnsName = '${{ steps.cluster-info.outputs.dns_name }}'; - const clusterName = '${{ steps.cluster-info.outputs.cluster_name }}'; - const imageTag = '${{ steps.build.outputs.image_tag }}'; - - const body = `## Ephemeral Environment Ready - - Your ephemeral environment has been deployed! - - **URL**: https://${dnsName} - **Cluster**: \`${clusterName}\` - **Image**: \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${imageTag}\` - - The environment will be automatically destroyed when this PR is closed. - `; - - github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - body: body - }); - - # ==================== CLEANUP ==================== - - name: Get kubeconfig for destruction - if: github.event.action == 'closed' || (failure() && steps.check-cluster.outputs.exists == 'false') - run: | - CLUSTER_NAME="${{ steps.cluster-info.outputs.cluster_name }}" - kubectl get secret ${CLUSTER_NAME}-kubeconfig \ - -n $CLUSTER_NAME \ - -o jsonpath='{.data.value}' --context tools --kubeconfig /home/runner/.kube/config | base64 -d > /tmp/kubeconfig || true - - # Rename context to match workspace name for OpenTofu - if [ -f /tmp/kubeconfig ]; then - ORIGINAL_CONTEXT=$(kubectl --kubeconfig /tmp/kubeconfig config current-context 2>/dev/null || echo "") - if [ -n "$ORIGINAL_CONTEXT" ]; then - kubectl --kubeconfig /tmp/kubeconfig config rename-context "$ORIGINAL_CONTEXT" "$CLUSTER_NAME" 2>/dev/null || true - kubectl --kubeconfig /tmp/kubeconfig config use-context "$CLUSTER_NAME" 2>/dev/null || true - fi - fi - - - name: Destroy ephemeral infrastructure - if: github.event.action == 'closed' || (failure() && steps.check-cluster.outputs.exists == 'false') - env: - KUBECONFIG: /tmp/kubeconfig - run: | - cd infra - CLUSTER_NAME="${{ steps.cluster-info.outputs.cluster_name }}" - - make ephemeral-init - make ephemeral-destroy WORKSPACE=${{ steps.cluster-info.outputs.cluster_name }} || true - - kubectl delete cluster "$CLUSTER_NAME" -n "$CLUSTER_NAME" --context tools --kubeconfig /home/runner/.kube/config || true - - ./clusters/scripts/ip_pool_manager.sh release "$CLUSTER_NAME" || true - - cypress-tests: - needs: manage-environment - if: github.event.action != 'closed' && needs.manage-environment.outputs.deployment_status == 'success' - runs-on: self-hosted - container: - image: cypress/included:13.6.4 - steps: - - name: Checkout demo-apps repository - uses: actions/checkout@v4 - with: - repository: fullstack-pw/demo-apps - path: . - - - name: Run Cypress tests - id: cypress - continue-on-error: true - uses: cypress-io/github-action@v6 - with: - spec: cypress/e2e/cks-backend.cy.js - config: baseUrl=https://${{ needs.manage-environment.outputs.dns_name }} - env: CKS_BACKEND_URL=https://${{ needs.manage-environment.outputs.dns_name }},TEST_ENV=ephemeral - browser: chrome - install-command: npm ci - summary-title: Cypress Test Results + ephemeral: + uses: homelabz-eu/pipelines/.github/workflows/ephemeral-environment.yml@main + with: + image-name: library/cks-backend + dev-hostname-placeholder: dev.api.cks.homelabz.eu + deployment-name: cks-backend + cypress-spec: cypress/e2e/cks-backend.cy.js + cypress-env-key: CKS_BACKEND_URL + secrets: inherit # pragma: allowlist secret diff --git a/.github/workflows/manual-pipeline.yml b/.github/workflows/manual-pipeline.yml index bf70bfc..e01c774 100644 --- a/.github/workflows/manual-pipeline.yml +++ b/.github/workflows/manual-pipeline.yml @@ -34,7 +34,7 @@ jobs: needs: [determine-app] if: needs.determine-app.outputs.apps != '[]' name: Build and Push - uses: fullstack-pw/pipelines/.github/workflows/build-and-push.yml@main + uses: homelabz-eu/pipelines/.github/workflows/build-and-push.yml@main with: app-context: "." app-name: "cks-backend" @@ -44,7 +44,7 @@ jobs: needs: [determine-app, docker-build-and-push] if: needs.determine-app.outputs.apps != '[]' && contains(github.event.inputs.deploy_target, 'dev') name: DEV deploy ${{ matrix.app.app_name }} - uses: fullstack-pw/pipelines/.github/workflows/deploy-kustomize.yml@main + uses: homelabz-eu/pipelines/.github/workflows/deploy-kustomize.yml@main with: kustomize-dir: "./kustomize/overlays/dev" context: "dev" @@ -54,14 +54,14 @@ jobs: # needs: dev-deploy # if: github.event.inputs.run_tests == 'true' && contains(github.event.inputs.deploy_target, 'dev') # name: DEV cypress - # uses: fullstack-pw/pipelines/.github/workflows/cypress.yml@main + # uses: homelabz-eu/pipelines/.github/workflows/cypress.yml@main # with: # start: npm run cypress:dev # env-vars: | # { - # "ENQUEUER_URL": "https://dev.enqueuer.fullstack.pw", - # "WRITER_URL": "https://dev.writer.fullstack.pw", - # "MEMORIZER_URL": "https://dev.memorizer.fullstack.pw", + # "ENQUEUER_URL": "https://dev.enqueuer.homelabz.eu", + # "WRITER_URL": "https://dev.writer.homelabz.eu", + # "MEMORIZER_URL": "https://dev.memorizer.homelabz.eu", # "ENVIRONMENT": "dev", # "TEST_RETRIES": "2" # } @@ -70,7 +70,7 @@ jobs: needs: [determine-app, docker-build-and-push] if: needs.determine-app.outputs.apps != '[]' && contains(github.event.inputs.deploy_target, 'stg') name: STG deploy ${{ matrix.app.app_name }} - uses: fullstack-pw/pipelines/.github/workflows/deploy-kustomize.yml@main + uses: homelabz-eu/pipelines/.github/workflows/deploy-kustomize.yml@main with: kustomize-dir: "./kustomize/overlays/stg" context: "stg" @@ -80,14 +80,14 @@ jobs: # needs: stg-deploy # if: github.event.inputs.run_tests == 'true' && contains(github.event.inputs.deploy_target, 'stg') # name: STG cypress - # uses: fullstack-pw/pipelines/.github/workflows/cypress.yml@main + # uses: homelabz-eu/pipelines/.github/workflows/cypress.yml@main # with: # start: npm run cypress:stg # env-vars: | # { - # "ENQUEUER_URL": "https://stg.enqueuer.fullstack.pw", - # "WRITER_URL": "https://stg.writer.fullstack.pw", - # "MEMORIZER_URL": "https://stg.memorizer.fullstack.pw", + # "ENQUEUER_URL": "https://stg.enqueuer.homelabz.eu", + # "WRITER_URL": "https://stg.writer.homelabz.eu", + # "MEMORIZER_URL": "https://stg.memorizer.homelabz.eu", # "ENVIRONMENT": "stg", # "TEST_RETRIES": "2" # } @@ -96,7 +96,7 @@ jobs: needs: [determine-app, docker-build-and-push] if: needs.determine-app.outputs.apps != '[]' && contains(github.event.inputs.deploy_target, 'prod') name: PROD deploy ${{ matrix.app.app_name }} - uses: fullstack-pw/pipelines/.github/workflows/deploy-kustomize.yml@main + uses: homelabz-eu/pipelines/.github/workflows/deploy-kustomize.yml@main with: kustomize-dir: "./kustomize/overlays/prod" context: "prod" diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 68e3cd3..161a7c6 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -11,14 +11,14 @@ permissions: jobs: # go-tests: # name: GO Tests - # uses: fullstack-pw/pipelines/.github/workflows/go-tests.yml@main + # uses: homelabz-eu/pipelines/.github/workflows/go-tests.yml@main # with: # go-dir: . docker-build-and-push: # needs: [go-tests] name: Build and Push - uses: fullstack-pw/pipelines/.github/workflows/build-and-push.yml@main + uses: homelabz-eu/pipelines/.github/workflows/build-and-push.yml@main with: app-context: "." app-name: "cks-backend" @@ -59,7 +59,7 @@ jobs: # dev-deploy: # needs: [docker-build-and-push] # name: DEV deploy - # uses: fullstack-pw/pipelines/.github/workflows/deploy-kustomize.yml@main + # uses: homelabz-eu/pipelines/.github/workflows/deploy-kustomize.yml@main # with: # kustomize-dir: "./kustomize/overlays/dev" # context: "dev" @@ -68,12 +68,12 @@ jobs: # dev-cypress-tests: # needs: dev-deploy # name: DEV cypress - # uses: fullstack-pw/pipelines/.github/workflows/cypress.yml@main + # uses: homelabz-eu/pipelines/.github/workflows/cypress.yml@main # with: # start: npm run cypress:dev # env-vars: | # { - # "ENQUEUER_URL": "https://dev.enqueuer.fullstack.pw", + # "ENQUEUER_URL": "https://dev.enqueuer.homelabz.eu", # "ENVIRONMENT": "dev", # "TEST_RETRIES": "2" # } @@ -81,7 +81,7 @@ jobs: # stg-deploy: # # needs: [dev-cypress-tests] # name: STG deploy - # uses: fullstack-pw/pipelines/.github/workflows/deploy-kustomize.yml@main + # uses: homelabz-eu/pipelines/.github/workflows/deploy-kustomize.yml@main # with: # kustomize-dir: "./${{ matrix.app.app_path }}/kustomize/overlays/stg" # context: "stg" @@ -90,14 +90,14 @@ jobs: # stg-cypress-tests: # needs: stg-deploy # name: STG cypress - # uses: fullstack-pw/pipelines/.github/workflows/cypress.yml@main + # uses: homelabz-eu/pipelines/.github/workflows/cypress.yml@main # with: # start: npm run cypress:stg # env-vars: | # { - # "ENQUEUER_URL": "https://stg.enqueuer.fullstack.pw", - # "WRITER_URL": "https://stg.writer.fullstack.pw", - # "MEMORIZER_URL": "https://stg.memorizer.fullstack.pw", + # "ENQUEUER_URL": "https://stg.enqueuer.homelabz.eu", + # "WRITER_URL": "https://stg.writer.homelabz.eu", + # "MEMORIZER_URL": "https://stg.memorizer.homelabz.eu", # "ENVIRONMENT": "stg", # "TEST_RETRIES": "2" # } @@ -106,7 +106,7 @@ jobs: # # needs: [stg-cypress-tests] # if: github.event_name == 'push' && github.ref == 'refs/heads/main' # name: PROD deploy - # uses: fullstack-pw/pipelines/.github/workflows/deploy-kustomize.yml@main + # uses: homelabz-eu/pipelines/.github/workflows/deploy-kustomize.yml@main # with: # kustomize-dir: "./${{ matrix.app.app_path }}/kustomize/overlays/prod" # context: "prod" diff --git a/README.md b/README.md index da8a1e3..44c281a 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ **Automated Pipeline** (`.github/workflows/pipeline.yml`) Job Flow: -1. **docker-build-and-push**: Multi-stage build, push to `registry.fullstack.pw/library/cks-backend` with commit SHA + latest tags +1. **docker-build-and-push**: Multi-stage build, push to `registry.toolz.homelabz.eu/library/cks-backend` with commit SHA + latest tags 2. **dev-deploy**: Kustomize overlay deployment to development cluster 3. **versioning**: Semantic version calculation from commit messages, GitHub release creation @@ -177,11 +177,11 @@ Applied to: ### Terminal Architecture -Terminal access is delegated to [cks-terminal-mgmt](https://github.com/fullstack-pw/cks-terminal-mgmt), a dedicated microservice running on the sandboxy cluster. The backend resolves VM names to IPs via the KubeVirt API and returns a terminal-mgmt URL for iframe embedding: +Terminal access is delegated to [cks-terminal-mgmt](https://github.com/homelabz-eu/cks-terminal-mgmt), a dedicated microservice running on the sandboxy cluster. The backend resolves VM names to IPs via the KubeVirt API and returns a terminal-mgmt URL for iframe embedding: ``` POST /api/v1/sessions/:id/terminals { target: "control-plane" } -→ { terminalUrl: "https://terminal.cks.fullstack.pw/terminal?vmIP=10.42.0.56" } +→ { terminalUrl: "https://terminal.cks.homelabz.eu/terminal?vmIP=10.42.0.56" } ``` The `TERMINAL_MGMT_URL` is configured via environment variable/ConfigMap. @@ -505,12 +505,12 @@ Key environment variables: | `GOLDEN_IMAGE_NAME` | Base image PVC name | `new-golden-image-1-33-0` | | `GOLDEN_IMAGE_NAMESPACE` | Image PVC namespace | `vm-templates` | | `POD_CIDR` | Pod network CIDR | `10.0.0.0/8` | -| `REDIS_URL` | Redis server address | `redis.fullstack.pw:6379` | +| `REDIS_URL` | Redis server address | `redis.homelabz.eu:6379` | | `REDIS_PASSWORD` | Redis authentication | `""` | | `REDIS_DB` | Redis database number | `0` | | `SESSION_TIMEOUT_MINUTES` | Session duration | `60` | | `CLEANUP_INTERVAL_MINUTES` | Cleanup frequency | `5` | -| `TERMINAL_MGMT_URL` | cks-terminal-mgmt external URL | `https://terminal.cks.fullstack.pw` | +| `TERMINAL_MGMT_URL` | cks-terminal-mgmt external URL | `https://terminal.cks.homelabz.eu` | ## Deployment Architecture diff --git a/kustomize/base/analysis-template.yaml b/kustomize/base/analysis-template.yaml index dbd2f39..490aebc 100644 --- a/kustomize/base/analysis-template.yaml +++ b/kustomize/base/analysis-template.yaml @@ -31,7 +31,7 @@ spec: # Clone the demo-apps repository apt-get update -o Acquire::AllowInsecureRepositories=true || true apt-get install -y git --allow-unauthenticated - git clone https://github.com/fullstack-pw/demo-apps.git /demo-apps + git clone https://github.com/homelabz-eu/demo-apps.git /demo-apps cd /demo-apps # Install dependencies diff --git a/kustomize/base/configmap.yaml b/kustomize/base/configmap.yaml index d9a07a9..9bf080a 100644 --- a/kustomize/base/configmap.yaml +++ b/kustomize/base/configmap.yaml @@ -22,8 +22,8 @@ data: GOLDEN_IMAGE_NAME: new-golden-image-1-33-0 GOLDEN_IMAGE_NAMESPACE: vm-templates VALIDATE_GOLDEN_IMAGE: true - REDIS_URL: redis.fullstack.pw:6379 + REDIS_URL: redis.homelabz.eu:6379 REDIS_DB: "0" - TERMINAL_MGMT_URL: https://terminal.cks.fullstack.pw + TERMINAL_MGMT_URL: https://terminal.cks.homelabz.eu TEMPLATE_PATH: /app/templates SCENARIOS_PATH: /app/scenarios diff --git a/kustomize/base/deployment.yaml b/kustomize/base/deployment.yaml index ed327a9..c719c36 100644 --- a/kustomize/base/deployment.yaml +++ b/kustomize/base/deployment.yaml @@ -40,7 +40,7 @@ spec: runAsUser: 0 containers: - name: cks-backend - image: registry.fullstack.pw/library/cks-backend:latest + image: registry.toolz.homelabz.eu/library/cks-backend:latest ports: - containerPort: 8080 protocol: TCP diff --git a/kustomize/base/promotion-template.yaml b/kustomize/base/promotion-template.yaml index eb984e3..0e31dec 100644 --- a/kustomize/base/promotion-template.yaml +++ b/kustomize/base/promotion-template.yaml @@ -29,18 +29,18 @@ spec: # Configure git git config --global user.name "Argo Rollouts Auto-Promotion" - git config --global user.email "noreply@fullstack.pw" + git config --global user.email "noreply@homelabz.eu" # Clone cks-backend repository - git clone https://github.com/fullstack-pw/cks-backend.git /workspace + git clone https://github.com/homelabz-eu/cks-backend.git /workspace cd /workspace # Get the current dev version (the version that just passed tests) DEV_KUSTOMIZATION="kustomize/overlays/dev/kustomization.yaml" PROD_KUSTOMIZATION="kustomize/overlays/prod/kustomization.yaml" - DEV_TAG=$(grep -A1 "name: registry.fullstack.pw/library/{{args.app-name}}" "$DEV_KUSTOMIZATION" | grep "newTag:" | awk '{print $2}') - PROD_TAG=$(grep -A1 "name: registry.fullstack.pw/library/{{args.app-name}}" "$PROD_KUSTOMIZATION" | grep "newTag:" | awk '{print $2}') + DEV_TAG=$(grep -A1 "name: registry.toolz.homelabz.eu/library/{{args.app-name}}" "$DEV_KUSTOMIZATION" | grep "newTag:" | awk '{print $2}') + PROD_TAG=$(grep -A1 "name: registry.toolz.homelabz.eu/library/{{args.app-name}}" "$PROD_KUSTOMIZATION" | grep "newTag:" | awk '{print $2}') echo "Dev is at version: $DEV_TAG" echo "Prod is at version: $PROD_TAG" @@ -61,7 +61,7 @@ spec: git commit -m "chore({{args.app-name}}): auto-promote $DEV_TAG to prod [skip ci]" # Push using GitHub token - git push https://${GITHUB_TOKEN}@github.com/fullstack-pw/cks-backend.git main + git push https://${GITHUB_TOKEN}@github.com/homelabz-eu/cks-backend.git main echo "Successfully promoted {{args.app-name}} to production" exit 0 diff --git a/kustomize/base/rollout.yaml b/kustomize/base/rollout.yaml index fe0e8e3..5e179db 100644 --- a/kustomize/base/rollout.yaml +++ b/kustomize/base/rollout.yaml @@ -40,7 +40,7 @@ spec: runAsUser: 0 containers: - name: cks-backend - image: registry.fullstack.pw/library/cks-backend:latest + image: registry.toolz.homelabz.eu/library/cks-backend:latest ports: - containerPort: 8080 protocol: TCP @@ -109,7 +109,7 @@ spec: - name: app-name value: cks-backend - name: app-url - value: "https://dev.api.cks.fullstack.pw" + value: "https://dev.api.cks.homelabz.eu" - name: environment value: "dev" postPromotionAnalysis: diff --git a/kustomize/base/virtualservice.yaml b/kustomize/base/virtualservice.yaml index bc79294..d604813 100644 --- a/kustomize/base/virtualservice.yaml +++ b/kustomize/base/virtualservice.yaml @@ -6,7 +6,7 @@ metadata: cert-manager.io/cluster-issuer: letsencrypt-prod spec: hosts: - - "dev.api.cks.fullstack.pw" # Will be overridden in overlays + - "dev.api.cks.homelabz.eu" # Will be overridden in overlays gateways: - istio-system/default-gateway http: diff --git a/kustomize/ephemeral-base/configmap.yaml b/kustomize/ephemeral-base/configmap.yaml index d9a07a9..e8031e6 100644 --- a/kustomize/ephemeral-base/configmap.yaml +++ b/kustomize/ephemeral-base/configmap.yaml @@ -10,9 +10,9 @@ data: SERVER_PORT: 8080 CORS_ALLOW_ORIGIN: "*" KUBECONFIG: /etc/kubeconfig - KUBERNETES_CONTEXT: sandboxy + KUBERNETES_CONTEXT: toolz KUBERNETES_SERVICE_PORT: 6443 - KUBERNETES_SERVICE_HOST: 192.168.1.21 + KUBERNETES_SERVICE_HOST: 192.168.1.30 KUBERNETES_VERSION: 1.33.0 VM_CPU_CORES: 2 VM_MEMORY: 2Gi @@ -22,8 +22,8 @@ data: GOLDEN_IMAGE_NAME: new-golden-image-1-33-0 GOLDEN_IMAGE_NAMESPACE: vm-templates VALIDATE_GOLDEN_IMAGE: true - REDIS_URL: redis.fullstack.pw:6379 + REDIS_URL: redis.toolz.homelabz.eu:6379 REDIS_DB: "0" - TERMINAL_MGMT_URL: https://terminal.cks.fullstack.pw + TERMINAL_MGMT_URL: https://terminal.toolz.cks.homelabz.eu TEMPLATE_PATH: /app/templates SCENARIOS_PATH: /app/scenarios diff --git a/kustomize/ephemeral-base/deployment.yaml b/kustomize/ephemeral-base/deployment.yaml index ed327a9..c719c36 100644 --- a/kustomize/ephemeral-base/deployment.yaml +++ b/kustomize/ephemeral-base/deployment.yaml @@ -40,7 +40,7 @@ spec: runAsUser: 0 containers: - name: cks-backend - image: registry.fullstack.pw/library/cks-backend:latest + image: registry.toolz.homelabz.eu/library/cks-backend:latest ports: - containerPort: 8080 protocol: TCP diff --git a/kustomize/overlays/dev/kustomization.yaml b/kustomize/overlays/dev/kustomization.yaml index baf5628..50dec0c 100644 --- a/kustomize/overlays/dev/kustomization.yaml +++ b/kustomize/overlays/dev/kustomization.yaml @@ -5,7 +5,7 @@ resources: - ../../base images: - - name: registry.fullstack.pw/library/cks-backend + - name: registry.toolz.homelabz.eu/library/cks-backend newTag: 2a259af37ebe4b46c07fc0480d9314ee34731d5c configMapGenerator: diff --git a/kustomize/overlays/ephemeral/kustomization.yaml b/kustomize/overlays/ephemeral/kustomization.yaml index 404ec0a..436e11f 100644 --- a/kustomize/overlays/ephemeral/kustomization.yaml +++ b/kustomize/overlays/ephemeral/kustomization.yaml @@ -7,20 +7,20 @@ resources: - ../../ephemeral-base images: - - name: registry.fullstack.pw/library/cks-backend + - name: registry.toolz.homelabz.eu/library/cks-backend newTag: pr-will-be-replaced patches: - patch: |- - op: replace path: /metadata/annotations/external-dns.alpha.kubernetes.io~1hostname - value: "dev.api.cks.fullstack.pw" + value: "dev.api.cks.homelabz.eu" - op: replace path: /spec/tls/0/hosts/0 - value: "dev.api.cks.fullstack.pw" + value: "dev.api.cks.homelabz.eu" - op: replace path: /spec/rules/0/host - value: "dev.api.cks.fullstack.pw" + value: "dev.api.cks.homelabz.eu" target: kind: Ingress name: cks-backend diff --git a/kustomize/overlays/prod/kustomization.yaml b/kustomize/overlays/prod/kustomization.yaml index ce61044..a29858d 100644 --- a/kustomize/overlays/prod/kustomization.yaml +++ b/kustomize/overlays/prod/kustomization.yaml @@ -5,14 +5,14 @@ resources: - ../../base images: - - name: registry.fullstack.pw/library/cks-backend + - name: registry.toolz.homelabz.eu/library/cks-backend newTag: 2a259af37ebe4b46c07fc0480d9314ee34731d5c patches: - patch: |- - op: replace path: /spec/hosts/0 - value: "api.cks.fullstack.pw" + value: "api.cks.homelabz.eu" target: kind: VirtualService name: cks-backend diff --git a/src/app b/src/app new file mode 100755 index 0000000..1a83d24 Binary files /dev/null and b/src/app differ diff --git a/src/cmd/server/main.go b/src/cmd/server/main.go index b2ba952..9408ebd 100644 --- a/src/cmd/server/main.go +++ b/src/cmd/server/main.go @@ -18,15 +18,15 @@ import ( "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" - "github.com/fullstack-pw/cks/backend/internal/clusterpool" - "github.com/fullstack-pw/cks/backend/internal/config" - "github.com/fullstack-pw/cks/backend/internal/controllers" - "github.com/fullstack-pw/cks/backend/internal/kubevirt" - "github.com/fullstack-pw/cks/backend/internal/middleware" - "github.com/fullstack-pw/cks/backend/internal/scenarios" - "github.com/fullstack-pw/cks/backend/internal/services" - "github.com/fullstack-pw/cks/backend/internal/sessions" - "github.com/fullstack-pw/cks/backend/internal/validation" + "github.com/homelabz-eu/cks/backend/internal/clusterpool" + "github.com/homelabz-eu/cks/backend/internal/config" + "github.com/homelabz-eu/cks/backend/internal/controllers" + "github.com/homelabz-eu/cks/backend/internal/kubevirt" + "github.com/homelabz-eu/cks/backend/internal/middleware" + "github.com/homelabz-eu/cks/backend/internal/scenarios" + "github.com/homelabz-eu/cks/backend/internal/services" + "github.com/homelabz-eu/cks/backend/internal/sessions" + "github.com/homelabz-eu/cks/backend/internal/validation" ) // createKubernetesConfig creates Kubernetes config with explicit context selection diff --git a/src/internal/clusterpool/manager.go b/src/internal/clusterpool/manager.go index ff73ecf..8704371 100644 --- a/src/internal/clusterpool/manager.go +++ b/src/internal/clusterpool/manager.go @@ -7,9 +7,9 @@ import ( "sync" "time" - "github.com/fullstack-pw/cks/backend/internal/config" - "github.com/fullstack-pw/cks/backend/internal/kubevirt" - "github.com/fullstack-pw/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/config" + "github.com/homelabz-eu/cks/backend/internal/kubevirt" + "github.com/homelabz-eu/cks/backend/internal/models" "github.com/sirupsen/logrus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" diff --git a/src/internal/config/config.go b/src/internal/config/config.go index 7dd88a7..2579f21 100644 --- a/src/internal/config/config.go +++ b/src/internal/config/config.go @@ -86,12 +86,12 @@ func LoadConfig() (*Config, error) { ValidateGoldenImage: getEnvAsBool("VALIDATE_GOLDEN_IMAGE", true), // Redis defaults - RedisURL: getEnv("REDIS_URL", "redis.fullstack.pw:6379"), + RedisURL: getEnv("REDIS_URL", "redis.homelabz.eu:6379"), RedisPassword: getEnv("REDIS_PASSWORD", ""), RedisDB: getEnvAsInt("REDIS_DB", 0), // Terminal management - TerminalMgmtURL: getEnv("TERMINAL_MGMT_URL", "https://terminal.cks.fullstack.pw"), + TerminalMgmtURL: getEnv("TERMINAL_MGMT_URL", "https://terminal.cks.homelabz.eu"), // Scenario defaults ScenariosPath: getEnv("SCENARIOS_PATH", "scenarios"), diff --git a/src/internal/controllers/admin_controller.go b/src/internal/controllers/admin_controller.go index 4bd20f1..82f5d09 100644 --- a/src/internal/controllers/admin_controller.go +++ b/src/internal/controllers/admin_controller.go @@ -9,9 +9,9 @@ import ( "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" - "github.com/fullstack-pw/cks/backend/internal/kubevirt" - "github.com/fullstack-pw/cks/backend/internal/models" - "github.com/fullstack-pw/cks/backend/internal/sessions" + "github.com/homelabz-eu/cks/backend/internal/kubevirt" + "github.com/homelabz-eu/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/sessions" ) // AdminController handles administrative operations diff --git a/src/internal/controllers/scenario_controller.go b/src/internal/controllers/scenario_controller.go index acbbaea..933da58 100644 --- a/src/internal/controllers/scenario_controller.go +++ b/src/internal/controllers/scenario_controller.go @@ -5,8 +5,8 @@ package controllers import ( "net/http" - "github.com/fullstack-pw/cks/backend/internal/models" - "github.com/fullstack-pw/cks/backend/internal/services" + "github.com/homelabz-eu/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/services" "github.com/gin-gonic/gin" ) diff --git a/src/internal/controllers/session_controller.go b/src/internal/controllers/session_controller.go index 388c86b..91005a9 100644 --- a/src/internal/controllers/session_controller.go +++ b/src/internal/controllers/session_controller.go @@ -8,9 +8,9 @@ import ( "net/http" "time" - "github.com/fullstack-pw/cks/backend/internal/models" - "github.com/fullstack-pw/cks/backend/internal/services" - "github.com/fullstack-pw/cks/backend/internal/validation" + "github.com/homelabz-eu/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/services" + "github.com/homelabz-eu/cks/backend/internal/validation" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" ) diff --git a/src/internal/controllers/terminal_controller.go b/src/internal/controllers/terminal_controller.go index 719730f..c58fcde 100644 --- a/src/internal/controllers/terminal_controller.go +++ b/src/internal/controllers/terminal_controller.go @@ -7,8 +7,8 @@ import ( "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" - "github.com/fullstack-pw/cks/backend/internal/models" - "github.com/fullstack-pw/cks/backend/internal/services" + "github.com/homelabz-eu/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/services" ) type TerminalController struct { diff --git a/src/internal/kubevirt/client.go b/src/internal/kubevirt/client.go index 4d6b3cf..33e67ca 100644 --- a/src/internal/kubevirt/client.go +++ b/src/internal/kubevirt/client.go @@ -24,7 +24,7 @@ import ( "k8s.io/client-go/rest" "kubevirt.io/client-go/kubecli" - "github.com/fullstack-pw/cks/backend/internal/config" + "github.com/homelabz-eu/cks/backend/internal/config" "github.com/sirupsen/logrus" snapshotv1beta1 "kubevirt.io/api/snapshot/v1beta1" ) @@ -468,7 +468,7 @@ func (c *Client) createCloudInitSecret(ctx context.Context, namespace, vmName, v renderedSecret := substituteEnvVars(string(secretContent), data) // Apply secret using kubectl - return applyYAML(ctx, renderedSecret) + return c.applyYAML(ctx, renderedSecret) } func (c *Client) createVM(ctx context.Context, namespace, vmName, vmType string) error { @@ -514,7 +514,7 @@ func (c *Client) createVM(ctx context.Context, namespace, vmName, vmType string) c.logger.Debug(renderedVM) c.logger.Debug("=== RENDERED VM YAML END ===") // Apply VM using kubectl - return applyYAML(ctx, renderedVM) + return c.applyYAML(ctx, renderedVM) } // WaitForVMsReady waits for multiple VMs to be ready @@ -886,30 +886,41 @@ func base64Encode(input string) string { } // applyYAML applies YAML to the cluster -func applyYAML(ctx context.Context, yaml string) error { - // Create a kubectl apply command with stdin for the YAML content - cmd := exec.CommandContext(ctx, "kubectl", "apply", "-f", "-") +func (c *Client) applyYAML(ctx context.Context, yaml string) error { + args := []string{"apply", "-f", "-"} + if c.kubernetesContext != "" { + args = append([]string{"--context", c.kubernetesContext}, args...) + } + + cmd := exec.CommandContext(ctx, "kubectl", args...) + + tempKubeconfigPath, _ := c.getOrCreateTempKubeconfig() + if tempKubeconfigPath != "" { + var env []string + for _, e := range os.Environ() { + if !strings.HasPrefix(e, "KUBECONFIG=") { + env = append(env, e) + } + } + env = append(env, "KUBECONFIG="+tempKubeconfigPath) + cmd.Env = env + } - // Create a pipe to write the YAML to stdin stdin, err := cmd.StdinPipe() if err != nil { return fmt.Errorf("failed to create stdin pipe: %w", err) } - // Create a buffer for the stderr output var stderr strings.Builder cmd.Stderr = &stderr - // Start the command if err := cmd.Start(); err != nil { return fmt.Errorf("failed to start kubectl apply: %w", err) } - // Write the YAML to stdin io.WriteString(stdin, yaml) stdin.Close() - // Wait for the command to complete if err := cmd.Wait(); err != nil { return fmt.Errorf("kubectl apply failed: %w, stderr: %s", err, stderr.String()) } diff --git a/src/internal/scenarios/initializer.go b/src/internal/scenarios/initializer.go index 467b4e6..ed33876 100644 --- a/src/internal/scenarios/initializer.go +++ b/src/internal/scenarios/initializer.go @@ -8,8 +8,8 @@ import ( "strings" "time" - "github.com/fullstack-pw/cks/backend/internal/kubevirt" - "github.com/fullstack-pw/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/kubevirt" + "github.com/homelabz-eu/cks/backend/internal/models" "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" "k8s.io/client-go/kubernetes" diff --git a/src/internal/scenarios/scenario_manager.go b/src/internal/scenarios/scenario_manager.go index 4f4c46e..f8233c7 100644 --- a/src/internal/scenarios/scenario_manager.go +++ b/src/internal/scenarios/scenario_manager.go @@ -10,7 +10,7 @@ import ( "strings" "sync" - "github.com/fullstack-pw/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/models" "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" ) diff --git a/src/internal/scenarios/vm_helpers.go b/src/internal/scenarios/vm_helpers.go index ec2d8af..4a56ddf 100644 --- a/src/internal/scenarios/vm_helpers.go +++ b/src/internal/scenarios/vm_helpers.go @@ -5,7 +5,7 @@ package scenarios import ( "fmt" - "github.com/fullstack-pw/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/models" ) // VMTarget represents the target VM for operations diff --git a/src/internal/services/interfaces.go b/src/internal/services/interfaces.go index f8aaeac..1fa0207 100644 --- a/src/internal/services/interfaces.go +++ b/src/internal/services/interfaces.go @@ -6,8 +6,8 @@ import ( "context" "time" - "github.com/fullstack-pw/cks/backend/internal/models" - "github.com/fullstack-pw/cks/backend/internal/validation" + "github.com/homelabz-eu/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/validation" ) // SessionService defines the interface for session-related operations diff --git a/src/internal/services/scenario_service.go b/src/internal/services/scenario_service.go index 9d84df3..ef362ff 100644 --- a/src/internal/services/scenario_service.go +++ b/src/internal/services/scenario_service.go @@ -3,8 +3,8 @@ package services import ( - "github.com/fullstack-pw/cks/backend/internal/models" - "github.com/fullstack-pw/cks/backend/internal/scenarios" + "github.com/homelabz-eu/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/scenarios" ) // ScenarioServiceImpl implements the ScenarioService interface diff --git a/src/internal/services/session_service.go b/src/internal/services/session_service.go index fd3eb49..df5352b 100644 --- a/src/internal/services/session_service.go +++ b/src/internal/services/session_service.go @@ -6,9 +6,9 @@ import ( "context" "time" - "github.com/fullstack-pw/cks/backend/internal/models" - "github.com/fullstack-pw/cks/backend/internal/sessions" - "github.com/fullstack-pw/cks/backend/internal/validation" + "github.com/homelabz-eu/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/sessions" + "github.com/homelabz-eu/cks/backend/internal/validation" ) // SessionServiceImpl implements the SessionService interface diff --git a/src/internal/services/terminal_service.go b/src/internal/services/terminal_service.go index 44b31a4..855ffd3 100644 --- a/src/internal/services/terminal_service.go +++ b/src/internal/services/terminal_service.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/fullstack-pw/cks/backend/internal/config" - "github.com/fullstack-pw/cks/backend/internal/kubevirt" + "github.com/homelabz-eu/cks/backend/internal/config" + "github.com/homelabz-eu/cks/backend/internal/kubevirt" ) type TerminalServiceImpl struct { diff --git a/src/internal/sessions/session_manager.go b/src/internal/sessions/session_manager.go index a399616..b7c3195 100644 --- a/src/internal/sessions/session_manager.go +++ b/src/internal/sessions/session_manager.go @@ -10,12 +10,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" - "github.com/fullstack-pw/cks/backend/internal/clusterpool" - "github.com/fullstack-pw/cks/backend/internal/config" - "github.com/fullstack-pw/cks/backend/internal/kubevirt" - "github.com/fullstack-pw/cks/backend/internal/models" - "github.com/fullstack-pw/cks/backend/internal/scenarios" - "github.com/fullstack-pw/cks/backend/internal/validation" + "github.com/homelabz-eu/cks/backend/internal/clusterpool" + "github.com/homelabz-eu/cks/backend/internal/config" + "github.com/homelabz-eu/cks/backend/internal/kubevirt" + "github.com/homelabz-eu/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/scenarios" + "github.com/homelabz-eu/cks/backend/internal/validation" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" diff --git a/src/internal/sessions/store.go b/src/internal/sessions/store.go index 6e492cd..b443594 100644 --- a/src/internal/sessions/store.go +++ b/src/internal/sessions/store.go @@ -3,7 +3,7 @@ package sessions import ( "context" - "github.com/fullstack-pw/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/models" ) type SessionStore interface { diff --git a/src/internal/sessions/store_redis.go b/src/internal/sessions/store_redis.go index 8e7fff8..2bb0b11 100644 --- a/src/internal/sessions/store_redis.go +++ b/src/internal/sessions/store_redis.go @@ -9,7 +9,7 @@ import ( "github.com/redis/go-redis/v9" "github.com/sirupsen/logrus" - "github.com/fullstack-pw/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/models" ) const ( diff --git a/src/internal/validation/unified_validator.go b/src/internal/validation/unified_validator.go index f853a30..a6352f8 100644 --- a/src/internal/validation/unified_validator.go +++ b/src/internal/validation/unified_validator.go @@ -6,8 +6,8 @@ import ( "strings" "time" - "github.com/fullstack-pw/cks/backend/internal/kubevirt" - "github.com/fullstack-pw/cks/backend/internal/models" + "github.com/homelabz-eu/cks/backend/internal/kubevirt" + "github.com/homelabz-eu/cks/backend/internal/models" "github.com/sirupsen/logrus" )