suite: ControlPlane StatefulSet
templates:
  - statefulset.yaml

tests:
  - it: should not create control-plane
    set:
      experimental:
        isolatedControlPlane:
          headless: true
    asserts:
      - hasDocuments:
          count: 0

  - it: image name
    set:
      controlPlane:
        statefulSet:
          image:
            registry: "custom-registry.com"
    asserts:
      - equal:
          path: spec.template.spec.containers[0].image
          value: custom-registry.com/loft-sh/vcluster-pro:0.0.1

  - it: defaultImageRegistry
    set:
      controlPlane:
        advanced:
          defaultImageRegistry: docker.io
    asserts:
      - equal:
          path: spec.template.spec.containers[0].image
          value: docker.io/loft-sh/vcluster-pro:0.0.1

  - it: custom tag
    set:
      controlPlane:
        statefulSet:
          image:
            repository: my-repo
            tag: "custom-tag"
    asserts:
      - equal:
          path: spec.template.spec.containers[0].image
          value: ghcr.io/my-repo:custom-tag

  - it: custom init container
    set:
      controlPlane:
        distro:
          k3s:
            enabled: true
            image:
              registry: "ghcr.io"
              repository: "test"
              tag: "123"
    asserts:
      - equal:
          path: spec.template.spec.initContainers[0].image
          value: ghcr.io/test:123

  - it: custom init container
    set:
      controlPlane:
        distro:
          k0s:
            enabled: true
            image:
              registry: ""
              repository: "k0s"
              tag: "123"
    asserts:
      - equal:
          path: spec.template.spec.initContainers[0].image
          value: k0s:123

  - it: disables serviceLinks for sts etcd pod
    set:
      controlPlane:
        statefulSet:
          enableServiceLinks: false
    asserts:
      - equal:
          path: spec.template.spec.enableServiceLinks
          value: false

  - it: custom init container
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
            controllerManager:
              image:
                registry: ""
                repository: "k8s-controller"
                tag: "123"
            apiServer:
              image:
                registry: ""
                repository: "k8s-api"
                tag: "456"
    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: k8s-controller:123
      - equal:
          path: spec.template.spec.initContainers[2].image
          value: k8s-api:456

  - it: custom init container
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
            controllerManager:
              image:
                repository: "k8s-controller"
                tag: "123"
            apiServer:
              image:
                repository: "k8s-api"
                tag: "456"
        advanced:
          defaultImageRegistry: "bbb.com"
    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: bbb.com/k8s-controller:123
      - equal:
          path: spec.template.spec.initContainers[2].image
          value: bbb.com/k8s-api:456

  - it: name & defaults
    release:
      name: my-release
      namespace: my-namespace
    capabilities:
      majorVersion: 1
      minorVersion: 29
    asserts:
      - hasDocuments:
          count: 1
      - equal:
          path: kind
          value: StatefulSet
      - lengthEqual:
          path: spec.template.spec.containers
          count: 1
      - equal:
          path: spec.template.spec.containers[0].image
          value: ghcr.io/loft-sh/vcluster-pro:0.0.1
      - contains:
          path: spec.template.spec.containers[0].env
          content:
            name: VCLUSTER_NAME
            value: my-release
      - contains:
          path: spec.template.spec.containers[0].volumeMounts
          content:
            name: data
            mountPath: /data
      - contains:
          path: spec.template.spec.containers[0].volumeMounts
          content:
            name: binaries
            mountPath: /binaries
      - contains:
          path: spec.template.spec.containers[0].volumeMounts
          content:
            name: certs
            mountPath: /pki
      - contains:
          path: spec.template.spec.containers[0].volumeMounts
          content:
            name: helm-cache
            mountPath: /.cache/helm
      - equal:
          path: metadata.name
          value: my-release
      - equal:
          path: metadata.namespace
          value: my-namespace
      - equal:
          path: spec.podManagementPolicy
          value: Parallel
      - equal:
          path: spec.persistentVolumeClaimRetentionPolicy.whenDeleted
          value: Retain
      - equal:
          path: spec.replicas
          value: 1
      - equal:
          path: spec.template.metadata.labels.app
          value: vcluster
      - equal:
          path: spec.template.spec.terminationGracePeriodSeconds
          value: 10
      - equal:
          path: spec.volumeClaimTemplates[0].spec.accessModes[0]
          value: ReadWriteOnce
      - equal:
          path: spec.volumeClaimTemplates[0].spec.resources.requests.storage
          value: 5Gi

  - it: fail when both backing stores are enabled
    set:
      controlPlane:
        backingStore:
          etcd:
            embedded:
              enabled: true
            deploy:
              enabled: true
    asserts:
      - failedTemplate:
          errorMessage: "you can only enable one backingStore at the same time"

  - it: not persistent when external etcd is enabled
    set:
      controlPlane:
        backingStore:
          etcd:
            deploy:
              enabled: true
    asserts:
      - equal:
          path: kind
          value: Deployment
      - notExists:
          path: spec.volumeClaimTemplates

  - it: not persistent when k8s and external database
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
        backingStore:
          database:
            external:
              enabled: true
    asserts:
      - equal:
          path: kind
          value: Deployment
      - notExists:
          path: spec.volumeClaimTemplates

  - it: persistent when embedded database
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
        backingStore:
          database:
            embedded:
              enabled: true
    asserts:
      - equal:
          path: kind
          value: StatefulSet
      - lengthEqual:
          path: spec.volumeClaimTemplates
          count: 1

  - it: persistent when k8s and embedded etcd
    set:
      controlPlane:
        backingStore:
          etcd:
            embedded:
              enabled: true
        distro:
          k8s:
            enabled: true
    asserts:
      - equal:
          path: kind
          value: StatefulSet
      - lengthEqual:
          path: spec.volumeClaimTemplates
          count: 1

  - it: persistent when embedded database
    asserts:
      - equal:
          path: kind
          value: StatefulSet
      - lengthEqual:
          path: spec.volumeClaimTemplates
          count: 1

  - it: plugin 1
    set:
      plugins:
        test:
          image: test
      plugin:
        test123:
          version: v2
          image: test
    asserts:
      - lengthEqual:
          path: spec.template.spec.volumes
          count: 7
      - lengthEqual:
          path: spec.template.spec.initContainers
          count: 5

  - it: plugin volumes 2
    set:
      controlPlane:
        distro:
          k0s:
            enabled: true
      plugin:
        test:
          version: v2
          image: test
    asserts:
      - equal:
          path: kind
          value: StatefulSet
      - lengthEqual:
          path: spec.template.spec.volumes
          count: 8
      - lengthEqual:
          path: spec.template.spec.initContainers
          count: 2

  - it: plugin volumes 3
    set:
      plugin:
        test:
          image: test
    asserts:
      - lengthEqual:
          path: spec.template.spec.volumes
          count: 6
      - lengthEqual:
          path: spec.template.spec.initContainers
          count: 3

  - it: add volumes
    set:
      controlPlane:
        distro:
          k3s:
            enabled: true
        statefulSet:
          persistence:
            addVolumes:
              - name: myVolume
    asserts:
      - contains:
          path: spec.template.spec.volumes
          content:
            name: myVolume
      - lengthEqual:
          path: spec.template.spec.volumes
          count: 8

  - it: enable k8s
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
    asserts:
      - equal:
          path: kind
          value: StatefulSet
      - lengthEqual:
          path: spec.volumeClaimTemplates
          count: 1

  - it: enable k8s with deploy etcd
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
        backingStore:
          etcd:
            deploy:
              enabled: true
    asserts:
      - equal:
          path: kind
          value: Deployment
      - notExists:
          path: spec.volumeClaimTemplates
      - contains:
          path: spec.template.spec.volumes
          content:
            name: data
            emptyDir: {}

  - it: enable k8s
    release:
      name: my-release
      namespace: my-namespace
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
        statefulSet:
          persistence:
            volumeClaim:
              enabled: false
            volumeClaimTemplates:
              - metadata:
                  name: data
                spec:
                  resources:
                    requests:
                      storage: 5Gi
    asserts:
      - equal:
          path: kind
          value: StatefulSet
      - equal:
          path: spec.serviceName
          value: my-release-headless
      - contains:
          path: spec.volumeClaimTemplates
          content:
            metadata:
              name: data
            spec:
              resources:
                requests:
                  storage: 5Gi

  - it: enable k8s
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
    release:
      name: my-release
      namespace: my-namespace
    asserts:
      - equal:
          path: kind
          value: StatefulSet
      - equal:
          path: spec.serviceName
          value: my-release-headless
      - lengthEqual:
          path: spec.volumeClaimTemplates
          count: 1

  - it: enable k8s with deploy etcd
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
        backingStore:
          etcd:
            deploy:
              enabled: true
    asserts:
      - equal:
          path: kind
          value: Deployment
      - notExists:
          path: spec.volumeClaimTemplates
      - contains:
          path: spec.template.spec.volumes
          content:
            name: data
            emptyDir: {}

  - it: enable k0s
    set:
      controlPlane:
        backingStore:
          etcd:
            deploy:
              enabled: true
        distro:
          k0s:
            enabled: true
    asserts:
      - equal:
          path: kind
          value: Deployment
      - notExists:
          path: spec.volumeClaimTemplates
      - contains:
          path: spec.template.spec.volumes
          content:
            name: data
            emptyDir: {}

  - it: append distro env
    set:
      controlPlane:
        distro:
          k3s:
            enabled: true
            env:
              - name: KEY
                value: VALUE
    asserts:
      - equal:
          path: kind
          value: StatefulSet
      - contains:
          path: spec.template.spec.containers[0].env
          content:
            name: KEY
            value: VALUE

  - it: should correctly set labels on the statefulset
    set:
      controlPlane:
        statefulSet:
          labels:
            my-label: my-value

    asserts:
      - equal:
          path: kind
          value: StatefulSet
      - equal:
          path: metadata.labels["my-label"]
          value: "my-value"

  - it: binariesVolume - should set to emptyDir by default
    asserts:
      - contains:
          path: spec.template.spec.volumes
          content:
            name: binaries
            emptyDir: {}

  - it: binariesVolume - should set the specified volume type correctly
    set:
      controlPlane:
        statefulSet:
          persistence:
            binariesVolume:
              - name: binaries
                persistentVolumeClaim:
                  claimName: my-pvc
    asserts:
      - contains:
          path: spec.template.spec.volumes
          content:
            name: binaries
            persistentVolumeClaim:
              claimName: my-pvc

  - it: dataVolume - should set the specified data volume type correctly
    set:
      controlPlane:
        statefulSet:
          persistence:
            dataVolume:
              - name: data
                persistentVolumeClaim:
                  claimName: my-custom-pvc
    asserts:
      - contains:
          path: spec.template.spec.volumes
          content:
            name: data
            persistentVolumeClaim:
              claimName: my-custom-pvc

  - it: k8s version not set, default tag images used for apiServer and controllerManager
    chart:
      version: "test-"
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: registry.k8s.io/kube-controller-manager:v1.31.1
      - equal:
          path: spec.template.spec.initContainers[2].image
          value: registry.k8s.io/kube-apiserver:v1.31.1

  - it: k8s capabilities set
    chart:
      version: "test-v1.29.3"
    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: registry.k8s.io/kube-controller-manager:v1.29.3
      - equal:
          path: spec.template.spec.initContainers[2].image
          value: registry.k8s.io/kube-apiserver:v1.29.3

  - it: k8s capabilities orbstack
    chart:
      version: "test-v1.29.3+orb1"
    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: registry.k8s.io/kube-controller-manager:v1.29.3
      - equal:
          path: spec.template.spec.initContainers[2].image
          value: registry.k8s.io/kube-apiserver:v1.29.3

  - it: k8s capabilities invalid
    chart:
      version: "test-invalid"
    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: registry.k8s.io/kube-controller-manager:v1.31.1

  - it: k8s capabilities incomplete
    chart:
      version: "test-v1.22"
    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: registry.k8s.io/kube-controller-manager:v1.31.1

  - it: k8s capabilities incomplete 2
    chart:
      version: "test-1.22.11"
    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: registry.k8s.io/kube-controller-manager:v1.31.1

  - it: k8s capabilities incomplete 2
    chart:
      version: "test-v1.22.33"
    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: registry.k8s.io/kube-controller-manager:v1.22.33

  - it: k8s version sets image tag for apiServer and controllerManager
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
            version: v1.35.999
    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: registry.k8s.io/kube-controller-manager:v1.35.999
      - equal:
          path: spec.template.spec.initContainers[2].image
          value: registry.k8s.io/kube-apiserver:v1.35.999

  - it: k8s version set but overridden by image tag for apiServer and controllerManager
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
            version: v1.30.999
            apiServer:
              image:
                tag: v99912
            controllerManager:
              image:
                tag: v23123

    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: registry.k8s.io/kube-controller-manager:v23123
      - equal:
          path: spec.template.spec.initContainers[2].image
          value: registry.k8s.io/kube-apiserver:v99912

  - it: k8s not version set but image tags for apiServer and controllerManager set
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
            apiServer:
              image:
                tag: v99914
            controllerManager:
              image:
                tag: v23127

    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: registry.k8s.io/kube-controller-manager:v23127
      - equal:
          path: spec.template.spec.initContainers[2].image
          value: registry.k8s.io/kube-apiserver:v99914

  - it: k8s version not set, default tag images used for apiServer and controllerManager (virtual scheduler enabled)
    chart:
      version: "test-"
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
        advanced:
          virtualScheduler:
            enabled: true
    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: registry.k8s.io/kube-controller-manager:v1.31.1
      - equal:
          path: spec.template.spec.initContainers[2].image
          value: registry.k8s.io/kube-scheduler:v1.31.1
      - equal:
          path: spec.template.spec.initContainers[3].image
          value: registry.k8s.io/kube-apiserver:v1.31.1

  - it: k8s version sets image tag for apiServer and controllerManager (virtual scheduler enabled)
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
            version: v1.35.999
        advanced:
          virtualScheduler:
            enabled: true
    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: registry.k8s.io/kube-controller-manager:v1.35.999
      - equal:
          path: spec.template.spec.initContainers[2].image
          value: registry.k8s.io/kube-scheduler:v1.35.999
      - equal:
          path: spec.template.spec.initContainers[3].image
          value: registry.k8s.io/kube-apiserver:v1.35.999

  - it: k8s version set but overridden by image tag for apiServer and controllerManager (virtual scheduler enabled)
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
            version: v1.30.999
            apiServer:
              image:
                tag: v99912
            controllerManager:
              image:
                tag: v23123
            scheduler:
              image:
                tag: v123654
        advanced:
          virtualScheduler:
            enabled: true

    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: registry.k8s.io/kube-controller-manager:v23123
      - equal:
          path: spec.template.spec.initContainers[2].image
          value: registry.k8s.io/kube-scheduler:v123654
      - equal:
          path: spec.template.spec.initContainers[3].image
          value: registry.k8s.io/kube-apiserver:v99912

  - it: k8s not version set but image tags for apiServer and controllerManager set (virtual scheduler enabled)
    set:
      controlPlane:
        distro:
          k8s:
            enabled: true
            apiServer:
              image:
                tag: v99914
            controllerManager:
              image:
                tag: v23127
            scheduler:
              image:
                tag: v123656

        advanced:
          virtualScheduler:
            enabled: true

    asserts:
      - equal:
          path: spec.template.spec.initContainers[1].image
          value: registry.k8s.io/kube-controller-manager:v23127
      - equal:
          path: spec.template.spec.initContainers[2].image
          value: registry.k8s.io/kube-scheduler:v123656
      - equal:
          path: spec.template.spec.initContainers[3].image
          value: registry.k8s.io/kube-apiserver:v99914

  - it: custom dnsPolicy
    set:
      controlPlane:
        statefulSet:
          dnsPolicy: "ClusterFirst"
    asserts:
      - equal:
          path: spec.template.spec.dnsPolicy
          value: "ClusterFirst"

  - it: custom dnsConfig
    set:
      controlPlane:
        statefulSet:
          dnsConfig:
            nameservers:
              - 192.0.2.1
            searches:
              - ns1.svc.cluster-domain.example
            options:
              - name: ndots
                value: "2"
    asserts:
      - equal:
          path: spec.template.spec.dnsConfig.nameservers[0]
          value: "192.0.2.1"
      - equal:
          path: spec.template.spec.dnsConfig.searches[0]
          value: "ns1.svc.cluster-domain.example"
      - equal:
          path: spec.template.spec.dnsConfig.options[0].name
          value: "ndots"
      - equal:
          path: spec.template.spec.dnsConfig.options[0].value
          value: "2"

  - it: must use StatefulSet for embedded etcd
    set:
      controlPlane:
        backingStore:
          etcd:
            embedded:
              enabled: true

    asserts:
      - equal:
          path: kind
          value: StatefulSet

  - it: must use StatefulSet for embedded etcd without persistence
    set:
      controlPlane:
        backingStore:
          etcd:
            embedded:
              enabled: true
        statefulSet:
          persistence:
            volumeClaim:
              enabled: false
            binariesVolume:
              - name: binaries
                emptyDir:
                  medium: Memory

    asserts:
      - equal:
          path: kind
          value: StatefulSet

  - it: sync custom resources
    set:
      sync:
        toHost:
          customResources:
            test.cert-manager.io:
              enabled: true
              patches:
                - path: spec.dnsNames[*]
                  expression: "value.startsWith('www.') ? value.slice(4) : value"
                  reverseExpression: '"www."+value'
    asserts:
      - equal:
          path: kind
          value: StatefulSet
