Skip to content

Conversation

@thunderboltsid
Copy link
Contributor

@thunderboltsid thunderboltsid commented Jul 23, 2025

Use XOR instead of OR for cluster and subnet presence check against failure domains on control plane and worker overrides.

How has this been tested?
Tested in conjunction with #1236 in #1226

  • Create a cluster with control plane and machine deployments with failure domains with cluster and subnet variables also set in controlPlane machineDetails and machineDeployment variables overrides.
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  labels:
    cluster.x-k8s.io/cluster-name: nkp-sid-caren
    cluster.x-k8s.io/provider: nutanix
  name: nkp-sid-caren
spec:
  ...
  topology:
    class: nutanix-quick-start
    controlPlane:
      metadata: {}
      replicas: 3
    variables:
    - name: clusterConfig
      value:
        ...
        controlPlane:
          nutanix:
            failureDomains:
            - fd-1
            - fd-2
            - fd-3
            machineDetails:
              bootType: uefi
              cluster:
                type: name
                name: ncn-dev-sandbox
              subnets:
              - type: name
                name: vlan173
              imageLookup:
                baseOS: rocky-9.6
                format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
              memorySize: 4Gi
              systemDiskSize: 40Gi
              vcpuSockets: 2
              vcpusPerSocket: 1
        ...
    - name: workerConfig
      value:
        nutanix:
          machineDetails:
            bootType: uefi
            cluster:
              name: ncn-dev-sandbox
              type: name
            imageLookup:
              baseOS: rocky-9.6
              format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
            memorySize: 4Gi
            subnets:
            - name: vlan173
              type: name
            systemDiskSize: 40Gi
            vcpuSockets: 2
            vcpusPerSocket: 1
    version: 1.33.1
    workers:
      machineDeployments:
      - class: default-worker
        failureDomain: fd-1
        metadata:
          annotations:
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "1"
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "1"
        name: md-0
        variables:
          overrides:
          - name: workerConfig
            value:
              nutanix:
                machineDetails:
                  bootType: uefi
                  cluster:
                    type: name
                    name: ncn-dev-sandbox
                  subnets:
                  - type: name
                    name: vlan173
                  imageLookup:
                    baseOS: rocky-9.6
                    format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
                  memorySize: 8Gi
                  systemDiskSize: 80Gi
                  vcpuSockets: 8
                  vcpusPerSocket: 1

and expect failures from the webhook

$ k apply -f nkp-sid-caren-neg.yaml
...
Error from server (Forbidden): error when creating "nkp-sid-caren-neg.yaml": admission webhook "cluster-validator.caren.nutanix.com" denied the request: [spec.topology.variables.clusterConfig.value.controlPlane.nutanix.machineDetails.cluster: Forbidden: "cluster" must not be set when failureDomains are configured., spec.topology.variables.clusterConfig.value.controlPlane.nutanix.machineDetails.subnets: Forbidden: "subnets" must not be set when failureDomains are configured., spec.topology.workers.machineDeployments.variables.overrides.workerConfig.value.nutanix.machineDetails.cluster: Forbidden: "cluster" must not be set when failureDomain is configured., spec.topology.workers.machineDeployments.variables.overrides.workerConfig.value.nutanix.machineDetails.subnets: Forbidden: "subnets" must not be set when failureDomain is configured.]
  • Create a cluster without failure domains with a machine deployment with cluster and subnet not set
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  labels:
    cluster.x-k8s.io/cluster-name: nkp-sid-caren-no-fd
    cluster.x-k8s.io/provider: nutanix
  name: nkp-sid-caren-no-fd
spec:
  ...
  topology:
    class: nutanix-quick-start
    controlPlane:
      metadata: {}
      replicas: 3
    variables:
    - name: clusterConfig
      value:
        ...
        controlPlane:
          nutanix:
            machineDetails:
              bootType: uefi
              imageLookup:
                baseOS: rocky-9.6
                format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
              memorySize: 4Gi
              systemDiskSize: 40Gi
              vcpuSockets: 2
              vcpusPerSocket: 1
        ...
    - name: workerConfig
      value:
        nutanix:
          machineDetails:
            bootType: uefi
            cluster:
              name: ncn-dev-sandbox
              type: name
            imageLookup:
              baseOS: rocky-9.6
              format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
            memorySize: 4Gi
            subnets:
            - name: vlan173
              type: name
            systemDiskSize: 40Gi
            vcpuSockets: 2
            vcpusPerSocket: 1
    version: 1.33.1
    workers:
      machineDeployments:
      - class: default-worker
        metadata:
          annotations:
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "1"
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "1"
        name: md-0
        variables:
          overrides:
          - name: workerConfig
            value:
              nutanix:
                machineDetails:
                  bootType: uefi
                  imageLookup:
                    baseOS: rocky-9.6
                    format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
                  memorySize: 8Gi
                  cluster:
                    type: name
                    name: ncn-dev-sandbox
                  subnets:
                  - type: name
                    name: vlan173
                  systemDiskSize: 80Gi
                  vcpuSockets: 8
                  vcpusPerSocket: 1
      - class: default-worker
        metadata:
          annotations:
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "1"
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "1"
        name: md-1
        variables:
          overrides:
          - name: workerConfig
            value:
              nutanix:
                machineDetails:
                  bootType: uefi
                  imageLookup:
                    baseOS: rocky-9.6
                    format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
                  memorySize: 8Gi
                  systemDiskSize: 80Gi
                  vcpuSockets: 8
                  vcpusPerSocket: 1

and expect failures from webhook

$ k apply -f no-fd-neg.yaml
...
Error from server (Forbidden): error when creating "no-fd-neg.yaml": admission webhook "cluster-validator.caren.nutanix.com" denied the request: [spec.topology.variables.clusterConfig.value.controlPlane.nutanix.machineDetails.cluster: Required value: "cluster" must be set when failureDomains are not configured., spec.topology.variables.clusterConfig.value.controlPlane.nutanix.machineDetails.subnets: Required value: "subnets" must be set when failureDomains are not configured., spec.topology.workers.machineDeployments.variables.overrides.workerConfig.value.nutanix.machineDetails.cluster: Required value: "cluster" must be set when failureDomain is not configured., spec.topology.workers.machineDeployments.variables.overrides.workerConfig.value.nutanix.machineDetails.subnets: Required value: "subnets" must be set when failureDomain is not configured.]

jimmidyson pushed a commit that referenced this pull request Jul 24, 2025
…an (#1236)

These changes ensure the resulting NutanixMachineTemplate patches also
reflect
the XOR between failureDomains and cluster/subnets.

**How has this been tested?**
Tested in conjunction with
#1233
in
#1226
* Run `make dev.run-on-kind` and see default NutanixMachineTemplates
when management cluster is created and observe no placeholder cluster
and subnet fields
```yaml
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nutanix-quick-start-cp-nmt
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: ClusterClass
      name: nutanix-quick-start
  spec:
    template:
      spec:
        bootType: legacy
        image:
          name: ""
          type: name
        memorySize: 4Gi
        systemDiskSize: 40Gi
        vcpuSockets: 2
        vcpusPerSocket: 1
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nutanix-quick-start-md-nmt
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: ClusterClass
      name: nutanix-quick-start
  spec:
    template:
      spec:
        bootType: legacy
        image:
          name: ""
          type: name
        memorySize: 4Gi
        systemDiskSize: 40Gi
        vcpuSockets: 2
        vcpusPerSocket: 1
```

* Create a cluster without failure domains with a machine deployment
with cluster and subnet set
```yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  ...
  name: nkp-sid-caren-no-fd
spec:
  ...
  topology:
    class: nutanix-quick-start
    controlPlane:
      metadata: {}
      replicas: 3
    variables:
    - name: clusterConfig
      value:
        ...
        controlPlane:
          nutanix:
            machineDetails:
              bootType: uefi
              imageLookup:
                baseOS: rocky-9.6
                format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
              memorySize: 4Gi
              systemDiskSize: 40Gi
              vcpuSockets: 2
              vcpusPerSocket: 1
              cluster:
                type: name
                name: ncn-dev-sandbox
              subnets:
              - type: name
                name: vlan173
        ...
    - name: workerConfig
      value:
        nutanix:
          machineDetails:
            bootType: uefi
            cluster:
              name: ncn-dev-sandbox
              type: name
            imageLookup:
              baseOS: rocky-9.6
              format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
            memorySize: 4Gi
            subnets:
            - name: vlan173
              type: name
            systemDiskSize: 40Gi
            vcpuSockets: 2
            vcpusPerSocket: 1
    version: 1.33.1
    workers:
      machineDeployments:
      - class: default-worker
        metadata:
          annotations:
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "1"
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "1"
        name: md-0
        variables:
          overrides:
          - name: workerConfig
            value:
              nutanix:
                machineDetails:
                  bootType: uefi
                  imageLookup:
                    baseOS: rocky-9.6
                    format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
                  memorySize: 8Gi
                  cluster:
                    type: name
                    name: ncn-dev-sandbox
                  subnets:
                  - type: name
                    name: vlan173
                  systemDiskSize: 80Gi
                  vcpuSockets: 8
                  vcpusPerSocket: 1
      - class: default-worker
        metadata:
          annotations:
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "1"
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "1"
        name: md-1
        variables:
          overrides:
          - name: workerConfig
            value:
              nutanix:
                machineDetails:
                  bootType: uefi
                  imageLookup:
                    baseOS: rocky-9.6
                    format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
                  memorySize: 8Gi
                  cluster:
                    type: uuid
                    uuid: 00061f7f-44f7-19dc-3be1-7cc25586ee44
                  subnets:
                  - type: name
                    name: vlan173
                  systemDiskSize: 80Gi
                  vcpuSockets: 8
                  vcpusPerSocket: 1
```
Observe the generated NutanixMachineTemplate has cluster and subnets set
correctly
```yaml
apiVersion: v1
items:
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-no-fd-7np7m
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren-no-fd
  spec:
    template:
      spec:
        bootType: uefi
        cluster:
          name: ncn-dev-sandbox
          type: name
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 4Gi
        subnet:
        - name: vlan173
          type: name
        systemDiskSize: 40Gi
        vcpuSockets: 2
        vcpusPerSocket: 1
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-no-fd-md-0-qnr58
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren-no-fd
  spec:
    template:
      spec:
        bootType: uefi
        cluster:
          name: ncn-dev-sandbox
          type: name
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 8Gi
        subnet:
        - name: vlan173
          type: name
        systemDiskSize: 80Gi
        vcpuSockets: 8
        vcpusPerSocket: 1
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-no-fd-md-1-59tlq
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren-no-fd
  spec:
    template:
      spec:
        bootType: uefi
        cluster:
          type: uuid
          uuid: 00061f7f-44f7-19dc-3be1-7cc25586ee44
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 8Gi
        subnet:
        - name: vlan173
          type: name
        systemDiskSize: 80Gi
        vcpuSockets: 8
        vcpusPerSocket: 1

```

* Create a cluster with control plane and machine deployment on failure
domains
```yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  labels:
    cluster.x-k8s.io/cluster-name: nkp-sid-caren
    cluster.x-k8s.io/provider: nutanix
  name: nkp-sid-caren
spec:
  ...
  topology:
    class: nutanix-quick-start
    controlPlane:
      metadata: {}
      replicas: 3
    variables:
    - name: clusterConfig
      value:
        ...
        controlPlane:
          nutanix:
            failureDomains:
            - fd-1
            - fd-2
            - fd-3
            machineDetails:
              bootType: uefi
              imageLookup:
                baseOS: rocky-9.6
                format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
              memorySize: 4Gi
              systemDiskSize: 40Gi
              vcpuSockets: 2
              vcpusPerSocket: 1
        ...
    - name: workerConfig
      value:
        nutanix:
          machineDetails:
            bootType: uefi
            cluster:
              name: ncn-dev-sandbox
              type: name
            imageLookup:
              baseOS: rocky-9.6
              format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
            memorySize: 4Gi
            subnets:
            - name: vlan173
              type: name
            systemDiskSize: 40Gi
            vcpuSockets: 2
            vcpusPerSocket: 1
    version: 1.33.1
    workers:
      machineDeployments:
      - class: default-worker
        failureDomain: fd-1
        metadata:
          annotations:
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "1"
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "1"
        name: md-0
        variables:
          overrides:
          - name: workerConfig
            value:
              nutanix:
                machineDetails:
                  bootType: uefi
                  imageLookup:
                    baseOS: rocky-9.6
                    format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
                  memorySize: 8Gi
                  systemDiskSize: 80Gi
                  vcpuSockets: 8
                  vcpusPerSocket: 1
```
Observe the generated NutanixMachineTemplate does not have cluster and
subnet set
```yaml
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-kp4nc
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren
  spec:
    template:
      spec:
        bootType: uefi
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 4Gi
        systemDiskSize: 40Gi
        vcpuSockets: 2
        vcpusPerSocket: 1
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-md-0-bfm6v
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren
  spec:
    template:
      spec:
        bootType: uefi
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 8Gi
        systemDiskSize: 80Gi
        vcpuSockets: 8
        vcpusPerSocket: 1
```
@jimmidyson jimmidyson enabled auto-merge (squash) July 24, 2025 09:18
@jimmidyson jimmidyson requested a review from mhrabovcin July 24, 2025 09:18
jimmidyson pushed a commit that referenced this pull request Jul 24, 2025
These changes ensure the resulting NutanixMachineTemplate patches also
reflect
the XOR between failureDomains and cluster/subnets.

**How has this been tested?**
Tested in conjunction with
#1233
in
#1226
* Run `make dev.run-on-kind` and see default NutanixMachineTemplates
when management cluster is created and observe no placeholder cluster
and subnet fields
```yaml
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nutanix-quick-start-cp-nmt
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: ClusterClass
      name: nutanix-quick-start
  spec:
    template:
      spec:
        bootType: legacy
        image:
          name: ""
          type: name
        memorySize: 4Gi
        systemDiskSize: 40Gi
        vcpuSockets: 2
        vcpusPerSocket: 1
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nutanix-quick-start-md-nmt
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: ClusterClass
      name: nutanix-quick-start
  spec:
    template:
      spec:
        bootType: legacy
        image:
          name: ""
          type: name
        memorySize: 4Gi
        systemDiskSize: 40Gi
        vcpuSockets: 2
        vcpusPerSocket: 1
```

* Create a cluster without failure domains with a machine deployment
with cluster and subnet set
```yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  ...
  name: nkp-sid-caren-no-fd
spec:
  ...
  topology:
    class: nutanix-quick-start
    controlPlane:
      metadata: {}
      replicas: 3
    variables:
    - name: clusterConfig
      value:
        ...
        controlPlane:
          nutanix:
            machineDetails:
              bootType: uefi
              imageLookup:
                baseOS: rocky-9.6
                format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
              memorySize: 4Gi
              systemDiskSize: 40Gi
              vcpuSockets: 2
              vcpusPerSocket: 1
              cluster:
                type: name
                name: ncn-dev-sandbox
              subnets:
              - type: name
                name: vlan173
        ...
    - name: workerConfig
      value:
        nutanix:
          machineDetails:
            bootType: uefi
            cluster:
              name: ncn-dev-sandbox
              type: name
            imageLookup:
              baseOS: rocky-9.6
              format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
            memorySize: 4Gi
            subnets:
            - name: vlan173
              type: name
            systemDiskSize: 40Gi
            vcpuSockets: 2
            vcpusPerSocket: 1
    version: 1.33.1
    workers:
      machineDeployments:
      - class: default-worker
        metadata:
          annotations:
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "1"
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "1"
        name: md-0
        variables:
          overrides:
          - name: workerConfig
            value:
              nutanix:
                machineDetails:
                  bootType: uefi
                  imageLookup:
                    baseOS: rocky-9.6
                    format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
                  memorySize: 8Gi
                  cluster:
                    type: name
                    name: ncn-dev-sandbox
                  subnets:
                  - type: name
                    name: vlan173
                  systemDiskSize: 80Gi
                  vcpuSockets: 8
                  vcpusPerSocket: 1
      - class: default-worker
        metadata:
          annotations:
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "1"
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "1"
        name: md-1
        variables:
          overrides:
          - name: workerConfig
            value:
              nutanix:
                machineDetails:
                  bootType: uefi
                  imageLookup:
                    baseOS: rocky-9.6
                    format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
                  memorySize: 8Gi
                  cluster:
                    type: uuid
                    uuid: 00061f7f-44f7-19dc-3be1-7cc25586ee44
                  subnets:
                  - type: name
                    name: vlan173
                  systemDiskSize: 80Gi
                  vcpuSockets: 8
                  vcpusPerSocket: 1
```
Observe the generated NutanixMachineTemplate has cluster and subnets set
correctly
```yaml
apiVersion: v1
items:
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-no-fd-7np7m
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren-no-fd
  spec:
    template:
      spec:
        bootType: uefi
        cluster:
          name: ncn-dev-sandbox
          type: name
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 4Gi
        subnet:
        - name: vlan173
          type: name
        systemDiskSize: 40Gi
        vcpuSockets: 2
        vcpusPerSocket: 1
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-no-fd-md-0-qnr58
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren-no-fd
  spec:
    template:
      spec:
        bootType: uefi
        cluster:
          name: ncn-dev-sandbox
          type: name
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 8Gi
        subnet:
        - name: vlan173
          type: name
        systemDiskSize: 80Gi
        vcpuSockets: 8
        vcpusPerSocket: 1
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-no-fd-md-1-59tlq
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren-no-fd
  spec:
    template:
      spec:
        bootType: uefi
        cluster:
          type: uuid
          uuid: 00061f7f-44f7-19dc-3be1-7cc25586ee44
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 8Gi
        subnet:
        - name: vlan173
          type: name
        systemDiskSize: 80Gi
        vcpuSockets: 8
        vcpusPerSocket: 1

```

* Create a cluster with control plane and machine deployment on failure
domains
```yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  labels:
    cluster.x-k8s.io/cluster-name: nkp-sid-caren
    cluster.x-k8s.io/provider: nutanix
  name: nkp-sid-caren
spec:
  ...
  topology:
    class: nutanix-quick-start
    controlPlane:
      metadata: {}
      replicas: 3
    variables:
    - name: clusterConfig
      value:
        ...
        controlPlane:
          nutanix:
            failureDomains:
            - fd-1
            - fd-2
            - fd-3
            machineDetails:
              bootType: uefi
              imageLookup:
                baseOS: rocky-9.6
                format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
              memorySize: 4Gi
              systemDiskSize: 40Gi
              vcpuSockets: 2
              vcpusPerSocket: 1
        ...
    - name: workerConfig
      value:
        nutanix:
          machineDetails:
            bootType: uefi
            cluster:
              name: ncn-dev-sandbox
              type: name
            imageLookup:
              baseOS: rocky-9.6
              format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
            memorySize: 4Gi
            subnets:
            - name: vlan173
              type: name
            systemDiskSize: 40Gi
            vcpuSockets: 2
            vcpusPerSocket: 1
    version: 1.33.1
    workers:
      machineDeployments:
      - class: default-worker
        failureDomain: fd-1
        metadata:
          annotations:
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "1"
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "1"
        name: md-0
        variables:
          overrides:
          - name: workerConfig
            value:
              nutanix:
                machineDetails:
                  bootType: uefi
                  imageLookup:
                    baseOS: rocky-9.6
                    format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
                  memorySize: 8Gi
                  systemDiskSize: 80Gi
                  vcpuSockets: 8
                  vcpusPerSocket: 1
```
Observe the generated NutanixMachineTemplate does not have cluster and
subnet set
```yaml
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-kp4nc
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren
  spec:
    template:
      spec:
        bootType: uefi
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 4Gi
        systemDiskSize: 40Gi
        vcpuSockets: 2
        vcpusPerSocket: 1
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-md-0-bfm6v
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren
  spec:
    template:
      spec:
        bootType: uefi
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 8Gi
        systemDiskSize: 80Gi
        vcpuSockets: 8
        vcpusPerSocket: 1
```
@jimmidyson jimmidyson disabled auto-merge July 24, 2025 09:22
@jimmidyson jimmidyson enabled auto-merge (rebase) July 24, 2025 09:25
Copy link
Contributor

@mhrabovcin mhrabovcin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL about omitzero

auto-merge was automatically disabled July 24, 2025 09:56

Base branch requires signed commits

@thunderboltsid
Copy link
Contributor Author

TIL about omitzero

Yeah, it started with go1.24

Use XOR instead of OR for cluster and subnet presence check against
failure domains on control plane and worker overrides.
These changes ensure the resulting NutanixMachineTemplate patches also
reflect
the XOR between failureDomains and cluster/subnets.

**How has this been tested?**
Tested in conjunction with
#1233
in
#1226
* Run `make dev.run-on-kind` and see default NutanixMachineTemplates
when management cluster is created and observe no placeholder cluster
and subnet fields
```yaml
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nutanix-quick-start-cp-nmt
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: ClusterClass
      name: nutanix-quick-start
  spec:
    template:
      spec:
        bootType: legacy
        image:
          name: ""
          type: name
        memorySize: 4Gi
        systemDiskSize: 40Gi
        vcpuSockets: 2
        vcpusPerSocket: 1
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nutanix-quick-start-md-nmt
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: ClusterClass
      name: nutanix-quick-start
  spec:
    template:
      spec:
        bootType: legacy
        image:
          name: ""
          type: name
        memorySize: 4Gi
        systemDiskSize: 40Gi
        vcpuSockets: 2
        vcpusPerSocket: 1
```

* Create a cluster without failure domains with a machine deployment
with cluster and subnet set
```yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  ...
  name: nkp-sid-caren-no-fd
spec:
  ...
  topology:
    class: nutanix-quick-start
    controlPlane:
      metadata: {}
      replicas: 3
    variables:
    - name: clusterConfig
      value:
        ...
        controlPlane:
          nutanix:
            machineDetails:
              bootType: uefi
              imageLookup:
                baseOS: rocky-9.6
                format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
              memorySize: 4Gi
              systemDiskSize: 40Gi
              vcpuSockets: 2
              vcpusPerSocket: 1
              cluster:
                type: name
                name: ncn-dev-sandbox
              subnets:
              - type: name
                name: vlan173
        ...
    - name: workerConfig
      value:
        nutanix:
          machineDetails:
            bootType: uefi
            cluster:
              name: ncn-dev-sandbox
              type: name
            imageLookup:
              baseOS: rocky-9.6
              format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
            memorySize: 4Gi
            subnets:
            - name: vlan173
              type: name
            systemDiskSize: 40Gi
            vcpuSockets: 2
            vcpusPerSocket: 1
    version: 1.33.1
    workers:
      machineDeployments:
      - class: default-worker
        metadata:
          annotations:
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "1"
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "1"
        name: md-0
        variables:
          overrides:
          - name: workerConfig
            value:
              nutanix:
                machineDetails:
                  bootType: uefi
                  imageLookup:
                    baseOS: rocky-9.6
                    format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
                  memorySize: 8Gi
                  cluster:
                    type: name
                    name: ncn-dev-sandbox
                  subnets:
                  - type: name
                    name: vlan173
                  systemDiskSize: 80Gi
                  vcpuSockets: 8
                  vcpusPerSocket: 1
      - class: default-worker
        metadata:
          annotations:
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "1"
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "1"
        name: md-1
        variables:
          overrides:
          - name: workerConfig
            value:
              nutanix:
                machineDetails:
                  bootType: uefi
                  imageLookup:
                    baseOS: rocky-9.6
                    format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
                  memorySize: 8Gi
                  cluster:
                    type: uuid
                    uuid: 00061f7f-44f7-19dc-3be1-7cc25586ee44
                  subnets:
                  - type: name
                    name: vlan173
                  systemDiskSize: 80Gi
                  vcpuSockets: 8
                  vcpusPerSocket: 1
```
Observe the generated NutanixMachineTemplate has cluster and subnets set
correctly
```yaml
apiVersion: v1
items:
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-no-fd-7np7m
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren-no-fd
  spec:
    template:
      spec:
        bootType: uefi
        cluster:
          name: ncn-dev-sandbox
          type: name
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 4Gi
        subnet:
        - name: vlan173
          type: name
        systemDiskSize: 40Gi
        vcpuSockets: 2
        vcpusPerSocket: 1
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-no-fd-md-0-qnr58
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren-no-fd
  spec:
    template:
      spec:
        bootType: uefi
        cluster:
          name: ncn-dev-sandbox
          type: name
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 8Gi
        subnet:
        - name: vlan173
          type: name
        systemDiskSize: 80Gi
        vcpuSockets: 8
        vcpusPerSocket: 1
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-no-fd-md-1-59tlq
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren-no-fd
  spec:
    template:
      spec:
        bootType: uefi
        cluster:
          type: uuid
          uuid: 00061f7f-44f7-19dc-3be1-7cc25586ee44
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 8Gi
        subnet:
        - name: vlan173
          type: name
        systemDiskSize: 80Gi
        vcpuSockets: 8
        vcpusPerSocket: 1

```

* Create a cluster with control plane and machine deployment on failure
domains
```yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  labels:
    cluster.x-k8s.io/cluster-name: nkp-sid-caren
    cluster.x-k8s.io/provider: nutanix
  name: nkp-sid-caren
spec:
  ...
  topology:
    class: nutanix-quick-start
    controlPlane:
      metadata: {}
      replicas: 3
    variables:
    - name: clusterConfig
      value:
        ...
        controlPlane:
          nutanix:
            failureDomains:
            - fd-1
            - fd-2
            - fd-3
            machineDetails:
              bootType: uefi
              imageLookup:
                baseOS: rocky-9.6
                format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
              memorySize: 4Gi
              systemDiskSize: 40Gi
              vcpuSockets: 2
              vcpusPerSocket: 1
        ...
    - name: workerConfig
      value:
        nutanix:
          machineDetails:
            bootType: uefi
            cluster:
              name: ncn-dev-sandbox
              type: name
            imageLookup:
              baseOS: rocky-9.6
              format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
            memorySize: 4Gi
            subnets:
            - name: vlan173
              type: name
            systemDiskSize: 40Gi
            vcpuSockets: 2
            vcpusPerSocket: 1
    version: 1.33.1
    workers:
      machineDeployments:
      - class: default-worker
        failureDomain: fd-1
        metadata:
          annotations:
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "1"
            cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "1"
        name: md-0
        variables:
          overrides:
          - name: workerConfig
            value:
              nutanix:
                machineDetails:
                  bootType: uefi
                  imageLookup:
                    baseOS: rocky-9.6
                    format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
                  memorySize: 8Gi
                  systemDiskSize: 80Gi
                  vcpuSockets: 8
                  vcpusPerSocket: 1
```
Observe the generated NutanixMachineTemplate does not have cluster and
subnet set
```yaml
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-kp4nc
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren
  spec:
    template:
      spec:
        bootType: uefi
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 4Gi
        systemDiskSize: 40Gi
        vcpuSockets: 2
        vcpusPerSocket: 1
- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
  kind: NutanixMachineTemplate
  metadata:
    ...
    name: nkp-sid-caren-md-0-bfm6v
    namespace: default
    ownerReferences:
    - apiVersion: cluster.x-k8s.io/v1beta1
      kind: Cluster
      name: nkp-sid-caren
  spec:
    template:
      spec:
        bootType: uefi
        imageLookup:
          baseOS: rocky-9.6
          format: nkp-{{.BaseOS}}-release-{{.K8sVersion}}-*
        memorySize: 8Gi
        systemDiskSize: 80Gi
        vcpuSockets: 8
        vcpusPerSocket: 1
```
@thunderboltsid thunderboltsid enabled auto-merge (rebase) July 24, 2025 10:29
@thunderboltsid
Copy link
Contributor Author

thunderboltsid commented Jul 24, 2025

had to manually push rebased commits due to signed commit requirement

auto-merge was automatically disabled July 24, 2025 10:59

Base branch requires signed commits

@jimmidyson jimmidyson merged commit 96e26c5 into main Jul 24, 2025
23 checks passed
@jimmidyson jimmidyson deleted the jira/NCN-108599 branch July 24, 2025 11:14
jimmidyson added a commit that referenced this pull request Jul 29, 2025
🤖 I have created a release *beep* *boop*
---


## 0.33.0 (2025-07-28)

<!-- Release notes generated using configuration in .github/release.yaml
at main -->

## What's Changed
### Exciting New Features 🎉
* feat: Reserve time to return preflight results before webhook timeout
by @dlipovetsky in
#1235
* feat: Support context for all Nutanix client calls by @dlipovetsky in
#1234
* feat: Support AWS PlacementGroups by @jimmidyson in
#1219
### Fixes 🔧
* fix(webhook): Update cluster webhook to validate failure domains by
@thunderboltsid in
#1233
* fix: More fixes to preflight result messages and fields by
@dlipovetsky in
#1240
* fix(deps): udpate CAPX to v1.7.0-beta.5 by @thunderboltsid in
#1241
### Other Changes
* build: Use GH client and token for coredns version mapping by
@jimmidyson in
#1238
* build: Update all tools by @jimmidyson in
#1237


**Full Changelog**:
v0.32.0...v0.33.0

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Dimitri Koshkin <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants