diff --git a/deploy/nuvolaris-permissions/operator-roles.yaml b/deploy/nuvolaris-permissions/operator-roles.yaml index ac61aad..36d3872 100644 --- a/deploy/nuvolaris-permissions/operator-roles.yaml +++ b/deploy/nuvolaris-permissions/operator-roles.yaml @@ -83,6 +83,10 @@ rules: verbs: ["get","patch","list","update","watch","create","delete"] # required for traefik middlewares +- apiGroups: ["traefik.containo.us"] + resources: ["middlewares"] + verbs: ["get","patch","list","update","watch","create","delete"] + - apiGroups: ["traefik.io"] resources: ["middlewares"] verbs: ["get","patch","list","update","watch","create","delete"] diff --git a/nuvolaris/endpoint.py b/nuvolaris/endpoint.py index f0226d0..ef4c676 100644 --- a/nuvolaris/endpoint.py +++ b/nuvolaris/endpoint.py @@ -240,11 +240,12 @@ def delete(owner=None): return res if(ingress_class == 'traefik'): - 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")) + middleware_resource = util.get_traefik_middleware_resource() + res = kube.kubectl("delete", middleware_resource,api_middleware_ingress_name(namespace,"apihost")) + res += kube.kubectl("delete", middleware_resource,api_middleware_ingress_name(namespace,"apihost-my")) + res += kube.kubectl("delete", middleware_resource,api_middleware_ingress_name(namespace,"apihost-info")) if should_delete_www: - res += kube.kubectl("delete", "middleware.traefik.io",api_middleware_ingress_name(namespace,"apihost-www-my")) + res += kube.kubectl("delete", middleware_resource,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 +322,9 @@ def delete_ow_api_endpoint(ucfg): return res if(ingress_class == 'traefik'): - 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")) + middleware_resource = util.get_traefik_middleware_resource() + res += kube.kubectl("delete", middleware_resource,api_middleware_ingress_name(namespace,"apihost")) + res += kube.kubectl("delete", middleware_resource,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/ingress_data.py b/nuvolaris/ingress_data.py index ff63fb2..1ac7e3d 100644 --- a/nuvolaris/ingress_data.py +++ b/nuvolaris/ingress_data.py @@ -41,6 +41,7 @@ def __init__(self, apihost): "hostname":hostname, "tls":tls, "ingress_class":ingress_class, + "traefik_middleware_api_version": util.get_traefik_middleware_api_version(), "path_type":path_type, "route_timeout_seconds":tutil.duration_in_second(util.get_controller_http_timeout()), 'needs_rewrite': False, @@ -121,4 +122,4 @@ def render_traefik_middleware_template(self, namespace,tpl="traefik-middleware-t logging.info(f"*** Rendering traefik middleware template using host {self._data['hostname']} endpoint for {self._data['ingress_name']} via template {tpl}") out = f"/tmp/__{namespace}_{tpl}" file = ntp.spool_template(tpl, out, self._data) - return os.path.abspath(file) \ No newline at end of file + return os.path.abspath(file) diff --git a/nuvolaris/minio_ingress.py b/nuvolaris/minio_ingress.py index 06e4a45..68d4009 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.io",endpoint.api_middleware_ingress_name(namespace,type)) + res = kube.kubectl("delete", util.get_traefik_middleware_resource(),endpoint.api_middleware_ingress_name(namespace,type)) return res except Exception as e: @@ -223,4 +223,4 @@ def delete_minio_ingresses(data, owner=None): if data['minio_console_ingress_enabled']: res += delete_minio_ingress(runtime, namespace, ingress_class, "minio-console", owner) - return res \ No newline at end of file + return res diff --git a/nuvolaris/registry_deploy.py b/nuvolaris/registry_deploy.py index 7e74fbe..e9c13fe 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.io",endpoint.api_middleware_ingress_name(namespace,"registry")) + res = kube.kubectl("delete", util.get_traefik_middleware_resource(),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 fc3de5e..81b4061 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.io",endpoint.api_middleware_ingress_name(namespace,type)) + res = kube.kubectl("delete", util.get_traefik_middleware_resource(),endpoint.api_middleware_ingress_name(namespace,type)) return res except Exception as e: @@ -170,4 +170,4 @@ def delete_seaweedfs_ingresses(data, owner=None): if data['seaweedfs_console_ingress_enabled']: res += delete_seaweedfs_ingress(runtime, namespace, ingress_class, "seaweedfs-filer", owner) - return res \ No newline at end of file + return res diff --git a/nuvolaris/storage_static.py b/nuvolaris/storage_static.py index 03825e7..c6be2c2 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.io",middleware_name) + res += kube.kubectl("delete", util.get_traefik_middleware_resource(),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.io",middleware_name) + res += kube.kubectl("delete", util.get_traefik_middleware_resource(),middleware_name) if should_delete_www: middleware_name = static_middleware_ingress_name("www-nuvolaris") - res += kube.kubectl("delete", "middleware.traefik.io",middleware_name) + res += kube.kubectl("delete", util.get_traefik_middleware_resource(),middleware_name) ingress_name = static_ingress_name("nuvolaris") res += kube.kubectl("delete", "ingress",ingress_name) @@ -264,4 +264,4 @@ def patch(status, action, owner=None): logging.info(f"*** hanlded request to {action} static") except Exception as e: logging.error('*** failed to update static: %s' % e) - operator_util.patch_operator_status(status,'static','error') \ No newline at end of file + operator_util.patch_operator_status(status,'static','error') diff --git a/nuvolaris/templates/traefik-middleware-tpl.yaml b/nuvolaris/templates/traefik-middleware-tpl.yaml index c3bc4c3..eeb748a 100644 --- a/nuvolaris/templates/traefik-middleware-tpl.yaml +++ b/nuvolaris/templates/traefik-middleware-tpl.yaml @@ -16,7 +16,7 @@ # under the License. # --- -apiVersion: traefik.io/v1alpha1 +apiVersion: {{traefik_middleware_api_version}} kind: Middleware metadata: namespace: {{namespace}} @@ -30,4 +30,4 @@ spec: replacePathRegex: regex: {{context_path}}{{context_regexp}} replacement: {{rewrite_target}} - {% endif %} \ No newline at end of file + {% endif %} diff --git a/nuvolaris/util.py b/nuvolaris/util.py index 99eea0f..b616851 100644 --- a/nuvolaris/util.py +++ b/nuvolaris/util.py @@ -189,6 +189,31 @@ def get_ingress_class(runtime): return ingress_class +def get_traefik_middleware_api_version(): + """ + Detect the Traefik Middleware apiVersion supported by the current cluster. + Prefer the new group `traefik.io`, while keeping compatibility with the + historical `traefik.containo.us` CRDs. + """ + candidates = [ + ("middlewares.traefik.io", "traefik.io/v1alpha1"), + ("middlewares.traefik.containo.us", "traefik.containo.us/v1alpha1"), + ] + for crd_name, api_version in candidates: + try: + kube.kubectl("get", "crd", crd_name, namespace=None, debugresult=False) + logging.info(f"detected Traefik middleware apiVersion {api_version} via CRD {crd_name}") + return api_version + except Exception: + continue + + logging.warning("could not auto-detect Traefik middleware CRD; defaulting to traefik.io/v1alpha1") + return "traefik.io/v1alpha1" + +def get_traefik_middleware_resource(): + api_group = get_traefik_middleware_api_version().split("/")[0] + return f"middleware.{api_group}" + # determine the ingress-nginx flavour def get_ingress_yaml(runtime): if runtime == "eks": @@ -907,4 +932,3 @@ def get_seaweedds_filer_host(): seaweedfs_filer_host = cfg.get("seaweedfs.host", "SEAWEEDFS_API_HOST", "seaweedfs") seaweedfs_filer_port = cfg.get("seaweedfs.port", "SEAWEEDFS_API_PORT", "9090") return f"http://{seaweedfs_filer_host}:{seaweedfs_filer_port}" - diff --git a/tests/auth.ipy b/tests/auth.ipy index e69de29..d0a78df 100644 --- a/tests/auth.ipy +++ b/tests/auth.ipy @@ -0,0 +1,17 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +#