From b5da74f12b723293eeccffbf4d57e7cb9413d215 Mon Sep 17 00:00:00 2001 From: MTimka Date: Wed, 13 May 2026 13:49:09 -0700 Subject: [PATCH] testing workflows --- .gitea/workflows/docker.yaml | 57 ++++++++++++++++++++---------------- k8s/all-in-one.yaml | 51 -------------------------------- k8s/app-deployment.yaml | 26 ++++++++++++++++ k8s/configmap.yaml | 6 ++++ k8s/image-tag.txt | 1 - k8s/ingress.yaml | 18 ++++++++++++ k8s/operator.yaml | 27 +++++++++++++++++ k8s/service.yaml | 12 ++++++++ operator/Dockerfile | 8 +++++ operator/operator.py | 55 ++++++++++++++++++++++++++++++++++ operator/requirements.txt | 2 ++ 11 files changed, 186 insertions(+), 77 deletions(-) delete mode 100644 k8s/all-in-one.yaml create mode 100644 k8s/app-deployment.yaml create mode 100644 k8s/configmap.yaml delete mode 100644 k8s/image-tag.txt create mode 100644 k8s/ingress.yaml create mode 100644 k8s/operator.yaml create mode 100644 k8s/service.yaml create mode 100644 operator/Dockerfile create mode 100644 operator/operator.py create mode 100644 operator/requirements.txt diff --git a/.gitea/workflows/docker.yaml b/.gitea/workflows/docker.yaml index 9ad1966..f7cbf74 100644 --- a/.gitea/workflows/docker.yaml +++ b/.gitea/workflows/docker.yaml @@ -1,4 +1,4 @@ -name: Build and Push Docker Image +name: Build and Deploy on: push: @@ -6,11 +6,11 @@ on: - main env: - REGISTRY: repositry.talutasku.ee - IMAGE_NAME: my-python-app + APP_IMAGE: my-python-app + OPERATOR_IMAGE: configmap-operator jobs: - build-and-push: + build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout code @@ -19,36 +19,43 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Log in to registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ secrets.REGISTRY_USERNAME }} - password: ${{ secrets.REGISTRY_PASSWORD }} - - name: Extract git SHA id: vars run: echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - - name: Build and push Docker image + - name: Build app image uses: docker/build-push-action@v5 with: context: . + file: ./Dockerfile push: true tags: | - ${{ env.REGISTRY }}/v2/${{ env.IMAGE_NAME }}:${{ steps.vars.outputs.sha }} - ${{ env.REGISTRY }}/v2/${{ env.IMAGE_NAME }}:latest - cache-from: type=gha - cache-to: type=gha,mode=max + repositry.talutasku.ee/v2/my-python-app:${{ steps.vars.outputs.sha }} + repositry.talutasku.ee/v2/my-python-app:latest - - name: Update image tag file - run: | - echo "${{ steps.vars.outputs.sha }}" > k8s/image-tag.txt + - name: Build operator image + uses: docker/build-push-action@v5 + with: + context: ./operator + file: ./operator/Dockerfile + push: true + tags: | + repositry.talutasku.ee/v2/configmap-operator:${{ steps.vars.outputs.sha }} + repositry.talutasku.ee/v2/configmap-operator:latest - - name: Commit and push image tag + - name: Set up kubectl + uses: azure/setup-kubectl@v4 + with: + version: 'latest' + + - name: Configure kubectl run: | - git config --local user.email "gitea-ci@example.com" - git config --local user.name "Gitea CI" - git add k8s/image-tag.txt - git commit -m "Update image tag to ${{ steps.vars.outputs.sha }}" || exit 0 - git push \ No newline at end of file + echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > kubeconfig + echo "KUBECONFIG=$(pwd)/kubeconfig" >> $GITHUB_ENV + + - name: Patch ConfigMap + run: | + kubectl patch configmap python-app-config \ + --namespace default \ + --type merge \ + --patch '{"data":{"IMAGE_TAG":"${{ steps.vars.outputs.sha }}"}}' \ No newline at end of file diff --git a/k8s/all-in-one.yaml b/k8s/all-in-one.yaml deleted file mode 100644 index f0c0051..0000000 --- a/k8s/all-in-one.yaml +++ /dev/null @@ -1,51 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: python-app - labels: - app: python-app -spec: - containers: - - name: python-app - image: repositry.talutasku.ee/v2/my-python-app:latest - ports: - - containerPort: 8000 - resources: - limits: - memory: "128Mi" - cpu: "500m" - requests: - memory: "64Mi" - cpu: "100m" ---- -apiVersion: v1 -kind: Service -metadata: - name: python-app -spec: - selector: - app: python-app - ports: - - protocol: TCP - port: 80 - targetPort: 8000 - type: ClusterIP ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: python-app - annotations: - kubernetes.io/ingress.class: traefik -spec: - rules: - - host: python-app.talutasku.ee - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: python-app - port: - number: 80 \ No newline at end of file diff --git a/k8s/app-deployment.yaml b/k8s/app-deployment.yaml new file mode 100644 index 0000000..be68aaf --- /dev/null +++ b/k8s/app-deployment.yaml @@ -0,0 +1,26 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: python-app +spec: + replicas: 2 + selector: + matchLabels: + app: python-app + template: + metadata: + labels: + app: python-app + spec: + containers: + - name: python-app + image: repositry.talutasku.ee/v2/my-python-app:latest + ports: + - containerPort: 8000 + resources: + limits: + memory: "128Mi" + cpu: "500m" + requests: + memory: "64Mi" + cpu: "100m" \ No newline at end of file diff --git a/k8s/configmap.yaml b/k8s/configmap.yaml new file mode 100644 index 0000000..6cab0d6 --- /dev/null +++ b/k8s/configmap.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: python-app-config +data: + IMAGE_TAG: "latest" \ No newline at end of file diff --git a/k8s/image-tag.txt b/k8s/image-tag.txt deleted file mode 100644 index b9bc2fd..0000000 --- a/k8s/image-tag.txt +++ /dev/null @@ -1 +0,0 @@ -latest \ No newline at end of file diff --git a/k8s/ingress.yaml b/k8s/ingress.yaml new file mode 100644 index 0000000..938be61 --- /dev/null +++ b/k8s/ingress.yaml @@ -0,0 +1,18 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: python-app + annotations: + kubernetes.io/ingress.class: traefik +spec: + rules: + - host: python-app.talutasku.ee + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: python-app + port: + number: 80 \ No newline at end of file diff --git a/k8s/operator.yaml b/k8s/operator.yaml new file mode 100644 index 0000000..919a2fb --- /dev/null +++ b/k8s/operator.yaml @@ -0,0 +1,27 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: configmap-operator +spec: + replicas: 1 + selector: + matchLabels: + app: configmap-operator + template: + metadata: + labels: + app: configmap-operator + spec: + containers: + - name: operator + image: repositry.talutasku.ee/v2/configmap-operator:latest + env: + - name: NAMESPACE + value: "default" + resources: + limits: + memory: "64Mi" + cpu: "100m" + requests: + memory: "32Mi" + cpu: "50m" \ No newline at end of file diff --git a/k8s/service.yaml b/k8s/service.yaml new file mode 100644 index 0000000..61a8d35 --- /dev/null +++ b/k8s/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: python-app +spec: + selector: + app: python-app + ports: + - protocol: TCP + port: 80 + targetPort: 8000 + type: ClusterIP \ No newline at end of file diff --git a/operator/Dockerfile b/operator/Dockerfile new file mode 100644 index 0000000..c5ceb5b --- /dev/null +++ b/operator/Dockerfile @@ -0,0 +1,8 @@ +FROM python:3.11-slim + +WORKDIR /app +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt +COPY operator.py . + +CMD ["python", "operator.py"] \ No newline at end of file diff --git a/operator/operator.py b/operator/operator.py new file mode 100644 index 0000000..b832c4a --- /dev/null +++ b/operator/operator.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +import os +import time +import subprocess +from kubernetes import client, config +from kubernetes.client.api import CoreV1Api +from kubernetes.client.models import V1ConfigMap + +NAMESPACE = os.getenv("NAMESPACE", "default") +CONFIGMAP_NAME = "python-app-config" +APP_DEPLOYMENT = "python-app" +APP_CONTAINER = "python-app" + +def load_kube_config(): + try: + config.load_incluster_config() + except Exception: + config.load_kube_config() + +def get_current_image_tag() -> str: + v1 = CoreV1Api() + cm = v1.read_namespaced_config_map(CONFIGMAP_NAME, NAMESPACE) + return cm.data.get("IMAGE_TAG", "latest") + +def set_deployment_image(new_tag: str): + image = f"repositry.talutasku.ee/v2/my-python-app:{new_tag}" + cmd = [ + "kubectl", "set", "image", + f"deployment/{APP_DEPLOYMENT}", + f"{APP_CONTAINER}={image}", + "--namespace", NAMESPACE + ] + subprocess.run(cmd, check=True) + +def watch_configmap(): + v1 = CoreV1Api() + last_tag = None + + print(f"Watching ConfigMap {CONFIGMAP_NAME} in namespace {NAMESPACE}...") + + while True: + try: + current_tag = get_current_image_tag() + if current_tag != last_tag: + print(f"ConfigMap updated: IMAGE_TAG={current_tag}") + set_deployment_image(current_tag) + last_tag = current_tag + except Exception as e: + print(f"Error: {e}") + + time.sleep(5) + +if __name__ == "__main__": + load_kube_config() + watch_configmap() \ No newline at end of file diff --git a/operator/requirements.txt b/operator/requirements.txt new file mode 100644 index 0000000..06fffca --- /dev/null +++ b/operator/requirements.txt @@ -0,0 +1,2 @@ +kubernetes>=28.0.0 +pyyaml>=6.0 \ No newline at end of file