From 0d60cab76db891b761288789bf6e54cea2a4159a Mon Sep 17 00:00:00 2001 From: Ed Beaty Date: Wed, 27 Mar 2024 04:55:21 -0700 Subject: [PATCH] . --- tests/Dockerfile | 23 + tests/README.md | 24 + tests/ut/setup_suite.bash | 3 + tests/ut/utils.bash | 74 +++ tests/ut/xrd-control-plane/cp_configmap.bats | 95 +++ .../cp_network-attachments.bats | 123 ++++ .../ut/xrd-control-plane/cp_statefulset.bats | 547 ++++++++++++++++ tests/ut/xrd-vrouter/vrouter_configmap.bats | 91 +++ .../vrouter_network-attachments.bats | 125 ++++ tests/ut/xrd-vrouter/vrouter_statefulset.bats | 588 ++++++++++++++++++ 10 files changed, 1693 insertions(+) create mode 100644 tests/Dockerfile create mode 100644 tests/README.md create mode 100644 tests/ut/setup_suite.bash create mode 100644 tests/ut/utils.bash create mode 100755 tests/ut/xrd-control-plane/cp_configmap.bats create mode 100644 tests/ut/xrd-control-plane/cp_network-attachments.bats create mode 100644 tests/ut/xrd-control-plane/cp_statefulset.bats create mode 100644 tests/ut/xrd-vrouter/vrouter_configmap.bats create mode 100644 tests/ut/xrd-vrouter/vrouter_network-attachments.bats create mode 100644 tests/ut/xrd-vrouter/vrouter_statefulset.bats diff --git a/tests/Dockerfile b/tests/Dockerfile new file mode 100644 index 00000000..43577d7e --- /dev/null +++ b/tests/Dockerfile @@ -0,0 +1,23 @@ +FROM bats/bats:1.9.0 + +WORKDIR /charts + +RUN echo "@community https://dl-cdn.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories + +RUN apk update && \ + apk upgrade && \ + apk add curl docker helm@community yamllint yq + +RUN curl -LO "https://github.com/kubernetes-sigs/kind/releases/download/v0.20.0/kind-linux-amd64" +RUN curl -L "https://github.com/kubernetes-sigs/kind/releases/download/v0.20.0/kind-linux-amd64.sha256sum" | sha256sum -c +RUN mv kind-linux-amd64 /usr/local/bin/kind && chmod +x /usr/local/bin/kind + +RUN curl -LO "https://github.com/yannh/kubeconform/releases/download/v0.6.4/kubeconform-linux-amd64.tar.gz" +RUN echo "2b4ebeaa4d5ac4843cf8f7b7e66a8874252b6b71bc7cbfc4ef1cbf85acec7c07 kubeconform-linux-amd64.tar.gz" | sha256sum -c +RUN tar -xz -C /usr/local/bin -f kubeconform-linux-amd64.tar.gz kubeconform && rm kubeconform-linux-amd64.tar.gz + +RUN curl -LO "https://dl.k8s.io/release/v1.29.1/bin/linux/amd64/kubectl" +RUN echo "$(curl -L https://dl.k8s.io/release/v1.29.1/bin/linux/amd64/kubectl.sha256) kubectl" | sha256sum -c +RUN mv kubectl /usr/local/bin/kubectl && chmod +x /usr/local/bin/kubectl + +ENTRYPOINT ["bash"] diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..6f8cf3c1 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,24 @@ +# XRd Helm chart tests + +## Prerequisites + +The following dependencies are required for unit tests: + +- [Bats](https://github.com/bats-core/bats-core) +- [Bats support](https://github.com/bats-core/bats-support) +- [Bats assert](https://github.com/bats-core/bats-assert) +- [Helm](https://helm.sh) +- [yq](https://github.com/mikefarah/yq) +- [yamllint](https://github.com/adrienverge/yamllint) +- [kubeconform](https://github.com/yannh/kubeconform) + +## Running the tests in a container + +A [Dockerfile](Dockerfile) is provided which defines a container image which includes all test dependencies. + +The unit tests can be run using any container manager. For example, using Docker: + +``` +docker build . -t helm-tests +docker run -v "$PWD/..:/charts" helm-tests bats tests/ut +``` diff --git a/tests/ut/setup_suite.bash b/tests/ut/setup_suite.bash new file mode 100644 index 00000000..d63cd2c2 --- /dev/null +++ b/tests/ut/setup_suite.bash @@ -0,0 +1,3 @@ +setup_suite () { + bats_require_minimum_version 1.5.0 +} diff --git a/tests/ut/utils.bash b/tests/ut/utils.bash new file mode 100644 index 00000000..421a97f4 --- /dev/null +++ b/tests/ut/utils.bash @@ -0,0 +1,74 @@ +bats_load_library "bats-assert/load.bash" +bats_load_library "bats-support/load.bash" + +cp_chart_dir () { + readlink -f "${BATS_TEST_DIRNAME}/../../../charts/xrd-control-plane" +} +vrouter_chart_dir () { + readlink -f "${BATS_TEST_DIRNAME}/../../../charts/xrd-vrouter" +} +common_chart_dir () { + readlink -f "${BATS_TEST_DIRNAME}/../../../charts/xrd-common" +} + +template () { + echo -n "# Run 'helm template'" + [ "$#" -eq 0 ] && echo "" || echo " with arguments: $*" + + run -0 helm template . \ + --set image.repository=local \ + --set image.tag=latest \ + -s "$TEMPLATE_UNDER_TEST" \ + "$@" + + # shellcheck disable=SC2154 + echo "$output" + + echo "# Assert output passes yamllint" + echo "$output" | yamllint -d '{extends: default, rules: {indentation: {indent-sequences: false}, line-length: disable}}' - + + echo "# Assert output passes Kubeconform" + echo "$output" | kubeconform -strict -schema-location default -schema-location 'https://raw.githubusercontent.com/datreeio/CRDs-catalog/v0.0.12/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json' +} + +template_failure () { + template_failure_no_set \ + --set image.repository=local \ + --set image.tag=latest \ + "$@" +} + +template_failure_no_set () { + echo -n "# Run 'helm template'" + [ "$#" -eq 0 ] && echo "" || echo " with arguments: $*" + echo "# (Expecting failure)" + + run helm template . \ + -s "$TEMPLATE_UNDER_TEST" \ + "$@" + + [ "$status" -eq 1 ] + + # shellcheck disable=SC2154 + echo "$output" +} + +assert_query () { + assert "$(echo "$output" | yq -e "$1")" "$2" +} + +assert_query_equal () { + assert_equal "$(echo "$output" | yq -e "$1")" "$2" +} + +assert_fields_equal () { + assert_equal "$(echo "$output" | yq -e "$1")" "$(echo "$output" | yq -e "$2")" +} + +assert_multiline_query_equal () { + assert_equal "$(echo "$output" | yq -e "$1")" "$(echo -e "$2")" +} + +assert_error_message_contains () { + assert_output --partial "$1" +} diff --git a/tests/ut/xrd-control-plane/cp_configmap.bats b/tests/ut/xrd-control-plane/cp_configmap.bats new file mode 100755 index 00000000..dae5b4c4 --- /dev/null +++ b/tests/ut/xrd-control-plane/cp_configmap.bats @@ -0,0 +1,95 @@ +#!/usr/bin/env bats + +load "utils.bash" + +export TEMPLATE_UNDER_TEST="templates/config-configmap.yaml" + +setup_file () { + cd "$(cp_chart_dir)" || exit + helm dependency update . +} + +@test "Control Plane ConfigMap: No ConfigMap is generated if no config is set" { + template_failure + assert_error_message_contains "could not find template templates/config-configmap.yaml in chart" +} + +@test "Control Plane ConfigMap: Name consists of the release name and the template name" { + template --set 'config.script=foo' + assert_query_equal '.metadata.name' "release-name-xrd-control-plane-config" +} + +@test "Control Plane ConfigMap: Name can be overridden with fullnameOverride" { + template --set 'fullnameOverride=xrd-test' --set 'config.script=foo' + assert_query_equal '.metadata.name' "xrd-test-config" +} + +@test "Control Plane ConfigMap: Name can be overridden with nameOverride" { + template --set 'nameOverride=xrd-test' --set 'config.script=foo' + assert_query_equal '.metadata.name' "release-name-xrd-test-config" +} + +@test "Control Plane ConfigMap: Namespace is default" { + template --set 'config.script=foo' + assert_query_equal '.metadata.namespace' "default" +} + +@test "Control Plane ConfigMap: No annotations are set by default" { + template --set 'config.script=foo' + assert_query '.metadata.annotations | not' +} + +@test "Control Plane ConfigMap: Global annotations and commonAnnotations can be added and are merged with expected precedence" { + template \ + --set 'global.annotations.foo=bar' \ + --set 'commonAnnotations.baz=baa' \ + --set 'commonAnnotations.foo=qux' \ + --set 'config.script=foo' + assert_query_equal '.metadata.annotations.foo' "qux" + assert_query_equal '.metadata.annotations.baz' "baa" +} + +@test "Control Plane ConfigMap: Recommended labels are set" { + template --set 'config.script=foo' + 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 ConfigMap: Global labels and commonLabels can be added and are correctly merged" { + template \ + --set 'global.labels.foo=bar' \ + --set 'commonLabels.baz=baa' \ + --set 'config.script=foo' + assert_query_equal '.metadata.labels.foo' "bar" + assert_query_equal '.metadata.labels.baz' "baa" +} + +@test "Control Plane ConfigMap: Startup config can be set using username and password" { + template --set 'config.username=foo' --set 'config.password=bar' + assert_multiline_query_equal '.data."startup.cfg"' \ + "username foo\n group root-lr\n group cisco-support\n password bar\n!" +} + +@test "Control Plane ConfigMap: Startup config can be set using ascii" { + template --set 'config.ascii=foo' + assert_query_equal '.data."startup.cfg"' "foo" +} + +@test "Control Plane ConfigMap: Startup script can be set" { + template --set 'config.script=foo' + assert_query_equal '.data."startup.sh"' "foo" +} + +@test "Control Plane ConfigMap: ztpIni can't be set without being enabled" { + template_failure --set 'config.ztpIni=foo' + assert_error_message_contains "ztpIni can only be specified if ztpEnable is set to true" +} + +@test "Control Plane ConfigMap: ztpIni can be set if it is enabled" { + template --set 'config.ztpIni=foo' --set 'config.ztpEnable=true' + assert_query_equal '.data."ztp.ini"' "foo" +} + diff --git a/tests/ut/xrd-control-plane/cp_network-attachments.bats b/tests/ut/xrd-control-plane/cp_network-attachments.bats new file mode 100644 index 00000000..c9150625 --- /dev/null +++ b/tests/ut/xrd-control-plane/cp_network-attachments.bats @@ -0,0 +1,123 @@ +#!/usr/bin/env bats + +load "utils.bash" + +export TEMPLATE_UNDER_TEST="templates/network-attachments.yaml" + +setup_file () { + cd "$(cp_chart_dir)" || exit + helm dependency update . +} + +@test "Control Plane NetworkAttachmentDefinition: Name consists of the release name, template name and index" { + template --set-json 'interfaces=[{"type": "multus"}]' + assert_query_equal '.metadata.name' "release-name-xrd-control-plane-0" +} + +@test "Control Plane NetworkAttachmentDefinition: Name can be overridden with fullnameOverride" { + template --set-json 'interfaces=[{"type": "multus"}]' --set 'fullnameOverride=xrd-test' + assert_query_equal '.metadata.name' "xrd-test-0" +} + +@test "Control Plane NetworkAttachmentDefinition: Name can be overridden with nameOverride" { + template --set-json 'interfaces=[{"type": "multus"}]' --set 'nameOverride=xrd-test' + assert_query_equal '.metadata.name' "release-name-xrd-test-0" +} + +@test "Control Plane NetworkAttachmentDefinition: Names have correct index when more than one interface requested" { + template \ + --set-json 'interfaces=[{"type": "multus"}, {"type": "multus"}]' \ + --set-json 'mgmtInterfaces=[{"type": "multus"}]' + assert_multiline_query_equal '.metadata.name' \ + "release-name-xrd-control-plane-0\n---\nrelease-name-xrd-control-plane-1\n---\nrelease-name-xrd-control-plane-2" +} + +@test "Control Plane NetworkAttachmentDefinition: Namespace is default" { + template --set-json 'interfaces=[{"type": "multus"}]' + assert_query_equal '.metadata.namespace' "default" +} + +@test "Control Plane NetworkAttachmentDefinition: No annotations are set by default" { + template --set-json 'interfaces=[{"type": "multus"}]' + assert_query '.metadata.annotations | not' +} + +@test "Control Plane NetworkAttachmentDefinition: Global annotations and commonAnnotations can be added and are correctly merged" { + template \ + --set-json 'interfaces=[{"type": "multus"}]' \ + --set 'global.annotations.foo=bar' \ + --set 'commonAnnotations.baz=baa' + assert_query_equal '.metadata.annotations.foo' "bar" + assert_query_equal '.metadata.annotations.baz' "baa" +} + +@test "Control Plane NetworkAttachmentDefinition: Recommended labels are set" { + template --set-json 'interfaces=[{"type": "multus"}]' + 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: Global labels and commonLabels can be added and are correctly merged" { + template \ + --set-json 'interfaces=[{"type": "multus"}]' \ + --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: Check default config" { + template --set-json 'interfaces=[{"type": "multus"}]' + assert_multiline_query_equal '.spec.config' \ + "{\n \"cniVersion\": \"0.3.1\",\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_multiline_query_equal '.spec.config'\ + "{\n \"cniVersion\": \"0.3.1\",\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_multiline_query_equal '.spec.config' \ + "{\n \"cniVersion\": \"0.3.1\",\n \"plugins\": [\n {\n \"foo\": \"bar\"\n }\n ]\n}" +} + +@test "Control Plane NetworkAttachmentDefinition: No interfaces" { + template_failure +} + +@test "Control Plane NetworkAttachmentDefinition: No custom resource created for defaultCNI" { + template_failure --set-json 'interfaces=[{"type": "defaultCni"}]' +} + +@test "Control Plane NetworkAttachmentDefinition: error if multiple defaultCNI requested" { + template_failure \ + --set-json 'interfaces=[{"type": "defaultCni"}]' \ + --set-json 'mgmtInterfaces=[{"type": "defaultCni"}]' + assert_error_message_contains "At most one defaultCni interface can be specified across both interfaces and mgmtInterfaces" +} + +@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\"" +} + +@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\"" +} + +@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\"" +} + +@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\"" +} \ No newline at end of file diff --git a/tests/ut/xrd-control-plane/cp_statefulset.bats b/tests/ut/xrd-control-plane/cp_statefulset.bats new file mode 100644 index 00000000..6a4af21d --- /dev/null +++ b/tests/ut/xrd-control-plane/cp_statefulset.bats @@ -0,0 +1,547 @@ +#!/usr/bin/env bats + +load "utils.bash" + +export TEMPLATE_UNDER_TEST="templates/statefulset.yaml" + +setup_file () { + cd "$(cp_chart_dir)" || exit + helm dependency update . +} + +@test "Control Plane StatefulSet: Name consists of the release name, template name and index" { + template + assert_query_equal '.metadata.name' "release-name-xrd-control-plane" +} + +@test "Control Plane StatefulSet: Name can be overridden with fullnameOverride" { + template --set 'fullnameOverride=xrd-test' + assert_query_equal '.metadata.name' "xrd-test" +} + +@test "Control Plane StatefulSet: Name can be overridden with nameOverride" { + template --set 'nameOverride=xrd-test' + assert_query_equal '.metadata.name' "release-name-xrd-test" +} + +@test "Control Plane StatefulSet: Namespace is default" { + template + assert_query_equal '.metadata.namespace' "default" +} + +@test "Control Plane StatefulSet: No annotations are set by default" { + template + assert_query '.metadata.annotations | not' +} + +@test "Control Plane StatefulSet: Global annotations and commonAnnotations can be set" { + template --set 'global.annotations.foo=bar' --set 'commonAnnotations.baz=baa' + assert_query_equal '.metadata.annotations.foo' "bar" + assert_query_equal '.metadata.annotations.baz' "baa" +} + +@test "Control Plane StatefulSet: Annotations, global annotations and commonAnnotations can be set" { + template \ + --set 'global.annotations.foo=bar' \ + --set 'commonAnnotations.baz=baa' \ + --set 'annotations.qux=quux' + assert_query_equal '.metadata.annotations.foo' "bar" + assert_query_equal '.metadata.annotations.baz' "baa" + assert_query_equal '.metadata.annotations.qux' "quux" +} + +@test "Control Plane StatefulSet: Recommended labels are set" { + template + 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 StatefulSet: Global labels and commonLabels can be set" { + template --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 StatefulSet: Labels can be added" { + template --set 'labels.foo=bar' + assert_query_equal '.metadata.labels.foo' "bar" +} + +@test "Control Plane StatefulSet: Replicas is one" { + template + assert_query_equal '.spec.replicas' "1" +} + +@test "Control Plane StatefulSet: serviceName is the name of the StatefulSet" { + template + assert_fields_equal '.spec.serviceName' '.metadata.name' +} + +@test "Control Plane StatefulSet: Selector labels are set" { + template + assert_multiline_query_equal '.spec.selector.matchLabels' \ + "app.kubernetes.io/name: xrd-control-plane\napp.kubernetes.io/instance: release-name" +} + +@test "Control Plane StatefulSet: No .spec.template annotations are set by default" { + template + assert_query '.spec.template.metadata.annotations | not' +} + +@test "Control Plane StatefulSet: .spec.template global annotations and commonAnnotations can be set" { + template --set 'global.annotations.foo=bar' --set 'commonAnnotations.baz=baa' + assert_query_equal '.spec.template.metadata.annotations.foo' "bar" + assert_query_equal '.spec.template.metadata.annotations.baz' "baa" +} + +@test "Control Plane StatefulSet: .spec.template annotations are added for multus interfaces" { + template --set-json 'interfaces=[{"type": "multus"}]' + assert_multiline_query_equal '.spec.template.metadata.annotations."k8s.v1.cni.cncf.io/networks"' \ + "[\n {\n \"name\": \"release-name-xrd-control-plane-0\"\n }\n]" +} + +@test "Control Plane StatefulSet: .spec.template podAnnotations can be set" { + template --set 'podAnnotations.foo=bar' + assert_query_equal '.spec.template.metadata.annotations.foo' "bar" +} + +@test "Control Plane StatefulSet: podNetworkAnnotations contain the desired information" { + template --set-json 'interfaces=[{"type": "multus", "attachmentConfig": {"foo": "bar"}, "config": {"baz": "baa"}}]' + assert_multiline_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]" +} + +@test "Control Plane StatefulSet: .spec.template recommended labels are set" { + template + assert_query_equal '.spec.template.metadata.labels."app.kubernetes.io/name"' "xrd-control-plane" + assert_query_equal '.spec.template.metadata.labels."app.kubernetes.io/instance"' "release-name" + assert_query_equal '.spec.template.metadata.labels."app.kubernetes.io/managed-by"' "Helm" + assert_query '.spec.template.metadata.labels | has("app.kubernetes.io/version")' + assert_query '.spec.template.metadata.labels | has("helm.sh/chart")' +} + +@test "Control Plane StatefulSet: Global and common labels can be set for .spec.template" { + template --set 'global.labels.foo=bar' --set 'commonLabels.baz=baa' + assert_query_equal '.spec.template.metadata.labels.foo' "bar" + assert_query_equal '.spec.template.metadata.labels.baz' "baa" +} + +@test "Control Plane StatefulSet: podLabels can be added for .spec.template" { + template --set 'podLabels.foo=bar' + assert_query_equal '.spec.template.metadata.labels.foo' "bar" +} + +@test "Control Plane StatefulSet: No hostNetwork by default" { + template + assert_query_equal '.spec.template.spec.hostNetwork' "null" +} + +@test "Control Plane StatefulSet: hostNetwork can be set to true" { + template --set 'hostNetwork=true' + assert_query_equal '.spec.template.spec.hostNetwork' "true" +} + +@test "Control Plane StatefulSet: no volumes by default" { + template + assert_query '.spec.template.spec.volumes | not' +} + +@test "Control Plane StatefulSet: Startup config is added to volumes" { + template --set 'config.username=foo' --set 'config.password=bar' + assert_query_equal '.spec.template.spec.volumes[0].name' "config" +} + +@test "Control Plane StatefulSet: Startup config can be set using username and password" { + template --set 'config.username=foo' --set 'config.password=bar' + assert_query_equal '.spec.template.spec.volumes[0].configMap.name' \ + "release-name-xrd-control-plane-config" + assert_multiline_query_equal '.spec.template.spec.volumes[0].configMap.items' \ + "- key: startup.cfg\n path: startup.cfg" +} + +@test "Control Plane StatefulSet: Startup config can be set using ascii" { + template --set 'config.ascii=foo' + assert_query_equal '.spec.template.spec.volumes[0].configMap.name' \ + "release-name-xrd-control-plane-config" + assert_multiline_query_equal '.spec.template.spec.volumes[0].configMap.items' \ + "- key: startup.cfg\n path: startup.cfg" +} + +@test "Control Plane StatefulSet: Startup script can be set" { + template --set 'config.script=foo' + assert_query_equal '.spec.template.spec.volumes[0].configMap.name' \ + "release-name-xrd-control-plane-config" + assert_multiline_query_equal '.spec.template.spec.volumes[0].configMap.items' \ + "- key: startup.sh\n path: startup.sh\n mode: 0744" +} + +@test "Control Plane StatefulSet: ztpIni can't be set without being enabled" { + template_failure --set 'config.ztpIni=foo' + assert_error_message_contains "ztpIni can only be specified if ztpEnable is set to true" +} + +@test "Control Plane StatefulSet: ztpIni can be set if it is enabled" { + template --set 'config.ztpIni=foo' --set 'config.ztpEnable=true' + assert_query_equal '.spec.template.spec.volumes[0].configMap.name' \ + "release-name-xrd-control-plane-config" + assert_multiline_query_equal '.spec.template.spec.volumes[0].configMap.items' \ + "- key: ztp.ini\n path: ztp.ini" +} + +@test "Control Plane StatefulSet: persistentVolumeClaim can be set" { + template --set 'persistence.enabled=true' --set 'persistence.existingClaim=foo' + assert_query_equal '.spec.template.spec.volumes[0].name' "xr-storage" + assert_query_equal '.spec.template.spec.volumes[0].persistentVolumeClaim.claimName' "foo" +} + +@test "Control Plane StatefulSet: Extra host path mounts can be set" { + template --set-json 'extraHostPathMounts[0]={"name": "foo", "hostPath": "bar"}' + assert_query_equal '.spec.template.spec.volumes[0].name' \ + "release-name-xrd-control-plane-hostmount-foo" + assert_query_equal '.spec.template.spec.volumes[0].hostPath.path' "bar" + assert_query_equal '.spec.template.spec.volumes[0].hostPath.type' "Directory" +} + +@test "Control Plane StatefulSet: Extra host path mounts can be set with create=true" { + template --set-json 'extraHostPathMounts[0]={"name": "foo", "hostPath": "bar", "create": "true"}' + assert_query_equal '.spec.template.spec.volumes[0].name' \ + "release-name-xrd-control-plane-hostmount-foo" + assert_query_equal '.spec.template.spec.volumes[0].hostPath.path' "bar" + assert_query_equal '.spec.template.spec.volumes[0].hostPath.type' "DirectoryOrCreate" +} + +@test "Control Plane StatefulSet: Two extra host path mounts can be set" { + template \ + --set-json 'extraHostPathMounts[0]={"name": "foo", "hostPath": "bar"}' \ + --set-json 'extraHostPathMounts[1]={"name": "baz", "hostPath": "baa"}' + assert_query_equal '.spec.template.spec.volumes[0].name' \ + "release-name-xrd-control-plane-hostmount-foo" + assert_query_equal '.spec.template.spec.volumes[0].hostPath.path' "bar" + assert_query_equal '.spec.template.spec.volumes[0].hostPath.type' "Directory" + assert_query_equal '.spec.template.spec.volumes[1].name' \ + "release-name-xrd-control-plane-hostmount-baz" + assert_query_equal '.spec.template.spec.volumes[1].hostPath.path' "baa" + assert_query_equal '.spec.template.spec.volumes[1].hostPath.type' "Directory" +} + +@test "Control Plane StatefulSet: extraVolumes can be set" { + template --set 'extraVolumes[0].name=foo' + assert_query_equal '.spec.template.spec.volumes[0].name' "foo" +} + +@test "Control Plane: Image repository must be specified" { + template_failure_no_set --set 'image.tag=latest' + assert_error_message_contains "image: repository is required" +} + +@test "Control Plane: Image tag must be specified" { + template_failure_no_set --set 'image.repository=local' + assert_error_message_contains "image: tag is required" +} + +@test "Control Plane StatefulSet: container image is set" { + template + assert_query_equal '.spec.template.spec.containers[0].image' "local:latest" +} + +@test "Control Plane StatefulSet: default container resources are set" { + template + assert_query_equal '.spec.template.spec.containers[0].resources.limits' "{}" + assert_query_equal '.spec.template.spec.containers[0].resources.requests.memory' "2Gi" +} + +@test "Control Plane StatefulSet: container image resources can be set" { + template --set 'resources.requests.foo=bar' --set 'resources.limits.baz=baa' + assert_query_equal '.spec.template.spec.containers[0].resources.requests.memory' "2Gi" + assert_query_equal '.spec.template.spec.containers[0].resources.requests.foo' "bar" + assert_query_equal '.spec.template.spec.containers[0].resources.limits.baz' "baa" +} + +@test "Control Plane StatefulSet: default memory resource request can be overridden" { + template --set 'resources.requests.memory=4Gi' + assert_query_equal '.spec.template.spec.containers[0].resources.limits' "{}" + assert_query_equal '.spec.template.spec.containers[0].resources.requests.memory' "4Gi" +} + +@test "Control Plane StatefulSet: container name is set" { + template + assert_query_equal '.spec.template.spec.containers[0].name' "main" +} + +@test "Control Plane StatefulSet: default container securityContext is set" { + template + assert_query_equal '.spec.template.spec.containers[0].securityContext.privileged' "true" +} + +@test "Control Plane StatefulSet: container securityContext can be set" { + template --set 'securityContext.privileged=false' + assert_query_equal '.spec.template.spec.containers[0].securityContext.privileged' "false" +} + +@test "Control Plane StatefulSet: default container imagePullPolicy is set" { + template + assert_query_equal '.spec.template.spec.containers[0].imagePullPolicy' "Always" +} + +@test "Control Plane StatefulSet: container imagePullPolicy can be set" { + template --set 'image.pullPolicy=IfNotPresent' + assert_query_equal '.spec.template.spec.containers[0].imagePullPolicy' "IfNotPresent" +} + +@test "Control Plane StatefulSet: illegal container imagePullPolicy are rejected" { + template_failure --set 'image.pullPolicy=foo' + assert_error_message_contains \ + "image.pullPolicy must be one of the following: \"Always\", \"IfNotPresent\", \"Never\"" +} + +@test "Control Plane StatefulSet: container tty is set" { + template + assert_query_equal '.spec.template.spec.containers[0].tty' "true" +} + +@test "Control Plane StatefulSet: container stdin is set" { + template + assert_query_equal '.spec.template.spec.containers[0].stdin' "true" +} + +@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" +} + +@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' "" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@test "Control Plane StatefulSet: don't set unsupported flags XR_INTERFACES" { + template_failure --set-json 'interfaces=[{"type": "multus"}, {"type": "defaultCni", "foo": "bar"}]' + assert_error_message_contains "Additional property foo is not allowed" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@test "Control Plane StatefulSet: default container volumeMounts is set" { + template + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[0].mountPath' "/etc/xrd" + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[0].name' "config" + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[0].readOnly' "true" +} + +@test "Control Plane StatefulSet: container volumeMounts for persistence is set if persistence is enabled" { + template --set 'persistence.enabled=true' + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].mountPath' "/xr-storage" + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].name' "xr-storage" +} + +@test "Control Plane StatefulSet: container volumeMounts for extra host path mounts can be set with default mountPath" { + template \ + --set 'extraHostPathMounts[0].name=foo' \ + --set 'extraHostPathMounts[0].hostPath=bar' + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].mountPath' "bar" + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].name' \ + "release-name-xrd-control-plane-hostmount-foo" +} + +@test "Control Plane StatefulSet: container volumeMounts for extra host path mounts can be set with specified mountPath" { + template --set-json 'extraHostPathMounts[0]={"name": "foo", "hostPath": "bar", "mountPath": "baz"}' + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].mountPath' "baz" + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].name' \ + "release-name-xrd-control-plane-hostmount-foo" +} + +@test "Control Plane StatefulSet: extra container volumeMounts can be set" { + template --set-json 'extraVolumeMounts[0]={"mountPath": "foo", "name": "bar"}' + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].mountPath' "foo" + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].name' "bar" +} + +@test "Control Plane StatefulSet: container imagePullSecrets can be set" { + template --set 'image.pullSecrets[0].name=foo' + assert_query_equal '.spec.template.spec.imagePullSecrets[0].name' "foo" +} + +@test "Control Plane StatefulSet: container nodeSelector can be set" { + template --set 'nodeSelector.foo=bar' + assert_query_equal '.spec.template.spec.nodeSelector.foo' "bar" +} + +@test "Control Plane StatefulSet: container affinity can be set" { + template \ + --set 'affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].key=foo' \ + --set 'affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].operator=bar' + assert_query_equal '.spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].key' \ + "foo" + assert_query_equal '.spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].operator' \ + "bar" +} + +@test "Control Plane StatefulSet: container tolerations can be set" { + template --set 'tolerations[0].key=foo' + assert_query_equal '.spec.template.spec.tolerations[0].key' "foo" +} + +@test "Control Plane StatefulSet: default container volumeClaimTemplates is set when persistence is enabled" { + template --set 'persistence.enabled=true' + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.name' "xr-storage" + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.labels."app.kubernetes.io/name"' "xrd-control-plane" + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.labels."app.kubernetes.io/instance"' "release-name" + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.labels."app.kubernetes.io/managed-by"' "Helm" + assert_query_equal '.spec.volumeClaimTemplates[0].spec.accessModes[0]' "ReadWriteOnce" + assert_query_equal '.spec.volumeClaimTemplates[0].spec.resources.requests.storage' "6Gi" +} + +@test "Control Plane StatefulSet: volumeClaimTemplates contains set annotations" { + template --set 'persistence.enabled=true' \ + --set 'global.annotations.foo=bar' \ + --set 'commonAnnotations.baz=baa' \ + --set 'persistence.annotations.qux=quux' + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.annotations.foo' "bar" + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.annotations.baz' "baa" + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.annotations.qux' "quux" +} + +@test "Control Plane StatefulSet: volumeClaimTemplates contains set labels" { + template --set 'persistence.enabled=true' \ + --set 'global.labels.foo=bar' \ + --set 'commonLabels.baz=baa' + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.labels.foo' "bar" + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.labels.baz' "baa" +} + +@test "Control Plane StatefulSet: volumeClaimTemplates accessModes can be set" { + template --set 'persistence.enabled=true' --set 'persistence.accessModes[0]=ReadOnly' + assert_query_equal '.spec.volumeClaimTemplates[0].spec.accessModes[0]' "ReadOnly" +} + +@test "Control Plane StatefulSet: volumeClaimTemplates selector can be set" { + template --set 'persistence.enabled=true' --set 'persistence.selector.matchLabels.release=foo' + assert_query_equal '.spec.volumeClaimTemplates[0].spec.selector.matchLabels.release' "foo" +} + +@test "Control Plane StatefulSet: volumeClaimTemplates contains the set storage size" { + template --set 'persistence.enabled=true' --set 'persistence.size=123kb' + assert_query_equal '.spec.volumeClaimTemplates[0].spec.resources.requests.storage' "123kb" +} + +@test "Control Plane StatefulSet: volumeClaimTemplates existing volume can be set" { + template --set 'persistence.enabled=true' --set 'persistence.existingVolume=foo' + assert_query_equal '.spec.volumeClaimTemplates[0].spec.volumeName' "foo" +} + +@test "Control Plane StatefulSet: volumeClaimTemplates storage class can be set" { + template --set 'persistence.enabled=true' --set 'persistence.storageClass=foo' + assert_query_equal '.spec.volumeClaimTemplates[0].spec.storageClassName' "foo" +} + +@test "Control Plane StatefulSet: volumeClaimTemplates data source can be set" { + template --set 'persistence.enabled=true' \ + --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" +} \ No newline at end of file diff --git a/tests/ut/xrd-vrouter/vrouter_configmap.bats b/tests/ut/xrd-vrouter/vrouter_configmap.bats new file mode 100644 index 00000000..b7a05a31 --- /dev/null +++ b/tests/ut/xrd-vrouter/vrouter_configmap.bats @@ -0,0 +1,91 @@ +#!/usr/bin/env bats + +load "utils.bash" + +export TEMPLATE_UNDER_TEST="templates/config-configmap.yaml" + +setup_file () { + cd "$(vrouter_chart_dir)" || exit + helm dependency update . +} + +@test "vRouter ConfigMap: No ConfigMap is generated if no config is set" { + template_failure + assert_error_message_contains "could not find template templates/config-configmap.yaml in chart" +} + +@test "vRouter ConfigMap: Name consists of the release name and the template name" { + template --set 'config.script=foo' + assert_query_equal '.metadata.name' "release-name-xrd-vrouter-config" +} + +@test "vRouter ConfigMap: Name can be overridden with fullnameOverride" { + template --set 'fullnameOverride=xrd-test' --set 'config.script=foo' + assert_query_equal '.metadata.name' "xrd-test-config" +} + +@test "vRouter ConfigMap: Name can be overridden with nameOverride" { + template --set 'nameOverride=xrd-test' --set 'config.script=foo' + assert_query_equal '.metadata.name' "release-name-xrd-test-config" +} + +@test "vRouter ConfigMap: Namespace is default" { + template --set 'config.script=foo' + assert_query_equal '.metadata.namespace' "default" +} + +@test "vRouter ConfigMap: No annotations are set by default" { + template --set 'config.script=foo' + assert_query '.metadata.annotations | not' +} + +@test "vRouter ConfigMap: Global annotations and commonAnnotations can be added and are correctly merged" { + template \ + --set 'global.annotations.foo=bar' \ + --set 'commonAnnotations.baz=baa' \ + --set 'config.script=foo' + assert_query_equal '.metadata.annotations.foo' "bar" + assert_query_equal '.metadata.annotations.baz' "baa" +} + +@test "vRouter ConfigMap: Recommended labels are set" { + template --set 'config.script=foo' + 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 ConfigMap: Global labels and commonLabels can be added and are correctly merged" { + template --set 'global.labels.foo=bar' --set 'commonLabels.baz=baa' --set 'config.script=foo' + assert_query_equal '.metadata.labels.foo' "bar" + assert_query_equal '.metadata.labels.baz' "baa" +} + +@test "vRouter ConfigMap: Startup config can be set using username and password" { + template --set 'config.username=foo' --set 'config.password=bar' + assert_multiline_query_equal '.data."startup.cfg"' \ + "username foo\n group root-lr\n group cisco-support\n password bar\n!" +} + +@test "vRouter ConfigMap: Startup config can be set using ascii" { + template --set 'config.ascii=foo' + assert_query_equal '.data."startup.cfg"' "foo" +} + +@test "vRouter ConfigMap: Startup script can be set" { + template --set 'config.script=foo' + assert_query_equal '.data."startup.sh"' "foo" +} + +@test "vRouter ConfigMap: ztpIni can't be set without being enabled" { + template_failure --set 'config.ztpIni=foo' + assert_error_message_contains "ztpIni can only be specified if ztpEnable is set to true" +} + +@test "vRouter ConfigMap: ztpIni can be set if it is enabled" { + template --set 'config.ztpIni=foo' --set 'config.ztpEnable=true' + assert_query_equal '.data."ztp.ini"' "foo" +} + diff --git a/tests/ut/xrd-vrouter/vrouter_network-attachments.bats b/tests/ut/xrd-vrouter/vrouter_network-attachments.bats new file mode 100644 index 00000000..c37cb854 --- /dev/null +++ b/tests/ut/xrd-vrouter/vrouter_network-attachments.bats @@ -0,0 +1,125 @@ +#!/usr/bin/env bats + +load "utils.bash" + +export TEMPLATE_UNDER_TEST="templates/network-attachments.yaml" + +setup_file () { + cd "$(vrouter_chart_dir)" || exit + helm dependency update . +} + +@test "vRouter NetworkAttachmentDefinition: 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" { + 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" { + 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" { + template --set-json 'mgmtInterfaces=[{"type": "multus"}]' + assert_query_equal '.metadata.namespace' "default" +} + +@test "vRouter NetworkAttachmentDefinition: 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" { + template \ + --set-json 'mgmtInterfaces=[{"type": "multus"}]' \ + --set 'global.annotations.foo=bar' \ + --set 'commonAnnotations.baz=baa' + assert_query_equal '.metadata.annotations.foo' "bar" + assert_query_equal '.metadata.annotations.baz' "baa" +} + +@test "vRouter NetworkAttachmentDefinition: 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" + 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: Global labels and commonLabels can be added and are correctly merged" { + template \ + --set-json 'mgmtInterfaces=[{"type": "multus"}]' \ + --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: Check default config" { + template --set-json 'mgmtInterfaces=[{"type": "multus"}]' + assert_multiline_query_equal '.spec.config' \ + "{\n \"cniVersion\": \"0.3.1\",\n \"plugins\": [\n null\n ]\n}" +} + +@test "vRouter NetworkAttachmentDefinition: Config can be set" { + template --set-json 'mgmtInterfaces=[{"type": "multus", "config": {"foo": "bar"}}]' + assert_multiline_query_equal '.spec.config' \ + "{\n \"cniVersion\": \"0.3.1\",\n \"plugins\": [\n {\n \"foo\": \"bar\"\n }\n ]\n}" +} + +@test "vRouter NetworkAttachmentDefinition: No interfaces" { + template_failure --set-json 'interfaces=[{"type": "pci"}]' +} + +@test "vRouter NetworkAttachmentDefinition: No custom resource created for defaultCNI" { + 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: Interface cannot be type defaultCNI" { + template_failure --set-json 'interfaces=[{"type": "defaultCni"}]' + assert_error_message_contains "type must be one of the following: \"pci\"" +} + +@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\"" +} + +@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\"" +} + +@test "vRouter NetworkAttachmentDefinition: At most one MGMT interface can bn specified" { + template_failure --set-json 'mgmtInterfaces=[{"type": "multus"}, {"type": "multus"}]' + assert_error_message_contains "Only one management interface can be specified on XRd vRouter" +} + +@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\"" +} + +@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\"" +} + +@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/vrouter_statefulset.bats b/tests/ut/xrd-vrouter/vrouter_statefulset.bats new file mode 100644 index 00000000..b7f9aa86 --- /dev/null +++ b/tests/ut/xrd-vrouter/vrouter_statefulset.bats @@ -0,0 +1,588 @@ +#!/usr/bin/env bats + +load "utils.bash" + +export TEMPLATE_UNDER_TEST="templates/statefulset.yaml" + +setup_file () { + cd "$(vrouter_chart_dir)" || exit + helm dependency update . +} + +@test "vRouter StatefulSet: Name consists of the release name, template name and index" { + template + assert_query_equal '.metadata.name' "release-name-xrd-vrouter" +} + +@test "vRouter StatefulSet: Name can be overridden with fullnameOverride" { + template --set 'fullnameOverride=xrd-test' + assert_query_equal '.metadata.name' "xrd-test" +} + +@test "vRouter StatefulSet: Name can be overridden with nameOverride" { + template --set 'nameOverride=xrd-test' + assert_query_equal '.metadata.name' "release-name-xrd-test" +} + +@test "vRouter StatefulSet: Namespace is default" { + template + assert_query_equal '.metadata.namespace' "default" +} + +@test "vRouter StatefulSet: No annotations are set by default" { + template + assert_query '.metadata.annotations | not' +} + +@test "vRouter StatefulSet: Global annotations and commonAnnotations can be set" { + template --set 'global.annotations.foo=bar' --set 'commonAnnotations.baz=baa' + assert_query_equal '.metadata.annotations.foo' "bar" + assert_query_equal '.metadata.annotations.baz' "baa" +} + +@test "vRouter StatefulSet: Annotations, global annotations and commonAnnotations can be set" { + template \ + --set 'global.annotations.foo=bar' \ + --set 'commonAnnotations.baz=baa' \ + --set 'annotations.qux=quux' + assert_query_equal '.metadata.annotations.foo' "bar" + assert_query_equal '.metadata.annotations.baz' "baa" + assert_query_equal '.metadata.annotations.qux' "quux" +} + +@test "vRouter StatefulSet: Recommended labels are set" { + template + 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 StatefulSet: Global labels and commonLabels can be set" { + template --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 StatefulSet: Labels can be added" { + template --set 'labels.foo=bar' + assert_query_equal '.metadata.labels.foo' "bar" +} + +@test "vRouter StatefulSet: Replicas is one" { + template + assert_query_equal '.spec.replicas' "1" +} + +@test "vRouter StatefulSet: serviceName is the name of the StatefulSet" { + template + assert_fields_equal '.spec.serviceName' '.metadata.name' +} + +@test "vRouter StatefulSet: Selector labels are set" { + template + assert_multiline_query_equal '.spec.selector.matchLabels' \ + "app.kubernetes.io/name: xrd-vrouter\napp.kubernetes.io/instance: release-name" +} + +@test "vRouter StatefulSet: No .spec.template annotations are set by default" { + template + assert_query '.spec.template.metadata.annotations | not' +} + +@test "vRouter StatefulSet: .spec.template global annotations and commonAnnotations can be set" { + template --set 'global.annotations.foo=bar' --set 'commonAnnotations.baz=baa' + assert_query_equal '.spec.template.metadata.annotations.foo' "bar" + assert_query_equal '.spec.template.metadata.annotations.baz' "baa" +} + +@test "vRouter StatefulSet: .spec.template annotations are added for multus interfaces" { + template --set-json 'mgmtInterfaces=[{"type": "multus"}]' + assert_multiline_query_equal '.spec.template.metadata.annotations."k8s.v1.cni.cncf.io/networks"' \ + "[\n {\n \"name\": \"release-name-xrd-vrouter-0\"\n }\n]" +} + +@test "vRouter StatefulSet: .spec.template podAnnotations can be set" { + template --set 'podAnnotations.foo=bar' + assert_query_equal '.spec.template.metadata.annotations.foo' "bar" +} + +@test "vRouter StatefulSet: podNetworkAnnotations contain the desired information" { + template --set-json 'mgmtInterfaces=[{"type": "multus", "attachmentConfig": {"foo": "bar"}}]' + assert_multiline_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]" +} + +@test "vRouter StatefulSet: .spec.template recommended labels are set" { + template + assert_query_equal '.spec.template.metadata.labels."app.kubernetes.io/name"' "xrd-vrouter" + assert_query_equal '.spec.template.metadata.labels."app.kubernetes.io/instance"' "release-name" + assert_query_equal '.spec.template.metadata.labels."app.kubernetes.io/managed-by"' "Helm" + assert_query '.spec.template.metadata.labels | has("app.kubernetes.io/version")' + assert_query '.spec.template.metadata.labels | has("helm.sh/chart")' +} + +@test "vRouter StatefulSet: Global and common labels can be set for .spec.template" { + template --set 'global.labels.foo=bar' --set 'commonLabels.baz=baa' + assert_query_equal '.spec.template.metadata.labels.foo' "bar" + assert_query_equal '.spec.template.metadata.labels.baz' "baa" +} + +@test "vRouter StatefulSet: podLabels can be added for .spec.template" { + template --set 'podLabels.foo=bar' + assert_query_equal '.spec.template.metadata.labels.foo' "bar" +} + +@test "vRouter StatefulSet: No hostNetwork by default" { + template + assert_query_equal '.spec.template.spec.hostNetwork' "null" +} + +@test "vRouter StatefulSet: hostNetwork can be set to true" { + template --set 'hostNetwork=true' + assert_query_equal '.spec.template.spec.hostNetwork' "true" +} + +@test "vRouter StatefulSet: no volumes by default" { + template + assert_query '.spec.template.spec.volumes | not' +} + +@test "vRouter StatefulSet: Startup config is added to volumes" { + template --set 'config.username=foo' --set 'config.password=bar' + assert_query_equal '.spec.template.spec.volumes[0].name' "config" +} + +@test "vRouter StatefulSet: Startup config can be set using username and password" { + template --set 'config.username=foo' --set 'config.password=bar' + assert_query_equal '.spec.template.spec.volumes[0].configMap.name' \ + "release-name-xrd-vrouter-config" + assert_multiline_query_equal '.spec.template.spec.volumes[0].configMap.items' \ + "- key: startup.cfg\n path: startup.cfg" +} + +@test "vRouter StatefulSet: Startup config can be set using ascii" { + template --set 'config.ascii=foo' + assert_query_equal '.spec.template.spec.volumes[0].configMap.name' \ + "release-name-xrd-vrouter-config" + assert_multiline_query_equal '.spec.template.spec.volumes[0].configMap.items' \ + "- key: startup.cfg\n path: startup.cfg" +} + +@test "vRouter StatefulSet: Startup script can be set" { + template --set 'config.script=foo' + assert_query_equal '.spec.template.spec.volumes[0].configMap.name' \ + "release-name-xrd-vrouter-config" + assert_multiline_query_equal '.spec.template.spec.volumes[0].configMap.items' \ + "- key: startup.sh\n path: startup.sh\n mode: 0744" +} + +@test "vRouter StatefulSet: ztpIni can't be set without being enabled" { + template_failure --set 'config.ztpIni=foo' + assert_error_message_contains "ztpIni can only be specified if ztpEnable is set to true" +} + +@test "vRouter StatefulSet: ztpIni can be set if it is enabled" { + template --set 'config.ztpIni=foo' --set 'config.ztpEnable=true' + assert_query_equal '.spec.template.spec.volumes[0].configMap.name' \ + "release-name-xrd-vrouter-config" + assert_multiline_query_equal '.spec.template.spec.volumes[0].configMap.items' \ + "- key: ztp.ini\n path: ztp.ini" +} + +@test "vRouter StatefulSet: persistentVolumeClaim can be set" { + template --set 'persistence.enabled=true' --set 'persistence.existingClaim=foo' + assert_query_equal '.spec.template.spec.volumes[0].name' "xr-storage" + assert_query_equal '.spec.template.spec.volumes[0].persistentVolumeClaim.claimName' "foo" +} + +@test "vRouter StatefulSet: Extra host path mounts can be set" { + template --set-json 'extraHostPathMounts[0]={"name": "foo", "hostPath": "bar"}' + assert_query_equal '.spec.template.spec.volumes[0].name' \ + "release-name-xrd-vrouter-hostmount-foo" + assert_query_equal '.spec.template.spec.volumes[0].hostPath.path' "bar" + assert_query_equal '.spec.template.spec.volumes[0].hostPath.type' "Directory" +} + +@test "vRouter StatefulSet: Extra host path mounts can be set with create=true" { + template --set-json 'extraHostPathMounts[0]={"name": "foo", "hostPath": "bar", "create": "true"}' + assert_query_equal '.spec.template.spec.volumes[0].name' \ + "release-name-xrd-vrouter-hostmount-foo" + assert_query_equal '.spec.template.spec.volumes[0].hostPath.path' "bar" + assert_query_equal '.spec.template.spec.volumes[0].hostPath.type' "DirectoryOrCreate" +} + +@test "vRouter StatefulSet: Two extra host path mounts can be set" { + template \ + --set-json 'extraHostPathMounts[0]={"name": "foo", "hostPath": "bar"}' \ + --set-json 'extraHostPathMounts[1]={"name": "baz", "hostPath": "baa"}' + assert_query_equal '.spec.template.spec.volumes[0].name' \ + "release-name-xrd-vrouter-hostmount-foo" + assert_query_equal '.spec.template.spec.volumes[0].hostPath.path' "bar" + assert_query_equal '.spec.template.spec.volumes[0].hostPath.type' "Directory" + assert_query_equal '.spec.template.spec.volumes[1].name' \ + "release-name-xrd-vrouter-hostmount-baz" + assert_query_equal '.spec.template.spec.volumes[1].hostPath.path' "baa" + assert_query_equal '.spec.template.spec.volumes[1].hostPath.type' "Directory" +} + +@test "vRouter StatefulSet: extraVolumes can be set" { + template --set 'extraVolumes[0].name=foo' + assert_query_equal '.spec.template.spec.volumes[0].name' "foo" +} + +@test "vRouter: Image repository must be specified" { + template_failure_no_set --set 'image.tag=latest' + assert_error_message_contains "image: repository is required" +} + +@test "vRouter: Image tag must be specified" { + template_failure_no_set --set 'image.repository=local' + assert_error_message_contains "image: tag is required" +} + +@test "vRouter StatefulSet: container image is set" { + template + assert_query_equal '.spec.template.spec.containers[0].image' "local:latest" +} + +@test "vRouter StatefulSet: default container resources are set" { + template + assert_query_equal '.spec.template.spec.containers[0].resources.limits.hugepages-1Gi' "3Gi" + assert_query_equal '.spec.template.spec.containers[0].resources.requests.memory' "5Gi" +} + +@test "vRouter StatefulSet: container image resources can be set" { + template --set 'resources.requests.foo=bar' --set 'resources.limits.baz=baa' + assert_query_equal '.spec.template.spec.containers[0].resources.limits.hugepages-1Gi' "3Gi" + assert_query_equal '.spec.template.spec.containers[0].resources.requests.memory' "5Gi" + assert_query_equal '.spec.template.spec.containers[0].resources.requests.foo' "bar" + assert_query_equal '.spec.template.spec.containers[0].resources.limits.baz' "baa" +} + +@test "vRouter StatefulSet: default memory resource request can be overridden" { + template --set 'resources.requests.memory=4Gi' --set 'resources.limits.hugepages-1Gi=6Gi' + assert_query_equal '.spec.template.spec.containers[0].resources.limits.hugepages-1Gi' "6Gi" + assert_query_equal '.spec.template.spec.containers[0].resources.requests.memory' "4Gi" +} + +@test "vRouter StatefulSet: container name is set" { + template + assert_query_equal '.spec.template.spec.containers[0].name' "main" +} + +@test "vRouter StatefulSet: default container securityContext is set" { + template + assert_query_equal '.spec.template.spec.containers[0].securityContext.privileged' "true" +} + +@test "vRouter StatefulSet: container securityContext can be set" { + template --set 'securityContext.privileged=false' + assert_query_equal '.spec.template.spec.containers[0].securityContext.privileged' "false" +} + +@test "vRouter StatefulSet: default container imagePullPolicy is set" { + template + assert_query_equal '.spec.template.spec.containers[0].imagePullPolicy' "Always" +} + +@test "vRouter StatefulSet: container imagePullPolicy can be set" { + template --set 'image.pullPolicy=IfNotPresent' + assert_query_equal '.spec.template.spec.containers[0].imagePullPolicy' "IfNotPresent" +} + +@test "vRouter StatefulSet: illegal container imagePullPolicy are rejected" { + template_failure --set 'image.pullPolicy=foo' + assert_error_message_contains \ + "image.pullPolicy must be one of the following: \"Always\", \"IfNotPresent\", \"Never\"" +} + +@test "vRouter StatefulSet: container tty is set" { + template + assert_query_equal '.spec.template.spec.containers[0].tty' "true" +} + +@test "vRouter StatefulSet: container stdin is set" { + template + assert_query_equal '.spec.template.spec.containers[0].stdin' "true" +} + +@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" +} + +@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' "" +} + +@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" +} + +@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" +} + +@test "vRouter StatefulSet: cpu set container env var can be set" { + template --set 'cpu.cpuset=foo' + assert_query_equal '.spec.template.spec.containers[0].env[3].name' "XR_VROUTER_CPUSET" + assert_query_equal '.spec.template.spec.containers[0].env[3].value' "foo" +} + +@test "vRouter StatefulSet: control plane cpu count container env var can be set" { + template --set 'cpu.controlPlaneCpuCount=10' + assert_query_equal '.spec.template.spec.containers[0].env[3].name' "XR_VROUTER_CP_NUM_CPUS" + assert_query_equal '.spec.template.spec.containers[0].env[3].value' "10" +} + +@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" +} + +@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" +} + +@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" +} + +@test "vRouter StatefulSet: XR_INTERFACES doesn'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: 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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@test "vRouter StatefulSet: don't set unsupported flags XR_MGMT_INTERFACES" { + template_failure --set-json 'mgmtInterfaces=[{"type": "multus", "foo": "bar"}]' + assert_error_message_contains "Additional property foo is not allowed" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@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" +} + +@test "vRouter StatefulSet: default container volumeMounts is set" { + template + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[0].mountPath' "/etc/xrd" + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[0].name' "config" + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[0].readOnly' "true" +} + +@test "vRouter StatefulSet: container volumeMounts for persistence is set if persistence is enabled" { + template --set 'persistence.enabled=true' + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].mountPath' "/xr-storage" + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].name' "xr-storage" +} + +@test "vRouter StatefulSet: container volumeMounts for extra host path mounts can be set with default mountPath" { + template \ + --set 'extraHostPathMounts[0].name=foo' \ + --set 'extraHostPathMounts[0].hostPath=bar' + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].mountPath' "bar" + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].name' \ + "release-name-xrd-vrouter-hostmount-foo" +} + +@test "vRouter StatefulSet: container volumeMounts for extra host path mounts can be set with specified mountPath" { + template --set-json 'extraHostPathMounts[0]={"name": "foo", "hostPath": "bar", "mountPath": "baz"}' + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].mountPath' "baz" + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].name' \ + "release-name-xrd-vrouter-hostmount-foo" +} + +@test "vRouter StatefulSet: extra container volumeMounts can be set" { + template --set-json 'extraVolumeMounts[0]={"mountPath": "foo", "name": "bar"}' + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].mountPath' "foo" + assert_query_equal '.spec.template.spec.containers[0].volumeMounts[1].name' "bar" +} + +@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" +} + +@test "vRouter StatefulSet: container nodeSelector can be set" { + template --set 'nodeSelector.foo=bar' + assert_query_equal '.spec.template.spec.nodeSelector.foo' "bar" +} + +@test "vRouter StatefulSet: container affinity can be set" { + template \ + --set 'affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].key=foo' \ + --set 'affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].operator=bar' + assert_query_equal '.spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].key' \ + "foo" + assert_query_equal '.spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].operator' \ + "bar" +} + +@test "vRouter StatefulSet: container tolerations can be set" { + template --set 'tolerations[0].key=foo' + assert_query_equal '.spec.template.spec.tolerations[0].key' "foo" +} + +@test "vRouter StatefulSet: default container volumeClaimTemplates is set when persistence is enabled" { + template --set 'persistence.enabled=true' + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.name' "xr-storage" + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.labels."app.kubernetes.io/name"' "xrd-vrouter" + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.labels."app.kubernetes.io/instance"' "release-name" + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.labels."app.kubernetes.io/managed-by"' "Helm" + assert_query_equal '.spec.volumeClaimTemplates[0].spec.accessModes[0]' "ReadWriteOnce" + assert_query_equal '.spec.volumeClaimTemplates[0].spec.resources.requests.storage' "6Gi" +} + +@test "vRouter StatefulSet: volumeClaimTemplates contains set annotations" { + template --set 'persistence.enabled=true' \ + --set 'global.annotations.foo=bar' \ + --set 'commonAnnotations.baz=baa' \ + --set 'persistence.annotations.qux=quux' + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.annotations.foo' "bar" + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.annotations.baz' "baa" + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.annotations.qux' "quux" +} + +@test "vRouter StatefulSet: volumeClaimTemplates contains set labels" { + template --set 'persistence.enabled=true' \ + --set 'global.labels.foo=bar' \ + --set 'commonLabels.baz=baa' + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.labels.foo' "bar" + assert_query_equal '.spec.volumeClaimTemplates[0].metadata.labels.baz' "baa" +} + +@test "vRouter StatefulSet: volumeClaimTemplates accessModes can be set" { + template --set 'persistence.enabled=true' --set 'persistence.accessModes[0]=ReadOnly' + assert_query_equal '.spec.volumeClaimTemplates[0].spec.accessModes[0]' "ReadOnly" +} + +@test "vRouter StatefulSet: volumeClaimTemplates selector can be set" { + template --set 'persistence.enabled=true' --set 'persistence.selector.matchLabels.release=foo' + assert_query_equal '.spec.volumeClaimTemplates[0].spec.selector.matchLabels.release' "foo" +} + +@test "vRouter StatefulSet: volumeClaimTemplates contains the set storage size" { + template --set 'persistence.enabled=true' --set 'persistence.size=123kb' + assert_query_equal '.spec.volumeClaimTemplates[0].spec.resources.requests.storage' "123kb" +} + +@test "vRouter StatefulSet: volumeClaimTemplates existing volume can be set" { + template --set 'persistence.enabled=true' --set 'persistence.existingVolume=foo' + assert_query_equal '.spec.volumeClaimTemplates[0].spec.volumeName' "foo" +} + +@test "vRouter StatefulSet: volumeClaimTemplates storage class can be set" { + template --set 'persistence.enabled=true' --set 'persistence.storageClass=foo' + assert_query_equal '.spec.volumeClaimTemplates[0].spec.storageClassName' "foo" +} + +@test "vRouter StatefulSet: volumeClaimTemplates data source can be set" { + template --set 'persistence.enabled=true' \ + --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" +} \ No newline at end of file