From a975b84306db5a384d6b59f19c4e5930f92c07b5 Mon Sep 17 00:00:00 2001 From: ebeaty-cisco <150805304+ebeaty-cisco@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:06:13 +0000 Subject: [PATCH] Helm chart changes to support OpenShift deployments (#16) --- .github/pull_request_template.md | 15 ++ CHANGELOG.md | 21 +++ README.md | 4 + charts/xrd-common/Chart.yaml | 2 +- charts/xrd-common/templates/_helpers.tpl | 11 ++ charts/xrd-common/templates/_interfaces.tpl | 74 ++++++-- .../templates/_network-attachments.tpl | 18 +- charts/xrd-common/templates/_statefulset.tpl | 20 ++- charts/xrd-control-plane/Chart.yaml | 4 +- .../templates/_interfaces.tpl | 39 +++- charts/xrd-control-plane/values.schema.json | 22 ++- charts/xrd-control-plane/values.yaml | 24 ++- charts/xrd-vrouter/Chart.yaml | 4 +- charts/xrd-vrouter/templates/_interfaces.tpl | 47 ++++- charts/xrd-vrouter/templates/statefulset.yaml | 11 +- charts/xrd-vrouter/values.schema.json | 36 +++- charts/xrd-vrouter/values.yaml | 50 +++++- docs/version-compatibility.md | 19 ++ .../network-attachments.bats | 94 +++++++++- tests/ut/xrd-control-plane/statefulset.bats | 118 +++++++----- tests/ut/xrd-vrouter/network-attachments.bats | 127 ++++++++++--- tests/ut/xrd-vrouter/statefulset.bats | 168 +++++++++++------- 22 files changed, 728 insertions(+), 200 deletions(-) create mode 100644 .github/pull_request_template.md create mode 100644 CHANGELOG.md create mode 100644 docs/version-compatibility.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..2541e501 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,15 @@ +### Summary + +*Main description goes here.* + + +### Checklist + +- [ ] Version incremented + +- [ ] Changelog updated + +- [ ] Version compatibility matrix updated (or not required) + +- [ ] Static analysis and tests passing + - See `tests/README.md` for details. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..d6a10610 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,21 @@ +# Changelog + +## XRd vRouter + +### v2 (active) + +The v2 release supports Cisco IOS-XR release version 24.4.1 and above. + +#### v2.0.0 + +- Change `cpu.hyperThreadingMode` options, adding `auto` and removing `off`. + +### v1 + +The v1 release supports Cisco IOS-XR release versions from 7.7.1 to 24.3.1. + +## XRd Control Plane + +### v1 (active) + +The v1 release supports Cisco IOS-XR release versions 7.7.1 and above. diff --git a/README.md b/README.md index 8b07dee0..e67c3eb5 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,10 @@ There are two application charts provided in this repository: There is also a library chart provided, xrd-common, that is used by both of the application charts. +See [CHANGELOG.md](./CHANGELOG.md) for a record of changes that have been made. + +See [version-compatibility.md](./version-compatibility.md) for the compatibility statement across versions. + ## Usage [Helm](https://helm.sh) must be installed to use the charts. Please refer to diff --git a/charts/xrd-common/Chart.yaml b/charts/xrd-common/Chart.yaml index 6a6fcfad..534a4992 100644 --- a/charts/xrd-common/Chart.yaml +++ b/charts/xrd-common/Chart.yaml @@ -8,4 +8,4 @@ keywords: - xrd sources: - https://github.com/ios-xr/xrd-helm -version: 1.0.4 +version: 1.1.0 diff --git a/charts/xrd-common/templates/_helpers.tpl b/charts/xrd-common/templates/_helpers.tpl index ad7a3734..cc66ee0f 100644 --- a/charts/xrd-common/templates/_helpers.tpl +++ b/charts/xrd-common/templates/_helpers.tpl @@ -106,4 +106,15 @@ Convert a k8s resource specification of Mi or Gi into MiB for XR env vars. {{- $out = "true" }} {{- end -}} {{ $out }} +{{- end -}} + +{{- /* +Should the NetworkStatusAnnotation be mounted? +Returns a string equivalent to boolean true if there are any sriov data +interfaces on vRouter, or an empty string otherwise. +*/ -}} +{{- define "xrd.mountNetworkStatusAnnotation" -}} +{{- if and (include "xrd.interfaces.anySRIOVData" .) (eq .Chart.Name "xrd-vrouter") }} +1 +{{- end }} {{- end -}} \ No newline at end of file diff --git a/charts/xrd-common/templates/_interfaces.tpl b/charts/xrd-common/templates/_interfaces.tpl index 05ea56ee..df8e103a 100644 --- a/charts/xrd-common/templates/_interfaces.tpl +++ b/charts/xrd-common/templates/_interfaces.tpl @@ -1,13 +1,4 @@ {{- /* Helper templates */ -}} -{{- define "xrd.interfaces.multusCount" -}} -{{- $c := 0 }} -{{- range . }} - {{- if eq .type "multus" }} - {{- $c = add1 $c }} - {{- end }} -{{- end }} -{{- $c }} -{{- end -}} {{- define "xrd.interfaces.anyMultus" -}} {{- /* @@ -22,6 +13,40 @@ or an empty string otherwise. {{- end }} {{- end -}} +{{- define "xrd.interfaces.anySRIOV" -}} +{{- /* +Returns a string equivalent to boolean true if there are any sriov interfaces, +or an empty string otherwise. +*/ -}} +{{- range (concat .Values.interfaces .Values.mgmtInterfaces) }} + {{- if eq .type "sriov" }} +1 + {{- end }} +{{- end }} +{{- end -}} + +{{- define "xrd.interfaces.anySRIOVData" -}} +{{- /* +Returns a string equivalent to boolean true if there are any sriov data interfaces, +or an empty string otherwise. +*/ -}} +{{- range .Values.interfaces }} + {{- if eq .type "sriov" }} +1 + {{- end }} +{{- end }} +{{- end -}} + +{{- define "xrd.interfaces.cniCount" -}} +{{- $c := 0 }} +{{- range .Values.interfaces }} + {{- if or (eq .type "sriov") (eq .type "multus") }} + {{- $c = add1 $c }} + {{- end }} +{{- end }} +{{- $c }} +{{- end -}} + {{- define "xrd.interfaces.checkDefaultCniCount" -}} {{- $c := 0 }} {{- range .Values.interfaces }} @@ -41,7 +66,7 @@ or an empty string otherwise. {{- define "xrd.interfaces.linuxflags" -}} {{- $flags := list }} -{{- $base := list "type" "config" "attachmentConfig" }} +{{- $base := list "type" "config" "attachmentConfig" "resource" }} {{- range $k, $v := . -}} {{- if eq $k "snoopIpv4Address" }} {{- if $v }} @@ -69,7 +94,7 @@ or an empty string otherwise. {{- end }} {{- $flags = append $flags (printf "xr_name=%s" $v) }} {{- else if not (has $k $base) }} - {{- fail (printf "%s may not be specified for defaultCni or multus interfaces" $k) }} + {{- fail (printf "%s may not be specified for defaultCni, multus or sriov interfaces" $k) }} {{- end }} {{- end }} {{- join "," $flags }} @@ -86,16 +111,37 @@ or an empty string otherwise. {{- join "," $flags }} {{- end -}} +{{- define "xrd.interfaces.sriovflags" -}} +{{- $flags := list }} +{{- $base := list "type" "config" "resource" }} +{{- range $k, $v := . -}} + {{- if not (has $k $base) }} + {{- fail (printf "%s may not be specified for sriov interfaces" $k) }} + {{- end }} +{{- end }} +{{- join "," $flags }} +{{- end -}} + {{- define "xrd.podNetworkAnnotations" -}} {{- $nets := list }} -{{- range $idx, $intf := concat .Values.interfaces .Values.mgmtInterfaces }} +{{- $cniIndex := 0}} +{{- range $intf := concat .Values.interfaces .Values.mgmtInterfaces }} {{- if eq $intf.type "multus" }} - {{- $netname := printf "%s-%d" (include "xrd.fullname" $) $idx }} - {{- $entry := dict "name" $netname }} + {{- $netname := printf "%s-%d" (include "xrd.fullname" $) $cniIndex }} + {{- $intfname := printf "net%d" $cniIndex }} + {{- $entry := dict "name" $netname "interface" $intfname}} {{- if $intf.attachmentConfig }} {{- $entry = merge $entry $intf.attachmentConfig }} {{- end }} {{- $nets = append $nets $entry }} + {{- $cniIndex = add1 $cniIndex }} + {{- end }} + {{- if eq $intf.type "sriov" }} + {{- $netname := printf "%s-%d" (include "xrd.fullname" $) $cniIndex }} + {{- $intfname := printf "net%d" $cniIndex }} + {{- $entry := dict "name" $netname "interface" $intfname}} + {{- $nets = append $nets $entry }} + {{- $cniIndex = add1 $cniIndex }} {{- end }} {{- end }} {{- toPrettyJson $nets }} diff --git a/charts/xrd-common/templates/_network-attachments.tpl b/charts/xrd-common/templates/_network-attachments.tpl index b3ec65c5..99167fb1 100644 --- a/charts/xrd-common/templates/_network-attachments.tpl +++ b/charts/xrd-common/templates/_network-attachments.tpl @@ -1,15 +1,21 @@ {{- define "xrd.network-attachments" -}} -{{- range $idx, $intf := concat .Values.interfaces .Values.mgmtInterfaces }} -{{- if eq $intf.type "multus" }} +{{- $cniIndex := 0 }} +{{- range $intf := concat .Values.interfaces .Values.mgmtInterfaces }} +{{- if or (eq $intf.type "multus") (eq $intf.type "sriov") }} --- apiVersion: k8s.cni.cncf.io/v1 kind: NetworkAttachmentDefinition metadata: - name: {{ include "xrd.fullname" $ }}-{{ $idx }} + name: {{ include "xrd.fullname" $ }}-{{ $cniIndex }} namespace: {{ $.Release.Namespace }} - {{- if gt (len (include "xrd.commonAnnotations" $ | fromYaml)) 0 }} + {{- if or (gt (len (include "xrd.commonAnnotations" $ | fromYaml)) 0) (eq $intf.type "sriov") }} annotations: - {{- include "xrd.commonAnnotations" $ | nindent 4 }} + {{- if eq $intf.type "sriov" }} + k8s.v1.cni.cncf.io/resourceName: {{ $intf.resource }} + {{- end }} + {{- if gt (len (include "xrd.commonAnnotations" $ | fromYaml)) 0 }} + {{- include "xrd.commonAnnotations" $ | nindent 4 }} + {{- end }} {{- end }} labels: {{- include "xrd.commonLabels" $ | nindent 4 }} @@ -17,11 +23,13 @@ spec: config: |- { "cniVersion": "0.3.1", + "name": "{{ include "xrd.fullname" $ }}-{{ $cniIndex }}", "plugins": [ {{- $intf.config | toPrettyJson | nindent 8 }} ] } ... +{{- $cniIndex = add1 $cniIndex}} {{- end }} {{- end -}} {{- end -}} \ No newline at end of file diff --git a/charts/xrd-common/templates/_statefulset.tpl b/charts/xrd-common/templates/_statefulset.tpl index 87e7b083..10caf016 100644 --- a/charts/xrd-common/templates/_statefulset.tpl +++ b/charts/xrd-common/templates/_statefulset.tpl @@ -40,7 +40,7 @@ spec: {{- if gt (len (include "xrd.commonAnnotations" . | fromYaml)) 0}} {{- include "xrd.commonAnnotations" . | nindent 8 }} {{- end }} - {{- if (include "xrd.interfaces.anyMultus" .) }} + {{- if or (include "xrd.interfaces.anyMultus" .) (include "xrd.interfaces.anySRIOV" .) }} k8s.v1.cni.cncf.io/networks: |- {{- include "xrd.podNetworkAnnotations" . | nindent 10 }} {{- end }} @@ -53,6 +53,12 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} spec: + {{- if .Values.serviceAccountName }} + serviceAccountName: {{ .Values.serviceAccountName }} + {{- end }} + {{- if .Values.runtimeClassName }} + runtimeClassName: {{ .Values.runtimeClassName }} + {{- end }} {{- if .Values.hostNetwork }} hostNetwork: true {{- end }} @@ -91,6 +97,14 @@ spec: type: Directory {{- end }} {{- end }} + {{- if (include "xrd.mountNetworkStatusAnnotation" .) }} + - downwardAPI: + items: + - fieldRef: + fieldPath: metadata.annotations['k8s.v1.cni.cncf.io/network-status'] + path: "network-status-annotation" + name: "network-status-annotation" + {{- end }} {{- if .Values.extraVolumes }} {{- toYaml .Values.extraVolumes | nindent 6 }} {{- end }} @@ -117,6 +131,10 @@ spec: name: config readOnly: true {{- end }} + {{- if (include "xrd.mountNetworkStatusAnnotation" .) }} + - mountPath: "/etc/xrd/network-status" + name: "network-status-annotation" + {{- end }} {{- if .Values.persistence.enabled }} - mountPath: /xr-storage name: xr-storage diff --git a/charts/xrd-control-plane/Chart.yaml b/charts/xrd-control-plane/Chart.yaml index 602063dd..cb5e8e52 100644 --- a/charts/xrd-control-plane/Chart.yaml +++ b/charts/xrd-control-plane/Chart.yaml @@ -8,8 +8,8 @@ keywords: - xrd sources: - https://github.com/ios-xr/xrd-helm -version: 1.0.4 +version: 1.1.0 dependencies: - name: xrd-common - version: 1.0.4 + version: 1.1.0 repository: "file://../xrd-common" diff --git a/charts/xrd-control-plane/templates/_interfaces.tpl b/charts/xrd-control-plane/templates/_interfaces.tpl index 39e83e26..d833cd6f 100644 --- a/charts/xrd-control-plane/templates/_interfaces.tpl +++ b/charts/xrd-control-plane/templates/_interfaces.tpl @@ -10,20 +10,33 @@ {{- if hasKey . "attachmentConfig" }} {{- fail "attachmentConfig may not be specified for defaultCni interfaces" }} {{- end }} + {{- if hasKey . "resource" }} + {{- fail "resource may not be specified for defaultCni interface types" }} + {{- end }} {{- $flags := include "xrd.interfaces.linuxflags" . }} {{- if $flags }} {{- $interfaces = append $interfaces (printf "linux:eth0,%s" $flags) }} {{- else }} {{- $interfaces = append $interfaces "linux:eth0" }} {{- end }} - {{- else if eq .type "multus" }} - {{- $cniIndex = add1 $cniIndex }} + {{- else if or (eq .type "multus") (eq .type "sriov") }} {{- $flags := include "xrd.interfaces.linuxflags" . }} + {{- if eq .type "sriov" }} + {{- if hasKey . "attachmentConfig" }} + {{- fail "attachmentConfig may not be specified for sriov interface types" }} + {{- end }} + {{- if not (hasKey . "resource") }} + {{- fail "Resource must be specified for sriov interface types" }} + {{- end }} + {{- else if hasKey . "resource" }} + {{- fail "resource may not be specified for multus interface types" }} + {{- end }} {{- if $flags }} {{- $interfaces = append $interfaces (printf "linux:net%d,%s" $cniIndex $flags) }} {{- else }} {{- $interfaces = append $interfaces (printf "linux:net%d" $cniIndex) }} {{- end }} + {{- $cniIndex = add1 $cniIndex }} {{- else }} {{- fail (printf "Invalid interface type %s" .type) }} {{- end }} @@ -34,24 +47,40 @@ {{- define "xrd-cp.mgmtInterfaces" -}} {{- /* Generate the XR_MGMT_INTERFACES environment variable content */ -}} {{- $interfaces := list }} -{{- $cniIndex := atoi (include "xrd.interfaces.multusCount" .Values.interfaces) }} +{{- $cniIndex := atoi (include "xrd.interfaces.cniCount" .) }} {{- include "xrd.interfaces.checkDefaultCniCount" . -}} {{- range .Values.mgmtInterfaces }} {{- if eq .type "defaultCni" }} + {{- if hasKey . "attachmentConfig" }} + {{- fail "attachmentConfig may not be specified for defaultCni mgmt interfaces" }} + {{- end }} + {{- if hasKey . "resource" }} + {{- fail "resource may not be specified for defaultCni mgmt interface types" }} + {{- end }} {{- $flags := include "xrd.interfaces.linuxflags" . }} {{- if $flags }} {{- $interfaces = append $interfaces (printf "linux:eth0,%s" $flags) }} {{- else }} {{- $interfaces = append $interfaces "linux:eth0" }} {{- end }} - {{- else if eq .type "multus" }} - {{- $cniIndex = add1 $cniIndex }} + {{- else if or (eq .type "multus") (eq .type "sriov") }} {{- $flags := include "xrd.interfaces.linuxflags" . }} + {{- if eq .type "sriov" }} + {{- if hasKey . "attachmentConfig" }} + {{- fail "attachmentConfig may not be specified for sriov mgmt interface types" }} + {{- end }} + {{- if not (hasKey . "resource") }} + {{- fail "Resource must be specified for sriov mgmt interface types" }} + {{- end }} + {{- else if hasKey . "resource" }} + {{- fail "resource may not be specified for multus mgmt interface types" }} + {{- end }} {{- if $flags }} {{- $interfaces = append $interfaces (printf "linux:net%d,%s" $cniIndex $flags) }} {{- else }} {{- $interfaces = append $interfaces (printf "linux:net%d" $cniIndex) }} {{- end }} + {{- $cniIndex = add1 $cniIndex }} {{- else }} {{- fail (printf "Invalid mgmt interface type %s" .type) }} {{- end }} diff --git a/charts/xrd-control-plane/values.schema.json b/charts/xrd-control-plane/values.schema.json index 7c15f72b..55382472 100644 --- a/charts/xrd-control-plane/values.schema.json +++ b/charts/xrd-control-plane/values.schema.json @@ -81,6 +81,10 @@ "description": "Annotations added to the XRd deployment", "type": "object" }, + "serviceAccountName": { + "description": "Name of the service account to use for the XRd pod", + "type": "string" + }, "resources": { "description": "Standard Kubernetes container resources object", "type": "object" @@ -254,11 +258,12 @@ "type": "object", "properties": { "type": { - "description": "Underying interface type. One of: 'defaultCni' or 'multus'", + "description": "Underlying interface type. One of: 'defaultCni', 'multus' or 'sriov'", "type": "string", "enum": [ "defaultCni", - "multus" + "multus", + "sriov" ] }, "config": { @@ -269,6 +274,10 @@ "description": "Network attachment annotation configuration, for multus-type interfaces only", "type": "object" }, + "resource": { + "description": "SR-IOV resource-pool name, for sriov-type interfaces only", + "type": "string" + }, "snoopIpv4Address": { "description": "Indicate whether to snoop the pre-existing IPv4 address of the interface into XR config", "type": "boolean", @@ -312,11 +321,12 @@ "type": "object", "properties": { "type": { - "description": "Underying interface type. One of: 'defaultCni' or 'multus'", + "description": "Underlying interface type. One of: 'defaultCni', 'multus' or 'sriov'", "type": "string", "enum": [ "defaultCni", - "multus" + "multus", + "sriov" ] }, "config": { @@ -327,6 +337,10 @@ "description": "Network attachment annotation configuration, for multus-type interfaces only", "type": "object" }, + "resource": { + "description": "SR-IOV resource-pool name, for sriov-type interfaces only", + "type": "string" + }, "snoopIpv4Address": { "description": "Indicate whether to snoop the pre-existing IPv4 address of the interface into XR config", "type": "boolean", diff --git a/charts/xrd-control-plane/values.yaml b/charts/xrd-control-plane/values.yaml index 643aab4b..71a06811 100644 --- a/charts/xrd-control-plane/values.yaml +++ b/charts/xrd-control-plane/values.yaml @@ -45,6 +45,9 @@ labels: {} # Annotations added to the XRd deployment. annotations: {} +# Pre-existing ServiceAccount for the XRd Pod to use. +#serviceAccountName: "" + # Pod resource configuration. # See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ # The default resources are: @@ -177,9 +180,17 @@ config: # specified under the 'config' field for the interface. # Any attachment annotation configuration may be specified under # the 'attachmentConfig' field. +# - sriov: This connects an additional network allocated from an SR-IOV +# network resource pool and created using a CNI plugin, driven +# by the multus meta-CNI plugin. +# An SR-IOV resource pool must be specified under the 'resource' +# key for the interface. +# The network attachment definition configuration must be +# specified under the 'config' field for the interface. Config +# is required to specify and configure the CNI used. # -# On 'defaultCni' and 'multus' interfaces, the following options may also -# be specified to control the interface behavior in XR: +# On 'defaultCni', 'multus' and 'sriov' interfaces, the following options may +# also be specified to control the interface behavior in XR: # - chksum: Turn on TCP/UDP checksum calculation for ingress packets (to # counteract checksum offload to hardware). # - xrName: Customize the XR interface name for this interface. @@ -201,6 +212,11 @@ interfaces: [] # type: host-device # device: eth1 # xrName: GigabitEthernet0/0/0/3 +#- type: sriov +# resource: intel.com/intel_sriov_netdevice_1 +# config: +# type: sriov +# vlan: 1 # XRd management interfaces. mgmtInterfaces: [] @@ -219,6 +235,10 @@ mgmtInterfaces: [] # attachmentConfig: # ips: # - "10.0.0.1/24" +#- type: sriov +# resource: intel.com/intel_sriov_netdevice_2 +# config: +# type: sriov # XRd advanced settings. # This section contains settings not required by most users. diff --git a/charts/xrd-vrouter/Chart.yaml b/charts/xrd-vrouter/Chart.yaml index 1aa73d0e..ecdd1765 100644 --- a/charts/xrd-vrouter/Chart.yaml +++ b/charts/xrd-vrouter/Chart.yaml @@ -8,8 +8,8 @@ keywords: - xrd sources: - https://github.com/ios-xr/xrd-helm -version: 1.0.6 +version: 2.0.0 dependencies: - name: xrd-common - version: 1.0.4 + version: 1.1.0 repository: "file://../xrd-common" diff --git a/charts/xrd-vrouter/templates/_interfaces.tpl b/charts/xrd-vrouter/templates/_interfaces.tpl index d0b8c39f..ed29e5bc 100644 --- a/charts/xrd-vrouter/templates/_interfaces.tpl +++ b/charts/xrd-vrouter/templates/_interfaces.tpl @@ -2,14 +2,18 @@ {{- /* Generate the XR_INTERFACES environment variable content */ -}} {{- $interfaces := list }} {{- $hasPci := 0 }} +{{- $hasNetwork := 0 }} {{- $hasPciRange := 0 }} {{- $cniIndex := 0 }} {{- include "xrd.interfaces.checkDefaultCniCount" . -}} -{{- range .Values.interfaces }} +{{- range $intf := .Values.interfaces }} {{- if eq .type "pci" }} {{- if hasKey . "attachmentConfig" }} {{- fail "attachmentConfig may not be specified for PCI interfaces" }} {{- end }} + {{- if hasKey . "resource" }} + {{- fail "resource may not be specified for PCI interfaces" }} + {{- end }} {{- $flags := include "xrd.interfaces.pciflags" . }} {{- if $hasPciRange }} {{- fail "If a pci interface range (i.e. with 'first' or 'last' config) is specified, no other pci interfaces may be specified" }} @@ -29,8 +33,8 @@ {{- fail "Cannot specify both 'first' and 'last' for PCI interface" }} {{- end }} {{- $hasPciRange = 1 }} - {{- if $hasPci }} - {{- fail "If a pci interface range (i.e. with 'first' or 'last' config) is specified, no other pci interfaces may be specified" }} + {{- if or $hasPci $hasNetwork }} + {{- fail "If a pci interface range (i.e. with 'first' or 'last' config) is specified, no other pci or sriov interfaces may be specified" }} {{- end }} {{- $config := "" }} {{- if .config.last }} @@ -46,6 +50,24 @@ {{- else }} {{- fail "Must specify one of 'device', 'first', or 'last' for PCI interfaces" }} {{- end }} + {{- else if eq .type "sriov" }} + {{- if hasKey . "attachmentConfig" }} + {{- fail "attachmentConfig may not be specified for sriov interface types" }} + {{- end }} + {{- $flags := include "xrd.interfaces.sriovflags" . }} + {{- $hasNetwork = 1 }} + {{- if $hasPciRange }} + {{- fail "If a pci interface range (i.e. 'pci' type with 'first' or 'last' config) is specified, no other pci or sriov interfaces may be specified" }} + {{- end }} + {{- if not (hasKey . "resource") }} + {{- fail "Resource must be specified for sriov interface types" }} + {{- end }} + {{- if $flags }} + {{- $interfaces = append $interfaces (printf "net-attach-def:%s/%s-%d,%s" $.Release.Namespace (include "xrd.fullname" $) $cniIndex $flags) }} + {{- else }} + {{- $interfaces = append $interfaces (printf "net-attach-def:%s/%s-%d" $.Release.Namespace (include "xrd.fullname" $) $cniIndex) }} + {{- end }} + {{- $cniIndex = add1 $cniIndex }} {{- else }} {{- fail (printf "Invalid interface type %s" .type) }} {{- end }} @@ -56,13 +78,16 @@ {{- define "xrd-vr.mgmtInterfaces" -}} {{- /* Generate the XR_MGMT_INTERFACES environment variable content */ -}} {{- $interfaces := list }} -{{- $cniIndex := atoi (include "xrd.interfaces.multusCount" .Values.interfaces) }} +{{- $cniIndex := atoi (include "xrd.interfaces.cniCount" .) }} {{- if gt (len .Values.mgmtInterfaces) 1 }} {{- fail "Only one management interface can be specified on XRd vRouter" }} {{- end }} {{- include "xrd.interfaces.checkDefaultCniCount" . -}} {{- range .Values.mgmtInterfaces }} {{- if eq .type "defaultCni" }} + {{- if hasKey . "attachmentConfig" }} + {{- fail "attachmentConfig may not be specified for defaultCni mgmt interface types" }} + {{- end }} {{- if (hasKey . "xrName") }} {{- fail "xrName may not be specified for interfaces on XRd vRouter" }} {{- end }} @@ -72,17 +97,27 @@ {{- else }} {{- $interfaces = append $interfaces "linux:eth0" }} {{- end }} - {{- else if eq .type "multus" }} - {{- $cniIndex = add1 $cniIndex }} + {{- else if or (eq .type "multus") (eq .type "sriov") }} {{- if (hasKey . "xrName") }} {{- fail "xrName may not be specified for interfaces on XRd vRouter" }} {{- end }} {{- $flags := include "xrd.interfaces.linuxflags" . }} + {{- if eq .type "sriov" }} + {{- if hasKey . "attachmentConfig" }} + {{- fail "attachmentConfig may not be specified for sriov mgmt interface types" }} + {{- end }} + {{- if not (hasKey . "resource") }} + {{- fail "Resource must be specified for sriov mgmt interface types" }} + {{- end }} + {{- else if hasKey . "resource" }} + {{- fail "resource may not be specified for multus mgmt interface types" }} + {{- end }} {{- if $flags }} {{- $interfaces = append $interfaces (printf "linux:net%d,%s" $cniIndex $flags) }} {{- else }} {{- $interfaces = append $interfaces (printf "linux:net%d" $cniIndex) }} {{- end }} + {{- $cniIndex = add1 $cniIndex }} {{- else }} {{- fail (printf "Invalid mgmt interface type %s" .type) }} {{- end }} diff --git a/charts/xrd-vrouter/templates/statefulset.yaml b/charts/xrd-vrouter/templates/statefulset.yaml index cd8317c9..ee4a95d2 100644 --- a/charts/xrd-vrouter/templates/statefulset.yaml +++ b/charts/xrd-vrouter/templates/statefulset.yaml @@ -53,6 +53,11 @@ Construct the resources including the default if that resource wasn't specified. {{- $hugepageMb := include "xrd.toMiB" $hugepageSize }} {{- $_ := set $env "XR_VROUTER_DP_HUGEPAGE_MB" $hugepageMb }} +{{- /* Generate PROFILE env var */}} +{{- if .Values.profile }} + {{- $_ := set $env "XR_VROUTER_PROFILE" .Values.profile }} +{{- end }} + {{- /* Generate CPU env vars */}} {{- if .Values.cpu }} {{- with .Values.cpu}} @@ -68,9 +73,6 @@ Construct the resources including the default if that resource wasn't specified. {{- end }} {{- if .controlPlaneCpuCount }} {{- fail "controlPlaneCpuCount must not be set if controlPlaneCpuset and dataPlaneCpuset are set" }} - {{- end }} - {{- if .hyperThreadingMode }} - {{- fail "hyperThreadingMode must not be set if controlPlaneCpuset and dataPlaneCpuset are set" }} {{- end }} {{- $_ := set $env "XR_VROUTER_DP_CPUSET" .dataPlaneCpuset }} {{- $_ := set $env "XR_VROUTER_CP_CPUSET" .controlPlaneCpuset }} @@ -95,6 +97,9 @@ Construct the resources including the default if that resource wasn't specified. {{- /* Generate the interface env vars */}} {{- $_ = set $env "XR_INTERFACES" (include "xrd-vr.interfaces" .) }} {{- $_ = set $env "XR_MGMT_INTERFACES" (include "xrd-vr.mgmtInterfaces" .) }} +{{- if (include "xrd.mountNetworkStatusAnnotation" .) }} + {{- $_ = set $env "XR_NETWORK_STATUS_ANNOTATION_PATH" "/etc/xrd/network-status/network-status-annotation" }} +{{- end }} {{- /* Create the args dict and invoke the generic template. */}} {{- $args := dict "root" $ "resources" $resources "environment" $env }} diff --git a/charts/xrd-vrouter/values.schema.json b/charts/xrd-vrouter/values.schema.json index ce0778ba..da616544 100644 --- a/charts/xrd-vrouter/values.schema.json +++ b/charts/xrd-vrouter/values.schema.json @@ -81,6 +81,10 @@ "description": "Annotations added to the XRd deployment", "type": "object" }, + "serviceAccountName": { + "description": "Name of the service account to use for the XRd pod", + "type": "string" + }, "resources": { "description": "Standard Kubernetes container resources object", "type": "object" @@ -254,12 +258,17 @@ "type": "object", "properties": { "type": { - "description": "Underying interface type. Must be 'pci'", + "description": "Underlying interface type. Must be 'pci' or 'sriov'", "type": "string", "enum": [ - "pci" + "pci", + "sriov" ] }, + "resource": { + "description": "Network resource to use for the interface", + "type": "string" + }, "config": { "description": "Type-dependent configuration", "type": "object" @@ -278,11 +287,12 @@ "type": "object", "properties": { "type": { - "description": "Underying interface type. One of: 'defaultCni' or 'multus'", + "description": "Underlying interface type. One of: 'defaultCni', 'multus' or 'sriov'", "type": "string", "enum": [ "defaultCni", - "multus" + "multus", + "sriov" ] }, "config": { @@ -293,6 +303,10 @@ "description": "Network attachment annotation configuration, for multus-type interfaces only", "type": "object" }, + "resource": { + "description": "SR-IOV resource-pool name, for sriov-type interfaces only", + "type": "string" + }, "snoopIpv4Address": { "description": "Indicate whether to snoop the pre-existing IPv4 address of the interface into XR config", "type": "boolean", @@ -329,6 +343,18 @@ "additionalProperties": false } }, + "profile": { + "description": "XRd vRouter profile", + "type": "string", + "enum": [ + "vpe", + "vrr" + ] + }, + "runtimeClassName": { + "description": "Runtime Class name for the XRd pod", + "type": "string" + }, "cpu": { "description": "CPU settings", "type": "object", @@ -353,7 +379,7 @@ "description": "HyperThreading mode for cpuset allocations", "type": "string", "enum": [ - "off", + "auto", "pairs" ], "default": "off" diff --git a/charts/xrd-vrouter/values.yaml b/charts/xrd-vrouter/values.yaml index c8bf0c6d..318c5b36 100644 --- a/charts/xrd-vrouter/values.yaml +++ b/charts/xrd-vrouter/values.yaml @@ -45,6 +45,9 @@ labels: {} # Annotations added to the XRd deployment. annotations: {} +# Pre-existing ServiceAccount for the XRd Pod to use. +#serviceAccountName: "" + # Pod resource configuration. # See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ # The default resources are: @@ -191,13 +194,21 @@ config: # - last: N, to use the final N network PCI devices. # This can be specified as a line interface only. # N.B. If PCI interfaces are specified with "first" or "last", -# that must be the ONLY "pci" interface definition. +# that must be the ONLY "pci" or "sriov" interface definition. +# - sriov: This connects an additional network allocated from an SR-IOV +# network resource pool and created using a CNI plugin, driven +# by the multus meta-CNI plugin. +# An SR-IOV resource pool must be specified under the 'resource' +# key for the interface. +# The network attachment definition configuration must be +# specified under the 'config' field for the interface. Config +# is required to specify and configure the CNI used. # -# On 'defaultCni' and 'multus' interfaces, the following options may also -# be specified to control the interface behavior in XR: +# On 'defaultCni' and 'multus' interfaces, and 'sriov' interfaces when used as +# a management interface, the following options may also be specified to +# control the interface behavior in XR: # - chksum: Turn on TCP/UDP checksum calculation for ingress packets (to # counteract checksum offload to hardware). -# - xrName: Customize the XR interface name for this interface. # - snoopIpv4Address: see below. # - snoopIpv4DefaultRoute: see below. # - snoopIpv6Address: see below. @@ -213,9 +224,14 @@ interfaces: [] # Example interfaces: # config: # device: 00.06.00:1 -#- type pci +#- type: pci # config: # last: 3 +#- type: sriov +# resource: intel.com/intel_sriov_netdevice_1 +# config: +# type: sriov +# vlan: 1 # XRd management interfaces. mgmtInterfaces: [] @@ -234,6 +250,23 @@ mgmtInterfaces: [] # attachmentConfig: # ips: # - "10.0.0.1/24" +#- type: sriov +# resource: intel.com/intel_sriov_netdevice_2 +# config: +# type: sriov +# snoopIpv4Address: true + +# Add a runtimeClassName to the XRd Pod. +# Refer to https://kubernetes.io/docs/concepts/containers/runtime-class/. +#runtimeClassName: "performance-cisco-ios-xr" + +# vRouter profile. Valid options: +# - "vpe": for cloud router use cases +# - "vrr": for virtual route reflector use cases. +# The choice of profile determines the way in which XRd uses available CPU +# cores, so that the usage is suitable for the specified use case. If no option +# is given, XRd uses the "vpe" profile. +#profile: "vpe" # CPU settings. cpu: {} @@ -249,14 +282,13 @@ cpu: {} # that the dataplane has whole physical CPU cores and to prevent 'noisy # neighbor' issues. # This mode supports two values: - # - 'off' - no hyperthreading (default) + # - 'auto' - detect if hyperthreading is enabled from the system (this only + # works on baremetal systems, not ESXi) # - 'pairs' - where hyperthreaded siblings are consecutive, i.e. # * physical core 0 has logical cores 0 and 1 # * physical core 1 has logical cores 2 and 3 # * etc... - # Must not be used in conjunction with controlPlaneCpuset and - # dataPlaneCpuset. - #hyperThreadingMode: "off" + #hyperThreadingMode: "auto" # # Deprecated cpu settings: # diff --git a/docs/version-compatibility.md b/docs/version-compatibility.md new file mode 100644 index 00000000..8f996b45 --- /dev/null +++ b/docs/version-compatibility.md @@ -0,0 +1,19 @@ +# Version Compatibility + +This file documents compatibility between versions of this project with XR releases. + +## XRd vRouter + +### v2 + +Supports XR version 24.4.1 and above. + +### v1 + +Supports all XR versions between 7.7.1 and 24.3.1. + +## XRd Control Plane + +### v1 + +Supports all XR versions 7.7.1 and above. \ No newline at end of file diff --git a/tests/ut/xrd-control-plane/network-attachments.bats b/tests/ut/xrd-control-plane/network-attachments.bats index e405e048..2efa8405 100644 --- a/tests/ut/xrd-control-plane/network-attachments.bats +++ b/tests/ut/xrd-control-plane/network-attachments.bats @@ -72,19 +72,19 @@ setup_file () { @test "Control Plane NetworkAttachmentDefinition: Check default config" { template --set-json 'interfaces=[{"type": "multus"}]' assert_query_equal '.spec.config' \ - "{\n \"cniVersion\": \"0.3.1\",\n \"plugins\": [\n null\n ]\n}" + "{\n \"cniVersion\": \"0.3.1\",\n \"name\": \"release-name-xrd-control-plane-0\",\n \"plugins\": [\n null\n ]\n}" } @test "Control Plane NetworkAttachmentDefinition: Config can be set for MGMT interfaces" { template --set-json 'mgmtInterfaces=[{"type": "multus", "config": {"foo": "bar"}}]' assert_query_equal '.spec.config'\ - "{\n \"cniVersion\": \"0.3.1\",\n \"plugins\": [\n {\n \"foo\": \"bar\"\n }\n ]\n}" + "{\n \"cniVersion\": \"0.3.1\",\n \"name\": \"release-name-xrd-control-plane-0\",\n \"plugins\": [\n {\n \"foo\": \"bar\"\n }\n ]\n}" } @test "Control Plane NetworkAttachmentDefinition: Config can be set for interfaces" { template --set-json 'interfaces=[{"type": "multus", "config": {"foo": "bar"}}]' assert_query_equal '.spec.config' \ - "{\n \"cniVersion\": \"0.3.1\",\n \"plugins\": [\n {\n \"foo\": \"bar\"\n }\n ]\n}" + "{\n \"cniVersion\": \"0.3.1\",\n \"name\": \"release-name-xrd-control-plane-0\",\n \"plugins\": [\n {\n \"foo\": \"bar\"\n }\n ]\n}" } @test "Control Plane NetworkAttachmentDefinition: No interfaces" { @@ -104,20 +104,100 @@ setup_file () { @test "Control Plane NetworkAttachmentDefinition: error if unknown interface type is requested" { template_failure --set-json 'interfaces=[{"type": "foo"}]' - assert_error_message_contains "must be one of the following: \"defaultCni\", \"multus\"" + assert_error_message_contains "must be one of the following: \"defaultCni\", \"multus\", \"sriov\"" } @test "Control Plane NetworkAttachmentDefinition: error if PCI interface type is requested" { template_failure --set-json 'interfaces=[{"type": "pci"}]' - assert_error_message_contains "must be one of the following: \"defaultCni\", \"multus\"" + assert_error_message_contains "must be one of the following: \"defaultCni\", \"multus\", \"sriov\"" } @test "Control Plane NetworkAttachmentDefinition: error if unknown mgmt interface type is requested" { template_failure --set-json 'mgmtInterfaces=[{"type": "foo"}]' - assert_error_message_contains "must be one of the following: \"defaultCni\", \"multus\"" + assert_error_message_contains "must be one of the following: \"defaultCni\", \"multus\", \"sriov\"" } @test "Control Plane NetworkAttachmentDefinition: error if PCI mgmt interface type is requested" { template_failure --set-json 'mgmtInterfaces=[{"type": "pci"}]' - assert_error_message_contains "must be one of the following: \"defaultCni\", \"multus\"" + assert_error_message_contains "must be one of the following: \"defaultCni\", \"multus\", \"sriov\"" +} + +@test "Control Plane NetworkAttachmentDefinition (sriov): Name consists of the release name, template name and index" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' + assert_query_equal '.metadata.name' "release-name-xrd-control-plane-0" +} + +@test "Control Plane NetworkAttachmentDefinition (sriov): Name can be overridden with fullnameOverride" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' \ + --set 'fullnameOverride=xrd-test' + assert_query_equal '.metadata.name' "xrd-test-0" +} + +@test "Control Plane NetworkAttachmentDefinition (sriov): Name can be overridden with nameOverride" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' \ + --set 'nameOverride=xrd-test' + assert_query_equal '.metadata.name' "release-name-xrd-test-0" +} + +@test "Control Plane NetworkAttachmentDefinition (sriov): Namespace is default" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' + assert_query_equal '.metadata.namespace' "default" +} + +@test "Control Plane NetworkAttachmentDefinition (sriov): Default annotations are set" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' + assert_query_equal '.metadata.annotations."k8s.v1.cni.cncf.io/resourceName"' "foo" +} + +@test "Control Plane NetworkAttachmentDefinition (sriov): Global annotations and commonAnnotations can be added and are correctly merged" { + template \ + --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' \ + --set 'global.annotations.foo=bar' \ + --set 'commonAnnotations.baz=baa' + assert_query_equal '.metadata.annotations."k8s.v1.cni.cncf.io/resourceName"' "foo" + assert_query_equal '.metadata.annotations.foo' "bar" + assert_query_equal '.metadata.annotations.baz' "baa" +} + +@test "Control Plane NetworkAttachmentDefinition (sriov): Recommended labels are set" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' + assert_query_equal '.metadata.labels."app.kubernetes.io/name"' "xrd-control-plane" + assert_query_equal '.metadata.labels."app.kubernetes.io/instance"' "release-name" + assert_query_equal '.metadata.labels."app.kubernetes.io/managed-by"' "Helm" + assert_query '.metadata.labels | has("app.kubernetes.io/version")' + assert_query '.metadata.labels | has("helm.sh/chart")' +} + +@test "Control Plane NetworkAttachmentDefinition (sriov): Global labels and commonLabels can be added and are correctly merged" { + template \ + --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' \ + --set 'global.labels.foo=bar' \ + --set 'commonLabels.baz=baa' + assert_query_equal '.metadata.labels.foo' "bar" + assert_query_equal '.metadata.labels.baz' "baa" +} + +@test "Control Plane NetworkAttachmentDefinition (sriov): Config can be set" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' + assert_query_equal '.spec.config' \ + "{\n \"cniVersion\": \"0.3.1\",\n \"name\": \"release-name-xrd-control-plane-0\",\n \"plugins\": [\n {\n \"type\": \"sriov\"\n }\n ]\n}" +} + +@test "Control Plane NetworkAttachmentDefinition: multiple sriov interfaces can be created together" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}},{"type": "sriov", "resource": "bar", "config": {"type": "sriov"}}]' + assert_query_equal '.metadata.name' \ + "release-name-xrd-control-plane-0\n---\nrelease-name-xrd-control-plane-1" +} + +@test "Control Plane NetworkAttachmentDefinition: sriov interfaces and multus mgmt interfaces can be created together" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' \ + --set-json 'mgmtInterfaces=[{"type": "multus"}]' + assert_query_equal '.metadata.name' \ + "release-name-xrd-control-plane-0\n---\nrelease-name-xrd-control-plane-1" +} + +@test "Control Plane NetworkAttachmentDefinition: sriov mgmt interface can be created" { + template --set-json 'mgmtInterfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' + assert_query_equal '.metadata.name' \ + "release-name-xrd-control-plane-0" } \ No newline at end of file diff --git a/tests/ut/xrd-control-plane/statefulset.bats b/tests/ut/xrd-control-plane/statefulset.bats index c3ccdecc..51f16283 100644 --- a/tests/ut/xrd-control-plane/statefulset.bats +++ b/tests/ut/xrd-control-plane/statefulset.bats @@ -100,7 +100,13 @@ setup_file () { @test "Control Plane StatefulSet: .spec.template annotations are added for multus interfaces" { template --set-json 'interfaces=[{"type": "multus"}]' assert_query_equal '.spec.template.metadata.annotations."k8s.v1.cni.cncf.io/networks"' \ - "[\n {\n \"name\": \"release-name-xrd-control-plane-0\"\n }\n]" + "[\n {\n \"interface\": \"net0\",\n \"name\": \"release-name-xrd-control-plane-0\"\n }\n]" +} + +@test "Control Plane StatefulSet: .spec.template annotations are added for sriov mgmt interfaces" { + template --set-json 'mgmtInterfaces=[{"type": "sriov", "resource": "foo"}]' + assert_query_equal '.spec.template.metadata.annotations."k8s.v1.cni.cncf.io/networks"' \ + "[\n {\n \"interface\": \"net0\",\n \"name\": \"release-name-xrd-control-plane-0\"\n }\n]" } @test "Control Plane StatefulSet: .spec.template podAnnotations can be set" { @@ -109,9 +115,10 @@ setup_file () { } @test "Control Plane StatefulSet: podNetworkAnnotations contain the desired information" { - template --set-json 'interfaces=[{"type": "multus", "attachmentConfig": {"foo": "bar"}, "config": {"baz": "baa"}}]' + template --set-json 'mgmtInterfaces=[{"type": "multus", "attachmentConfig": {"qux": "quuz"}}]' \ + --set-json 'interfaces=[{"type": "multus", "attachmentConfig": {"foo": "bar"}, "config": {"baz": "baa"}}, {"type": "sriov", "resource": "baz"}]' assert_query_equal '.spec.template.metadata.annotations."k8s.v1.cni.cncf.io/networks"' \ - "[\n {\n \"foo\": \"bar\",\n \"name\": \"release-name-xrd-control-plane-0\"\n }\n]" + "[\n {\n \"foo\": \"bar\",\n \"interface\": \"net0\",\n \"name\": \"release-name-xrd-control-plane-0\"\n },\n {\n \"interface\": \"net1\",\n \"name\": \"release-name-xrd-control-plane-1\"\n },\n {\n \"interface\": \"net2\",\n \"name\": \"release-name-xrd-control-plane-2\",\n \"qux\": \"quuz\"\n }\n]" } @test "Control Plane StatefulSet: .spec.template recommended labels are set" { @@ -134,6 +141,16 @@ setup_file () { assert_query_equal '.spec.template.metadata.labels.foo' "bar" } +@test "Control Plane StatefulSet: No serviceAccountName by default" { + template + assert_query '.spec.serviceAccountName | not' +} + +@test "Control Plane StatefulSet: serviceAccountName can be set" { + template --set 'serviceAccountName=foo' + assert_query_equal '.spec.template.spec.serviceAccountName' "foo" +} + @test "Control Plane StatefulSet: No hostNetwork by default" { template assert_query_equal '.spec.template.spec.hostNetwork' "null" @@ -309,58 +326,63 @@ setup_file () { @test "Control Plane StatefulSet: container env vars version is set" { template - assert_query_equal '.spec.template.spec.containers[0].env[0].name' "XR_ENV_VARS_VERSION" - assert_query_equal '.spec.template.spec.containers[0].env[0].value' "1" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_ENV_VARS_VERSION"))][0][0].value' "1" } @test "Control Plane StatefulSet: empty container interface env vars are set by default" { template - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "" - assert_query_equal '.spec.template.spec.containers[0].env[2].name' "XR_MGMT_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[2].value' "" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_INTERFACES"))][0][0].value' "" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_MGMT_INTERFACES"))][0][0].value' "" } @test "Control Plane StatefulSet: XR_INTERFACES container env vars is correctly set" { - template --set-json 'interfaces=[{"type": "multus"}, {"type": "defaultCni"}]' - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "linux:net1;linux:eth0" + template --set-json 'interfaces=[{"type": "multus"}, {"type": "defaultCni"}, {"type": "sriov", "resource": "foo/bar"}]' + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_INTERFACES"))][0][0].value' "linux:net0;linux:eth0;linux:net1" } @test "Control Plane StatefulSet: set snoopIpv4Address flag in XR_INTERFACES" { template --set-json 'interfaces=[{"type": "multus"}, {"type": "defaultCni", "snoopIpv4Address": true}]' - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "linux:net1;linux:eth0,snoop_v4" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_INTERFACES"))][0][0].value' "linux:net0;linux:eth0,snoop_v4" } @test "Control Plane StatefulSet: set snoopIpv4DefaultRoot flag in XR_INTERFACES" { template --set-json 'interfaces=[{"type": "multus"}, {"type": "defaultCni", "snoopIpv4DefaultRoute": true}]' - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "linux:net1;linux:eth0,snoop_v4_default_route" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_INTERFACES"))][0][0].value' "linux:net0;linux:eth0,snoop_v4_default_route" } @test "Control Plane StatefulSet: set snoopIpv6Address flag in XR_INTERFACES" { template --set-json 'interfaces=[{"type": "multus"}, {"type": "defaultCni", "snoopIpv6Address": true}]' - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "linux:net1;linux:eth0,snoop_v6" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_INTERFACES"))][0][0].value' "linux:net0;linux:eth0,snoop_v6" } @test "Control Plane StatefulSet: set snoopIpv6DefaultRoot flag in XR_INTERFACES" { template --set-json 'interfaces=[{"type": "multus"}, {"type": "defaultCni", "snoopIpv6DefaultRoute": true}]' - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "linux:net1;linux:eth0,snoop_v6_default_route" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_INTERFACES"))][0][0].value' "linux:net0;linux:eth0,snoop_v6_default_route" } @test "Control Plane StatefulSet: set chksum flag in XR_INTERFACES" { template --set-json 'interfaces=[{"type": "multus"}, {"type": "defaultCni", "chksum": true}]' - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "linux:net1;linux:eth0,chksum" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_INTERFACES"))][0][0].value' "linux:net0;linux:eth0,chksum" } @test "Control Plane StatefulSet: set xrName flag in XR_INTERFACES" { template --set-json 'interfaces=[{"type": "multus"}, {"type": "defaultCni", "xrName": "foo"}]' - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "linux:net1;linux:eth0,xr_name=foo" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_INTERFACES"))][0][0].value' "linux:net0;linux:eth0,xr_name=foo" +} + +@test "Control Plane StatefulSet: set snoopIpv4Address flag in XR_INTERFACES for sriov interfaces" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "snoopIpv4Address": true}]' + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_INTERFACES"))][0][0].value' "linux:net0,snoop_v4" +} + +@test "Control Plane StatefulSet: multiple multus interfaces" { + template --set-json 'interfaces=[{"type": "multus"}, {"type": "defaultCni"}, {"type": "multus"}]' + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_INTERFACES"))][0][0].value' "linux:net0;linux:eth0;linux:net1" +} + +@test "Control Plane StatefulSet: multiple multus and sriov interfaces" { + template --set-json 'interfaces=[{"type": "multus"}, {"type": "defaultCni"}, {"type": "multus"}, {"type": "sriov", "resource": "foo/bar"}]' + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_INTERFACES"))][0][0].value' "linux:net0;linux:eth0;linux:net1;linux:net2" } @test "Control Plane StatefulSet: don't set unsupported flags XR_INTERFACES" { @@ -369,61 +391,57 @@ setup_file () { } @test "Control Plane StatefulSet: XR_MGMT_INTERFACES container env vars is correctly set" { - template --set-json 'mgmtInterfaces=[{"type": "multus", "chksum": true}, {"type": "defaultCni"}]' - assert_query_equal '.spec.template.spec.containers[0].env[2].name' "XR_MGMT_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[2].value' "linux:net1,chksum;linux:eth0" + template --set-json 'mgmtInterfaces=[{"type": "multus", "chksum": true}, {"type": "sriov", "resource": "foo"}, {"type": "defaultCni"}]' + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_MGMT_INTERFACES"))][0][0].value' "linux:net0,chksum;linux:net1;linux:eth0" +} + +@test "Control Plane StatefulSet: XR_MGMT_INTERFACES container env vars is correctly set when sriov interface is present" { + template --set-json 'mgmtInterfaces=[{"type": "multus"}]' \ + --set-json 'interfaces=[{"type": "sriov", "resource": "foo/bar"}]' + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_MGMT_INTERFACES"))][0][0].value' "linux:net1" } @test "Control Plane StatefulSet: XR_DISK_USAGE_LIMIT is set if persistence is enabled with default value" { template --set 'persistence.enabled=true' - assert_query_equal '.spec.template.spec.containers[0].env[0].name' "XR_DISK_USAGE_LIMIT" - assert_query_equal '.spec.template.spec.containers[0].env[0].value' "6G" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_DISK_USAGE_LIMIT"))][0][0].value' "6G" } @test "Control Plane StatefulSet: value of XR_DISK_USAGE_LIMIT can be set" { template --set 'persistence.enabled=true' --set 'persistence.size=123kb' - assert_query_equal '.spec.template.spec.containers[0].env[0].name' "XR_DISK_USAGE_LIMIT" - assert_query_equal '.spec.template.spec.containers[0].env[0].value' "123K" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_DISK_USAGE_LIMIT"))][0][0].value' "123K" } @test "Control Plane StatefulSet: XR_FIRST_BOOT_CONFIG is set if config is to be applied on first boot" { template --set 'config.username=foo' --set 'config.password=bar' - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_FIRST_BOOT_CONFIG" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "/etc/xrd/startup.cfg" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_FIRST_BOOT_CONFIG"))][0][0].value' "/etc/xrd/startup.cfg" } @test "Control Plane StatefulSet: XR_EVERY_BOOT_CONFIG is set if ascii config is to be applied on every boot" { template --set 'config.ascii=foo' --set 'config.asciiEveryBoot=true' - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_EVERY_BOOT_CONFIG" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "/etc/xrd/startup.cfg" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_EVERY_BOOT_CONFIG"))][0][0].value' "/etc/xrd/startup.cfg" } @test "Control Plane StatefulSet: XR_ZTP_ENABLE can be set" { template --set 'config.ztpEnable=true' - assert_query_equal '.spec.template.spec.containers[0].env[3].name' "XR_ZTP_ENABLE" - assert_query_equal '.spec.template.spec.containers[0].env[3].value' "1" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_ZTP_ENABLE"))][0][0].value' "1" } @test "Control Plane StatefulSet: XR_ZTP_INI can be set" { template --set 'config.ztpEnable=true' --set 'config.ztpIni=foo' - assert_query_equal '.spec.template.spec.containers[0].env[3].name' "XR_ZTP_ENABLE" - assert_query_equal '.spec.template.spec.containers[0].env[3].value' "1" - assert_query_equal '.spec.template.spec.containers[0].env[4].name' "XR_ZTP_ENABLE_WITH_INI" - assert_query_equal '.spec.template.spec.containers[0].env[4].value' "/etc/xrd/ztp.ini" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_ZTP_ENABLE"))][0][0].value' "1" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_ZTP_ENABLE_WITH_INI"))][0][0].value' "/etc/xrd/ztp.ini" } @test "Control Plane StatefulSet: advanced settings can be used to add env vars" { template --set 'advancedSettings.FOO=bar' - assert_query_equal '.spec.template.spec.containers[0].env[0].name' "FOO" - assert_query_equal '.spec.template.spec.containers[0].env[0].value' "bar" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "FOO"))][0][0].value' "bar" } @test "Control Plane StatefulSet: advanced settings can be used to override default settings" { template \ --set 'config.ascii=foo' \ --set 'advancedSettings.XR_FIRST_BOOT_CONFIG=foo' - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_FIRST_BOOT_CONFIG" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "foo" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_FIRST_BOOT_CONFIG"))][0][0].value' "foo" } @test "Control Plane StatefulSet: no container volumeMounts by default" { @@ -549,4 +567,14 @@ setup_file () { --set-json 'persistence.dataSource={"name": "foo", "kind": "bar"}' assert_query_equal '.spec.volumeClaimTemplates[0].spec.dataSource.name' "foo" assert_query_equal '.spec.volumeClaimTemplates[0].spec.dataSource.kind' "bar" +} + +@test "Control Plane StatefulSet: XR_NETWORK_STATUS_ANNOTATION_PATH is not set when there is an sriov network" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo"}]' + assert_query_equal '.spec.template.spec.containers[0].env | map(select(.name == "XR_NETWORK_STATUS_ANNOTATION_PATH"))' "[]" +} + +@test "Control Plane StatefulSet: downwardAPI volume is not set if sriov network" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo"}]' + assert_query '.spec.template.spec.volumes[0].downwardAPI | not' } \ No newline at end of file diff --git a/tests/ut/xrd-vrouter/network-attachments.bats b/tests/ut/xrd-vrouter/network-attachments.bats index 0fa7c993..e0f73b96 100644 --- a/tests/ut/xrd-vrouter/network-attachments.bats +++ b/tests/ut/xrd-vrouter/network-attachments.bats @@ -9,34 +9,34 @@ setup_file () { helm dependency update . } -@test "vRouter NetworkAttachmentDefinition: Name consists of the release name, template name and index" { +@test "vRouter NetworkAttachmentDefinition (multus): Name consists of the release name, template name and index" { template --set-json 'mgmtInterfaces=[{"type": "multus"}]' assert_query_equal '.metadata.name' "release-name-xrd-vrouter-0" } -@test "vRouter NetworkAttachmentDefinition: Name can be overridden with fullnameOverride" { +@test "vRouter NetworkAttachmentDefinition (multus): Name can be overridden with fullnameOverride" { template --set-json 'mgmtInterfaces=[{"type": "multus"}]' \ --set 'fullnameOverride=xrd-test' assert_query_equal '.metadata.name' "xrd-test-0" } -@test "vRouter NetworkAttachmentDefinition: Name can be overridden with nameOverride" { +@test "vRouter NetworkAttachmentDefinition (multus): Name can be overridden with nameOverride" { template --set-json 'mgmtInterfaces=[{"type": "multus"}]' \ --set 'nameOverride=xrd-test' assert_query_equal '.metadata.name' "release-name-xrd-test-0" } -@test "vRouter NetworkAttachmentDefinition: Namespace is default" { +@test "vRouter NetworkAttachmentDefinition (multus): Namespace is default" { template --set-json 'mgmtInterfaces=[{"type": "multus"}]' assert_query_equal '.metadata.namespace' "default" } -@test "vRouter NetworkAttachmentDefinition: No annotations are set by default" { +@test "vRouter NetworkAttachmentDefinition (multus): No annotations are set by default" { template --set-json 'mgmtInterfaces=[{"type": "multus"}]' assert_query '.metadata.annotations | not' } -@test "vRouter NetworkAttachmentDefinition: Global annotations and commonAnnotations can be added and are correctly merged" { +@test "vRouter NetworkAttachmentDefinition (multus): Global annotations and commonAnnotations can be added and are correctly merged" { template \ --set-json 'mgmtInterfaces=[{"type": "multus"}]' \ --set 'global.annotations.foo=bar' \ @@ -45,7 +45,7 @@ setup_file () { assert_query_equal '.metadata.annotations.baz' "baa" } -@test "vRouter NetworkAttachmentDefinition: Recommended labels are set" { +@test "vRouter NetworkAttachmentDefinition (multus): Recommended labels are set" { template --set-json 'mgmtInterfaces=[{"type": "multus"}]' assert_query_equal '.metadata.labels."app.kubernetes.io/name"' "xrd-vrouter" assert_query_equal '.metadata.labels."app.kubernetes.io/instance"' "release-name" @@ -54,7 +54,7 @@ setup_file () { assert_query '.metadata.labels | has("helm.sh/chart")' } -@test "vRouter NetworkAttachmentDefinition: Global labels and commonLabels can be added and are correctly merged" { +@test "vRouter NetworkAttachmentDefinition (multus): Global labels and commonLabels can be added and are correctly merged" { template \ --set-json 'mgmtInterfaces=[{"type": "multus"}]' \ --set 'global.labels.foo=bar' \ @@ -63,45 +63,119 @@ setup_file () { assert_query_equal '.metadata.labels.baz' "baa" } -@test "vRouter NetworkAttachmentDefinition: Check default config" { +@test "vRouter NetworkAttachmentDefinition (multus): Check default config" { template --set-json 'mgmtInterfaces=[{"type": "multus"}]' assert_query_equal '.spec.config' \ - "{\n \"cniVersion\": \"0.3.1\",\n \"plugins\": [\n null\n ]\n}" + "{\n \"cniVersion\": \"0.3.1\",\n \"name\": \"release-name-xrd-vrouter-0\",\n \"plugins\": [\n null\n ]\n}" } -@test "vRouter NetworkAttachmentDefinition: Config can be set" { +@test "vRouter NetworkAttachmentDefinition (multus): Config can be set" { template --set-json 'mgmtInterfaces=[{"type": "multus", "config": {"foo": "bar"}}]' assert_query_equal '.spec.config' \ - "{\n \"cniVersion\": \"0.3.1\",\n \"plugins\": [\n {\n \"foo\": \"bar\"\n }\n ]\n}" + "{\n \"cniVersion\": \"0.3.1\",\n \"name\": \"release-name-xrd-vrouter-0\",\n \"plugins\": [\n {\n \"foo\": \"bar\"\n }\n ]\n}" } -@test "vRouter NetworkAttachmentDefinition: No interfaces" { - template_failure --set-json 'interfaces=[{"type": "pci"}]' +@test "vRouter NetworkAttachmentDefinition (sriov): Name consists of the release name, template name and index" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' + assert_query_equal '.metadata.name' "release-name-xrd-vrouter-0" +} + +@test "vRouter NetworkAttachmentDefinition (sriov): Name can be overridden with fullnameOverride" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' \ + --set 'fullnameOverride=xrd-test' + assert_query_equal '.metadata.name' "xrd-test-0" +} + +@test "vRouter NetworkAttachmentDefinition (sriov): Name can be overridden with nameOverride" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' \ + --set 'nameOverride=xrd-test' + assert_query_equal '.metadata.name' "release-name-xrd-test-0" +} + +@test "vRouter NetworkAttachmentDefinition (sriov): Namespace is default" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' + assert_query_equal '.metadata.namespace' "default" +} + +@test "vRouter NetworkAttachmentDefinition (sriov): Default annotations are set" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' + assert_query_equal '.metadata.annotations."k8s.v1.cni.cncf.io/resourceName"' "foo" +} + +@test "vRouter NetworkAttachmentDefinition (sriov): Global annotations and commonAnnotations can be added and are correctly merged" { + template \ + --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' \ + --set 'global.annotations.foo=bar' \ + --set 'commonAnnotations.baz=baa' + assert_query_equal '.metadata.annotations."k8s.v1.cni.cncf.io/resourceName"' "foo" + assert_query_equal '.metadata.annotations.foo' "bar" + assert_query_equal '.metadata.annotations.baz' "baa" +} + +@test "vRouter NetworkAttachmentDefinition (sriov): Recommended labels are set" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' + assert_query_equal '.metadata.labels."app.kubernetes.io/name"' "xrd-vrouter" + assert_query_equal '.metadata.labels."app.kubernetes.io/instance"' "release-name" + assert_query_equal '.metadata.labels."app.kubernetes.io/managed-by"' "Helm" + assert_query '.metadata.labels | has("app.kubernetes.io/version")' + assert_query '.metadata.labels | has("helm.sh/chart")' +} + +@test "vRouter NetworkAttachmentDefinition (sriov): Global labels and commonLabels can be added and are correctly merged" { + template \ + --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' \ + --set 'global.labels.foo=bar' \ + --set 'commonLabels.baz=baa' + assert_query_equal '.metadata.labels.foo' "bar" + assert_query_equal '.metadata.labels.baz' "baa" +} + +@test "vRouter NetworkAttachmentDefinition (sriov): Config can be set" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' + assert_query_equal '.spec.config' \ + "{\n \"cniVersion\": \"0.3.1\",\n \"name\": \"release-name-xrd-vrouter-0\",\n \"plugins\": [\n {\n \"type\": \"sriov\"\n }\n ]\n}" +} + +@test "vRouter NetworkAttachmentDefinition: multiple sriov interfaces can be created together" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}},{"type": "sriov", "resource": "bar", "config": {"type": "sriov"}}]' + assert_query_equal '.metadata.name' \ + "release-name-xrd-vrouter-0\n---\nrelease-name-xrd-vrouter-1" +} + +@test "vRouter NetworkAttachmentDefinition: sriov interfaces and multus mgmt interfaces can be created together" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "config": {"type": "sriov"}}]' \ + --set-json 'mgmtInterfaces=[{"type": "multus"}]' + assert_query_equal '.metadata.name' \ + "release-name-xrd-vrouter-0\n---\nrelease-name-xrd-vrouter-1" } -@test "vRouter NetworkAttachmentDefinition: No custom resource created for defaultCNI" { +@test "vRouter NetworkAttachmentDefinition: No custom resource created for defaultCNI mgmt interfaces" { template_failure --set-json 'mgmtInterfaces=[{"type": "defaultCni"}]' } -@test "vRouter NetworkAttachmentDefinition: Error if multiple defaultCNI requested" { - template_failure --set-json 'mgmtInterfaces=[{"type": "defaultCni"}, {"type": "defaultCni"}]' - assert_error_message_contains \ - "At most one defaultCni interface can be specified across both interfaces and mgmtInterfaces" +@test "vRouter NetworkAttachmentDefinition: No custom resource created for pci interfaces" { + template_failure --set-json 'interfaces=[{"type": "pci"}]' } @test "vRouter NetworkAttachmentDefinition: Interface cannot be type defaultCNI" { template_failure --set-json 'interfaces=[{"type": "defaultCni"}]' - assert_error_message_contains "type must be one of the following: \"pci\"" + assert_error_message_contains "type must be one of the following: \"pci\", \"sriov\"" } @test "vRouter NetworkAttachmentDefinition: Interface cannot be type multus" { template_failure --set-json 'interfaces=[{"type": "multus"}]' - assert_error_message_contains "type must be one of the following: \"pci\"" + assert_error_message_contains "type must be one of the following: \"pci\", \"sriov\"" } @test "vRouter NetworkAttachmentDefinition: MGMT interface cannot be type pci" { template_failure --set-json 'mgmtInterfaces=[{"type": "pci"}]' - assert_error_message_contains "type must be one of the following: \"defaultCni\", \"multus\"" + assert_error_message_contains "type must be one of the following: \"defaultCni\", \"multus\", \"sriov\"" +} + +@test "vRouter NetworkAttachmentDefinition: Error if multiple defaultCNI requested" { + template_failure --set-json 'mgmtInterfaces=[{"type": "defaultCni"}, {"type": "defaultCni"}]' + assert_error_message_contains \ + "At most one defaultCni interface can be specified across both interfaces and mgmtInterfaces" } @test "vRouter NetworkAttachmentDefinition: At most one MGMT interface can be specified" { @@ -111,15 +185,10 @@ setup_file () { @test "vRouter NetworkAttachmentDefinition: error if unknown interface type is requested" { template_failure --set-json 'interfaces=[{"type": "foo"}]' - assert_error_message_contains "must be one of the following: \"pci\"" + assert_error_message_contains "must be one of the following: \"pci\", \"sriov\"" } @test "vRouter NetworkAttachmentDefinition: error if unknown mgmt interface type is requested" { template_failure --set-json 'mgmtInterfaces=[{"type": "foo"}]' - assert_error_message_contains "must be one of the following: \"defaultCni\", \"multus\"" + assert_error_message_contains "must be one of the following: \"defaultCni\", \"multus\", \"sriov\"" } - -@test "vRouter NetworkAttachmentDefinition: error if PCI mgmt interface is requested" { - template_failure --set-json 'mgmtInterfaces=[{"type": "pci"}]' - assert_error_message_contains "must be one of the following: \"defaultCni\", \"multus\"" -} \ No newline at end of file diff --git a/tests/ut/xrd-vrouter/statefulset.bats b/tests/ut/xrd-vrouter/statefulset.bats index aad8ed55..04e47276 100644 --- a/tests/ut/xrd-vrouter/statefulset.bats +++ b/tests/ut/xrd-vrouter/statefulset.bats @@ -80,6 +80,16 @@ setup_file () { assert_fields_equal '.spec.serviceName' '.metadata.name' } +@test "vRouter StatefulSet: No serviceAccountName by default" { + template + assert_query '.spec.serviceAccountName | not' +} + +@test "vRouter StatefulSet: serviceAccountName can be set" { + template --set 'serviceAccountName=foo' + assert_query_equal '.spec.template.spec.serviceAccountName' "foo" +} + @test "vRouter StatefulSet: Selector labels are set" { template assert_query_equal '.spec.selector.matchLabels' \ @@ -100,7 +110,13 @@ setup_file () { @test "vRouter StatefulSet: .spec.template annotations are added for multus interfaces" { template --set-json 'mgmtInterfaces=[{"type": "multus"}]' assert_query_equal '.spec.template.metadata.annotations."k8s.v1.cni.cncf.io/networks"' \ - "[\n {\n \"name\": \"release-name-xrd-vrouter-0\"\n }\n]" + "[\n {\n \"interface\": \"net0\",\n \"name\": \"release-name-xrd-vrouter-0\"\n }\n]" +} + +@test "vRouter StatefulSet: .spec.template annotations are added for sriov mgmt interfaces" { + template --set-json 'mgmtInterfaces=[{"type": "sriov", "resource": "foo"}]' + assert_query_equal '.spec.template.metadata.annotations."k8s.v1.cni.cncf.io/networks"' \ + "[\n {\n \"interface\": \"net0\",\n \"name\": \"release-name-xrd-vrouter-0\"\n }\n]" } @test "vRouter StatefulSet: .spec.template podAnnotations can be set" { @@ -109,9 +125,10 @@ setup_file () { } @test "vRouter StatefulSet: podNetworkAnnotations contain the desired information" { - template --set-json 'mgmtInterfaces=[{"type": "multus", "attachmentConfig": {"foo": "bar"}}]' + template --set-json 'mgmtInterfaces=[{"type": "multus", "attachmentConfig": {"foo": "bar"}}]' \ + --set-json 'interfaces=[{"type": "sriov", "resource": "baz"}]' assert_query_equal '.spec.template.metadata.annotations."k8s.v1.cni.cncf.io/networks"' \ - "[\n {\n \"foo\": \"bar\",\n \"name\": \"release-name-xrd-vrouter-0\"\n }\n]" + "[\n {\n \"interface\": \"net0\",\n \"name\": \"release-name-xrd-vrouter-0\"\n },\n {\n \"foo\": \"bar\",\n \"interface\": \"net1\",\n \"name\": \"release-name-xrd-vrouter-1\"\n }\n]" } @test "vRouter StatefulSet: .spec.template recommended labels are set" { @@ -232,6 +249,18 @@ setup_file () { assert_query_equal '.spec.template.spec.volumes[0].name' "foo" } +@test "vRouter StatefulSet: downwardAPI volume is set if sriov network" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo"}]' + assert_query_equal '.spec.template.spec.volumes[0].name' "network-status-annotation" + assert_query_equal '.spec.template.spec.volumes[0].downwardAPI.items[0].fieldRef.fieldPath' "metadata.annotations['k8s.v1.cni.cncf.io/network-status']" + assert_query_equal '.spec.template.spec.volumes[0].downwardAPI.items[0].path' "network-status-annotation" +} + +@test "vRouter StatefulSet: downwardAPI volume is not set if sriov mgmt network" { + template --set-json 'mgmtInterfaces=[{"type": "sriov", "resource": "foo"}]' + assert_query '.spec.template.spec.volumes[0].downwardAPI | not' +} + @test "vRouter: Image repository must be specified" { template_failure_no_set --set 'image.tag=latest' assert_error_message_contains "image: repository is required" @@ -310,28 +339,28 @@ setup_file () { @test "vRouter StatefulSet: container env vars version is set" { template - assert_query_equal '.spec.template.spec.containers[0].env[0].name' "XR_ENV_VARS_VERSION" - assert_query_equal '.spec.template.spec.containers[0].env[0].value' "1" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_ENV_VARS_VERSION"))][0][0].value' "1" } @test "vRouter StatefulSet: empty container interface env vars are set by default" { template - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "" - assert_query_equal '.spec.template.spec.containers[0].env[2].name' "XR_MGMT_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[2].value' "" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_INTERFACES"))][0][0].value' "" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_MGMT_INTERFACES"))][0][0].value' "" } @test "vRouter StatefulSet: default hugepage size container env var is set" { template - assert_query_equal '.spec.template.spec.containers[0].env[3].name' "XR_VROUTER_DP_HUGEPAGE_MB" - assert_query_equal '.spec.template.spec.containers[0].env[3].value' "3072" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_VROUTER_DP_HUGEPAGE_MB"))][0][0].value' "3072" } @test "vRouter StatefulSet: non-default hugepage size container env var has correct size" { template --set 'resources.limits.hugepages-1Gi=6Gi' - assert_query_equal '.spec.template.spec.containers[0].env[3].name' "XR_VROUTER_DP_HUGEPAGE_MB" - assert_query_equal '.spec.template.spec.containers[0].env[3].value' "6144" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_VROUTER_DP_HUGEPAGE_MB"))][0][0].value' "6144" +} + +@test "vRouter StatefulSet: runtimeClassName can be set" { + template --set 'runtimeClassName=foo' + assert_query_equal '.spec.template.spec.runtimeClassName' "foo" } @test "vRouter StatefulSet: XR_VROUTER_CP_CPUSET and XR_VROUTER_DP_CPUSET can be set" { @@ -374,73 +403,85 @@ setup_file () { assert_error_message_contains "controlPlaneCpuCount must not be set if controlPlaneCpuset and dataPlaneCpuset are set" } -@test "vRouter StatefulSet: hyperThreadingMode can't be specified if controlPlaneCpuset and dataPlaneCpuset are" { - template_failure --set 'cpu.hyperThreadingMode=off' \ - --set 'cpu.controlPlaneCpuset=foo'\ - --set 'cpu.dataPlaneCpuset=bar' - assert_error_message_contains "hyperThreadingMode must not be set if controlPlaneCpuset and dataPlaneCpuset are set" -} - @test "vRouter StatefulSet: hyperthreading mode container env var can be set" { - template --set 'cpu.hyperThreadingMode=off' - assert_query_equal '.spec.template.spec.containers[0].env[4].name' "XR_VROUTER_HT_MODE" - assert_query_equal '.spec.template.spec.containers[0].env[4].value' "off" + template --set 'cpu.hyperThreadingMode=pairs' + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_VROUTER_HT_MODE"))][0][0].value' "pairs" } @test "vRouter StatefulSet: PCI driver container env var can be set" { template --set 'pciDriver=vfio-pci' - assert_query_equal '.spec.template.spec.containers[0].env[4].name' "XR_VROUTER_PCI_DRIVER" - assert_query_equal '.spec.template.spec.containers[0].env[4].value' "vfio-pci" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_VROUTER_PCI_DRIVER"))][0][0].value' "vfio-pci" } @test "vRouter StatefulSet: XR_INTERFACES container env vars is correctly set" { - template --set-json 'interfaces=[{"type": "pci", "config": {"device": "00:00.0"}}, {"type": "pci", "config": {"device": "11:11.1"}}]' - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "pci:00:00.0;pci:11:11.1" + template --set-json 'interfaces=[{"type": "pci", "config": {"device": "00:00.0"}}, {"type": "sriov", "resource": "foo/bar"}]' + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_INTERFACES"))][0][0].value' "pci:00:00.0;net-attach-def:default/release-name-xrd-vrouter-0" } -@test "vRouter StatefulSet: XR_INTERFACES doesn't support any flags currently" { +@test "vRouter StatefulSet: XR_INTERFACES container env vars is correctly set (sriov) with name override" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo/bar"}]' \ + --set 'fullnameOverride=xrd-test' + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_INTERFACES"))][0][0].value' "net-attach-def:default/xrd-test-0" +} + +@test "vRouter StatefulSet: pci XR_INTERFACES don't support any flags currently" { template_failure --set-json 'interfaces=[{"type": "pci", "config": {"device": "00:00.0"}, "chksum": true}]' assert_error_message_contains "Additional property chksum is not allowed" } +@test "vRouter StatefulSet: sriov XR_INTERFACES don't support any flags currently" { + template_failure --set-json 'interfaces=[{"type": "sriov", "resource": "foo", "chksum": true}]' + assert_error_message_contains "Additional property chksum is not allowed" +} + @test "vRouter StatefulSet: XR_MGMT_INTERFACES container env vars is correctly set" { template --set-json 'mgmtInterfaces=[{"type": "multus"}]' - assert_query_equal '.spec.template.spec.containers[0].env[2].name' "XR_MGMT_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[2].value' "linux:net1" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_MGMT_INTERFACES"))][0][0].value' "linux:net0" +} + +@test "vRouter StatefulSet: XR_MGMT_INTERFACES container env vars is correctly set when sriov interface is present" { + template --set-json 'mgmtInterfaces=[{"type": "multus"}]' \ + --set-json 'interfaces=[{"type": "sriov", "resource": "foo/bar"}]' + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_MGMT_INTERFACES"))][0][0].value' "linux:net1" +} + +@test "vRouter StatefulSet: XR_MGMT_INTERFACES container env vars is correctly for sriov mgmt interface when sriov interface is present" { + template --set-json 'mgmtInterfaces=[{"type": "sriov", "resource": "foo"}]' \ + --set-json 'interfaces=[{"type": "sriov", "resource": "bar"}]' + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_MGMT_INTERFACES"))][0][0].value' "linux:net1" } @test "vRouter StatefulSet: set snoopIpv4Address flag in XR_MGMT_INTERFACES" { template --set-json 'mgmtInterfaces=[{"type": "multus", "snoopIpv4Address": true}]' - assert_query_equal '.spec.template.spec.containers[0].env[2].name' "XR_MGMT_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[2].value' "linux:net1,snoop_v4" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_MGMT_INTERFACES"))][0][0].value' "linux:net0,snoop_v4" } @test "vRouter StatefulSet: set snoopIpv4DefaultRoot flag in XR_MGMT_INTERFACES" { template --set-json 'mgmtInterfaces=[{"type": "multus", "snoopIpv4DefaultRoute": true}]' - assert_query_equal '.spec.template.spec.containers[0].env[2].name' "XR_MGMT_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[2].value' "linux:net1,snoop_v4_default_route" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_MGMT_INTERFACES"))][0][0].value' "linux:net0,snoop_v4_default_route" } @test "vRouter StatefulSet: set snoopIpv6Address flag in XR_MGMT_INTERFACES" { template --set-json 'mgmtInterfaces=[{"type": "multus", "snoopIpv6Address": true}]' - assert_query_equal '.spec.template.spec.containers[0].env[2].name' "XR_MGMT_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[2].value' "linux:net1,snoop_v6" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_MGMT_INTERFACES"))][0][0].value' "linux:net0,snoop_v6" } @test "vRouter StatefulSet: set snoopIpv6DefaultRoot flag in XR_MGMT_INTERFACES" { template --set-json 'mgmtInterfaces=[{"type": "multus", "snoopIpv6DefaultRoute": true}]' - assert_query_equal '.spec.template.spec.containers[0].env[2].name' "XR_MGMT_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[2].value' "linux:net1,snoop_v6_default_route" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_MGMT_INTERFACES"))][0][0].value' "linux:net0,snoop_v6_default_route" } @test "vRouter StatefulSet: set chksum flag in XR_MGMT_INTERFACES" { template --set-json 'mgmtInterfaces=[{"type": "multus", "chksum": true}]' - assert_query_equal '.spec.template.spec.containers[0].env[2].name' "XR_MGMT_INTERFACES" - assert_query_equal '.spec.template.spec.containers[0].env[2].value' "linux:net1,chksum" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_MGMT_INTERFACES"))][0][0].value' "linux:net0,chksum" } -@test "vRouter StatefulSet: xrName flag is not allowed for vRouter" { +@test "vRouter StatefulSet: set chksum flag in XR_MGMT_INTERFACES for sriov interface" { + template --set-json 'mgmtInterfaces=[{"type": "sriov", "resource": "foo", "chksum": true}]' + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_MGMT_INTERFACES"))][0][0].value' "linux:net0,chksum" +} + +@test "vRouter StatefulSet: xrName flag is not allowed for vRouter" { template_failure --set-json 'mgmtInterfaces=[{"type": "multus", "xrName": "foo"}]' assert_error_message_contains "xrName may not be specified for interfaces on XRd vRouter" } @@ -450,56 +491,57 @@ setup_file () { assert_error_message_contains "Additional property foo is not allowed" } +@test "vRouter StatefulSet: XR_NETWORK_STATUS_ANNOTATION_PATH is not set by default" { + template + assert_query '[.spec.template.spec.containers[0].env | map(select(.name == "XR_NETWORK_STATUS_ANNOTATION_PATH"))][0][0] | not' +} + +@test "vRouter StatefulSet: XR_NETWORK_STATUS_ANNOTATION_PATH is set when there is an sriov network" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo"}]' + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_NETWORK_STATUS_ANNOTATION_PATH"))][0][0].value' "/etc/xrd/network-status/network-status-annotation" +} + @test "vRouter StatefulSet: XR_DISK_USAGE_LIMIT is set if persistence is enabled with default value" { template --set 'persistence.enabled=true' - assert_query_equal '.spec.template.spec.containers[0].env[0].name' "XR_DISK_USAGE_LIMIT" - assert_query_equal '.spec.template.spec.containers[0].env[0].value' "6G" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_DISK_USAGE_LIMIT"))][0][0].value' "6G" } @test "vRouter StatefulSet: value of XR_DISK_USAGE_LIMIT can be set" { template --set 'persistence.enabled=true' --set 'persistence.size=123kb' - assert_query_equal '.spec.template.spec.containers[0].env[0].name' "XR_DISK_USAGE_LIMIT" - assert_query_equal '.spec.template.spec.containers[0].env[0].value' "123K" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_DISK_USAGE_LIMIT"))][0][0].value' "123K" } @test "vRouter StatefulSet: XR_FIRST_BOOT_CONFIG is set if config is to be applied on first boot" { template --set 'config.username=foo' --set 'config.password=bar' - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_FIRST_BOOT_CONFIG" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "/etc/xrd/startup.cfg" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_FIRST_BOOT_CONFIG"))][0][0].value' "/etc/xrd/startup.cfg" } @test "vRouter StatefulSet: XR_EVERY_BOOT_CONFIG is set if ascii config is to be applied on every boot" { template --set 'config.ascii=foo' --set 'config.asciiEveryBoot=true' - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_EVERY_BOOT_CONFIG" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "/etc/xrd/startup.cfg" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_EVERY_BOOT_CONFIG"))][0][0].value' "/etc/xrd/startup.cfg" } @test "vRouter StatefulSet: XR_ZTP_ENABLE can be set" { template --set 'config.ztpEnable=true' - assert_query_equal '.spec.template.spec.containers[0].env[4].name' "XR_ZTP_ENABLE" - assert_query_equal '.spec.template.spec.containers[0].env[4].value' "1" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_ZTP_ENABLE"))][0][0].value' "1" } @test "vRouter StatefulSet: XR_ZTP_INI can be set" { template --set 'config.ztpEnable=true' --set 'config.ztpIni=foo' - assert_query_equal '.spec.template.spec.containers[0].env[4].name' "XR_ZTP_ENABLE" - assert_query_equal '.spec.template.spec.containers[0].env[4].value' "1" - assert_query_equal '.spec.template.spec.containers[0].env[5].name' "XR_ZTP_ENABLE_WITH_INI" - assert_query_equal '.spec.template.spec.containers[0].env[5].value' "/etc/xrd/ztp.ini" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_ZTP_ENABLE"))][0][0].value' "1" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_ZTP_ENABLE_WITH_INI"))][0][0].value' "/etc/xrd/ztp.ini" } @test "vRouter StatefulSet: advanced settings can be used to add env vars" { template --set 'advancedSettings.FOO=bar' - assert_query_equal '.spec.template.spec.containers[0].env[0].name' "FOO" - assert_query_equal '.spec.template.spec.containers[0].env[0].value' "bar" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "FOO"))][0][0].value' "bar" } @test "vRouter StatefulSet: advanced settings can be used to override default settings" { template \ --set 'config.ascii=foo' \ --set 'advancedSettings.XR_FIRST_BOOT_CONFIG=foo' - assert_query_equal '.spec.template.spec.containers[0].env[1].name' "XR_FIRST_BOOT_CONFIG" - assert_query_equal '.spec.template.spec.containers[0].env[1].value' "foo" + assert_query_equal '[.spec.template.spec.containers[0].env | map(select(.name == "XR_FIRST_BOOT_CONFIG"))][0][0].value' "foo" } @test "vRouter StatefulSet: no container volumeMounts by default" { @@ -542,6 +584,12 @@ setup_file () { assert_query_equal '.spec.template.spec.containers[0].volumeMounts[0].name' "bar" } +@test "vRouter StatefulSet: network-status annotation is mounted if there is sriov network" { + template --set-json 'interfaces=[{"type": "sriov", "resource": "foo"}]' + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[0].mountPath' "/etc/xrd/network-status" + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[0].name' "network-status-annotation" +} + @test "vRouter StatefulSet: container imagePullSecrets can be set" { template --set 'image.pullSecrets[0].name=foo' assert_query_equal '.spec.template.spec.imagePullSecrets[0].name' "foo"