diff --git a/.github/workflows/image.yml b/.github/workflows/image.yml index 62006905..36758ed4 100644 --- a/.github/workflows/image.yml +++ b/.github/workflows/image.yml @@ -48,7 +48,8 @@ jobs: - name: Assign Custom Image Name if: ${{ github.repository_owner != 'apache'}} run: | - echo "MY_OPERATOR_IMAGE=${{ vars.MY_OPERATOR_IMAGE }}" >> "$GITHUB_ENV" + echo "MY_OPERATOR_IMAGE=ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}" >> "$GITHUB_ENV" + echo "IMAGE_REGISTRY=ghcr.io" >> "$GITHUB_ENV" - name: Set up Python 3.12 uses: actions/setup-python@v4 with: @@ -85,9 +86,9 @@ jobs: - name: Registry login uses: docker/login-action@v3 with: - registry: ${{ vars.IMAGE_REGISTRY || 'registry.hub.docker.com' }} - username: ${{ secrets.DOCKERHUB_USER || github.actor }} - password: ${{ secrets.DOCKERHUB_TOKEN || secrets.GITHUB_TOKEN }} + registry: ${{ env.IMAGE_REGISTRY || 'registry.hub.docker.com' }} + username: ${{ env.IMAGE_REGISTRY == 'ghcr.io' && github.repository_owner || secrets.DOCKERHUB_USER }} + password: ${{ env.IMAGE_REGISTRY == 'ghcr.io' && secrets.GITHUB_TOKEN || secrets.DOCKERHUB_TOKEN }} - name: Set up QEMU uses: docker/setup-qemu-action@v3 with: diff --git a/.github/workflows/trigger-testing.yaml b/.github/workflows/trigger-testing.yaml index 214e9f9e..1dfcaba1 100644 --- a/.github/workflows/trigger-testing.yaml +++ b/.github/workflows/trigger-testing.yaml @@ -16,67 +16,69 @@ # under the License. # name: Trigger Testing -run-name: Dispatch operator PR test for ${{ github.event.issue.number || github.event.inputs.pr_number }} +run-name: Dispatch operator PR test for PR #${{ github.event.pull_request.number }} on: - issue_comment: - types: [created] - workflow_dispatch: - inputs: - pr_number: - description: "PR number to test" - required: true - type: string - platform: - description: "Platform to test on (e.g. k3s-amd, eks-amd)" - required: true - type: string + pull_request_target: + types: [labeled, synchronize, reopened] jobs: dispatch: name: Dispatch operator-pr-test runs-on: ubuntu-22.04 - # Run on /testing comments from authorized users, or on manual dispatch - if: >- - github.event_name == 'workflow_dispatch' || - ( - github.event.issue.pull_request && - startsWith(github.event.comment.body, '/testing ') && - contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association) - ) steps: - - name: Parse comment + - name: Parse testing tag id: parse + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + PR_REF: ${{ github.event.pull_request.head.ref }} + PR_SHA: ${{ github.event.pull_request.head.sha }} + PR_REPO: ${{ github.event.pull_request.head.repo.full_name }} run: | - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - echo "platform=${{ github.event.inputs.platform }}" >> "$GITHUB_OUTPUT" - echo "pr_number=${{ github.event.inputs.pr_number }}" >> "$GITHUB_OUTPUT" - else - COMMENT="${{ github.event.comment.body }}" - PLATFORM="${COMMENT#/testing }" - echo "platform=${PLATFORM}" >> "$GITHUB_OUTPUT" - echo "pr_number=${{ github.event.issue.number }}" >> "$GITHUB_OUTPUT" + VALID_TEST_RE='^(kind|k3s|k3sarm|k8s|k8sarm|mk8s|mk8sarm|eks|eksarm|aks|aksarm|gke|gkearm|osh|osharm)-([0-9a-f]{7,40})$' + MATCHING_TAGS=() + + while IFS= read -r label; do + [[ -n "$label" ]] || continue + if [[ "$label" =~ $VALID_TEST_RE ]]; then + label_hash="${BASH_REMATCH[2]}" + if [[ "$PR_SHA" == "$label_hash"* ]]; then + MATCHING_TAGS+=("$label") + fi + fi + done < <(jq -r '.pull_request.labels[]?.name // empty' "$GITHUB_EVENT_PATH") + + echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT" + echo "pr_ref=$PR_REF" >> "$GITHUB_OUTPUT" + echo "pr_sha=$PR_SHA" >> "$GITHUB_OUTPUT" + echo "repo=$PR_REPO" >> "$GITHUB_OUTPUT" + + if [[ "${#MATCHING_TAGS[@]}" -gt 1 ]]; then + echo "Found multiple matching - tags for PR SHA $PR_SHA:" >&2 + printf ' - %s\n' "${MATCHING_TAGS[@]}" >&2 + exit 1 fi - - name: Get PR details - id: pr - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - PR_JSON=$(gh api repos/${{ github.repository }}/pulls/${{ steps.parse.outputs.pr_number }}) - echo "ref=$(echo "$PR_JSON" | jq -r '.head.ref')" >> "$GITHUB_OUTPUT" - echo "repo=$(echo "$PR_JSON" | jq -r '.head.repo.full_name')" >> "$GITHUB_OUTPUT" - echo "sha=$(echo "$PR_JSON" | jq -r '.head.sha')" >> "$GITHUB_OUTPUT" + if [[ "${#MATCHING_TAGS[@]}" -eq 1 ]]; then + TEST_TAG="${MATCHING_TAGS[0]}" + TEST_NAME="${TEST_TAG%-*}" + TEST_HASH="${TEST_TAG##*-}" + echo "enabled=true" >> "$GITHUB_OUTPUT" + echo "test_tag=$TEST_TAG" >> "$GITHUB_OUTPUT" + echo "test_name=$TEST_NAME" >> "$GITHUB_OUTPUT" + echo "test_hash=$TEST_HASH" >> "$GITHUB_OUTPUT" + echo "reason=Matched testing tag $TEST_TAG for PR SHA $PR_SHA" >> "$GITHUB_OUTPUT" + else + echo "enabled=false" >> "$GITHUB_OUTPUT" + echo "reason=No - tag found on PR labels for current SHA $PR_SHA" >> "$GITHUB_OUTPUT" + fi - - name: Add reaction to comment - if: github.event_name != 'workflow_dispatch' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh api repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions \ - -f content=rocket + - name: Skip when no matching testing tag is present + if: steps.parse.outputs.enabled != 'true' + run: echo "${{ steps.parse.outputs.reason }}" - name: Dispatch to testing repo + if: steps.parse.outputs.enabled == 'true' env: GH_TOKEN: ${{ secrets.OPENSERVERLESS_TESTING_PAT }} run: | @@ -84,7 +86,9 @@ jobs: -X POST \ -f event_type=operator-pr-test \ -f 'client_payload[pr_number]=${{ steps.parse.outputs.pr_number }}' \ - -f 'client_payload[pr_ref]=${{ steps.pr.outputs.ref }}' \ - -f 'client_payload[pr_sha]=${{ steps.pr.outputs.sha }}' \ - -f 'client_payload[operator_repo]=${{ steps.pr.outputs.repo }}' \ - -f 'client_payload[platform]=${{ steps.parse.outputs.platform }}' + -f 'client_payload[pr_ref]=${{ steps.parse.outputs.pr_ref }}' \ + -f 'client_payload[pr_sha]=${{ steps.parse.outputs.pr_sha }}' \ + -f 'client_payload[operator_repo]=${{ steps.parse.outputs.repo }}' \ + -f 'client_payload[test_tag]=${{ steps.parse.outputs.test_tag }}' \ + -f 'client_payload[test_name]=${{ steps.parse.outputs.test_name }}' \ + -f 'client_payload[test_hash]=${{ steps.parse.outputs.test_hash }}' diff --git a/.gitmodules b/.gitmodules index 09b65757..e824f4e0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "olaris"] path = olaris - url = https://github.com/apache/openserverless-task.git + url = https://github.com/nuvolaris/openserverless-task.git diff --git a/README.md b/README.md index 7f6ec17f..b5b0e271 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ We describe how to build and test the operator in our development environment Please refer to the [website](https://openserverless.apache.org) for user information. +For PR-driven infrastructure tests on GitHub, use a PR label in the form `-`, for example `k3s-abcdef1`. + ## How to build and use an operator image Ensure you have satisfied the prerequisites below. Most notably, you need to use our development virtual machine and you @@ -90,4 +92,3 @@ task all The operator instance will be configured applying the `test/k3s/whisk.yaml` template. All the components are activated except TLS and MONITORING. - diff --git a/deploy/ferretdb/ferretdb-sts.yaml b/deploy/ferretdb/ferretdb-sts.yaml index 93cff826..6ef2dc69 100644 --- a/deploy/ferretdb/ferretdb-sts.yaml +++ b/deploy/ferretdb/ferretdb-sts.yaml @@ -36,9 +36,12 @@ spec: app: nuvolaris-mongodb name: nuvolaris-mongodb spec: + securityContext: + fsGroup: 1001 + fsGroupChangePolicy: Always containers: - image: ghcr.io/nuvolaris/ferretdb:1.6.0 name: ferretdb env: - name: FERRETDB_POSTGRESQL_URL - value: postgresql://nuvolaris:s0meP%40ass3@nuvolaris-postgres.nuvolaris.svc.cluster.local:5432/nuvolaris \ No newline at end of file + value: postgresql://nuvolaris:s0meP%40ass3@nuvolaris-postgres.nuvolaris.svc.cluster.local:5432/nuvolaris diff --git a/deploy/nuvolaris-permissions/operator-roles.yaml b/deploy/nuvolaris-permissions/operator-roles.yaml index c058e794..ac61aadf 100644 --- a/deploy/nuvolaris-permissions/operator-roles.yaml +++ b/deploy/nuvolaris-permissions/operator-roles.yaml @@ -83,7 +83,7 @@ rules: verbs: ["get","patch","list","update","watch","create","delete"] # required for traefik middlewares -- apiGroups: ["traefik.containo.us"] +- apiGroups: ["traefik.io"] resources: ["middlewares"] verbs: ["get","patch","list","update","watch","create","delete"] diff --git a/nuvolaris/endpoint.py b/nuvolaris/endpoint.py index 0165e10c..f0226d05 100644 --- a/nuvolaris/endpoint.py +++ b/nuvolaris/endpoint.py @@ -240,11 +240,11 @@ def delete(owner=None): return res if(ingress_class == 'traefik'): - res = kube.kubectl("delete", "middleware.traefik.containo.us",api_middleware_ingress_name(namespace,"apihost")) - res += kube.kubectl("delete", "middleware.traefik.containo.us",api_middleware_ingress_name(namespace,"apihost-my")) - res += kube.kubectl("delete", "middleware.traefik.containo.us",api_middleware_ingress_name(namespace,"apihost-info")) + res = kube.kubectl("delete", "middleware.traefik.io",api_middleware_ingress_name(namespace,"apihost")) + res += kube.kubectl("delete", "middleware.traefik.io",api_middleware_ingress_name(namespace,"apihost-my")) + res += kube.kubectl("delete", "middleware.traefik.io",api_middleware_ingress_name(namespace,"apihost-info")) if should_delete_www: - res += kube.kubectl("delete", "middleware.traefik.containo.us",api_middleware_ingress_name(namespace,"apihost-www-my")) + res += kube.kubectl("delete", "middleware.traefik.io",api_middleware_ingress_name(namespace,"apihost-www-my")) res += kube.kubectl("delete", "ingress",api_ingress_name(namespace,"apihost")) res += kube.kubectl("delete", "ingress",api_ingress_name(namespace,"apihost-my")) @@ -321,8 +321,8 @@ def delete_ow_api_endpoint(ucfg): return res if(ingress_class == 'traefik'): - res += kube.kubectl("delete", "middleware.traefik.containo.us",api_middleware_ingress_name(namespace,"apihost")) - res += kube.kubectl("delete", "middleware.traefik.containo.us",api_middleware_ingress_name(namespace,"apihost-my")) + res += kube.kubectl("delete", "middleware.traefik.io",api_middleware_ingress_name(namespace,"apihost")) + res += kube.kubectl("delete", "middleware.traefik.io",api_middleware_ingress_name(namespace,"apihost-my")) res += kube.kubectl("delete", "ingress",api_ingress_name(namespace,"apihost")) res += kube.kubectl("delete", "ingress",api_ingress_name(namespace,"apihost-my")) diff --git a/nuvolaris/main.py b/nuvolaris/main.py index 2c72f6e2..44ccbe81 100644 --- a/nuvolaris/main.py +++ b/nuvolaris/main.py @@ -50,13 +50,26 @@ def configure(settings: kopf.OperatorSettings, **_): # tested by an integration test @kopf.on.login() -def login(**kwargs): +def login(logger, **kwargs): token = '/var/run/secrets/kubernetes.io/serviceaccount/token' if os.path.isfile(token): - logging.debug("found serviceaccount token: login via pykube in kubernetes") - return kopf.login_via_pykube(**kwargs) - logging.debug("login via client") - return kopf.login_via_client(**kwargs) + for method, handler in [ + ("service-account", kopf.login_with_service_account), + ("client", kopf.login_via_client), + ("pykube", kopf.login_via_pykube), + ]: + try: + credentials = handler(logger=logger, **kwargs) + except Exception: + logger.exception("login via %s failed", method) + continue + if credentials is not None: + logger.info("authenticated in-cluster via %s", method) + return credentials + logger.warning("login via %s returned no credentials", method) + raise kopf.LoginError("No in-cluster credentials were retrieved from service account, client, or pykube.") + logger.debug("login via client") + return kopf.login_via_client(logger=logger, **kwargs) # tested by an integration test @kopf.on.create('nuvolaris.org', 'v1', 'whisks') @@ -421,4 +434,4 @@ def runtimes_cm_event_watcher(event, **kwargs): patcher.patch_preloader(owner) if cfg.get('components.openwhisk'): - patcher.restart_whisk(owner) \ No newline at end of file + patcher.restart_whisk(owner) diff --git a/nuvolaris/minio_ingress.py b/nuvolaris/minio_ingress.py index 14d6d397..06e4a458 100644 --- a/nuvolaris/minio_ingress.py +++ b/nuvolaris/minio_ingress.py @@ -203,7 +203,7 @@ def delete_minio_ingress(runtime, namespace, ingress_class, type, owner=None): res += kube.kubectl("delete", "ingress",endpoint.api_ingress_name(namespace,type)) if(ingress_class == 'traefik'): - res = kube.kubectl("delete", "middleware.traefik.containo.us",endpoint.api_middleware_ingress_name(namespace,type)) + res = kube.kubectl("delete", "middleware.traefik.io",endpoint.api_middleware_ingress_name(namespace,type)) return res except Exception as e: diff --git a/nuvolaris/registry_deploy.py b/nuvolaris/registry_deploy.py index db211a51..7e74fbea 100644 --- a/nuvolaris/registry_deploy.py +++ b/nuvolaris/registry_deploy.py @@ -221,7 +221,7 @@ def delete_registry_ingress(owner=None, namespace="nuvolaris"): res += kube.kubectl("delete", "ingress",endpoint.api_ingress_name(namespace,"registry")) if(ingress_class == 'traefik'): - res = kube.kubectl("delete", "middleware.traefik.containo.us",endpoint.api_middleware_ingress_name(namespace,"registry")) + res = kube.kubectl("delete", "middleware.traefik.io",endpoint.api_middleware_ingress_name(namespace,"registry")) return res except Exception as e: diff --git a/nuvolaris/seaweedfs_ingress.py b/nuvolaris/seaweedfs_ingress.py index 1c0eb725..fc3de5e7 100644 --- a/nuvolaris/seaweedfs_ingress.py +++ b/nuvolaris/seaweedfs_ingress.py @@ -151,7 +151,7 @@ def delete_seaweedfs_ingress(runtime, namespace, ingress_class, type, owner=None res += kube.kubectl("delete", "ingress",endpoint.api_ingress_name(namespace,type)) if(ingress_class == 'traefik'): - res = kube.kubectl("delete", "middleware.traefik.containo.us",endpoint.api_middleware_ingress_name(namespace,type)) + res = kube.kubectl("delete", "middleware.traefik.io",endpoint.api_middleware_ingress_name(namespace,type)) return res except Exception as e: diff --git a/nuvolaris/storage_static.py b/nuvolaris/storage_static.py index db4b8db7..03825e7a 100644 --- a/nuvolaris/storage_static.py +++ b/nuvolaris/storage_static.py @@ -177,7 +177,7 @@ def delete_ow_static_endpoint(ucfg): if(ingress_class == 'traefik'): middleware_name = static_middleware_ingress_name(namespace) - res += kube.kubectl("delete", "middleware.traefik.containo.us",middleware_name) + res += kube.kubectl("delete", "middleware.traefik.io",middleware_name) ingress_name = static_ingress_name(namespace) res += kube.kubectl("delete", "ingress",ingress_name) @@ -221,11 +221,11 @@ def delete_nuv_ingresses(): if(ingress_class == 'traefik'): middleware_name = static_middleware_ingress_name("nuvolaris") - res += kube.kubectl("delete", "middleware.traefik.containo.us",middleware_name) + res += kube.kubectl("delete", "middleware.traefik.io",middleware_name) if should_delete_www: middleware_name = static_middleware_ingress_name("www-nuvolaris") - res += kube.kubectl("delete", "middleware.traefik.containo.us",middleware_name) + res += kube.kubectl("delete", "middleware.traefik.io",middleware_name) ingress_name = static_ingress_name("nuvolaris") res += kube.kubectl("delete", "ingress",ingress_name) diff --git a/nuvolaris/templates/ferretdb-sts.yaml b/nuvolaris/templates/ferretdb-sts.yaml index 92542255..c09bb4fb 100644 --- a/nuvolaris/templates/ferretdb-sts.yaml +++ b/nuvolaris/templates/ferretdb-sts.yaml @@ -36,14 +36,12 @@ spec: app: nuvolaris-mongodb name: nuvolaris-mongodb spec: - {% if applypodsecurity %} securityContext: - fsGroup: 65534 - runAsUser: 65534 - {% endif %} + fsGroup: 1001 + fsGroupChangePolicy: Always containers: - image: ghcr.io/nuvolaris/ferretdb:1.6.0 name: ferretdb env: - name: FERRETDB_POSTGRESQL_URL - value: {{ferretdb_postgres_url}} \ No newline at end of file + value: {{ferretdb_postgres_url}} diff --git a/nuvolaris/templates/traefik-middleware-tpl.yaml b/nuvolaris/templates/traefik-middleware-tpl.yaml index 5acebfb5..c3bc4c3c 100644 --- a/nuvolaris/templates/traefik-middleware-tpl.yaml +++ b/nuvolaris/templates/traefik-middleware-tpl.yaml @@ -16,7 +16,7 @@ # under the License. # --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: namespace: {{namespace}} diff --git a/nuvolaris/util.py b/nuvolaris/util.py index 0d0211a3..99eea0fe 100644 --- a/nuvolaris/util.py +++ b/nuvolaris/util.py @@ -158,17 +158,35 @@ def get_ingress_class(runtime): logging.warn(f"skipping ingress class auto detection and returning {ingress_class}") return ingress_class - # ingress class default to nginx + # Default according to the historical runtime assumptions. ingress_class = "nginx" - - # On microk8s ingress class must be public if runtime == "microk8s": ingress_class = "public" - - # On k3s ingress class must be traefik - if runtime == "k3s": + elif runtime == "k3s": ingress_class = "traefik" + # Prefer the ingress class that actually exists in the current cluster. + try: + detected = kube.kubectl( + "get", + "ingressclass", + namespace=None, + jsonpath=r"{.items[*].metadata.name}", + debugresult=False, + ) + detected = [item for item in detected if item] + if detected: + logging.info(f"auto-detected ingress classes: {detected}") + if "nginx" in detected: + return "nginx" + if runtime == "microk8s" and "public" in detected: + return "public" + if runtime == "k3s" and "traefik" in detected: + return "traefik" + return detected[0] + except Exception as e: + logging.warning(f"failed to auto-detect ingress classes, using default {ingress_class}: {e}") + return ingress_class # determine the ingress-nginx flavour @@ -890,4 +908,3 @@ def get_seaweedds_filer_host(): seaweedfs_filer_port = cfg.get("seaweedfs.port", "SEAWEEDFS_API_PORT", "9090") return f"http://{seaweedfs_filer_host}:{seaweedfs_filer_port}" - diff --git a/olaris b/olaris index 775b7279..7799a2a8 160000 --- a/olaris +++ b/olaris @@ -1 +1 @@ -Subproject commit 775b7279cf7fa7d5c427ccfd249fa34f2b880b87 +Subproject commit 7799a2a80802d6648f0ed523aebab694552450d0 diff --git a/poetry.lock b/poetry.lock index 1c39818a..842ac829 100644 --- a/poetry.lock +++ b/poetry.lock @@ -698,21 +698,6 @@ pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] reauth = ["pyu2f (>=0.1.5)"] requests = ["requests (>=2.20.0,<3.0.0.dev0)"] -[[package]] -name = "httplib2" -version = "0.22.0" -description = "A comprehensive HTTP client library." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] -files = [ - {file = "httplib2-0.22.0-py3-none-any.whl", hash = "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc"}, - {file = "httplib2-0.22.0.tar.gz", hash = "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81"}, -] - -[package.dependencies] -pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""} - [[package]] name = "idna" version = "3.10" @@ -1077,25 +1062,6 @@ files = [ {file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"}, ] -[[package]] -name = "oauth2client" -version = "4.1.3" -description = "OAuth 2.0 client library" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "oauth2client-4.1.3-py2.py3-none-any.whl", hash = "sha256:b8a81cc5d60e2d364f0b1b98f958dbd472887acaf1a5b05e21c28c31a2d6d3ac"}, - {file = "oauth2client-4.1.3.tar.gz", hash = "sha256:d486741e451287f69568a4d26d70d9acd73a2bbfa275746c535b4209891cccc6"}, -] - -[package.dependencies] -httplib2 = ">=0.9.1" -pyasn1 = ">=0.1.7" -pyasn1-modules = ">=0.0.5" -rsa = ">=3.1.4" -six = ">=1.6.1" - [[package]] name = "oauthlib" version = "3.2.2" @@ -1475,26 +1441,6 @@ files = [ [package.extras] windows-terminal = ["colorama (>=0.4.6)"] -[[package]] -name = "pykube" -version = "0.15.0" -description = "Python client library for Kubernetes" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "pykube-0.15.0-py2.py3-none-any.whl", hash = "sha256:8d50b09b63d5e754f3379032be58bed035692e2e308a0b35e57b0074b3f90bb9"}, - {file = "pykube-0.15.0.tar.gz", hash = "sha256:e53800d0d45f13911aa4ebca8463ae5cc82afad461f6575a0a217d2fce5f088b"}, -] - -[package.dependencies] -oauth2client = "*" -PyYAML = "*" -requests = ">=2.12" -requests-oauthlib = "*" -six = ">=1.10.0" -tzlocal = "*" - [[package]] name = "pykube-ng" version = "23.6.0" @@ -1516,21 +1462,6 @@ urllib3 = ">=1.26.9" gcp = ["google-auth", "jsonpath-ng"] oidc = ["requests-oauthlib (>=1.3.0,<2.0.0)"] -[[package]] -name = "pyparsing" -version = "3.2.1" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pyparsing-3.2.1-py3-none-any.whl", hash = "sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1"}, - {file = "pyparsing-3.2.1.tar.gz", hash = "sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a"}, -] - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -1763,30 +1694,12 @@ description = "Provider of IANA time zone data" optional = false python-versions = ">=2" groups = ["main"] -markers = "platform_system == \"Windows\" or sys_platform == \"win32\"" +markers = "sys_platform == \"win32\"" files = [ {file = "tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"}, {file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"}, ] -[[package]] -name = "tzlocal" -version = "5.2" -description = "tzinfo object for the local timezone" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "tzlocal-5.2-py3-none-any.whl", hash = "sha256:49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8"}, - {file = "tzlocal-5.2.tar.gz", hash = "sha256:8d399205578f1a9342816409cc1e46a93ebd5755e39ea2d85334bea911bf0e6e"}, -] - -[package.dependencies] -tzdata = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"] - [[package]] name = "urllib3" version = "2.3.0" @@ -1934,4 +1847,4 @@ propcache = ">=0.2.0" [metadata] lock-version = "2.1" python-versions = "^3.12" -content-hash = "96fb6aaa01cff4e1fd8b926967d18bfdf537e64ab6c36a897277930e31b270c5" +content-hash = "a02951a9f022362b76646aceeecc5ae110cf27bd011db6daf1ae7c55ee8ded39" diff --git a/pyproject.toml b/pyproject.toml index c11a0496..7bb2e669 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ license = "Apache-2.0" python = "^3.12" kopf = {extras = ["full-auth"], version = "^1.36.1"} PyYAML = "^6.0" -pykube = "^0.15.0" +pykube-ng = "^23.6.0" Jinja2 = "^3.0.3" requests = "^2.32.4" flatdict = "^4.1.0" diff --git a/run.sh b/run.sh index d0c273ad..8a40774d 100755 --- a/run.sh +++ b/run.sh @@ -27,7 +27,6 @@ then mkdir -p deploy fi # start the operator if possible if kubectl -n nuvolaris get cm/config -then poetry run kopf run -n nuvolaris -m nuvolaris nuvolaris/main.py nuvolaris/user_handlers.py nuvolaris/workflows.py "$@" +then exec /home/nuvolaris/.venv/bin/kopf run -n nuvolaris -m nuvolaris nuvolaris/main.py nuvolaris/user_handlers.py nuvolaris/workflows.py "$@" else echo "You need to 'kubectl apply -f deploy/permissions' before starting the operator." fi -