# Copyright (c) 2023 VEXXHOST, Inc.
#
# Licensed 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.

import abc
import glob
import importlib.resources
import os
import textwrap
import types
import typing

import certifi
import pkg_resources
import pykube  # type: ignore
import yaml
from magnum import objects as magnum_objects  # type: ignore
from magnum.common import context, neutron  # type: ignore
from magnum.common.cert_manager import cert_manager  # type: ignore
from magnum.common.x509 import operations as x509  # type: ignore
from magnum.conductor.handlers.common import (
    cert_manager as cert_manager_handlers,  # type: ignore
)
from oslo_config import cfg  # type: ignore
from oslo_serialization import base64  # type: ignore
from oslo_utils import encodeutils  # type: ignore

from magnum_cluster_api import (
    clients,
    helm,
    image_utils,
    images,
    json_patches,
    magnum_cluster_api,
    objects,
    utils,
)
from magnum_cluster_api.integrations import cinder, cloud_provider, manila

CONF = cfg.CONF
CALICO_TAG = "v3.24.2"
CILIUM_TAG = "v1.15.3"

CLUSTER_CLASS_VERSION = pkg_resources.require("magnum_cluster_api")[0].version
CLUSTER_CLASS_NAME = f"magnum-v{CLUSTER_CLASS_VERSION}"
CLUSTER_CLASS_NODE_VOLUME_DETACH_TIMEOUT = "300s"  # seconds

PLACEHOLDER = "PLACEHOLDER"
PLACEHOLDER_UUID = "00000000-0000-0000-0000-000000000000"

AUTOSCALE_ANNOTATION_MIN = "cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size"
AUTOSCALE_ANNOTATION_MAX = "cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size"

DEFAULT_POD_CIDR = "10.100.0.0/16"


class ClusterAutoscalerHelmRelease:
    def __init__(self, api, cluster) -> None:
        self.cluster = cluster

    @property
    def apply(self):
        image = images.get_cluster_autoscaler_image(
            utils.get_kube_tag(self.cluster),
        )
        image_repo, image_tag = image.split(":", 1)

        return helm.UpgradeReleaseCommand(
            namespace="magnum-system",
            release_name=self.cluster.stack_id,
            chart_ref=os.path.join(
                pkg_resources.resource_filename("magnum_cluster_api", "charts"),
                "cluster-autoscaler/",
            ),
            values={
                "fullnameOverride": f"{self.cluster.stack_id}-autoscaler",
                "cloudProvider": "clusterapi",
                "clusterAPIMode": "kubeconfig-incluster",
                "clusterAPIKubeconfigSecret": f"{self.cluster.stack_id}-kubeconfig",
                "autoDiscovery": {
                    "clusterName": self.cluster.stack_id,
                },
                "image": {
                    "repository": image_repo,
                    "tag": image_tag,
                },
                "nodeSelector": {
                    "openstack-control-plane": "enabled",
                },
            },
        )

    @property
    def delete(self):
        return helm.DeleteReleaseCommand(
            namespace="magnum-system",
            release_name=self.cluster.stack_id,
            skip_missing=True,
        )


class ClusterServerGroups:
    def __init__(
        self, context: context.RequestContext, cluster: magnum_objects.Cluster
    ) -> None:
        self.cluster = cluster
        self.context = context
        self.osc = clients.get_openstack_api(self.context)

    def apply(self):
        # Create a server group for controlplane
        utils.ensure_controlplane_server_group(ctx=self.context, cluster=self.cluster)

        # Create a server group per a nodegroup
        for ng in self.cluster.nodegroups:
            if ng.role == "master":
                continue
            utils.ensure_worker_server_group(
                ctx=self.context, cluster=self.cluster, node_group=ng
            )

    def delete(self):
        # delete controlplane server group
        utils.delete_controlplane_server_group(ctx=self.context, cluster=self.cluster)

        # Create worker server groups
        for ng in self.cluster.nodegroups:
            if ng.role == "master":
                continue

            utils.delete_worker_server_group(
                ctx=self.context, cluster=self.cluster, node_group=ng
            )


class Base(abc.ABC):
    def __init__(self, api: magnum_cluster_api.KubeClient, namespace="magnum-system"):
        self.api = api
        self.namespace = namespace

    @property
    @abc.abstractmethod
    def api_version(self) -> str:
        pass

    @property
    @abc.abstractmethod
    def kind(self) -> str:
        pass

    @property
    @abc.abstractmethod
    def name(self) -> str:
        pass

    @abc.abstractmethod
    def get_object(self) -> dict:
        pass

    def get_resource(self) -> dict:
        resource = self.get_object()

        resource["apiVersion"] = self.api_version
        resource["kind"] = self.kind

        resource.setdefault("metadata", {})
        resource["metadata"].setdefault("name", self.name)
        if self.kind != "Namespace":
            resource["metadata"].setdefault("namespace", self.namespace)

        return resource

    def apply(self):
        resource = self.get_resource()
        self.api.create_or_update(resource)

    def delete(self) -> None:
        self.api.delete(
            self.api_version, self.kind, self.name, namespace=self.namespace
        )


class Namespace(Base):
    @property
    def api_version(self) -> str:
        return "v1"

    @property
    def kind(self) -> str:
        return "Namespace"

    @property
    def name(self) -> str:
        return self.namespace

    def get_object(self) -> dict:
        return {}


class ClusterBase(Base):
    def __init__(
        self, api: magnum_cluster_api.KubeClient, cluster: magnum_objects.Cluster
    ):
        super().__init__(api)
        self.cluster = cluster

    @property
    def name(self) -> str:
        return self.cluster.uuid

    @property
    def labels(self) -> dict:
        return {
            "cluster-uuid": self.cluster.uuid,
        }


class ClusterResourcesConfigMap(ClusterBase):
    def __init__(
        self,
        context: context.RequestContext,
        api: magnum_cluster_api.KubeClient,
        pykube_api: pykube.HTTPClient,
        cluster: magnum_objects.Cluster,
        namespace: str = "magnum-system",
    ):
        self.context = context
        self.api = api
        self.pykube_api = pykube_api
        self.cluster = cluster
        self.namespace = namespace

    @property
    def api_version(self) -> str:
        return "v1"

    @property
    def kind(self) -> str:
        return "ConfigMap"

    def get_object(self) -> dict:
        manifests_path = pkg_resources.resource_filename(
            "magnum_cluster_api", "manifests"
        )
        calico_version = self.cluster.labels.get("calico_tag", CALICO_TAG)
        cilium_version = self.cluster.labels.get("cilium_tag", CILIUM_TAG)

        repository = utils.get_cluster_container_infra_prefix(self.cluster)

        osc = clients.get_openstack_api(self.context)

        data = {
            **{
                os.path.basename(manifest): image_utils.update_manifest_images(
                    self.cluster.uuid,
                    manifest,
                    repository=repository,
                    replacements=[
                        (
                            "docker.io/k8scloudprovider/openstack-cloud-controller-manager:latest",
                            cloud_provider.get_image(self.cluster),
                        ),
                    ],
                )
                for manifest in glob.glob(os.path.join(manifests_path, "ccm/*.yaml"))
            },
        }

        if self.cluster.cluster_template.network_driver == "cilium":
            data = {
                **data,
                **{
                    "cilium.yml": helm.TemplateReleaseCommand(
                        namespace="kube-system",
                        release_name="cilium",
                        chart_ref=os.path.join(
                            pkg_resources.resource_filename(
                                "magnum_cluster_api", "charts"
                            ),
                            "cilium/",
                        ),
                        values={
                            "cni": {"chainingMode": "portmap"},
                            "image": {
                                "tag": cilium_version,
                            },
                            # NOTE(okozachenko): cilium has a limitation https://github.com/cilium/cilium/issues/9207
                            #                    Because of that, it fails on the test
                            #                    `Services should serve endpoints on same port and different protocols`.
                            #                    https://github.com/kubernetes/kubernetes/pull/120069#issuecomment-2111252221
                            "k8s": {"serviceProxyName": "cilium"},
                            "operator": {
                                "image": {
                                    "tag": cilium_version,
                                },
                            },
                            # NOTE(okozachenko): For users who run with kube-proxy (i.e. with Cilium's kube-proxy
                            #                    replacement disabled), the ClusterIP service loadbalancing when a
                            #                    request is sent from a pod running in a non-host network namespace
                            #                    is still performed at the pod network interface (until
                            #                    https://github.com/cilium/cilium/issues/16197 is fixed). For this
                            #                    case the session affinity support is disabled by default.
                            "sessionAffinity": "true",
                            "ipam": {
                                "operator": {
                                    "clusterPoolIPv4PodCIDRList": [
                                        self.cluster.labels.get(
                                            "cilium_ipv4pool",
                                            DEFAULT_POD_CIDR,
                                        ),
                                    ],
                                },
                            },
                        },
                    )(repository=repository)
                },
            }

        if self.cluster.cluster_template.network_driver == "calico":
            data = {
                **data,
                **{
                    "calico.yml": image_utils.update_manifest_images(
                        self.cluster.uuid,
                        os.path.join(manifests_path, f"calico/{calico_version}.yaml"),
                        repository=repository,
                    )
                },
            }

        if cinder.is_enabled(self.cluster):
            volume_types = osc.cinder().volume_types.list()
            default_volume_type = osc.cinder().volume_types.default()
            data = {
                **data,
                **{
                    os.path.basename(manifest): image_utils.update_manifest_images(
                        self.cluster.uuid,
                        manifest,
                        repository=repository,
                        replacements=[
                            (
                                "docker.io/k8scloudprovider/cinder-csi-plugin:latest",
                                cinder.get_image(self.cluster),
                            ),
                        ],
                    )
                    for manifest in glob.glob(
                        os.path.join(manifests_path, "cinder-csi/*.yaml")
                    )
                },
                **{
                    f"storageclass-block-{vt.name}.yaml": yaml.dump(
                        {
                            "apiVersion": objects.StorageClass.version,
                            "allowVolumeExpansion": True,
                            "kind": objects.StorageClass.kind,
                            "metadata": {
                                "annotations": (
                                    {
                                        "storageclass.kubernetes.io/is-default-class": "true"
                                    }
                                    if default_volume_type.name == vt.name
                                    else {}
                                ),
                                "name": "block-%s" % utils.convert_to_rfc1123(vt.name),
                            },
                            "provisioner": "cinder.csi.openstack.org",
                            "parameters": {
                                "type": vt.name,
                            },
                            "reclaimPolicy": "Delete",
                            "volumeBindingMode": "Immediate",
                        }
                    )
                    for vt in volume_types
                    if vt.name != "__DEFAULT__"
                },
            }

        if manila.is_enabled(self.cluster):
            share_types = osc.manila().share_types.list()
            share_network_id = self.cluster.labels.get("manila_csi_share_network_id")
            data = {
                **data,
                **{
                    "manila-csi-secret.yaml": yaml.dump(
                        {
                            "apiVersion": pykube.Secret.version,
                            "kind": pykube.Secret.kind,
                            "metadata": {
                                "name": "csi-manila-secrets",
                                "namespace": "kube-system",
                            },
                            "stringData": utils.generate_manila_csi_cloud_config(
                                self.context,
                                self.pykube_api,
                                self.cluster,
                            ),
                        },
                    )
                },
                **{
                    os.path.basename(manifest): image_utils.update_manifest_images(
                        self.cluster.uuid,
                        manifest,
                        repository=repository,
                    )
                    for manifest in glob.glob(
                        os.path.join(manifests_path, "nfs-csi/*.yaml")
                    )
                },
                **{
                    os.path.basename(manifest): image_utils.update_manifest_images(
                        self.cluster.uuid,
                        manifest,
                        repository=repository,
                        replacements=[
                            (
                                "registry.k8s.io/provider-os/manila-csi-plugin:latest",
                                manila.get_image(self.cluster),
                            ),
                        ],
                    )
                    for manifest in glob.glob(
                        os.path.join(manifests_path, "manila-csi/*.yaml")
                    )
                },
            }
            # NOTE: We only create StorageClasses if share_network_id specified.
            if share_network_id:
                data = {
                    **data,
                    **{
                        f"storageclass-share-{st.name}.yaml": yaml.dump(
                            {
                                "apiVersion": objects.StorageClass.version,
                                "allowVolumeExpansion": True,
                                "kind": objects.StorageClass.kind,
                                "metadata": {
                                    "name": "share-%s"
                                    % utils.convert_to_rfc1123(st.name),
                                },
                                "provisioner": "manila.csi.openstack.org",
                                "parameters": {
                                    "type": st.name,
                                    "shareNetworkID": share_network_id,
                                    "csi.storage.k8s.io/provisioner-secret-name": "csi-manila-secrets",
                                    "csi.storage.k8s.io/provisioner-secret-namespace": "kube-system",
                                    "csi.storage.k8s.io/controller-expand-secret-name": "csi-manila-secrets",
                                    "csi.storage.k8s.io/controller-expand-secret-namespace": "kube-system",
                                    "csi.storage.k8s.io/node-stage-secret-name": "csi-manila-secrets",
                                    "csi.storage.k8s.io/node-stage-secret-namespace": "kube-system",
                                    "csi.storage.k8s.io/node-publish-secret-name": "csi-manila-secrets",
                                    "csi.storage.k8s.io/node-publish-secret-namespace": "kube-system",
                                },
                                "reclaimPolicy": "Delete",
                                "volumeBindingMode": "Immediate",
                            }
                        )
                        for st in share_types
                    },
                }

        if utils.get_cluster_label_as_bool(self.cluster, "keystone_auth_enabled", True):
            auth_url = osc.url_for(
                service_type="identity",
                interface="public",
            )
            data = {
                **data,
                **{
                    "keystone-auth.yaml": helm.TemplateReleaseCommand(
                        namespace="kube-system",
                        release_name="k8s-keystone-auth",
                        chart_ref=os.path.join(
                            pkg_resources.resource_filename(
                                "magnum_cluster_api", "charts"
                            ),
                            "k8s-keystone-auth/",
                        ),
                        values={
                            "conf": {
                                "auth_url": auth_url
                                + ("" if auth_url.endswith("/v3") else "/v3"),
                                "ca_cert": utils.get_cloud_ca_cert(),
                                "policy": utils.get_keystone_auth_default_policy(
                                    self.cluster
                                ),
                            },
                        },
                    )(repository=repository)
                },
            }

        return {
            "data": data,
        }

    def get_or_none(self) -> objects.Cluster:
        return pykube.ConfigMap.objects(
            self.pykube_api, namespace="magnum-system"
        ).get_or_none(name=self.name)

    def delete(self):
        cr_cm = self.get_or_none()
        if cr_cm:
            cr_cm.delete()


class ClusterResourceSet(ClusterBase):
    @property
    def api_version(self) -> str:
        return "addons.cluster.x-k8s.io/v1beta1"

    @property
    def kind(self) -> str:
        return "ClusterResourceSet"

    def get_object(self) -> dict:
        return {
            "spec": {
                "clusterSelector": {
                    "matchLabels": {
                        "cluster-uuid": self.cluster.uuid,
                    },
                },
                "resources": [
                    {
                        "name": self.cluster.uuid,
                        "kind": "ConfigMap",
                    },
                ],
            },
        }


class CertificateAuthoritySecret(ClusterBase):
    def __init__(
        self,
        context: context.RequestContext,
        api: magnum_cluster_api.KubeClient,
        pykube_api: pykube.HTTPClient,
        cluster: magnum_objects.Cluster,
    ):
        super().__init__(api, cluster)
        self.pykube_api = pykube_api
        self.context = context

    @abc.abstractmethod
    def certificate_name(self) -> str:
        pass

    @abc.abstractmethod
    def magnum_cert_ref_name(self) -> str:
        pass

    @property
    def api_version(self) -> str:
        return "v1"

    @property
    def kind(self) -> str:
        return "Secret"

    @property
    def name(self) -> str:
        return f"{self.cluster.stack_id}-{self.certificate_name()}"

    def delete(self) -> None:
        resource = self.get_or_none()
        if resource:
            resource.delete()

    def get_or_none(self) -> pykube.Secret:
        return pykube.Secret.objects(
            self.pykube_api, namespace="magnum-system"
        ).get_or_none(name=self.name)

    def get_certificate(self) -> cert_manager.Cert:
        raise NotImplementedError()

    def get_object(self) -> dict:
        cert_ref = getattr(self.cluster, self.magnum_cert_ref_name())
        if cert_ref is None:
            raise Exception(
                "Certificate for %s doesn't exist." % self.magnum_cert_ref_name()
            )
        ca_cert = self.get_certificate()

        return {
            "type": "cluster.x-k8s.io/secret",
            "metadata": {
                "labels": {
                    "cluster.x-k8s.io/cluster-name": f"{self.cluster.stack_id}",
                },
            },
            "stringData": {
                "tls.crt": encodeutils.safe_decode(ca_cert.get_certificate()),
                "tls.key": encodeutils.safe_decode(
                    x509.decrypt_key(
                        ca_cert.get_private_key(),
                        ca_cert.get_private_key_passphrase(),
                    )
                ),
            },
        }


class ApiCertificateAuthoritySecret(CertificateAuthoritySecret):
    def certificate_name(self):
        return "ca"

    def magnum_cert_ref_name(self):
        return "ca_cert_ref"

    def get_certificate(self) -> cert_manager.Cert:
        return cert_manager_handlers.get_cluster_ca_certificate(
            self.cluster, self.context, "kubernetes"
        )


class EtcdCertificateAuthoritySecret(CertificateAuthoritySecret):
    def certificate_name(self):
        return "etcd"

    def magnum_cert_ref_name(self):
        return "etcd_ca_cert_ref"

    def get_certificate(self) -> cert_manager.Cert:
        return cert_manager_handlers.get_cluster_ca_certificate(
            self.cluster, self.context, "etcd"
        )


class FrontProxyCertificateAuthoritySecret(CertificateAuthoritySecret):
    def certificate_name(self):
        return "proxy"

    def magnum_cert_ref_name(self):
        return "front_proxy_ca_cert_ref"

    def get_certificate(self) -> cert_manager.Cert:
        return cert_manager_handlers.get_cluster_ca_certificate(
            self.cluster, self.context, "front-proxy"
        )


class ServiceAccountCertificateAuthoritySecret(CertificateAuthoritySecret):
    def certificate_name(self):
        return "sa"

    def magnum_cert_ref_name(self):
        return "magnum_cert_ref"

    def get_certificate(self) -> cert_manager.Cert:
        return cert_manager_handlers.get_cluster_magnum_cert(self.cluster, self.context)


class CloudConfigSecret(ClusterBase):
    def __init__(
        self,
        context: context.RequestContext,
        api: magnum_cluster_api.KubeClient,
        cluster: magnum_objects.Cluster,
        region_name: typing.Optional[str] = None,
        credential: types.SimpleNamespace = types.SimpleNamespace(id=None, secret=None),
    ):
        super().__init__(api, cluster)
        self.context = context
        osc = clients.get_openstack_api(self.context)
        self.auth_url = osc.url_for(
            service_type="identity",
            interface=CONF.capi_client.endpoint_type.replace("URL", ""),
        )
        self.region_name = region_name
        self.credential = credential

    @property
    def api_version(self) -> str:
        return "v1"

    @property
    def kind(self) -> str:
        return "Secret"

    @property
    def name(self) -> str:
        return utils.get_cluster_api_cloud_config_secret_name(self.cluster)

    def get_object(self) -> dict:
        ca_certificate = utils.get_capi_client_ca_cert()

        return {
            "metadata": {
                "labels": self.labels,
            },
            "stringData": {
                "cacert": (
                    ca_certificate
                    if ca_certificate
                    else open(certifi.where(), "r").read()
                ),
                "clouds.yaml": yaml.dump(
                    {
                        "clouds": {
                            "default": {
                                "region_name": self.region_name,
                                "endpoint_type": CONF.capi_client.endpoint_type.replace(
                                    "URL", ""
                                ),
                                "identity_api_version": 3,
                                "verify": not CONF.capi_client.insecure,
                                "auth": {
                                    "auth_url": self.auth_url,
                                    "application_credential_id": self.credential.id,
                                    "application_credential_secret": self.credential.secret,
                                },
                            }
                        }
                    }
                ),
            },
        }


class KubeadmControlPlaneTemplate(Base):
    @property
    def api_version(self) -> str:
        return "controlplane.cluster.x-k8s.io/v1beta1"

    @property
    def kind(self) -> str:
        return "KubeadmControlPlaneTemplate"

    @property
    def name(self) -> str:
        return CLUSTER_CLASS_NAME

    def get_object(self) -> dict:
        manifests_path = pkg_resources.resource_filename(
            "magnum_cluster_api", "manifests"
        )
        audit_policy = open(os.path.join(manifests_path, "audit/policy.yaml")).read()
        keystone_auth_webhook = open(
            os.path.join(manifests_path, "keystone-auth/webhook.yaml")
        ).read()

        return {
            "spec": {
                "template": {
                    "spec": {
                        "rolloutBefore": {
                            "certificatesExpiryDays": 21,
                        },
                        "kubeadmConfigSpec": {
                            "clusterConfiguration": {
                                "apiServer": {
                                    "extraArgs": {
                                        "cloud-provider": "external",
                                        "profiling": "false",
                                    },
                                    "extraVolumes": [
                                        # Note(oleks): Add this as default as a workaround of the json patch limitation # noqa: E501
                                        # https://cluster-api.sigs.k8s.io/tasks/experimental-features/cluster-class/write-clusterclass#json-patches-tips--tricks
                                        {
                                            "name": "webhooks",
                                            "hostPath": "/etc/kubernetes/webhooks",
                                            "mountPath": "/etc/kubernetes/webhooks",
                                        }
                                    ],
                                },
                                "etcd": {
                                    "local": {
                                        "extraArgs": {
                                            "listen-metrics-urls": "http://0.0.0.0:2381",
                                        },
                                    },
                                },
                                "controllerManager": {
                                    "extraArgs": {
                                        "bind-address": "0.0.0.0",
                                        "cloud-provider": "external",
                                        "profiling": "false",
                                    },
                                },
                                "scheduler": {
                                    "extraArgs": {
                                        "bind-address": "0.0.0.0",
                                        "profiling": "false",
                                    },
                                },
                            },
                            "files": [
                                {
                                    "path": "/etc/kubernetes/audit-policy/apiserver-audit-policy.yaml",
                                    "permissions": "0600",
                                    "content": base64.encode_as_text(audit_policy),
                                    "encoding": "base64",
                                },
                                {
                                    "path": "/etc/kubernetes/webhooks/webhookconfig.yaml",
                                    "owner": "root:root",
                                    "permissions": "0644",
                                    "content": base64.encode_as_text(
                                        keystone_auth_webhook
                                    ),
                                    "encoding": "base64",
                                },
                                {
                                    "path": "/run/kubeadm/configure-kube-proxy.sh",
                                    "permissions": "0755",
                                    "content": base64.encode_as_text(
                                        importlib.resources.files(
                                            "magnum_cluster_api.files.run.kubeadm"
                                        )
                                        .joinpath("configure-kube-proxy.sh")
                                        .read_text()
                                    ),
                                    "encoding": "base64",
                                },
                            ],
                            "initConfiguration": {
                                "nodeRegistration": {
                                    "name": "{{ local_hostname }}",
                                    "kubeletExtraArgs": {
                                        "cloud-provider": "external",
                                    },
                                },
                            },
                            "joinConfiguration": {
                                "nodeRegistration": {
                                    "name": "{{ local_hostname }}",
                                    "kubeletExtraArgs": {
                                        "cloud-provider": "external",
                                    },
                                },
                            },
                            "preKubeadmCommands": [
                                "rm /var/lib/etcd/lost+found -rf",
                                "bash /run/kubeadm/configure-kube-proxy.sh",
                            ],
                            "postKubeadmCommands": [
                                "echo PLACEHOLDER",
                            ],
                        },
                    },
                },
            },
        }


class KubeadmConfigTemplate(Base):
    @property
    def api_version(self) -> str:
        return "bootstrap.cluster.x-k8s.io/v1beta1"

    @property
    def kind(self) -> str:
        return "KubeadmConfigTemplate"

    @property
    def name(self) -> str:
        return CLUSTER_CLASS_NAME

    def get_object(self) -> dict:
        return {
            "spec": {
                "template": {
                    "spec": {
                        "files": [
                            {
                                "path": "/etc/kubernetes/.placeholder",
                                "permissions": "0644",
                                "content": base64.encode_as_text(PLACEHOLDER),
                                "encoding": "base64",
                            },
                        ],
                        "joinConfiguration": {
                            "nodeRegistration": {
                                "name": "{{ local_hostname }}",
                                "kubeletExtraArgs": {
                                    "cloud-provider": "external",
                                },
                            },
                        },
                    },
                },
            },
        }


class OpenStackMachineTemplate(Base):
    @property
    def api_version(self) -> str:
        return "infrastructure.cluster.x-k8s.io/v1beta1"

    @property
    def kind(self) -> str:
        return "OpenStackMachineTemplate"

    @property
    def name(self) -> str:
        return CLUSTER_CLASS_NAME

    def get_object(self) -> dict:
        return {
            "spec": {
                "template": {
                    "spec": {
                        "image": {
                            "id": PLACEHOLDER_UUID,
                        },
                        "identityRef": {
                            "name": PLACEHOLDER,
                            "cloudName": "default",
                        },
                        "flavor": PLACEHOLDER,
                    }
                }
            },
        }


class OpenStackClusterTemplate(Base):
    @property
    def api_version(self) -> str:
        return "infrastructure.cluster.x-k8s.io/v1beta1"

    @property
    def kind(self) -> str:
        return "OpenStackClusterTemplate"

    @property
    def name(self) -> str:
        return CLUSTER_CLASS_NAME

    def get_object(self) -> dict:
        return {
            "spec": {
                "template": {
                    "spec": {
                        "identityRef": {
                            "name": PLACEHOLDER,
                            "cloudName": "default",
                        },
                        "managedSecurityGroups": {
                            "allowAllInClusterTraffic": True,
                        },
                    },
                },
            },
        }


class ClusterClass(Base):
    @property
    def api_version(self) -> str:
        return "cluster.x-k8s.io/v1beta1"

    @property
    def kind(self) -> str:
        return "ClusterClass"

    @property
    def name(self) -> str:
        return CLUSTER_CLASS_NAME

    def get_object(self) -> dict:
        return {
            "spec": {
                "controlPlane": {
                    "nodeVolumeDetachTimeout": CLUSTER_CLASS_NODE_VOLUME_DETACH_TIMEOUT,
                    "ref": {
                        "apiVersion": objects.KubeadmControlPlaneTemplate.version,
                        "kind": objects.KubeadmControlPlaneTemplate.kind,
                        "name": self.name,
                    },
                    "machineInfrastructure": {
                        "ref": {
                            "apiVersion": objects.OpenStackMachineTemplate.version,
                            "kind": objects.OpenStackMachineTemplate.kind,
                            "name": self.name,
                        },
                    },
                    "machineHealthCheck": {
                        "maxUnhealthy": "80%",
                        "unhealthyConditions": [
                            {
                                "type": "Ready",
                                "status": "False",
                                "timeout": "5m",
                            },
                            {
                                "type": "Ready",
                                "status": "Unknown",
                                "timeout": "5m",
                            },
                        ],
                    },
                },
                "infrastructure": {
                    "ref": {
                        "apiVersion": objects.OpenStackClusterTemplate.version,
                        "kind": objects.OpenStackClusterTemplate.kind,
                        "name": self.name,
                    },
                },
                "workers": {
                    "machineDeployments": [
                        {
                            "class": "default-worker",
                            "nodeVolumeDetachTimeout": CLUSTER_CLASS_NODE_VOLUME_DETACH_TIMEOUT,
                            "template": {
                                "bootstrap": {
                                    "ref": {
                                        "apiVersion": objects.KubeadmConfigTemplate.version,
                                        "kind": objects.KubeadmConfigTemplate.kind,
                                        "name": self.name,
                                    }
                                },
                                "infrastructure": {
                                    "ref": {
                                        "apiVersion": objects.OpenStackMachineTemplate.version,
                                        "kind": objects.OpenStackMachineTemplate.kind,
                                        "name": self.name,
                                    }
                                },
                            },
                            "machineHealthCheck": {
                                "maxUnhealthy": "80%",
                                "unhealthyConditions": [
                                    {
                                        "type": "Ready",
                                        "status": "False",
                                        "timeout": "5m",
                                    },
                                    {
                                        "type": "Ready",
                                        "status": "Unknown",
                                        "timeout": "5m",
                                    },
                                ],
                            },
                        }
                    ],
                },
                "variables": [
                    {
                        "name": "apiServerLoadBalancer",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "object",
                                "required": ["enabled"],
                                "properties": {
                                    "enabled": {
                                        "type": "boolean",
                                    },
                                    "provider": {
                                        "type": "string",
                                    },
                                },
                            },
                        },
                    },
                    {
                        "name": "apiServerTLSCipherSuites",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "openidConnect",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "object",
                                "required": [
                                    "issuerUrl",
                                    "clientId",
                                    "usernameClaim",
                                    "usernamePrefix",
                                    "groupsClaim",
                                    "groupsPrefix",
                                ],
                                "properties": {
                                    "issuerUrl": {
                                        "type": "string",
                                    },
                                    "clientId": {
                                        "type": "string",
                                    },
                                    "usernameClaim": {
                                        "type": "string",
                                    },
                                    "usernamePrefix": {
                                        "type": "string",
                                    },
                                    "groupsClaim": {
                                        "type": "string",
                                    },
                                    "groupsPrefix": {
                                        "type": "string",
                                    },
                                },
                            },
                        },
                    },
                    {
                        "name": "auditLog",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "object",
                                "required": [
                                    "enabled",
                                    "maxAge",
                                    "maxBackup",
                                    "maxSize",
                                ],
                                "properties": {
                                    "enabled": {
                                        "type": "boolean",
                                    },
                                    "maxAge": {
                                        "type": "string",
                                    },
                                    "maxBackup": {
                                        "type": "string",
                                    },
                                    "maxSize": {
                                        "type": "string",
                                    },
                                },
                            },
                        },
                    },
                    {
                        "name": "bootVolume",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "object",
                                "required": ["size"],
                                "properties": {
                                    "size": {
                                        "type": "integer",
                                    },
                                    "type": {
                                        "type": "string",
                                    },
                                },
                            },
                        },
                    },
                    {
                        "name": "clusterIdentityRefName",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "cloudCaCert",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "cloudControllerManagerConfig",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "systemdProxyConfig",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "aptProxyConfig",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "containerdConfig",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "controlPlaneFlavor",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "disableAPIServerFloatingIP",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "boolean",
                            },
                        },
                    },
                    {
                        "name": "dnsNameservers",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "array",
                                "items": {
                                    "type": "string",
                                },
                            },
                        },
                    },
                    {
                        "name": "externalNetworkId",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "fixedNetworkId",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "fixedSubnetId",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "flavor",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "imageRepository",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "imageUUID",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "kubeletTLSCipherSuites",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "apiServerSANs",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "nodeCidr",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "sshKeyName",
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "operatingSystem",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                                "enum": utils.AVAILABLE_OPERATING_SYSTEMS,
                                "default": "ubuntu",
                            },
                        },
                    },
                    {
                        "name": "enableDockerVolume",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "boolean",
                            },
                        },
                    },
                    {
                        "name": "dockerVolumeSize",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "integer",
                            },
                        },
                    },
                    {
                        "name": "dockerVolumeType",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "enableEtcdVolume",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "boolean",
                            },
                        },
                    },
                    {
                        "name": "etcdVolumeSize",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "integer",
                            },
                        },
                    },
                    {
                        "name": "etcdVolumeType",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "availabilityZone",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "enableKeystoneAuth",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "boolean",
                            },
                        },
                    },
                    {
                        "name": "controlPlaneAvailabilityZones",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "array",
                                "items": {
                                    "type": "string",
                                },
                            },
                        },
                    },
                    {
                        "name": "serverGroupId",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "string",
                            },
                        },
                    },
                    {
                        "name": "isServerGroupDiffFailureDomain",
                        "required": True,
                        "schema": {
                            "openAPIV3Schema": {
                                "type": "boolean",
                            },
                        },
                    },
                ],
                "patches": [
                    {
                        "name": "auditLog",
                        "enabledIf": "{{ if .auditLog.enabled }}true{{end}}",
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.KubeadmControlPlaneTemplate.version,
                                    "kind": objects.KubeadmControlPlaneTemplate.kind,
                                    "matchResources": {
                                        "controlPlane": True,
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/audit-log-path",  # noqa: E501
                                        "value": "/var/log/audit/kube-apiserver-audit.log",
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/audit-log-maxage",  # noqa: E501
                                        "valueFrom": {
                                            "variable": "auditLog.maxAge",
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/audit-log-maxbackup",  # noqa: E501
                                        "valueFrom": {
                                            "variable": "auditLog.maxBackup",
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/audit-log-maxsize",  # noqa: E501
                                        "valueFrom": {
                                            "variable": "auditLog.maxSize",
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/audit-policy-file",  # noqa: E501
                                        "value": "/etc/kubernetes/audit-policy/apiserver-audit-policy.yaml",
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraVolumes/-",  # noqa: E501
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    name: audit-policy
                                                    hostPath: /etc/kubernetes/audit-policy
                                                    mountPath: /etc/kubernetes/audit-policy
                                                    """
                                            ),
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraVolumes/-",  # noqa: E501
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    name: audit-logs
                                                    hostPath: /var/log/kubernetes/audit
                                                    mountPath: /var/log/audit
                                                    """
                                            ),
                                        },
                                    },
                                ],
                            }
                        ],
                    },
                    {
                        "name": "openidConnect",
                        "enabledIf": "{{ if .openidConnect.issuerUrl }}true{{end}}",
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.KubeadmControlPlaneTemplate.version,
                                    "kind": objects.KubeadmControlPlaneTemplate.kind,
                                    "matchResources": {
                                        "controlPlane": True,
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/oidc-issuer-url",  # noqa: E501
                                        "valueFrom": {
                                            "variable": "openidConnect.issuerUrl",
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/oidc-client-id",  # noqa: E501
                                        "valueFrom": {
                                            "variable": "openidConnect.clientId",
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/oidc-username-claim",  # noqa: E501
                                        "valueFrom": {
                                            "variable": "openidConnect.usernameClaim",
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/oidc-username-prefix",  # noqa: E501
                                        "valueFrom": {
                                            "variable": "openidConnect.usernamePrefix",
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/oidc-groups-claim",  # noqa: E501
                                        "valueFrom": {
                                            "variable": "openidConnect.groupsClaim",
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/oidc-groups-prefix",  # noqa: E501
                                        "valueFrom": {
                                            "variable": "openidConnect.groupsPrefix",
                                        },
                                    },
                                ],
                            }
                        ],
                    },
                    {
                        "name": "bootVolume",
                        "enabledIf": "{{ if gt .bootVolume.size 0.0 }}true{{end}}",
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.OpenStackMachineTemplate.version,
                                    "kind": objects.OpenStackMachineTemplate.kind,
                                    "matchResources": {
                                        "controlPlane": True,
                                        "machineDeploymentClass": {
                                            "names": ["default-worker"],
                                        },
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/rootVolume",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    sizeGiB: {{ .bootVolume.size }}
                                                    type: {{ .bootVolume.type }}
                                                    """
                                            ),
                                        },
                                    },
                                ],
                            }
                        ],
                    },
                    {
                        "name": "ubuntu",
                        "enabledIf": '{{ if eq .operatingSystem "ubuntu" }}true{{end}}',
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.KubeadmControlPlaneTemplate.version,
                                    "kind": objects.KubeadmControlPlaneTemplate.kind,
                                    "matchResources": {
                                        "controlPlane": True,
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/files/-",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    path: "/etc/apt/apt.conf.d/90proxy"
                                                    owner: "root:root"
                                                    permissions: "0644"
                                                    content: "{{ .aptProxyConfig }}"
                                                    encoding: "base64"
                                                    """
                                            ),
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/preKubeadmCommands/-",
                                        "value": "systemctl daemon-reload && systemctl restart containerd",
                                    },
                                ],
                            },
                            {
                                "selector": {
                                    "apiVersion": objects.KubeadmConfigTemplate.version,
                                    "kind": objects.KubeadmConfigTemplate.kind,
                                    "matchResources": {
                                        "machineDeploymentClass": {
                                            "names": ["default-worker"],
                                        }
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/files/-",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    path: "/etc/apt/apt.conf.d/90proxy"
                                                    owner: "root:root"
                                                    permissions: "0644"
                                                    content: "{{ .aptProxyConfig }}"
                                                    encoding: "base64"
                                                    """
                                            ),
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/preKubeadmCommands",
                                        "value": [
                                            "systemctl daemon-reload",
                                            "systemctl restart containerd",
                                        ],
                                    },
                                ],
                            },
                        ],
                    },
                    {
                        "name": "flatcar",
                        "enabledIf": '{{ if eq .operatingSystem "flatcar" }}true{{end}}',
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.KubeadmControlPlaneTemplate.version,
                                    "kind": objects.KubeadmControlPlaneTemplate.kind,
                                    "matchResources": {
                                        "controlPlane": True,
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/preKubeadmCommands/-",
                                        "value": textwrap.dedent(
                                            """\
                                            bash -c "sed -i 's/__REPLACE_NODE_NAME__/$(hostname -s)/g' /etc/kubeadm.yml"
                                            bash -c "test -f /tmp/containerd-bootstrap || (touch /tmp/containerd-bootstrap && systemctl daemon-reload && systemctl restart containerd)"
                                            """  # noqa: E501
                                        ),
                                    },
                                    {
                                        "op": "replace",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/format",
                                        "value": "ignition",
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/ignition",
                                        "value": {
                                            "containerLinuxConfig": {
                                                "additionalConfig": textwrap.dedent(
                                                    """\
                                                        systemd:
                                                          units:
                                                          - name: coreos-metadata-sshkeys@.service
                                                            enabled: true
                                                          - name: kubeadm.service
                                                            enabled: true
                                                            dropins:
                                                            - name: 10-flatcar.conf
                                                              contents: |
                                                                [Unit]
                                                                Requires=containerd.service coreos-metadata.service
                                                                After=containerd.service coreos-metadata.service
                                                                [Service]
                                                                EnvironmentFile=/run/metadata/flatcar
                                                        """  # noqa: E501
                                                ),
                                            },
                                        },
                                    },
                                    {
                                        "op": "replace",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/initConfiguration/nodeRegistration/name",  # noqa: E501
                                        "value": "__REPLACE_NODE_NAME__",
                                    },
                                    {
                                        "op": "replace",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/joinConfiguration/nodeRegistration/name",  # noqa: E501
                                        "value": "__REPLACE_NODE_NAME__",
                                    },
                                ],
                            },
                            {
                                "selector": {
                                    "apiVersion": objects.KubeadmConfigTemplate.version,
                                    "kind": objects.KubeadmConfigTemplate.kind,
                                    "matchResources": {
                                        "machineDeploymentClass": {
                                            "names": ["default-worker"],
                                        }
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/preKubeadmCommands",
                                        "value": [
                                            textwrap.dedent(
                                                """\
                                                bash -c "sed -i 's/__REPLACE_NODE_NAME__/$(hostname -s)/g' /etc/kubeadm.yml"
                                                bash -c "test -f /tmp/containerd-bootstrap || (touch /tmp/containerd-bootstrap && systemctl daemon-reload && systemctl restart containerd)"
                                                """  # noqa: E501
                                            )
                                        ],
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/format",
                                        "value": "ignition",
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/ignition",
                                        "value": {
                                            "containerLinuxConfig": {
                                                "additionalConfig": textwrap.dedent(
                                                    """\
                                                        systemd:
                                                          units:
                                                          - name: coreos-metadata-sshkeys@.service
                                                            enabled: true
                                                          - name: kubeadm.service
                                                            enabled: true
                                                            dropins:
                                                            - name: 10-flatcar.conf
                                                              contents: |
                                                                [Unit]
                                                                Requires=containerd.service coreos-metadata.service
                                                                After=containerd.service coreos-metadata.service
                                                                [Service]
                                                                EnvironmentFile=/run/metadata/flatcar
                                                        """  # noqa: E501
                                                ),
                                            },
                                        },
                                    },
                                    {
                                        "op": "replace",
                                        "path": "/spec/template/spec/joinConfiguration/nodeRegistration/name",
                                        "value": "__REPLACE_NODE_NAME__",
                                    },
                                ],
                            },
                        ],
                    },
                    {
                        "name": "clusterConfig",
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.OpenStackMachineTemplate.version,
                                    "kind": objects.OpenStackMachineTemplate.kind,
                                    "matchResources": {
                                        "controlPlane": True,
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/flavor",
                                        "valueFrom": {
                                            "variable": "controlPlaneFlavor",
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/serverGroup",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    id: {{ .serverGroupId }}
                                                    """
                                            ),
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/schedulerHintAdditionalProperties",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    - name: different_failure_domain
                                                      value:
                                                        type: Bool
                                                        bool: {{ .isServerGroupDiffFailureDomain }}
                                                    """
                                            ),
                                        },
                                    },
                                ],
                            },
                            {
                                "selector": {
                                    "apiVersion": objects.OpenStackMachineTemplate.version,
                                    "kind": objects.OpenStackMachineTemplate.kind,
                                    "matchResources": {
                                        "machineDeploymentClass": {
                                            "names": ["default-worker"],
                                        },
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/flavor",
                                        "valueFrom": {
                                            "variable": "flavor",
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/serverGroup",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    id: {{ .serverGroupId }}
                                                    """
                                            ),
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/schedulerHintAdditionalProperties",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    - name: different_failure_domain
                                                      value:
                                                        type: Bool
                                                        bool: {{ .isServerGroupDiffFailureDomain }}
                                                    """
                                            ),
                                        },
                                    },
                                ],
                            },
                            {
                                "selector": {
                                    "apiVersion": objects.OpenStackMachineTemplate.version,
                                    "kind": objects.OpenStackMachineTemplate.kind,
                                    "matchResources": {
                                        "controlPlane": True,
                                        "machineDeploymentClass": {
                                            "names": ["default-worker"],
                                        },
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "replace",
                                        "path": "/spec/template/spec/identityRef/name",
                                        "valueFrom": {
                                            "variable": "clusterIdentityRefName"
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/sshKeyName",
                                        "valueFrom": {"variable": "sshKeyName"},
                                    },
                                    {
                                        "op": "replace",
                                        "path": "/spec/template/spec/image/id",
                                        "valueFrom": {"variable": "imageUUID"},
                                    },
                                ],
                            },
                            {
                                "selector": {
                                    "apiVersion": objects.OpenStackClusterTemplate.version,
                                    "kind": objects.OpenStackClusterTemplate.kind,
                                    "matchResources": {
                                        "infrastructureCluster": True,
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/apiServerLoadBalancer",
                                        "valueFrom": {
                                            "variable": "apiServerLoadBalancer"
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/identityRef/name",
                                        "valueFrom": {
                                            "variable": "clusterIdentityRefName"
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/externalNetwork",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    id: {{ .externalNetworkId }}
                                                    """
                                            ),
                                        },
                                    },
                                ],
                            },
                        ],
                    },
                    {
                        "name": "disableAPIServerFloatingIP",
                        "enabledIf": "{{ if .disableAPIServerFloatingIP }}true{{end}}",
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.OpenStackClusterTemplate.version,
                                    "kind": objects.OpenStackClusterTemplate.kind,
                                    "matchResources": {
                                        "infrastructureCluster": True,
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/disableAPIServerFloatingIP",
                                        "valueFrom": {
                                            "variable": "disableAPIServerFloatingIP"
                                        },
                                    },
                                ],
                            },
                        ],
                    },
                    {
                        "name": "controlPlaneAvailabilityZones",
                        "enabledIf": '{{ if ne (index .controlPlaneAvailabilityZones 0) "" }}true{{end}}',
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.OpenStackClusterTemplate.version,
                                    "kind": objects.OpenStackClusterTemplate.kind,
                                    "matchResources": {
                                        "infrastructureCluster": True,
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/controlPlaneAvailabilityZones",
                                        "valueFrom": {
                                            "variable": "controlPlaneAvailabilityZones"
                                        },
                                    },
                                ],
                            },
                        ],
                    },
                    {
                        "name": "newNetworkConfig",
                        "enabledIf": '{{ if eq .fixedNetworkId "" }}true{{end}}',
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.OpenStackClusterTemplate.version,
                                    "kind": objects.OpenStackClusterTemplate.kind,
                                    "matchResources": {
                                        "infrastructureCluster": True,
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/managedSubnets",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    - cidr: {{ .nodeCidr }}
                                                      dnsNameservers: {{ .dnsNameservers }}
                                                    """
                                            ),
                                        },
                                    },
                                ],
                            },
                        ],
                    },
                    {
                        "name": "existingFixedNetworkIdConfig",
                        "enabledIf": '{{ if ne .fixedNetworkId "" }}true{{end}}',
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.OpenStackClusterTemplate.version,
                                    "kind": objects.OpenStackClusterTemplate.kind,
                                    "matchResources": {
                                        "infrastructureCluster": True,
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/network",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    id: {{ .fixedNetworkId }}
                                                    """
                                            ),
                                        },
                                    },
                                ],
                            },
                        ],
                    },
                    {
                        "name": "existingFixedSubnetIdConfig",
                        "enabledIf": '{{ if ne .fixedSubnetId "" }}true{{end}}',
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.OpenStackClusterTemplate.version,
                                    "kind": objects.OpenStackClusterTemplate.kind,
                                    "matchResources": {
                                        "infrastructureCluster": True,
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/subnets",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    - id: {{ .fixedSubnetId }}
                                                    """
                                            ),
                                        },
                                    },
                                ],
                            },
                        ],
                    },
                    {
                        "name": "customImageRepository",
                        "enabledIf": '{{ if ne .imageRepository "" }}true{{end}}',
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.KubeadmControlPlaneTemplate.version,
                                    "kind": objects.KubeadmControlPlaneTemplate.kind,
                                    "matchResources": {
                                        "controlPlane": True,
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/imageRepository",  # noqa: E501
                                        "valueFrom": {
                                            "variable": "imageRepository",
                                        },
                                    },
                                ],
                            },
                            {
                                "selector": {
                                    "apiVersion": objects.KubeadmConfigTemplate.version,
                                    "kind": objects.KubeadmConfigTemplate.kind,
                                    "matchResources": {
                                        "machineDeploymentClass": {
                                            "names": ["default-worker"],
                                        }
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/clusterConfiguration",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    imageRepository: "{{ .imageRepository }}"
                                                    """
                                            ),
                                        },
                                    },
                                ],
                            },
                        ],
                    },
                    {
                        "name": "etcdVolumeAndDockerVolume",
                        "enabledIf": "{{ if and .enableEtcdVolume .enableDockerVolume }}true{{ end }}",
                        "definitions": json_patches.Volumes(
                            control_plane_disks=[
                                json_patches.DiskConfig(
                                    type="etcd",
                                    mount_path="/var/lib/etcd",
                                ),
                                json_patches.DiskConfig(
                                    type="docker",
                                    mount_path="/var/lib/containerd",
                                ),
                            ],
                            worker_disks=[
                                json_patches.DiskConfig(
                                    type="docker",
                                    mount_path="/var/lib/containerd",
                                )
                            ],
                        ).definitions,
                    },
                    {
                        "name": "onlyDockerVolume",
                        "enabledIf": "{{ if and .enableDockerVolume (not .enableEtcdVolume) }}true{{ end }}",
                        "definitions": json_patches.Volumes(
                            control_plane_disks=[
                                json_patches.DiskConfig(
                                    type="docker",
                                    mount_path="/var/lib/containerd",
                                )
                            ],
                            worker_disks=[
                                json_patches.DiskConfig(
                                    type="docker",
                                    mount_path="/var/lib/containerd",
                                )
                            ],
                        ).definitions,
                    },
                    {
                        "name": "onlyEtcdVolume",
                        "enabledIf": "{{ if and .enableEtcdVolume (not .enableDockerVolume) }}true{{ end }}",
                        "definitions": json_patches.Volumes(
                            control_plane_disks=[
                                json_patches.DiskConfig(
                                    type="etcd",
                                    mount_path="/var/lib/etcd",
                                )
                            ],
                        ).definitions,
                    },
                    {
                        "name": "keystoneAuth",
                        "enabledIf": "{{ if .enableKeystoneAuth }}true{{end}}",
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.KubeadmControlPlaneTemplate.version,
                                    "kind": objects.KubeadmControlPlaneTemplate.kind,
                                    "matchResources": {
                                        "controlPlane": True,
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/files/-",
                                        "value": {
                                            "path": "/etc/kubernetes/keystone-kustomization/kustomization.yml",
                                            "permissions": "0644",
                                            "owner": "root:root",
                                            "content": textwrap.dedent(
                                                """\
                                                    resources:
                                                      - kube-apiserver.yaml
                                                    patches:
                                                      - target:
                                                          group: ""
                                                          version: v1
                                                          kind: Pod
                                                          name: kube-apiserver
                                                        patch: |-
                                                          - op: add
                                                            path: /spec/containers/0/command/-
                                                            value: --authentication-token-webhook-config-file=/etc/kubernetes/webhooks/webhookconfig.yaml # noqa: E501
                                                          - op: add
                                                            path: /spec/containers/0/command/-
                                                            value: --authorization-webhook-config-file=/etc/kubernetes/webhooks/webhookconfig.yaml # noqa: E501
                                                          - op: add
                                                            path: /spec/containers/0/command/-
                                                            value: --authorization-mode=Webhook
                                                    """
                                            ),
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/preKubeadmCommands/-",
                                        "value": "mkdir -p /etc/kubernetes/keystone-kustomization",
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/postKubeadmCommands/-",
                                        "value": "cp /etc/kubernetes/manifests/kube-apiserver.yaml /etc/kubernetes/keystone-kustomization/kube-apiserver.yaml",  # noqa: E501
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/postKubeadmCommands/-",
                                        "value": "kubectl kustomize /etc/kubernetes/keystone-kustomization -o /etc/kubernetes/manifests/kube-apiserver.yaml",  # noqa: E501
                                    },
                                ],
                            }
                        ],
                    },
                    {
                        "name": "controlPlaneConfig",
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.KubeadmControlPlaneTemplate.version,
                                    "kind": objects.KubeadmControlPlaneTemplate.kind,
                                    "matchResources": {
                                        "controlPlane": True,
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/tls-cipher-suites",  # noqa: E501
                                        "valueFrom": {
                                            "variable": "apiServerTLSCipherSuites",
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/initConfiguration/nodeRegistration/kubeletExtraArgs/tls-cipher-suites",  # noqa: E501
                                        "valueFrom": {
                                            "variable": "kubeletTLSCipherSuites",
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/joinConfiguration/nodeRegistration/kubeletExtraArgs/tls-cipher-suites",  # noqa: E501
                                        "valueFrom": {
                                            "variable": "kubeletTLSCipherSuites",
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/certSANs",  # noqa: E501
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    - {{ .builtin.cluster.name }}
                                                    - {{ .builtin.cluster.name }}.{{ .builtin.cluster.namespace }}
                                                    - {{ .builtin.cluster.name }}.{{ .builtin.cluster.namespace }}.svc
                                                    - {{ .builtin.cluster.name }}.{{ .builtin.cluster.namespace }}.svc.cluster.local # noqa: E501
                                                    {{ .apiServerSANs }}
                                                    """
                                            ),
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/files/-",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    path: "/etc/containerd/config.toml"
                                                    owner: "root:root"
                                                    permissions: "0644"
                                                    content: "{{ .containerdConfig }}"
                                                    encoding: "base64"
                                                    """
                                            )
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/files/-",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    path: "/etc/kubernetes/cloud.conf"
                                                    owner: "root:root"
                                                    permissions: "0600"
                                                    content: "{{ .cloudControllerManagerConfig }}"
                                                    encoding: "base64"
                                                    """
                                            )
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/files/-",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    path: "/etc/kubernetes/cloud_ca.crt"
                                                    owner: "root:root"
                                                    permissions: "0600"
                                                    content: "{{ .cloudCaCert }}"
                                                    encoding: "base64"
                                                    """
                                            )
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/kubeadmConfigSpec/files/-",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    path: "/etc/systemd/system/containerd.service.d/proxy.conf"
                                                    owner: "root:root"
                                                    permissions: "0644"
                                                    content: "{{ .systemdProxyConfig }}"
                                                    encoding: "base64"
                                                    """
                                            )
                                        },
                                    },
                                ],
                            },
                            {
                                "selector": {
                                    "apiVersion": objects.KubeadmConfigTemplate.version,
                                    "kind": objects.KubeadmConfigTemplate.kind,
                                    "matchResources": {
                                        "machineDeploymentClass": {
                                            "names": ["default-worker"],
                                        }
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/files/-",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    path: "/etc/kubernetes/cloud.conf"
                                                    owner: "root:root"
                                                    permissions: "0600"
                                                    content: "{{ .cloudControllerManagerConfig }}"
                                                    encoding: "base64"
                                                    """
                                            ),
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/files/-",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    path: "/etc/kubernetes/cloud_ca.crt"
                                                    owner: "root:root"
                                                    permissions: "0600"
                                                    content: "{{ .cloudCaCert }}"
                                                    encoding: "base64"
                                                    """
                                            ),
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/files/-",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    path: "/etc/containerd/config.toml"
                                                    owner: "root:root"
                                                    permissions: "0644"
                                                    content: "{{ .containerdConfig }}"
                                                    encoding: "base64"
                                                    """
                                            ),
                                        },
                                    },
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/files/-",
                                        "valueFrom": {
                                            "template": textwrap.dedent(
                                                """\
                                                    path: "/etc/systemd/system/containerd.service.d/proxy.conf"
                                                    owner: "root:root"
                                                    permissions: "0644"
                                                    content: "{{ .systemdProxyConfig }}"
                                                    encoding: "base64"
                                                    """
                                            ),
                                        },
                                    },
                                ],
                            },
                        ],
                    },
                    {
                        "name": "workerConfig",
                        "definitions": [
                            {
                                "selector": {
                                    "apiVersion": objects.KubeadmConfigTemplate.version,
                                    "kind": objects.KubeadmConfigTemplate.kind,
                                    "matchResources": {
                                        "machineDeploymentClass": {
                                            "names": ["default-worker"],
                                        }
                                    },
                                },
                                "jsonPatches": [
                                    {
                                        "op": "add",
                                        "path": "/spec/template/spec/joinConfiguration/nodeRegistration/kubeletExtraArgs/tls-cipher-suites",  # noqa: E501
                                        "valueFrom": {
                                            "variable": "kubeletTLSCipherSuites",
                                        },
                                    },
                                ],
                            },
                        ],
                    },
                ],
            },
        }


def create_cluster_class(
    api: magnum_cluster_api.KubeClient,
    namespace: str = "magnum-system",
) -> ClusterClass:
    """
    Create a ClusterClass and all of it's supporting resources from a Magnum
    cluster template using server-side apply.
    """

    KubeadmControlPlaneTemplate(api, namespace).apply()
    KubeadmConfigTemplate(api, namespace).apply()
    OpenStackMachineTemplate(api, namespace).apply()
    OpenStackClusterTemplate(api, namespace).apply()

    cc = ClusterClass(api, namespace)
    cc.apply()

    return cc


def mutate_machine_deployment(
    context: context.RequestContext,
    cluster: objects.Cluster,
    node_group: magnum_objects.NodeGroup,
    machine_deployment: dict = None,
):
    """
    This function will either makes updates to machine deployment fields which
    will not cause a rolling update or will return a new machine deployment
    if none is provided.
    """

    # NOTE(okozachenko1203): Initialize as an empty dict if not provided
    #                        instead of using mutable default argument.
    if machine_deployment is None:
        machine_deployment = {}

    auto_scaling_enabled = utils.get_auto_scaling_enabled(cluster)

    machine_deployment.setdefault(
        "metadata",
        {
            "annotations": {},
            "labels": {},
        },
    )

    # Node labels
    machine_deployment["metadata"]["labels"] = {
        f"node-role.kubernetes.io/{node_group.role}": "",
        "node.cluster.x-k8s.io/nodegroup": node_group.name,
    }

    # Replicas (or min/max if auto-scaling is enabled)
    if auto_scaling_enabled:
        machine_deployment["replicas"] = None
        machine_deployment["metadata"]["annotations"] = {
            AUTOSCALE_ANNOTATION_MIN: str(
                utils.get_node_group_min_node_count(node_group)
            ),
            AUTOSCALE_ANNOTATION_MAX: str(
                utils.get_node_group_max_node_count(node_group)
            ),
        }
    else:
        machine_deployment["replicas"] = node_group.node_count
        machine_deployment["metadata"]["annotations"] = {}

    # Fixes
    machine_deployment["nodeVolumeDetachTimeout"] = (
        CLUSTER_CLASS_NODE_VOLUME_DETACH_TIMEOUT
    )

    # Anything beyond this point will *NOT* be changed in the machine deployment
    # for update operations (i.e. if the machine deployment already exists).
    if machine_deployment.get("name") == node_group.name:
        return machine_deployment

    # At this point, this is all code that will be added for brand-new machine
    # deployments.  We can bring any of this code into the above block if we
    # want to change it for existing machine deployments.

    machine_deployment.update(
        {
            "class": "default-worker",
            "name": node_group.name,
            "failureDomain": node_group.labels.get("availability_zone", ""),
            "machineHealthCheck": {"enable": utils.get_auto_healing_enabled(cluster)},
            "variables": {
                "overrides": [
                    {
                        "name": "bootVolume",
                        "value": {
                            "size": utils.get_node_group_label_as_int(
                                node_group,
                                "boot_volume_size",
                                CONF.cinder.default_boot_volume_size,
                            ),
                            "type": node_group.labels.get(
                                "boot_volume_type",
                                cinder.get_default_boot_volume_type(context),
                            ),
                        },
                    },
                    {
                        "name": "flavor",
                        "value": node_group.flavor_id,
                    },
                    {
                        "name": "imageRepository",
                        "value": node_group.labels.get(
                            "container_infra_prefix",
                            "",
                        ),
                    },
                    {
                        "name": "imageUUID",
                        "value": utils.get_image_uuid(node_group.image_id, context),
                    },
                    # NOTE(oleks): Override using MachineDeployment-level variables for node groups
                    {
                        "name": "serverGroupId",
                        "value": utils.ensure_worker_server_group(
                            ctx=context, cluster=cluster, node_group=node_group
                        ),
                    },
                    {
                        "name": "isServerGroupDiffFailureDomain",
                        "value": utils.is_node_group_different_failure_domain(
                            node_group=node_group, cluster=cluster
                        ),
                    },
                ],
            },
        }
    )
    return machine_deployment


def generate_machine_deployments_for_cluster(
    context: context.RequestContext, cluster: objects.Cluster
) -> list:
    machine_deployments = []
    for ng in cluster.nodegroups:
        if ng.role == "master" or ng.status.startswith("DELETE"):
            continue

        machine_deployment = mutate_machine_deployment(context, cluster, ng)
        machine_deployments.append(machine_deployment)

    return machine_deployments


class Cluster(ClusterBase):
    def __init__(
        self,
        context: context.RequestContext,
        api: magnum_cluster_api.KubeClient,
        pykube_api: pykube.HTTPClient,
        cluster: magnum_objects.Cluster,
        namespace: str = "magnum-system",
    ):
        self.context = context
        self.api = api
        self.pykube_api = pykube_api
        self.cluster = cluster
        self.namespace = namespace

    @property
    def api_version(self) -> str:
        return "cluster.x-k8s.io/v1beta1"

    @property
    def kind(self) -> str:
        return "Cluster"

    @property
    def name(self) -> str:
        return self.cluster.stack_id

    @property
    def labels(self) -> dict:
        labels = {}
        if self.cluster.cluster_template.network_driver == "calico":
            cni_version = self.cluster.labels.get("calico_tag", CALICO_TAG)
            labels = {
                "cni": f"calico-{cni_version}",
            }
        if self.cluster.cluster_template.network_driver == "cilium":
            cni_version = self.cluster.labels.get("cilium_tag", CILIUM_TAG)
            labels = {
                "cni": f"cilium-{cni_version}",
            }

        return {**super().labels, **labels}

    def get_or_none(self) -> objects.Cluster:
        return objects.Cluster.objects(
            self.pykube_api, namespace=self.namespace
        ).get_or_none(name=self.cluster.stack_id)

    def get_object(self) -> dict:
        osc = clients.get_openstack_api(self.context)
        default_volume_type = osc.cinder().volume_types.default()
        pod_cidr = DEFAULT_POD_CIDR
        if self.cluster.cluster_template.network_driver == "calico":
            pod_cidr = self.cluster.labels.get(
                "calico_ipv4pool",
                DEFAULT_POD_CIDR,
            )
        if self.cluster.cluster_template.network_driver == "cilium":
            pod_cidr = self.cluster.labels.get(
                "cilium_ipv4pool",
                DEFAULT_POD_CIDR,
            )

        return {
            "metadata": {
                "labels": self.labels,
            },
            "spec": {
                "clusterNetwork": {
                    "serviceDomain": self.cluster.labels.get(
                        "dns_cluster_domain", "cluster.local"
                    ),
                    "pods": {
                        "cidrBlocks": [pod_cidr],
                    },
                    "services": {
                        "cidrBlocks": [
                            self.cluster.labels.get(
                                "service_cluster_ip_range", "10.254.0.0/16"
                            )
                        ],
                    },
                },
                "topology": {
                    "class": CLUSTER_CLASS_NAME,
                    "version": utils.get_kube_tag(self.cluster),
                    "controlPlane": {
                        "metadata": {
                            "labels": {
                                "node-role.kubernetes.io/master": "",
                            }
                        },
                        "replicas": self.cluster.master_count,
                        "machineHealthCheck": {
                            "enable": utils.get_auto_healing_enabled(self.cluster)
                        },
                    },
                    "workers": {
                        "machineDeployments": generate_machine_deployments_for_cluster(
                            self.context, self.cluster
                        ),
                    },
                    "variables": [
                        {
                            "name": "apiServerLoadBalancer",
                            "value": {
                                "enabled": self.cluster.master_lb_enabled,
                                "provider": self.cluster.labels.get(
                                    "octavia_provider", "amphora"
                                ),
                            },
                        },
                        {
                            "name": "apiServerTLSCipherSuites",
                            "value": self.cluster.labels.get(
                                "api_server_tls_cipher_suites",
                                "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",  # noqa: E501
                            ),
                        },
                        {
                            "name": "openidConnect",
                            "value": {
                                "clientId": self.cluster.labels.get(
                                    "oidc_client_id", ""
                                ),
                                "groupsClaim": self.cluster.labels.get(
                                    "oidc_groups_claim", ""
                                ),
                                "groupsPrefix": self.cluster.labels.get(
                                    "oidc_groups_prefix", ""
                                ),
                                "issuerUrl": self.cluster.labels.get(
                                    "oidc_issuer_url", ""
                                ),
                                "usernameClaim": self.cluster.labels.get(
                                    "oidc_username_claim", "sub"
                                ),
                                "usernamePrefix": self.cluster.labels.get(
                                    "oidc_username_prefix", "-"
                                ),
                            },
                        },
                        {
                            "name": "auditLog",
                            "value": {
                                "enabled": utils.get_cluster_label_as_bool(
                                    self.cluster, "audit_log_enabled", False
                                ),
                                "maxAge": self.cluster.labels.get(
                                    "audit_log_max_age", "30"
                                ),
                                "maxBackup": self.cluster.labels.get(
                                    "audit_log_max_backup", "10"
                                ),
                                "maxSize": self.cluster.labels.get(
                                    "audit_log_max_size", "100"
                                ),
                            },
                        },
                        {
                            "name": "bootVolume",
                            "value": {
                                "size": utils.get_cluster_label_as_int(
                                    self.cluster,
                                    "boot_volume_size",
                                    CONF.cinder.default_boot_volume_size,
                                ),
                                "type": self.cluster.labels.get(
                                    "boot_volume_type",
                                    cinder.get_default_boot_volume_type(self.context),
                                ),
                            },
                        },
                        {
                            "name": "clusterIdentityRefName",
                            "value": utils.get_cluster_api_cloud_config_secret_name(
                                self.cluster
                            ),
                        },
                        {
                            "name": "cloudCaCert",
                            "value": base64.encode_as_text(utils.get_cloud_ca_cert()),
                        },
                        {
                            "name": "cloudControllerManagerConfig",
                            "value": base64.encode_as_text(
                                utils.generate_cloud_controller_manager_config(
                                    self.context,
                                    self.pykube_api,
                                    self.cluster,
                                )
                            ),
                        },
                        {
                            "name": "systemdProxyConfig",
                            "value": base64.encode_as_text(
                                utils.generate_systemd_proxy_config(self.cluster)
                            ),
                        },
                        {
                            "name": "aptProxyConfig",
                            "value": base64.encode_as_text(
                                utils.generate_apt_proxy_config(self.cluster)
                            ),
                        },
                        {
                            "name": "containerdConfig",
                            "value": base64.encode_as_text(
                                utils.generate_containerd_config(self.cluster)
                            ),
                        },
                        {
                            "name": "controlPlaneFlavor",
                            "value": self.cluster.master_flavor_id,
                        },
                        {
                            "name": "disableAPIServerFloatingIP",
                            "value": utils.get_cluster_floating_ip_disabled(
                                self.cluster
                            ),
                        },
                        {
                            "name": "dnsNameservers",
                            "value": self.cluster.cluster_template.dns_nameserver.split(
                                ","
                            ),
                        },
                        {
                            "name": "externalNetworkId",
                            "value": neutron.get_external_network_id(
                                self.context,
                                self.cluster.cluster_template.external_network_id,
                            ),
                        },
                        {
                            "name": "fixedNetworkId",
                            "value": utils.get_fixed_network_id(
                                self.context, self.cluster.fixed_network
                            )
                            or "",
                        },
                        {
                            "name": "fixedSubnetId",
                            "value": neutron.get_fixed_subnet_id(
                                self.context, self.cluster.fixed_subnet
                            )
                            or "",
                        },
                        {
                            "name": "flavor",
                            "value": self.cluster.flavor_id,
                        },
                        {
                            "name": "imageRepository",
                            "value": utils.get_cluster_container_infra_prefix(
                                self.cluster,
                            ),
                        },
                        {
                            "name": "imageUUID",
                            "value": utils.get_image_uuid(
                                self.cluster.default_ng_master.image_id,
                                self.context,
                            ),
                        },
                        {
                            "name": "kubeletTLSCipherSuites",
                            "value": self.cluster.labels.get(
                                "kubelet_tls_cipher_suites",
                                "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",  # noqa: E501
                            ),
                        },
                        {
                            "name": "apiServerSANs",
                            "value": utils.generate_api_cert_san_list(self.cluster),
                        },
                        {
                            "name": "nodeCidr",
                            "value": self.cluster.labels.get(
                                "fixed_subnet_cidr",
                                "10.0.0.0/24",
                            ),
                        },
                        {
                            "name": "sshKeyName",
                            "value": self.cluster.keypair or "",
                        },
                        {
                            "name": "operatingSystem",
                            "value": utils.get_operating_system(self.cluster),
                        },
                        {
                            "name": "enableDockerVolume",
                            "value": utils.get_cluster_label_as_int(
                                self.cluster,
                                "docker_volume_size",
                                0,
                            )
                            > 0,
                        },
                        {
                            "name": "dockerVolumeSize",
                            "value": utils.get_cluster_label_as_int(
                                self.cluster,
                                "docker_volume_size",
                                0,
                            ),
                        },
                        {
                            "name": "dockerVolumeType",
                            "value": self.cluster.labels.get(
                                "docker_volume_type",
                                default_volume_type.name,
                            ),
                        },
                        {
                            "name": "enableEtcdVolume",
                            "value": utils.get_cluster_label_as_int(
                                self.cluster,
                                "etcd_volume_size",
                                0,
                            )
                            > 0,
                        },
                        {
                            "name": "etcdVolumeSize",
                            "value": utils.get_cluster_label_as_int(
                                self.cluster,
                                "etcd_volume_size",
                                0,
                            ),
                        },
                        {
                            "name": "etcdVolumeType",
                            "value": self.cluster.labels.get(
                                "etcd_volume_type",
                                default_volume_type.name,
                            ),
                        },
                        {
                            "name": "availabilityZone",
                            "value": self.cluster.labels.get("availability_zone", ""),
                        },
                        {
                            "name": "enableKeystoneAuth",
                            "value": utils.get_cluster_label_as_bool(
                                self.cluster, "keystone_auth_enabled", True
                            ),
                        },
                        {
                            "name": "controlPlaneAvailabilityZones",
                            "value": self.cluster.labels.get(
                                "control_plane_availability_zones", ""
                            ).split(","),
                        },
                        # NOTE(oleks): Set cluster-level variable using server group id for controlplane.
                        #              Override this for node groups via  MachineDeployment-level variable.
                        {
                            "name": "serverGroupId",
                            "value": utils.ensure_controlplane_server_group(
                                ctx=self.context, cluster=self.cluster
                            ),
                        },
                        # NOTE(oleks): Set cluster-level variable using cluster label for controlplane.
                        #              Override this using node group label for node groups via  MachineDeployment-level variable. # noqa: E501
                        {
                            "name": "isServerGroupDiffFailureDomain",
                            "value": utils.is_controlplane_different_failure_domain(
                                cluster=self.cluster
                            ),
                        },
                    ],
                },
            },
        }

    def delete(self):
        capi_cluster = self.get_or_none()
        if capi_cluster:
            capi_cluster.delete()


def apply_cluster_from_magnum_cluster(
    context: context.RequestContext,
    api: magnum_cluster_api.KubeClient,
    pykube_api: pykube.HTTPClient,
    cluster: magnum_objects.Cluster,
    skip_auto_scaling_release: bool = False,
) -> None:
    """
    Create a ClusterAPI cluster given a Magnum Cluster object.
    """
    create_cluster_class(api)

    ClusterServerGroups(context, cluster).apply()
    ClusterResourcesConfigMap(context, api, pykube_api, cluster).apply()
    ClusterResourceSet(api, cluster).apply()
    Cluster(context, api, pykube_api, cluster).apply()

    if not skip_auto_scaling_release and utils.get_auto_scaling_enabled(cluster):
        ClusterAutoscalerHelmRelease(api, cluster).apply()


def get_kubeadm_control_plane(
    api: pykube.HTTPClient, cluster: magnum_objects.Cluster
) -> typing.Optional[objects.KubeadmControlPlane]:
    kcps = objects.KubeadmControlPlane.objects(api, namespace="magnum-system").filter(
        selector={
            "cluster.x-k8s.io/cluster-name": cluster.stack_id,
        },
    )
    if len(kcps) == 1:
        return list(kcps)[0]
    return None
