diff --git a/library/common-test/tests/externalInterface/metadata_test.yaml b/library/common-test/tests/externalInterface/metadata_test.yaml new file mode 100644 index 0000000000..d548d4254c --- /dev/null +++ b/library/common-test/tests/externalInterface/metadata_test.yaml @@ -0,0 +1,220 @@ +suite: externalInterface metadata test +templates: + - common.yaml +release: + name: release-name +tests: + - it: should generate correct annotations without selector + set: + # Simulate middleware injection + ixExternalInterfacesConfiguration: + - '{"cniVersion": "0.3.1", "name": "ix-release-name-0", "type": "macvlan", "master": "ens3s0", "ipam": {"type": "dhcp"}}' + - '{"cniVersion": "0.3.1", "name": "ix-release-name-0", "type": "macvlan", "master": "ens4s0", "ipam": {"type": "dhcp"}}' + ixExternalInterfacesConfigurationNames: + - ix-release-name-0 + - ix-release-name-1 + scaleExternalInterface: + - hostInterface: enp0s3 + ipam: + type: dhcp + - hostInterface: enp0s4 + ipam: + type: dhcp + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: + containers: + container-name1: + enabled: true + primary: true + imageSelector: image + workload-name2: + enabled: true + primary: false + type: StatefulSet + podSpec: + containers: + container-name1: + enabled: true + primary: true + imageSelector: image + asserts: + - documentIndex: &deploymentDoc 2 + isKind: + of: Deployment + - documentIndex: *deploymentDoc + isAPIVersion: + of: apps/v1 + - documentIndex: *deploymentDoc + equal: + path: metadata.name + value: release-name-common-test + - documentIndex: *deploymentDoc + isSubset: + path: spec.template.metadata.annotations + content: + k8s.v1.cni.cncf.io/networks: ix-release-name-0, ix-release-name-1 + - documentIndex: &statefulSetDoc 3 + isKind: + of: StatefulSet + - documentIndex: *statefulSetDoc + isAPIVersion: + of: apps/v1 + - documentIndex: *statefulSetDoc + equal: + path: metadata.name + value: release-name-common-test-workload-name2 + - documentIndex: *statefulSetDoc + isNotSubset: + path: spec.template.metadata.annotations + content: + k8s.v1.cni.cncf.io/networks: ix-release-name-0, ix-release-name-1 + + - it: should generate correct annotations with targetSelectAll + set: + # Simulate middleware injection + ixExternalInterfacesConfiguration: + - '{"cniVersion": "0.3.1", "name": "ix-release-name-0", "type": "macvlan", "master": "ens3s0", "ipam": {"type": "dhcp"}}' + - '{"cniVersion": "0.3.1", "name": "ix-release-name-0", "type": "macvlan", "master": "ens4s0", "ipam": {"type": "dhcp"}}' + ixExternalInterfacesConfigurationNames: + - ix-release-name-0 + - ix-release-name-1 + scaleExternalInterface: + - hostInterface: enp0s3 + ipam: + type: dhcp + targetSelectAll: true + - hostInterface: enp0s4 + ipam: + type: dhcp + targetSelectAll: true + workload: + workload-name1: + enabled: true + primary: true + type: DaemonSet + podSpec: + containers: + container-name1: + enabled: true + primary: true + imageSelector: image + workload-name2: + enabled: true + primary: false + type: Job + podSpec: + containers: + container-name1: + enabled: true + primary: true + imageSelector: image + asserts: + - documentIndex: &daemonSetDoc 2 + isKind: + of: DaemonSet + - documentIndex: *daemonSetDoc + isAPIVersion: + of: apps/v1 + - documentIndex: *daemonSetDoc + equal: + path: metadata.name + value: release-name-common-test + - documentIndex: *daemonSetDoc + isSubset: + path: spec.template.metadata.annotations + content: + k8s.v1.cni.cncf.io/networks: ix-release-name-0, ix-release-name-1 + - documentIndex: &jobDoc 3 + isKind: + of: Job + - documentIndex: *jobDoc + isAPIVersion: + of: batch/v1 + - documentIndex: *jobDoc + equal: + path: metadata.name + value: release-name-common-test-workload-name2 + - documentIndex: *jobDoc + isSubset: + path: spec.template.metadata.annotations + content: + k8s.v1.cni.cncf.io/networks: ix-release-name-0, ix-release-name-1 + + - it: should generate correct annotations with targetSelector + set: + # Simulate middleware injection + ixExternalInterfacesConfiguration: + - '{"cniVersion": "0.3.1", "name": "ix-release-name-0", "type": "macvlan", "master": "ens3s0", "ipam": {"type": "dhcp"}}' + - '{"cniVersion": "0.3.1", "name": "ix-release-name-0", "type": "macvlan", "master": "ens4s0", "ipam": {"type": "dhcp"}}' + ixExternalInterfacesConfigurationNames: + - ix-release-name-0 + - ix-release-name-1 + scaleExternalInterface: + - hostInterface: enp0s3 + ipam: + type: dhcp + targetSelector: + - workload-name1 + - workload-name2 + - hostInterface: enp0s4 + ipam: + type: dhcp + targetSelector: + - workload-name1 + workload: + workload-name1: + enabled: true + primary: true + type: DaemonSet + podSpec: + containers: + container-name1: + enabled: true + primary: true + imageSelector: image + workload-name2: + enabled: true + primary: false + type: CronJob + schedule: "*/1 * * * *" + podSpec: + containers: + container-name1: + enabled: true + primary: true + imageSelector: image + asserts: + - documentIndex: &daemonSetDoc 2 + isKind: + of: DaemonSet + - documentIndex: *daemonSetDoc + isAPIVersion: + of: apps/v1 + - documentIndex: *daemonSetDoc + equal: + path: metadata.name + value: release-name-common-test + - documentIndex: *daemonSetDoc + isSubset: + path: spec.template.metadata.annotations + content: + k8s.v1.cni.cncf.io/networks: ix-release-name-0, ix-release-name-1 + - documentIndex: &cronJobDoc 3 + isKind: + of: CronJob + - documentIndex: *cronJobDoc + isAPIVersion: + of: batch/v1 + - documentIndex: *cronJobDoc + equal: + path: metadata.name + value: release-name-common-test-workload-name2 + - documentIndex: *cronJobDoc + isSubset: + path: spec.jobTemplate.spec.template.metadata.annotations + content: + k8s.v1.cni.cncf.io/networks: ix-release-name-0 diff --git a/library/common-test/tests/externalInterface/name_test.yaml b/library/common-test/tests/externalInterface/name_test.yaml new file mode 100644 index 0000000000..e6a39b9ec7 --- /dev/null +++ b/library/common-test/tests/externalInterface/name_test.yaml @@ -0,0 +1,43 @@ +suite: externalInterface name test +templates: + - common.yaml +release: + name: release-name +tests: + - it: should generate correct name NetworkAttachmentDefinition + set: + # Simulate middleware injection + ixExternalInterfacesConfiguration: + - '{"cniVersion": "0.3.1", "name": "ix-release-name-0", "type": "macvlan", "master": "ens3s0", "ipam": {"type": "dhcp"}}' + - '{"cniVersion": "0.3.1", "name": "ix-release-name-0", "type": "macvlan", "master": "ens4s0", "ipam": {"type": "dhcp"}}' + ixExternalInterfacesConfigurationNames: + - ix-release-name-0 + - ix-release-name-1 + scaleExternalInterface: + - hostInterface: enp0s3 + ipam: + type: dhcp + - hostInterface: enp0s4 + ipam: + type: dhcp + asserts: + - documentIndex: &networkDoc 0 + isKind: + of: NetworkAttachmentDefinition + - documentIndex: *networkDoc + isAPIVersion: + of: k8s.cni.cncf.io/v1 + - documentIndex: *networkDoc + equal: + path: metadata.name + value: ix-release-name-0 + - documentIndex: &otherNetworkDoc 1 + isKind: + of: NetworkAttachmentDefinition + - documentIndex: *otherNetworkDoc + isAPIVersion: + of: k8s.cni.cncf.io/v1 + - documentIndex: *otherNetworkDoc + equal: + path: metadata.name + value: ix-release-name-1 diff --git a/library/common-test/tests/externalInterface/validation_test.yaml b/library/common-test/tests/externalInterface/validation_test.yaml index fdc0f39935..0ebaaae149 100644 --- a/library/common-test/tests/externalInterface/validation_test.yaml +++ b/library/common-test/tests/externalInterface/validation_test.yaml @@ -1,6 +1,8 @@ suite: external interface validation test templates: - common.yaml +release: + name: release-name tests: - it: should fail with targetSelector not a list set: @@ -112,3 +114,24 @@ tests: asserts: - failedTemplate: errorMessage: External Interface - Expected non-empty in + + - it: should fail with empty ixExternalInterfaceConfigurationNames when interface is defined + set: + # Simulate middleware injection + ixExternalInterfacesConfiguration: + - '{"cniVersion": "0.3.1", "name": "ix-release-name-0", "type": "macvlan", "master": "ens3s0", "ipam": {"type": "dhcp"}}' + ixExternalInterfaceConfigurationNames: [] + scaleExternalInterface: + - hostInterface: enp0s3 + ipam: + type: dhcp + workload: + workload-name1: + enabled: true + primary: true + type: CronJob + schedule: "*/1 * * * *" + podSpec: {} + asserts: + - failedTemplate: + errorMessage: External Interface - Expected non empty diff --git a/library/common/1.0.0/README.md b/library/common/1.0.0/README.md index e8f72c9553..102c2556c4 100644 --- a/library/common/1.0.0/README.md +++ b/library/common/1.0.0/README.md @@ -17,6 +17,7 @@ - Containers: `$ContainerName` - ConfigMap: `$FullName-$ConfigMapName` - Secret: `$FullName-$SecretName` +- Scale External Interface: `ix-$ReleaseName-$index` > Full name -> `$ReleaseName-$ChartName` > Any name that exceeds 63 characters, will throw an error diff --git a/library/common/1.0.0/docs/scaleExternalInterface.md b/library/common/1.0.0/docs/scaleExternalInterface.md new file mode 100644 index 0000000000..17a4abdce1 --- /dev/null +++ b/library/common/1.0.0/docs/scaleExternalInterface.md @@ -0,0 +1,47 @@ +# Scale External Interface + +| Key | Type | Required | Helm Template | Default | Description | +| :------------------------------------------------ | :-------: | :-----------------------------: | :-----------: | :-----: | :------------------------------------------------------------------------------ | +| scaleExternalInterface | `list` | ❌ | ❌ | `[]` | Define the external interfaces as list | +| scaleExternalInterface.targetSelectAll | `boolean` | ❌ | ❌ | `false` | Whether to add the annotation for this external interface to all workloads | +| scaleExternalInterface.targetSelector | `list` | ❌ | ❌ | `[]` | Which workloads to add the annotations | +| scaleExternalInterface.hostInterface | `string` | ✅ | ❌ | `""` | Define the hostInterface, (options in GUI populated from Middleware references) | +| scaleExternalInterface.ipam | `dict` | ✅ | ❌ | `{}` | Define the ipam | +| scaleExternalInterface.ipam.type | `string` | ✅ | ❌ | `""` | Define the ipam type (dchp, static) | +| scaleExternalInterface.staticIPConfiguration | `list` | ✅ (Only when static ipam type) | ❌ | `[]` | Define static IP Configuration (Only with static ipam type) | +| scaleExternalInterface.staticIPConfiguration.[IP] | `string` | ✅ | ❌ | `""` | Define the static IP (Only with static ipam type) | +| scaleExternalInterface.staticRoutes | `list` | ❌ | ❌ | `[]` | Define static routes (Only with static ipam type) | +| scaleExternalInterface.staticRoutes.destination | `string` | ✅ | ❌ | `""` | Define the static destination (Only with static ipam type) | +| scaleExternalInterface.staticRoutes.gateway | `string` | ✅ | ❌ | `""` | Define the static gateway (Only with static ipam type) | + +> When `targetSelectAll` is `true`, it will add the annotations to all pods (`targetSelector` is ignored in this case) +> When `targetSelector` is a list, each entry is a string, referencing the pod(s) name that will add the annotations +> When `targetSelector` is a empty, it will add the annotations to the primary pod + +--- + +Appears in: + +- `.Values.scaleExternalInterface` + +--- + +Naming scheme: + +- `ix-$ReleaseName-$index` (ix-release-name-0) + +--- + +Examples: + +```yaml +scaleExternalInterface: + - hostInterface: "" + ipam: + type: "" + staticRoutes: [] + staticIPConfigurations: [] + # targetSelectAll: false + targetSelector: + - workload-name +``` diff --git a/library/common/1.0.0/templates/class/_networkAttachmentDefinition.tpl b/library/common/1.0.0/templates/class/_networkAttachmentDefinition.tpl new file mode 100644 index 0000000000..8f6efae131 --- /dev/null +++ b/library/common/1.0.0/templates/class/_networkAttachmentDefinition.tpl @@ -0,0 +1,34 @@ +{{/* Network Attachment Definition Class */}} +{{/* Call this template: +{{ include "ix.v1.common.class.networkAttachmentDefinition" (dict "rootCtx" $ "objectData" $objectData) }} + +rootCtx: The root context of the template. It is used to access the global context. +objectData: + name: The name of the Network Attachment Definition. + labels: The labels of the Network Attachment Definition. + annotations: The annotations of the Network Attachment Definition. + config: The config of the interface +*/}} + +{{- define "ix.v1.common.class.networkAttachmentDefinition" -}} + + {{- $rootCtx := .rootCtx -}} + {{- $objectData := .objectData }} +--- +apiVersion: k8s.cni.cncf.io/v1 +kind: NetworkAttachmentDefinition +metadata: + name: {{ $objectData.name }} + {{- $labels := (include "ix.v1.common.lib.metadata.allLabels" $rootCtx | fromYaml) | default dict -}} + {{- with (include "ix.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "labels" $labels) | trim) }} + labels: + {{- . | nindent 4 }} + {{- end -}} + {{- $annotations := (include "ix.v1.common.lib.metadata.allAnnotations" $rootCtx | fromYaml) | default dict -}} + {{- with (include "ix.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "annotations" $annotations) | trim) }} + annotations: + {{- . | nindent 4 }} + {{- end }} +spec: + config: {{ $objectData.config | squote }} +{{- end -}} diff --git a/library/common/1.0.0/templates/lib/metadata/_externalInterfaceAnnotations.tpl b/library/common/1.0.0/templates/lib/metadata/_externalInterfaceAnnotations.tpl new file mode 100644 index 0000000000..62ce550714 --- /dev/null +++ b/library/common/1.0.0/templates/lib/metadata/_externalInterfaceAnnotations.tpl @@ -0,0 +1,52 @@ + + +{{/* External Interface Annotations that are added to podSpec */}} +{{/* Call this template: +{{ include "ix.v1.common.lib.metadata.externalInterfacePodAnnotations" (dict "rootCtx" $ "podShortName" $podShortName) }} +rootCtx is the root context of the chart +objectData is object containing the data of the pod +*/}} +{{- define "ix.v1.common.lib.metadata.externalInterfacePodAnnotations" -}} + {{- $objectData := .objectData -}} + {{- $rootCtx := .rootCtx -}} + + {{- $ifaceIndexes := list -}} + + {{- range $index, $iface := $rootCtx.Values.scaleExternalInterface -}} + {{/* If targetSelectAll is set append the index */}} + {{- if .targetSelectAll -}} + {{- $ifaceIndexes = mustAppend $ifaceIndexes $index -}} + {{/* Else If targetSelector is set and pod is selected append the index */}} + {{- else if and .targetSelector (mustHas $objectData.shortName .targetSelector) -}} + {{- $ifaceIndexes = mustAppend $ifaceIndexes $index -}} + {{/* Else If none of the above, but pod is primary append the index */}} + {{- else if $objectData.primary -}} + {{- $ifaceIndexes = mustAppend $ifaceIndexes $index -}} + {{- end -}} + {{- end -}} + + {{- $ifaceNames := list -}} + {{- if $rootCtx.Values.ixExternalInterfacesConfiguration -}} + {{- with $rootCtx.Values.ixExternalInterfacesConfigurationNames -}} + {{- range $ifaceName := . -}} + {{/* Get the index by splitting the iFaceName (ix-RELEASE-NAME-0) */}} + {{- $index := splitList "-" $ifaceName -}} + {{/* And pick the last item on the list */}} + {{- $index = mustLast $index -}} + + {{/* If the index is in the list of indexes to be added, append the name */}} + {{- if mustHas (int $index) $ifaceIndexes -}} + {{- $ifaceNames = mustAppend $ifaceNames $ifaceName -}} + {{- end -}} + + {{- end -}} + {{- else -}} + {{- fail "External Interface - Expected non empty " -}} + {{- end -}} + {{- end -}} + + {{/* If we have ifaceNames, then add the annotations to the pod calling this template */}} + {{- if $ifaceNames }} +k8s.v1.cni.cncf.io/networks: {{ join ", " $ifaceNames }} + {{- end -}} +{{- end -}} diff --git a/library/common/1.0.0/templates/spawner/_externalInterface.tpl b/library/common/1.0.0/templates/spawner/_externalInterface.tpl new file mode 100644 index 0000000000..19ce301787 --- /dev/null +++ b/library/common/1.0.0/templates/spawner/_externalInterface.tpl @@ -0,0 +1,32 @@ +{{/* External Interface Spawwner */}} +{{/* Call this template: +{{ include "ix.v1.common.spawner.externalInterface" $ -}} +*/}} + +{{- define "ix.v1.common.spawner.externalInterface" -}} + + {{- range $iface := .Values.scaleExternalInterface -}} + {{- include "ix.v1.common.lib.externalInterface.validation" (dict "objectData" $iface) -}} + {{- end -}} + + {{/* Now we have validated interfaces, render the objects */}} + + {{- range $index, $interface := .Values.ixExternalInterfacesConfiguration -}} + + {{- $objectData := dict -}} + {{/* Create a copy of the interface and put it in objectData.config */}} + {{- $_ := set $objectData "config" (mustDeepCopy $interface) -}} + + {{- $objectName := (printf "ix-%s-%v" $.Release.Name $index) -}} + {{/* Perform validations */}} + {{- include "ix.v1.common.lib.chart.names.validation" (dict "name" $objectName) -}} + + {{/* Set the name of the object to objectData.name */}} + {{- $_ := set $objectData "name" $objectName -}} + + {{/* Call class to create the object */}} + {{- include "ix.v1.common.class.networkAttachmentDefinition" (dict "rootCtx" $ "objectData" $objectData) -}} + + {{- end -}} + +{{- end -}} diff --git a/library/common/1.0.0/values.yaml b/library/common/1.0.0/values.yaml index 5c67948ebc..f6cb76b577 100644 --- a/library/common/1.0.0/values.yaml +++ b/library/common/1.0.0/values.yaml @@ -1,3 +1,4 @@ +# TODO: Docs # -- Global values global: # -- Set additional global labels @@ -11,6 +12,7 @@ global: # -- Minimum nodePort value minNodePort: 9000 +# TODO: Docs fallbackDefaults: # -- Define a storageClassName that will be used for all PVCs # Can be overruled per PVC @@ -42,6 +44,7 @@ ixCertificates: [] # Only for reference here ixVolumes: [] +# TODO: Docs # -- Image values image: # -- Image repository @@ -51,8 +54,9 @@ image: # -- Image pull policy pullPolicy: IfNotPresent +# TODO: Docs TZ: UTC - +# TODO: Docs # -- Security Context securityContext: # -- Container security context for all containers @@ -78,6 +82,7 @@ securityContext: supplementalGroups: [] sysctls: [] +# TODO: Docs containerOptions: # -- Resources # Can be overruled per container @@ -97,7 +102,7 @@ containerOptions: NVIDIA_CAPS: - all -# -- Options for all pods +# -- Options for all pods # TODO: Docs # Can be overruled per pod podOptions: enableServiceLinks: false @@ -288,19 +293,11 @@ scaleGPU: pod-name: - container-name -# -- SCALE External Interfaces -scaleExternalInterfaces: - - hostInterface: "" - ipam: - type: "" - staticRoutes: [] - staticIPConfigurations: [] - # targetSelector: all - targetSelector: - - pod-name +# -- (docs/scaleExternalInterface.md) +scaleExternalInterface: [] -# -- SCALE Certificates -scaleCerts: +# -- SCALE Certificate +scaleCert: # -- Certificate name cert-name: # -- Enables the certificate @@ -320,8 +317,8 @@ scaleCerts: certPath: "" keyPath: "" -# -- Devices -devices: +# -- Device +device: # -- Device name device-name: # -- Enables the device