diff --git a/baremetal-operator-image/Dockerfile b/baremetal-operator-image/Dockerfile
new file mode 100644
index 0000000..6b45179
--- /dev/null
+++ b/baremetal-operator-image/Dockerfile
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: Apache-2.0
+#!BuildTag: %%IMG_PREFIX%%baremetal-operator:%%baremetal-operator_version%%
+#!BuildTag: %%IMG_PREFIX%%baremetal-operator:%%baremetal-operator_version%%-%RELEASE%
+#!BuildVersion: 15.6
+ARG SLE_VERSION
+FROM registry.suse.com/bci/bci-micro:$SLE_VERSION AS micro
+
+FROM registry.suse.com/bci/bci-base:$SLE_VERSION AS base
+COPY --from=micro / /installroot/
+RUN zypper --installroot /installroot --non-interactive install --no-recommends baremetal-operator iproute2 bind-utils vim shadow; zypper -n clean; rm -rf /var/log/*
+
+FROM micro AS final
+# Define labels according to https://en.opensuse.org/Building_derived_containers
+# labelprefix=com.suse.application.baremetal-operator
+LABEL org.opencontainers.image.authors="SUSE LLC (https://www.suse.com/)"
+LABEL org.opencontainers.image.title="SLE baremetal-operator Container Image"
+LABEL org.opencontainers.image.description="baremetal-operator based on the SLE Base Container Image."
+LABEL org.opencontainers.image.version="%%baremetal-operator_version%%"
+LABEL org.opencontainers.image.url="https://www.suse.com/products/server/"
+LABEL org.opencontainers.image.created="%BUILDTIME%"
+LABEL org.opencontainers.image.vendor="SUSE LLC"
+LABEL org.opensuse.reference="%%IMG_REPO%%/%%IMG_PREFIX%%baremetal-operator:%%baremetal-operator_version%%-%RELEASE%"
+LABEL org.openbuildservice.disturl="%DISTURL%"
+LABEL com.suse.supportlevel="l3"
+LABEL com.suse.eula="SUSE Combined EULA February 2024"
+LABEL com.suse.lifecycle-url="https://www.suse.com/lifecycle"
+LABEL com.suse.image-type="application"
+LABEL com.suse.release-stage="released"
+# endlabelprefix
+
+COPY --from=base /installroot /
+RUN groupadd -r -g 11000 bmo
+RUN useradd -u 11000 -g 11000 bmo
+ENTRYPOINT [ "/usr/bin/baremetal-operator" ]
diff --git a/baremetal-operator-image/_service b/baremetal-operator-image/_service
new file mode 100644
index 0000000..88c8e8c
--- /dev/null
+++ b/baremetal-operator-image/_service
@@ -0,0 +1,17 @@
+
+
+
+
+ Dockerfile
+ %%baremetal-operator_version%%
+ baremetal-operator
+ patch
+
+
+ Dockerfile
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+
diff --git a/cdi-chart/Chart.yaml b/cdi-chart/Chart.yaml
new file mode 100644
index 0000000..641cfc7
--- /dev/null
+++ b/cdi-chart/Chart.yaml
@@ -0,0 +1,9 @@
+#!BuildTag: %%IMG_PREFIX%%cdi-chart:0.4.0
+#!BuildTag: %%IMG_PREFIX%%cdi-chart:0.4.0-%RELEASE%
+apiVersion: v2
+appVersion: 1.60.1
+description: A Helm chart for Containerized Data Importer (CDI)
+icon: https://raw.githubusercontent.com/cncf/artwork/main/projects/kubevirt/icon/color/kubevirt-icon-color.svg
+name: cdi
+type: application
+version: 0.4.0
diff --git a/cdi-chart/_service b/cdi-chart/_service
new file mode 100644
index 0000000..6b8f891
--- /dev/null
+++ b/cdi-chart/_service
@@ -0,0 +1,8 @@
+
+
+
+ Chart.yaml
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+
+
diff --git a/cdi-chart/crds/cdi.yaml b/cdi-chart/crds/cdi.yaml
new file mode 100644
index 0000000..8621e0f
--- /dev/null
+++ b/cdi-chart/crds/cdi.yaml
@@ -0,0 +1,5082 @@
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: cdis.cdi.kubevirt.io
+spec:
+ group: cdi.kubevirt.io
+ names:
+ kind: CDI
+ listKind: CDIList
+ plural: cdis
+ shortNames:
+ - cdi
+ - cdis
+ singular: cdi
+ scope: Cluster
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ - jsonPath: .status.phase
+ name: Phase
+ type: string
+ name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: CDI is the CDI Operator CRD
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: CDISpec defines our specification for the CDI installation
+ properties:
+ certConfig:
+ description: certificate configuration
+ properties:
+ ca:
+ description: |-
+ CA configuration
+ CA certs are kept in the CA bundle as long as they are valid
+ properties:
+ duration:
+ description: The requested 'duration' (i.e. lifetime) of the
+ Certificate.
+ type: string
+ renewBefore:
+ description: |-
+ The amount of time before the currently issued certificate's `notAfter`
+ time that we will begin to attempt to renew the certificate.
+ type: string
+ type: object
+ client:
+ description: |-
+ Client configuration
+ Certs are rotated and discarded
+ properties:
+ duration:
+ description: The requested 'duration' (i.e. lifetime) of the
+ Certificate.
+ type: string
+ renewBefore:
+ description: |-
+ The amount of time before the currently issued certificate's `notAfter`
+ time that we will begin to attempt to renew the certificate.
+ type: string
+ type: object
+ server:
+ description: |-
+ Server configuration
+ Certs are rotated and discarded
+ properties:
+ duration:
+ description: The requested 'duration' (i.e. lifetime) of the
+ Certificate.
+ type: string
+ renewBefore:
+ description: |-
+ The amount of time before the currently issued certificate's `notAfter`
+ time that we will begin to attempt to renew the certificate.
+ type: string
+ type: object
+ type: object
+ cloneStrategyOverride:
+ description: 'Clone strategy override: should we use a host-assisted
+ copy even if snapshots are available?'
+ enum:
+ - copy
+ - snapshot
+ - csi-clone
+ type: string
+ config:
+ description: CDIConfig at CDI level
+ properties:
+ dataVolumeTTLSeconds:
+ description: DataVolumeTTLSeconds is the time in seconds after
+ DataVolume completion it can be garbage collected. Disabled
+ by default.
+ format: int32
+ type: integer
+ featureGates:
+ description: FeatureGates are a list of specific enabled feature
+ gates
+ items:
+ type: string
+ type: array
+ filesystemOverhead:
+ description: FilesystemOverhead describes the space reserved for
+ overhead when using Filesystem volumes. A value is between 0
+ and 1, if not defined it is 0.055 (5.5% overhead)
+ properties:
+ global:
+ description: Global is how much space of a Filesystem volume
+ should be reserved for overhead. This value is used unless
+ overridden by a more specific value (per storageClass)
+ pattern: ^(0(?:\.\d{1,3})?|1)$
+ type: string
+ storageClass:
+ additionalProperties:
+ description: |-
+ Percent is a string that can only be a value between [0,1)
+ (Note: we actually rely on reconcile to reject invalid values)
+ pattern: ^(0(?:\.\d{1,3})?|1)$
+ type: string
+ description: StorageClass specifies how much space of a Filesystem
+ volume should be reserved for safety. The keys are the storageClass
+ and the values are the overhead. This value overrides the
+ global value
+ type: object
+ type: object
+ imagePullSecrets:
+ description: The imagePullSecrets used to pull the container images
+ items:
+ description: |-
+ LocalObjectReference contains enough information to let you locate the
+ referenced object inside the same namespace.
+ properties:
+ name:
+ default: ""
+ description: |-
+ Name of the referent.
+ This field is effectively required, but due to backwards compatibility is
+ allowed to be empty. Instances of this type with an empty value here are
+ almost certainly wrong.
+ TODO: Add other useful fields. apiVersion, kind, uid?
+ More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
+ TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
+ type: string
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ importProxy:
+ description: ImportProxy contains importer pod proxy configuration.
+ properties:
+ HTTPProxy:
+ description: HTTPProxy is the URL http://:@:
+ of the import proxy for HTTP requests. Empty means unset
+ and will not result in the import pod env var.
+ type: string
+ HTTPSProxy:
+ description: HTTPSProxy is the URL https://:@:
+ of the import proxy for HTTPS requests. Empty means unset
+ and will not result in the import pod env var.
+ type: string
+ noProxy:
+ description: NoProxy is a comma-separated list of hostnames
+ and/or CIDRs for which the proxy should not be used. Empty
+ means unset and will not result in the import pod env var.
+ type: string
+ trustedCAProxy:
+ description: "TrustedCAProxy is the name of a ConfigMap in
+ the cdi namespace that contains a user-provided trusted
+ certificate authority (CA) bundle.\nThe TrustedCAProxy ConfigMap
+ is consumed by the DataImportCron controller for creating
+ cronjobs, and by the import controller referring a copy
+ of the ConfigMap in the import namespace.\nHere is an example
+ of the ConfigMap (in yaml):\n\n\napiVersion: v1\nkind: ConfigMap\nmetadata:\n
+ \ name: my-ca-proxy-cm\n namespace: cdi\ndata:\n ca.pem:
+ |\n -----BEGIN CERTIFICATE-----\n\t ... ...\n\t -----END CERTIFICATE-----"
+ type: string
+ type: object
+ insecureRegistries:
+ description: InsecureRegistries is a list of TLS disabled registries
+ items:
+ type: string
+ type: array
+ logVerbosity:
+ description: LogVerbosity overrides the default verbosity level
+ used to initialize loggers
+ format: int32
+ type: integer
+ podResourceRequirements:
+ description: ResourceRequirements describes the compute resource
+ requirements.
+ properties:
+ claims:
+ description: |-
+ Claims lists the names of resources, defined in spec.resourceClaims,
+ that are used by this container.
+
+
+ This is an alpha field and requires enabling the
+ DynamicResourceAllocation feature gate.
+
+
+ This field is immutable. It can only be set for containers.
+ items:
+ description: ResourceClaim references one entry in PodSpec.ResourceClaims.
+ properties:
+ name:
+ description: |-
+ Name must match the name of one entry in pod.spec.resourceClaims of
+ the Pod where this field is used. It makes that resource available
+ inside a container.
+ type: string
+ required:
+ - name
+ type: object
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ limits:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ description: |-
+ Limits describes the maximum amount of compute resources allowed.
+ More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
+ type: object
+ requests:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ description: |-
+ Requests describes the minimum amount of compute resources required.
+ If Requests is omitted for a container, it defaults to Limits if that is explicitly specified,
+ otherwise to an implementation-defined value. Requests cannot exceed Limits.
+ More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
+ type: object
+ type: object
+ preallocation:
+ description: Preallocation controls whether storage for DataVolumes
+ should be allocated in advance.
+ type: boolean
+ scratchSpaceStorageClass:
+ description: 'Override the storage class to used for scratch space
+ during transfer operations. The scratch space storage class
+ is determined in the following order: 1. value of scratchSpaceStorageClass,
+ if that doesn''t exist, use the default storage class, if there
+ is no default storage class, use the storage class of the DataVolume,
+ if no storage class specified, use no storage class for scratch
+ space'
+ type: string
+ tlsSecurityProfile:
+ description: TLSSecurityProfile is used by operators to apply
+ cluster-wide TLS security settings to operands.
+ properties:
+ custom:
+ description: |-
+ custom is a user-defined TLS security profile. Be extremely careful using a custom
+ profile as invalid configurations can be catastrophic. An example custom profile
+ looks like this:
+
+
+ ciphers:
+ - ECDHE-ECDSA-CHACHA20-POLY1305
+ - ECDHE-RSA-CHACHA20-POLY1305
+ - ECDHE-RSA-AES128-GCM-SHA256
+ - ECDHE-ECDSA-AES128-GCM-SHA256
+ minTLSVersion: VersionTLS11
+ nullable: true
+ properties:
+ ciphers:
+ description: |-
+ ciphers is used to specify the cipher algorithms that are negotiated
+ during the TLS handshake. Operators may remove entries their operands
+ do not support. For example, to use DES-CBC3-SHA (yaml):
+
+
+ ciphers:
+ - DES-CBC3-SHA
+ items:
+ type: string
+ type: array
+ minTLSVersion:
+ description: |-
+ minTLSVersion is used to specify the minimal version of the TLS protocol
+ that is negotiated during the TLS handshake. For example, to use TLS
+ versions 1.1, 1.2 and 1.3 (yaml):
+
+
+ minTLSVersion: VersionTLS11
+
+
+ NOTE: currently the highest minTLSVersion allowed is VersionTLS12
+ enum:
+ - VersionTLS10
+ - VersionTLS11
+ - VersionTLS12
+ - VersionTLS13
+ type: string
+ required:
+ - ciphers
+ - minTLSVersion
+ type: object
+ intermediate:
+ description: |-
+ intermediate is a TLS security profile based on:
+
+
+ https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29
+
+
+ and looks like this (yaml):
+
+
+ ciphers:
+ - TLS_AES_128_GCM_SHA256
+ - TLS_AES_256_GCM_SHA384
+ - TLS_CHACHA20_POLY1305_SHA256
+ - ECDHE-ECDSA-AES128-GCM-SHA256
+ - ECDHE-RSA-AES128-GCM-SHA256
+ - ECDHE-ECDSA-AES256-GCM-SHA384
+ - ECDHE-RSA-AES256-GCM-SHA384
+ - ECDHE-ECDSA-CHACHA20-POLY1305
+ - ECDHE-RSA-CHACHA20-POLY1305
+ - DHE-RSA-AES128-GCM-SHA256
+ - DHE-RSA-AES256-GCM-SHA384
+ minTLSVersion: VersionTLS12
+ nullable: true
+ type: object
+ modern:
+ description: |-
+ modern is a TLS security profile based on:
+
+
+ https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
+
+
+ and looks like this (yaml):
+
+
+ ciphers:
+ - TLS_AES_128_GCM_SHA256
+ - TLS_AES_256_GCM_SHA384
+ - TLS_CHACHA20_POLY1305_SHA256
+ minTLSVersion: VersionTLS13
+
+
+ NOTE: Currently unsupported.
+ nullable: true
+ type: object
+ old:
+ description: |-
+ old is a TLS security profile based on:
+
+
+ https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility
+
+
+ and looks like this (yaml):
+
+
+ ciphers:
+ - TLS_AES_128_GCM_SHA256
+ - TLS_AES_256_GCM_SHA384
+ - TLS_CHACHA20_POLY1305_SHA256
+ - ECDHE-ECDSA-AES128-GCM-SHA256
+ - ECDHE-RSA-AES128-GCM-SHA256
+ - ECDHE-ECDSA-AES256-GCM-SHA384
+ - ECDHE-RSA-AES256-GCM-SHA384
+ - ECDHE-ECDSA-CHACHA20-POLY1305
+ - ECDHE-RSA-CHACHA20-POLY1305
+ - DHE-RSA-AES128-GCM-SHA256
+ - DHE-RSA-AES256-GCM-SHA384
+ - DHE-RSA-CHACHA20-POLY1305
+ - ECDHE-ECDSA-AES128-SHA256
+ - ECDHE-RSA-AES128-SHA256
+ - ECDHE-ECDSA-AES128-SHA
+ - ECDHE-RSA-AES128-SHA
+ - ECDHE-ECDSA-AES256-SHA384
+ - ECDHE-RSA-AES256-SHA384
+ - ECDHE-ECDSA-AES256-SHA
+ - ECDHE-RSA-AES256-SHA
+ - DHE-RSA-AES128-SHA256
+ - DHE-RSA-AES256-SHA256
+ - AES128-GCM-SHA256
+ - AES256-GCM-SHA384
+ - AES128-SHA256
+ - AES256-SHA256
+ - AES128-SHA
+ - AES256-SHA
+ - DES-CBC3-SHA
+ minTLSVersion: VersionTLS10
+ nullable: true
+ type: object
+ type:
+ description: |-
+ type is one of Old, Intermediate, Modern or Custom. Custom provides
+ the ability to specify individual TLS security profile parameters.
+ Old, Intermediate and Modern are TLS security profiles based on:
+
+
+ https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations
+
+
+ The profiles are intent based, so they may change over time as new ciphers are developed and existing ciphers
+ are found to be insecure. Depending on precisely which ciphers are available to a process, the list may be
+ reduced.
+
+
+ Note that the Modern profile is currently not supported because it is not
+ yet well adopted by common software libraries.
+ enum:
+ - Old
+ - Intermediate
+ - Modern
+ - Custom
+ type: string
+ type: object
+ uploadProxyURLOverride:
+ description: Override the URL used when uploading to a DataVolume
+ type: string
+ type: object
+ customizeComponents:
+ description: CustomizeComponents defines patches for components deployed
+ by the CDI operator.
+ properties:
+ flags:
+ description: Configure the value used for deployment and daemonset
+ resources
+ properties:
+ api:
+ additionalProperties:
+ type: string
+ type: object
+ controller:
+ additionalProperties:
+ type: string
+ type: object
+ uploadProxy:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ patches:
+ items:
+ description: CustomizeComponentsPatch defines a patch for some
+ resource.
+ properties:
+ patch:
+ type: string
+ resourceName:
+ minLength: 1
+ type: string
+ resourceType:
+ minLength: 1
+ type: string
+ type:
+ description: PatchType defines the patch type.
+ type: string
+ required:
+ - patch
+ - resourceName
+ - resourceType
+ - type
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ imagePullPolicy:
+ description: PullPolicy describes a policy for if/when to pull a container
+ image
+ enum:
+ - Always
+ - IfNotPresent
+ - Never
+ type: string
+ infra:
+ description: Selectors and tolerations that should apply to cdi infrastructure
+ components
+ properties:
+ affinity:
+ description: |-
+ affinity enables pod affinity/anti-affinity placement expanding the types of constraints
+ that can be expressed with nodeSelector.
+ affinity is going to be applied to the relevant kind of pods in parallel with nodeSelector
+ See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity
+ properties:
+ nodeAffinity:
+ description: Describes node affinity scheduling rules for
+ the pod.
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ The scheduler will prefer to schedule pods to nodes that satisfy
+ the affinity expressions specified by this field, but it may choose
+ a node that violates one or more of the expressions. The node that is
+ most preferred is the one with the greatest sum of weights, i.e.
+ for each node that meets all of the scheduling requirements (resource
+ request, requiredDuringScheduling affinity expressions, etc.),
+ compute a sum by iterating through the elements of this field and adding
+ "weight" to the sum if the node matches the corresponding matchExpressions; the
+ node(s) with the highest sum are the most preferred.
+ items:
+ description: |-
+ An empty preferred scheduling term matches all objects with implicit weight 0
+ (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op).
+ properties:
+ preference:
+ description: A node selector term, associated with
+ the corresponding weight.
+ properties:
+ matchExpressions:
+ description: A list of node selector requirements
+ by node's labels.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchFields:
+ description: A list of node selector requirements
+ by node's fields.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ x-kubernetes-map-type: atomic
+ weight:
+ description: Weight associated with matching the
+ corresponding nodeSelectorTerm, in the range 1-100.
+ format: int32
+ type: integer
+ required:
+ - preference
+ - weight
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ requiredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ If the affinity requirements specified by this field are not met at
+ scheduling time, the pod will not be scheduled onto the node.
+ If the affinity requirements specified by this field cease to be met
+ at some point during pod execution (e.g. due to an update), the system
+ may or may not try to eventually evict the pod from its node.
+ properties:
+ nodeSelectorTerms:
+ description: Required. A list of node selector terms.
+ The terms are ORed.
+ items:
+ description: |-
+ A null or empty node selector term matches no objects. The requirements of
+ them are ANDed.
+ The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.
+ properties:
+ matchExpressions:
+ description: A list of node selector requirements
+ by node's labels.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchFields:
+ description: A list of node selector requirements
+ by node's fields.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - nodeSelectorTerms
+ type: object
+ x-kubernetes-map-type: atomic
+ type: object
+ podAffinity:
+ description: Describes pod affinity scheduling rules (e.g.
+ co-locate this pod in the same node, zone, etc. as some
+ other pod(s)).
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ The scheduler will prefer to schedule pods to nodes that satisfy
+ the affinity expressions specified by this field, but it may choose
+ a node that violates one or more of the expressions. The node that is
+ most preferred is the one with the greatest sum of weights, i.e.
+ for each node that meets all of the scheduling requirements (resource
+ request, requiredDuringScheduling affinity expressions, etc.),
+ compute a sum by iterating through the elements of this field and adding
+ "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ node(s) with the highest sum are the most preferred.
+ items:
+ description: The weights of all of the matched WeightedPodAffinityTerm
+ fields are added per-node to find the most preferred
+ node(s)
+ properties:
+ podAffinityTerm:
+ description: Required. A pod affinity term, associated
+ with the corresponding weight.
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ weight:
+ description: |-
+ weight associated with matching the corresponding podAffinityTerm,
+ in the range 1-100.
+ format: int32
+ type: integer
+ required:
+ - podAffinityTerm
+ - weight
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ requiredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ If the affinity requirements specified by this field are not met at
+ scheduling time, the pod will not be scheduled onto the node.
+ If the affinity requirements specified by this field cease to be met
+ at some point during pod execution (e.g. due to a pod label update), the
+ system may or may not try to eventually evict the pod from its node.
+ When there are multiple elements, the lists of nodes corresponding to each
+ podAffinityTerm are intersected, i.e. all terms must be satisfied.
+ items:
+ description: |-
+ Defines a set of pods (namely those matching the labelSelector
+ relative to the given namespace(s)) that this pod should be
+ co-located (affinity) or not co-located (anti-affinity) with,
+ where co-located is defined as running on a node whose value of
+ the label with key matches that of any node on which
+ a pod of the set of pods is running
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ podAntiAffinity:
+ description: Describes pod anti-affinity scheduling rules
+ (e.g. avoid putting this pod in the same node, zone, etc.
+ as some other pod(s)).
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ The scheduler will prefer to schedule pods to nodes that satisfy
+ the anti-affinity expressions specified by this field, but it may choose
+ a node that violates one or more of the expressions. The node that is
+ most preferred is the one with the greatest sum of weights, i.e.
+ for each node that meets all of the scheduling requirements (resource
+ request, requiredDuringScheduling anti-affinity expressions, etc.),
+ compute a sum by iterating through the elements of this field and adding
+ "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ node(s) with the highest sum are the most preferred.
+ items:
+ description: The weights of all of the matched WeightedPodAffinityTerm
+ fields are added per-node to find the most preferred
+ node(s)
+ properties:
+ podAffinityTerm:
+ description: Required. A pod affinity term, associated
+ with the corresponding weight.
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ weight:
+ description: |-
+ weight associated with matching the corresponding podAffinityTerm,
+ in the range 1-100.
+ format: int32
+ type: integer
+ required:
+ - podAffinityTerm
+ - weight
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ requiredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ If the anti-affinity requirements specified by this field are not met at
+ scheduling time, the pod will not be scheduled onto the node.
+ If the anti-affinity requirements specified by this field cease to be met
+ at some point during pod execution (e.g. due to a pod label update), the
+ system may or may not try to eventually evict the pod from its node.
+ When there are multiple elements, the lists of nodes corresponding to each
+ podAffinityTerm are intersected, i.e. all terms must be satisfied.
+ items:
+ description: |-
+ Defines a set of pods (namely those matching the labelSelector
+ relative to the given namespace(s)) that this pod should be
+ co-located (affinity) or not co-located (anti-affinity) with,
+ where co-located is defined as running on a node whose value of
+ the label with key matches that of any node on which
+ a pod of the set of pods is running
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ type: object
+ apiServerReplicas:
+ description: ApiserverReplicas set Replicas for cdi-apiserver
+ format: int32
+ type: integer
+ deploymentReplicas:
+ description: DeploymentReplicas set Replicas for cdi-deployment
+ format: int32
+ type: integer
+ nodeSelector:
+ additionalProperties:
+ type: string
+ description: |-
+ nodeSelector is the node selector applied to the relevant kind of pods
+ It specifies a map of key-value pairs: for the pod to be eligible to run on a node,
+ the node must have each of the indicated key-value pairs as labels
+ (it can have additional labels as well).
+ See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
+ type: object
+ tolerations:
+ description: |-
+ tolerations is a list of tolerations applied to the relevant kind of pods
+ See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ for more info.
+ These are additional tolerations other than default ones.
+ items:
+ description: |-
+ The pod this Toleration is attached to tolerates any taint that matches
+ the triple using the matching operator .
+ properties:
+ effect:
+ description: |-
+ Effect indicates the taint effect to match. Empty means match all taint effects.
+ When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.
+ type: string
+ key:
+ description: |-
+ Key is the taint key that the toleration applies to. Empty means match all taint keys.
+ If the key is empty, operator must be Exists; this combination means to match all values and all keys.
+ type: string
+ operator:
+ description: |-
+ Operator represents a key's relationship to the value.
+ Valid operators are Exists and Equal. Defaults to Equal.
+ Exists is equivalent to wildcard for value, so that a pod can
+ tolerate all taints of a particular category.
+ type: string
+ tolerationSeconds:
+ description: |-
+ TolerationSeconds represents the period of time the toleration (which must be
+ of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default,
+ it is not set, which means tolerate the taint forever (do not evict). Zero and
+ negative values will be treated as 0 (evict immediately) by the system.
+ format: int64
+ type: integer
+ value:
+ description: |-
+ Value is the taint value the toleration matches to.
+ If the operator is Exists, the value should be empty, otherwise just a regular string.
+ type: string
+ type: object
+ type: array
+ uploadProxyReplicas:
+ description: UploadproxyReplicas set Replicas for cdi-uploadproxy
+ format: int32
+ type: integer
+ type: object
+ priorityClass:
+ description: PriorityClass of the CDI control plane
+ type: string
+ uninstallStrategy:
+ description: CDIUninstallStrategy defines the state to leave CDI on
+ uninstall
+ enum:
+ - RemoveWorkloads
+ - BlockUninstallIfWorkloadsExist
+ type: string
+ workload:
+ description: Restrict on which nodes CDI workload pods will be scheduled
+ properties:
+ affinity:
+ description: |-
+ affinity enables pod affinity/anti-affinity placement expanding the types of constraints
+ that can be expressed with nodeSelector.
+ affinity is going to be applied to the relevant kind of pods in parallel with nodeSelector
+ See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity
+ properties:
+ nodeAffinity:
+ description: Describes node affinity scheduling rules for
+ the pod.
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ The scheduler will prefer to schedule pods to nodes that satisfy
+ the affinity expressions specified by this field, but it may choose
+ a node that violates one or more of the expressions. The node that is
+ most preferred is the one with the greatest sum of weights, i.e.
+ for each node that meets all of the scheduling requirements (resource
+ request, requiredDuringScheduling affinity expressions, etc.),
+ compute a sum by iterating through the elements of this field and adding
+ "weight" to the sum if the node matches the corresponding matchExpressions; the
+ node(s) with the highest sum are the most preferred.
+ items:
+ description: |-
+ An empty preferred scheduling term matches all objects with implicit weight 0
+ (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op).
+ properties:
+ preference:
+ description: A node selector term, associated with
+ the corresponding weight.
+ properties:
+ matchExpressions:
+ description: A list of node selector requirements
+ by node's labels.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchFields:
+ description: A list of node selector requirements
+ by node's fields.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ x-kubernetes-map-type: atomic
+ weight:
+ description: Weight associated with matching the
+ corresponding nodeSelectorTerm, in the range 1-100.
+ format: int32
+ type: integer
+ required:
+ - preference
+ - weight
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ requiredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ If the affinity requirements specified by this field are not met at
+ scheduling time, the pod will not be scheduled onto the node.
+ If the affinity requirements specified by this field cease to be met
+ at some point during pod execution (e.g. due to an update), the system
+ may or may not try to eventually evict the pod from its node.
+ properties:
+ nodeSelectorTerms:
+ description: Required. A list of node selector terms.
+ The terms are ORed.
+ items:
+ description: |-
+ A null or empty node selector term matches no objects. The requirements of
+ them are ANDed.
+ The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.
+ properties:
+ matchExpressions:
+ description: A list of node selector requirements
+ by node's labels.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchFields:
+ description: A list of node selector requirements
+ by node's fields.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - nodeSelectorTerms
+ type: object
+ x-kubernetes-map-type: atomic
+ type: object
+ podAffinity:
+ description: Describes pod affinity scheduling rules (e.g.
+ co-locate this pod in the same node, zone, etc. as some
+ other pod(s)).
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ The scheduler will prefer to schedule pods to nodes that satisfy
+ the affinity expressions specified by this field, but it may choose
+ a node that violates one or more of the expressions. The node that is
+ most preferred is the one with the greatest sum of weights, i.e.
+ for each node that meets all of the scheduling requirements (resource
+ request, requiredDuringScheduling affinity expressions, etc.),
+ compute a sum by iterating through the elements of this field and adding
+ "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ node(s) with the highest sum are the most preferred.
+ items:
+ description: The weights of all of the matched WeightedPodAffinityTerm
+ fields are added per-node to find the most preferred
+ node(s)
+ properties:
+ podAffinityTerm:
+ description: Required. A pod affinity term, associated
+ with the corresponding weight.
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ weight:
+ description: |-
+ weight associated with matching the corresponding podAffinityTerm,
+ in the range 1-100.
+ format: int32
+ type: integer
+ required:
+ - podAffinityTerm
+ - weight
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ requiredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ If the affinity requirements specified by this field are not met at
+ scheduling time, the pod will not be scheduled onto the node.
+ If the affinity requirements specified by this field cease to be met
+ at some point during pod execution (e.g. due to a pod label update), the
+ system may or may not try to eventually evict the pod from its node.
+ When there are multiple elements, the lists of nodes corresponding to each
+ podAffinityTerm are intersected, i.e. all terms must be satisfied.
+ items:
+ description: |-
+ Defines a set of pods (namely those matching the labelSelector
+ relative to the given namespace(s)) that this pod should be
+ co-located (affinity) or not co-located (anti-affinity) with,
+ where co-located is defined as running on a node whose value of
+ the label with key matches that of any node on which
+ a pod of the set of pods is running
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ podAntiAffinity:
+ description: Describes pod anti-affinity scheduling rules
+ (e.g. avoid putting this pod in the same node, zone, etc.
+ as some other pod(s)).
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ The scheduler will prefer to schedule pods to nodes that satisfy
+ the anti-affinity expressions specified by this field, but it may choose
+ a node that violates one or more of the expressions. The node that is
+ most preferred is the one with the greatest sum of weights, i.e.
+ for each node that meets all of the scheduling requirements (resource
+ request, requiredDuringScheduling anti-affinity expressions, etc.),
+ compute a sum by iterating through the elements of this field and adding
+ "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ node(s) with the highest sum are the most preferred.
+ items:
+ description: The weights of all of the matched WeightedPodAffinityTerm
+ fields are added per-node to find the most preferred
+ node(s)
+ properties:
+ podAffinityTerm:
+ description: Required. A pod affinity term, associated
+ with the corresponding weight.
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ weight:
+ description: |-
+ weight associated with matching the corresponding podAffinityTerm,
+ in the range 1-100.
+ format: int32
+ type: integer
+ required:
+ - podAffinityTerm
+ - weight
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ requiredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ If the anti-affinity requirements specified by this field are not met at
+ scheduling time, the pod will not be scheduled onto the node.
+ If the anti-affinity requirements specified by this field cease to be met
+ at some point during pod execution (e.g. due to a pod label update), the
+ system may or may not try to eventually evict the pod from its node.
+ When there are multiple elements, the lists of nodes corresponding to each
+ podAffinityTerm are intersected, i.e. all terms must be satisfied.
+ items:
+ description: |-
+ Defines a set of pods (namely those matching the labelSelector
+ relative to the given namespace(s)) that this pod should be
+ co-located (affinity) or not co-located (anti-affinity) with,
+ where co-located is defined as running on a node whose value of
+ the label with key matches that of any node on which
+ a pod of the set of pods is running
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ type: object
+ nodeSelector:
+ additionalProperties:
+ type: string
+ description: |-
+ nodeSelector is the node selector applied to the relevant kind of pods
+ It specifies a map of key-value pairs: for the pod to be eligible to run on a node,
+ the node must have each of the indicated key-value pairs as labels
+ (it can have additional labels as well).
+ See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
+ type: object
+ tolerations:
+ description: |-
+ tolerations is a list of tolerations applied to the relevant kind of pods
+ See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ for more info.
+ These are additional tolerations other than default ones.
+ items:
+ description: |-
+ The pod this Toleration is attached to tolerates any taint that matches
+ the triple using the matching operator .
+ properties:
+ effect:
+ description: |-
+ Effect indicates the taint effect to match. Empty means match all taint effects.
+ When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.
+ type: string
+ key:
+ description: |-
+ Key is the taint key that the toleration applies to. Empty means match all taint keys.
+ If the key is empty, operator must be Exists; this combination means to match all values and all keys.
+ type: string
+ operator:
+ description: |-
+ Operator represents a key's relationship to the value.
+ Valid operators are Exists and Equal. Defaults to Equal.
+ Exists is equivalent to wildcard for value, so that a pod can
+ tolerate all taints of a particular category.
+ type: string
+ tolerationSeconds:
+ description: |-
+ TolerationSeconds represents the period of time the toleration (which must be
+ of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default,
+ it is not set, which means tolerate the taint forever (do not evict). Zero and
+ negative values will be treated as 0 (evict immediately) by the system.
+ format: int64
+ type: integer
+ value:
+ description: |-
+ Value is the taint value the toleration matches to.
+ If the operator is Exists, the value should be empty, otherwise just a regular string.
+ type: string
+ type: object
+ type: array
+ type: object
+ type: object
+ status:
+ description: CDIStatus defines the status of the installation
+ properties:
+ conditions:
+ description: A list of current conditions of the resource
+ items:
+ description: |-
+ Condition represents the state of the operator's
+ reconciliation functionality.
+ properties:
+ lastHeartbeatTime:
+ format: date-time
+ type: string
+ lastTransitionTime:
+ format: date-time
+ type: string
+ message:
+ type: string
+ reason:
+ type: string
+ status:
+ type: string
+ type:
+ description: ConditionType is the state of the operator's reconciliation
+ functionality.
+ type: string
+ required:
+ - status
+ - type
+ type: object
+ type: array
+ observedVersion:
+ description: The observed version of the resource
+ type: string
+ operatorVersion:
+ description: The version of the resource as defined by the operator
+ type: string
+ phase:
+ description: Phase is the current phase of the deployment
+ type: string
+ targetVersion:
+ description: The desired version of the resource
+ type: string
+ type: object
+ required:
+ - spec
+ type: object
+ served: true
+ storage: false
+ subresources: {}
+ - additionalPrinterColumns:
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ - jsonPath: .status.phase
+ name: Phase
+ type: string
+ name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: CDI is the CDI Operator CRD
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: CDISpec defines our specification for the CDI installation
+ properties:
+ certConfig:
+ description: certificate configuration
+ properties:
+ ca:
+ description: |-
+ CA configuration
+ CA certs are kept in the CA bundle as long as they are valid
+ properties:
+ duration:
+ description: The requested 'duration' (i.e. lifetime) of the
+ Certificate.
+ type: string
+ renewBefore:
+ description: |-
+ The amount of time before the currently issued certificate's `notAfter`
+ time that we will begin to attempt to renew the certificate.
+ type: string
+ type: object
+ client:
+ description: |-
+ Client configuration
+ Certs are rotated and discarded
+ properties:
+ duration:
+ description: The requested 'duration' (i.e. lifetime) of the
+ Certificate.
+ type: string
+ renewBefore:
+ description: |-
+ The amount of time before the currently issued certificate's `notAfter`
+ time that we will begin to attempt to renew the certificate.
+ type: string
+ type: object
+ server:
+ description: |-
+ Server configuration
+ Certs are rotated and discarded
+ properties:
+ duration:
+ description: The requested 'duration' (i.e. lifetime) of the
+ Certificate.
+ type: string
+ renewBefore:
+ description: |-
+ The amount of time before the currently issued certificate's `notAfter`
+ time that we will begin to attempt to renew the certificate.
+ type: string
+ type: object
+ type: object
+ cloneStrategyOverride:
+ description: 'Clone strategy override: should we use a host-assisted
+ copy even if snapshots are available?'
+ enum:
+ - copy
+ - snapshot
+ - csi-clone
+ type: string
+ config:
+ description: CDIConfig at CDI level
+ properties:
+ dataVolumeTTLSeconds:
+ description: DataVolumeTTLSeconds is the time in seconds after
+ DataVolume completion it can be garbage collected. Disabled
+ by default.
+ format: int32
+ type: integer
+ featureGates:
+ description: FeatureGates are a list of specific enabled feature
+ gates
+ items:
+ type: string
+ type: array
+ filesystemOverhead:
+ description: FilesystemOverhead describes the space reserved for
+ overhead when using Filesystem volumes. A value is between 0
+ and 1, if not defined it is 0.055 (5.5% overhead)
+ properties:
+ global:
+ description: Global is how much space of a Filesystem volume
+ should be reserved for overhead. This value is used unless
+ overridden by a more specific value (per storageClass)
+ pattern: ^(0(?:\.\d{1,3})?|1)$
+ type: string
+ storageClass:
+ additionalProperties:
+ description: |-
+ Percent is a string that can only be a value between [0,1)
+ (Note: we actually rely on reconcile to reject invalid values)
+ pattern: ^(0(?:\.\d{1,3})?|1)$
+ type: string
+ description: StorageClass specifies how much space of a Filesystem
+ volume should be reserved for safety. The keys are the storageClass
+ and the values are the overhead. This value overrides the
+ global value
+ type: object
+ type: object
+ imagePullSecrets:
+ description: The imagePullSecrets used to pull the container images
+ items:
+ description: |-
+ LocalObjectReference contains enough information to let you locate the
+ referenced object inside the same namespace.
+ properties:
+ name:
+ default: ""
+ description: |-
+ Name of the referent.
+ This field is effectively required, but due to backwards compatibility is
+ allowed to be empty. Instances of this type with an empty value here are
+ almost certainly wrong.
+ TODO: Add other useful fields. apiVersion, kind, uid?
+ More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
+ TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
+ type: string
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ importProxy:
+ description: ImportProxy contains importer pod proxy configuration.
+ properties:
+ HTTPProxy:
+ description: HTTPProxy is the URL http://:@:
+ of the import proxy for HTTP requests. Empty means unset
+ and will not result in the import pod env var.
+ type: string
+ HTTPSProxy:
+ description: HTTPSProxy is the URL https://:@:
+ of the import proxy for HTTPS requests. Empty means unset
+ and will not result in the import pod env var.
+ type: string
+ noProxy:
+ description: NoProxy is a comma-separated list of hostnames
+ and/or CIDRs for which the proxy should not be used. Empty
+ means unset and will not result in the import pod env var.
+ type: string
+ trustedCAProxy:
+ description: "TrustedCAProxy is the name of a ConfigMap in
+ the cdi namespace that contains a user-provided trusted
+ certificate authority (CA) bundle.\nThe TrustedCAProxy ConfigMap
+ is consumed by the DataImportCron controller for creating
+ cronjobs, and by the import controller referring a copy
+ of the ConfigMap in the import namespace.\nHere is an example
+ of the ConfigMap (in yaml):\n\n\napiVersion: v1\nkind: ConfigMap\nmetadata:\n
+ \ name: my-ca-proxy-cm\n namespace: cdi\ndata:\n ca.pem:
+ |\n -----BEGIN CERTIFICATE-----\n\t ... ...\n\t -----END CERTIFICATE-----"
+ type: string
+ type: object
+ insecureRegistries:
+ description: InsecureRegistries is a list of TLS disabled registries
+ items:
+ type: string
+ type: array
+ logVerbosity:
+ description: LogVerbosity overrides the default verbosity level
+ used to initialize loggers
+ format: int32
+ type: integer
+ podResourceRequirements:
+ description: ResourceRequirements describes the compute resource
+ requirements.
+ properties:
+ claims:
+ description: |-
+ Claims lists the names of resources, defined in spec.resourceClaims,
+ that are used by this container.
+
+
+ This is an alpha field and requires enabling the
+ DynamicResourceAllocation feature gate.
+
+
+ This field is immutable. It can only be set for containers.
+ items:
+ description: ResourceClaim references one entry in PodSpec.ResourceClaims.
+ properties:
+ name:
+ description: |-
+ Name must match the name of one entry in pod.spec.resourceClaims of
+ the Pod where this field is used. It makes that resource available
+ inside a container.
+ type: string
+ required:
+ - name
+ type: object
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ limits:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ description: |-
+ Limits describes the maximum amount of compute resources allowed.
+ More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
+ type: object
+ requests:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ description: |-
+ Requests describes the minimum amount of compute resources required.
+ If Requests is omitted for a container, it defaults to Limits if that is explicitly specified,
+ otherwise to an implementation-defined value. Requests cannot exceed Limits.
+ More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
+ type: object
+ type: object
+ preallocation:
+ description: Preallocation controls whether storage for DataVolumes
+ should be allocated in advance.
+ type: boolean
+ scratchSpaceStorageClass:
+ description: 'Override the storage class to used for scratch space
+ during transfer operations. The scratch space storage class
+ is determined in the following order: 1. value of scratchSpaceStorageClass,
+ if that doesn''t exist, use the default storage class, if there
+ is no default storage class, use the storage class of the DataVolume,
+ if no storage class specified, use no storage class for scratch
+ space'
+ type: string
+ tlsSecurityProfile:
+ description: TLSSecurityProfile is used by operators to apply
+ cluster-wide TLS security settings to operands.
+ properties:
+ custom:
+ description: |-
+ custom is a user-defined TLS security profile. Be extremely careful using a custom
+ profile as invalid configurations can be catastrophic. An example custom profile
+ looks like this:
+
+
+ ciphers:
+ - ECDHE-ECDSA-CHACHA20-POLY1305
+ - ECDHE-RSA-CHACHA20-POLY1305
+ - ECDHE-RSA-AES128-GCM-SHA256
+ - ECDHE-ECDSA-AES128-GCM-SHA256
+ minTLSVersion: VersionTLS11
+ nullable: true
+ properties:
+ ciphers:
+ description: |-
+ ciphers is used to specify the cipher algorithms that are negotiated
+ during the TLS handshake. Operators may remove entries their operands
+ do not support. For example, to use DES-CBC3-SHA (yaml):
+
+
+ ciphers:
+ - DES-CBC3-SHA
+ items:
+ type: string
+ type: array
+ minTLSVersion:
+ description: |-
+ minTLSVersion is used to specify the minimal version of the TLS protocol
+ that is negotiated during the TLS handshake. For example, to use TLS
+ versions 1.1, 1.2 and 1.3 (yaml):
+
+
+ minTLSVersion: VersionTLS11
+
+
+ NOTE: currently the highest minTLSVersion allowed is VersionTLS12
+ enum:
+ - VersionTLS10
+ - VersionTLS11
+ - VersionTLS12
+ - VersionTLS13
+ type: string
+ required:
+ - ciphers
+ - minTLSVersion
+ type: object
+ intermediate:
+ description: |-
+ intermediate is a TLS security profile based on:
+
+
+ https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29
+
+
+ and looks like this (yaml):
+
+
+ ciphers:
+ - TLS_AES_128_GCM_SHA256
+ - TLS_AES_256_GCM_SHA384
+ - TLS_CHACHA20_POLY1305_SHA256
+ - ECDHE-ECDSA-AES128-GCM-SHA256
+ - ECDHE-RSA-AES128-GCM-SHA256
+ - ECDHE-ECDSA-AES256-GCM-SHA384
+ - ECDHE-RSA-AES256-GCM-SHA384
+ - ECDHE-ECDSA-CHACHA20-POLY1305
+ - ECDHE-RSA-CHACHA20-POLY1305
+ - DHE-RSA-AES128-GCM-SHA256
+ - DHE-RSA-AES256-GCM-SHA384
+ minTLSVersion: VersionTLS12
+ nullable: true
+ type: object
+ modern:
+ description: |-
+ modern is a TLS security profile based on:
+
+
+ https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
+
+
+ and looks like this (yaml):
+
+
+ ciphers:
+ - TLS_AES_128_GCM_SHA256
+ - TLS_AES_256_GCM_SHA384
+ - TLS_CHACHA20_POLY1305_SHA256
+ minTLSVersion: VersionTLS13
+
+
+ NOTE: Currently unsupported.
+ nullable: true
+ type: object
+ old:
+ description: |-
+ old is a TLS security profile based on:
+
+
+ https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility
+
+
+ and looks like this (yaml):
+
+
+ ciphers:
+ - TLS_AES_128_GCM_SHA256
+ - TLS_AES_256_GCM_SHA384
+ - TLS_CHACHA20_POLY1305_SHA256
+ - ECDHE-ECDSA-AES128-GCM-SHA256
+ - ECDHE-RSA-AES128-GCM-SHA256
+ - ECDHE-ECDSA-AES256-GCM-SHA384
+ - ECDHE-RSA-AES256-GCM-SHA384
+ - ECDHE-ECDSA-CHACHA20-POLY1305
+ - ECDHE-RSA-CHACHA20-POLY1305
+ - DHE-RSA-AES128-GCM-SHA256
+ - DHE-RSA-AES256-GCM-SHA384
+ - DHE-RSA-CHACHA20-POLY1305
+ - ECDHE-ECDSA-AES128-SHA256
+ - ECDHE-RSA-AES128-SHA256
+ - ECDHE-ECDSA-AES128-SHA
+ - ECDHE-RSA-AES128-SHA
+ - ECDHE-ECDSA-AES256-SHA384
+ - ECDHE-RSA-AES256-SHA384
+ - ECDHE-ECDSA-AES256-SHA
+ - ECDHE-RSA-AES256-SHA
+ - DHE-RSA-AES128-SHA256
+ - DHE-RSA-AES256-SHA256
+ - AES128-GCM-SHA256
+ - AES256-GCM-SHA384
+ - AES128-SHA256
+ - AES256-SHA256
+ - AES128-SHA
+ - AES256-SHA
+ - DES-CBC3-SHA
+ minTLSVersion: VersionTLS10
+ nullable: true
+ type: object
+ type:
+ description: |-
+ type is one of Old, Intermediate, Modern or Custom. Custom provides
+ the ability to specify individual TLS security profile parameters.
+ Old, Intermediate and Modern are TLS security profiles based on:
+
+
+ https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations
+
+
+ The profiles are intent based, so they may change over time as new ciphers are developed and existing ciphers
+ are found to be insecure. Depending on precisely which ciphers are available to a process, the list may be
+ reduced.
+
+
+ Note that the Modern profile is currently not supported because it is not
+ yet well adopted by common software libraries.
+ enum:
+ - Old
+ - Intermediate
+ - Modern
+ - Custom
+ type: string
+ type: object
+ uploadProxyURLOverride:
+ description: Override the URL used when uploading to a DataVolume
+ type: string
+ type: object
+ customizeComponents:
+ description: CustomizeComponents defines patches for components deployed
+ by the CDI operator.
+ properties:
+ flags:
+ description: Configure the value used for deployment and daemonset
+ resources
+ properties:
+ api:
+ additionalProperties:
+ type: string
+ type: object
+ controller:
+ additionalProperties:
+ type: string
+ type: object
+ uploadProxy:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ patches:
+ items:
+ description: CustomizeComponentsPatch defines a patch for some
+ resource.
+ properties:
+ patch:
+ type: string
+ resourceName:
+ minLength: 1
+ type: string
+ resourceType:
+ minLength: 1
+ type: string
+ type:
+ description: PatchType defines the patch type.
+ type: string
+ required:
+ - patch
+ - resourceName
+ - resourceType
+ - type
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ imagePullPolicy:
+ description: PullPolicy describes a policy for if/when to pull a container
+ image
+ enum:
+ - Always
+ - IfNotPresent
+ - Never
+ type: string
+ infra:
+ description: Selectors and tolerations that should apply to cdi infrastructure
+ components
+ properties:
+ affinity:
+ description: |-
+ affinity enables pod affinity/anti-affinity placement expanding the types of constraints
+ that can be expressed with nodeSelector.
+ affinity is going to be applied to the relevant kind of pods in parallel with nodeSelector
+ See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity
+ properties:
+ nodeAffinity:
+ description: Describes node affinity scheduling rules for
+ the pod.
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ The scheduler will prefer to schedule pods to nodes that satisfy
+ the affinity expressions specified by this field, but it may choose
+ a node that violates one or more of the expressions. The node that is
+ most preferred is the one with the greatest sum of weights, i.e.
+ for each node that meets all of the scheduling requirements (resource
+ request, requiredDuringScheduling affinity expressions, etc.),
+ compute a sum by iterating through the elements of this field and adding
+ "weight" to the sum if the node matches the corresponding matchExpressions; the
+ node(s) with the highest sum are the most preferred.
+ items:
+ description: |-
+ An empty preferred scheduling term matches all objects with implicit weight 0
+ (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op).
+ properties:
+ preference:
+ description: A node selector term, associated with
+ the corresponding weight.
+ properties:
+ matchExpressions:
+ description: A list of node selector requirements
+ by node's labels.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchFields:
+ description: A list of node selector requirements
+ by node's fields.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ x-kubernetes-map-type: atomic
+ weight:
+ description: Weight associated with matching the
+ corresponding nodeSelectorTerm, in the range 1-100.
+ format: int32
+ type: integer
+ required:
+ - preference
+ - weight
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ requiredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ If the affinity requirements specified by this field are not met at
+ scheduling time, the pod will not be scheduled onto the node.
+ If the affinity requirements specified by this field cease to be met
+ at some point during pod execution (e.g. due to an update), the system
+ may or may not try to eventually evict the pod from its node.
+ properties:
+ nodeSelectorTerms:
+ description: Required. A list of node selector terms.
+ The terms are ORed.
+ items:
+ description: |-
+ A null or empty node selector term matches no objects. The requirements of
+ them are ANDed.
+ The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.
+ properties:
+ matchExpressions:
+ description: A list of node selector requirements
+ by node's labels.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchFields:
+ description: A list of node selector requirements
+ by node's fields.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - nodeSelectorTerms
+ type: object
+ x-kubernetes-map-type: atomic
+ type: object
+ podAffinity:
+ description: Describes pod affinity scheduling rules (e.g.
+ co-locate this pod in the same node, zone, etc. as some
+ other pod(s)).
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ The scheduler will prefer to schedule pods to nodes that satisfy
+ the affinity expressions specified by this field, but it may choose
+ a node that violates one or more of the expressions. The node that is
+ most preferred is the one with the greatest sum of weights, i.e.
+ for each node that meets all of the scheduling requirements (resource
+ request, requiredDuringScheduling affinity expressions, etc.),
+ compute a sum by iterating through the elements of this field and adding
+ "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ node(s) with the highest sum are the most preferred.
+ items:
+ description: The weights of all of the matched WeightedPodAffinityTerm
+ fields are added per-node to find the most preferred
+ node(s)
+ properties:
+ podAffinityTerm:
+ description: Required. A pod affinity term, associated
+ with the corresponding weight.
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ weight:
+ description: |-
+ weight associated with matching the corresponding podAffinityTerm,
+ in the range 1-100.
+ format: int32
+ type: integer
+ required:
+ - podAffinityTerm
+ - weight
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ requiredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ If the affinity requirements specified by this field are not met at
+ scheduling time, the pod will not be scheduled onto the node.
+ If the affinity requirements specified by this field cease to be met
+ at some point during pod execution (e.g. due to a pod label update), the
+ system may or may not try to eventually evict the pod from its node.
+ When there are multiple elements, the lists of nodes corresponding to each
+ podAffinityTerm are intersected, i.e. all terms must be satisfied.
+ items:
+ description: |-
+ Defines a set of pods (namely those matching the labelSelector
+ relative to the given namespace(s)) that this pod should be
+ co-located (affinity) or not co-located (anti-affinity) with,
+ where co-located is defined as running on a node whose value of
+ the label with key matches that of any node on which
+ a pod of the set of pods is running
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ podAntiAffinity:
+ description: Describes pod anti-affinity scheduling rules
+ (e.g. avoid putting this pod in the same node, zone, etc.
+ as some other pod(s)).
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ The scheduler will prefer to schedule pods to nodes that satisfy
+ the anti-affinity expressions specified by this field, but it may choose
+ a node that violates one or more of the expressions. The node that is
+ most preferred is the one with the greatest sum of weights, i.e.
+ for each node that meets all of the scheduling requirements (resource
+ request, requiredDuringScheduling anti-affinity expressions, etc.),
+ compute a sum by iterating through the elements of this field and adding
+ "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ node(s) with the highest sum are the most preferred.
+ items:
+ description: The weights of all of the matched WeightedPodAffinityTerm
+ fields are added per-node to find the most preferred
+ node(s)
+ properties:
+ podAffinityTerm:
+ description: Required. A pod affinity term, associated
+ with the corresponding weight.
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ weight:
+ description: |-
+ weight associated with matching the corresponding podAffinityTerm,
+ in the range 1-100.
+ format: int32
+ type: integer
+ required:
+ - podAffinityTerm
+ - weight
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ requiredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ If the anti-affinity requirements specified by this field are not met at
+ scheduling time, the pod will not be scheduled onto the node.
+ If the anti-affinity requirements specified by this field cease to be met
+ at some point during pod execution (e.g. due to a pod label update), the
+ system may or may not try to eventually evict the pod from its node.
+ When there are multiple elements, the lists of nodes corresponding to each
+ podAffinityTerm are intersected, i.e. all terms must be satisfied.
+ items:
+ description: |-
+ Defines a set of pods (namely those matching the labelSelector
+ relative to the given namespace(s)) that this pod should be
+ co-located (affinity) or not co-located (anti-affinity) with,
+ where co-located is defined as running on a node whose value of
+ the label with key matches that of any node on which
+ a pod of the set of pods is running
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ type: object
+ apiServerReplicas:
+ description: ApiserverReplicas set Replicas for cdi-apiserver
+ format: int32
+ type: integer
+ deploymentReplicas:
+ description: DeploymentReplicas set Replicas for cdi-deployment
+ format: int32
+ type: integer
+ nodeSelector:
+ additionalProperties:
+ type: string
+ description: |-
+ nodeSelector is the node selector applied to the relevant kind of pods
+ It specifies a map of key-value pairs: for the pod to be eligible to run on a node,
+ the node must have each of the indicated key-value pairs as labels
+ (it can have additional labels as well).
+ See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
+ type: object
+ tolerations:
+ description: |-
+ tolerations is a list of tolerations applied to the relevant kind of pods
+ See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ for more info.
+ These are additional tolerations other than default ones.
+ items:
+ description: |-
+ The pod this Toleration is attached to tolerates any taint that matches
+ the triple using the matching operator .
+ properties:
+ effect:
+ description: |-
+ Effect indicates the taint effect to match. Empty means match all taint effects.
+ When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.
+ type: string
+ key:
+ description: |-
+ Key is the taint key that the toleration applies to. Empty means match all taint keys.
+ If the key is empty, operator must be Exists; this combination means to match all values and all keys.
+ type: string
+ operator:
+ description: |-
+ Operator represents a key's relationship to the value.
+ Valid operators are Exists and Equal. Defaults to Equal.
+ Exists is equivalent to wildcard for value, so that a pod can
+ tolerate all taints of a particular category.
+ type: string
+ tolerationSeconds:
+ description: |-
+ TolerationSeconds represents the period of time the toleration (which must be
+ of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default,
+ it is not set, which means tolerate the taint forever (do not evict). Zero and
+ negative values will be treated as 0 (evict immediately) by the system.
+ format: int64
+ type: integer
+ value:
+ description: |-
+ Value is the taint value the toleration matches to.
+ If the operator is Exists, the value should be empty, otherwise just a regular string.
+ type: string
+ type: object
+ type: array
+ uploadProxyReplicas:
+ description: UploadproxyReplicas set Replicas for cdi-uploadproxy
+ format: int32
+ type: integer
+ type: object
+ priorityClass:
+ description: PriorityClass of the CDI control plane
+ type: string
+ uninstallStrategy:
+ description: CDIUninstallStrategy defines the state to leave CDI on
+ uninstall
+ enum:
+ - RemoveWorkloads
+ - BlockUninstallIfWorkloadsExist
+ type: string
+ workload:
+ description: Restrict on which nodes CDI workload pods will be scheduled
+ properties:
+ affinity:
+ description: |-
+ affinity enables pod affinity/anti-affinity placement expanding the types of constraints
+ that can be expressed with nodeSelector.
+ affinity is going to be applied to the relevant kind of pods in parallel with nodeSelector
+ See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity
+ properties:
+ nodeAffinity:
+ description: Describes node affinity scheduling rules for
+ the pod.
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ The scheduler will prefer to schedule pods to nodes that satisfy
+ the affinity expressions specified by this field, but it may choose
+ a node that violates one or more of the expressions. The node that is
+ most preferred is the one with the greatest sum of weights, i.e.
+ for each node that meets all of the scheduling requirements (resource
+ request, requiredDuringScheduling affinity expressions, etc.),
+ compute a sum by iterating through the elements of this field and adding
+ "weight" to the sum if the node matches the corresponding matchExpressions; the
+ node(s) with the highest sum are the most preferred.
+ items:
+ description: |-
+ An empty preferred scheduling term matches all objects with implicit weight 0
+ (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op).
+ properties:
+ preference:
+ description: A node selector term, associated with
+ the corresponding weight.
+ properties:
+ matchExpressions:
+ description: A list of node selector requirements
+ by node's labels.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchFields:
+ description: A list of node selector requirements
+ by node's fields.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ x-kubernetes-map-type: atomic
+ weight:
+ description: Weight associated with matching the
+ corresponding nodeSelectorTerm, in the range 1-100.
+ format: int32
+ type: integer
+ required:
+ - preference
+ - weight
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ requiredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ If the affinity requirements specified by this field are not met at
+ scheduling time, the pod will not be scheduled onto the node.
+ If the affinity requirements specified by this field cease to be met
+ at some point during pod execution (e.g. due to an update), the system
+ may or may not try to eventually evict the pod from its node.
+ properties:
+ nodeSelectorTerms:
+ description: Required. A list of node selector terms.
+ The terms are ORed.
+ items:
+ description: |-
+ A null or empty node selector term matches no objects. The requirements of
+ them are ANDed.
+ The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.
+ properties:
+ matchExpressions:
+ description: A list of node selector requirements
+ by node's labels.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchFields:
+ description: A list of node selector requirements
+ by node's fields.
+ items:
+ description: |-
+ A node selector requirement is a selector that contains values, a key, and an operator
+ that relates the key and values.
+ properties:
+ key:
+ description: The label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ Represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
+ type: string
+ values:
+ description: |-
+ An array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. If the operator is Gt or Lt, the values
+ array must have a single element, which will be interpreted as an integer.
+ This array is replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - nodeSelectorTerms
+ type: object
+ x-kubernetes-map-type: atomic
+ type: object
+ podAffinity:
+ description: Describes pod affinity scheduling rules (e.g.
+ co-locate this pod in the same node, zone, etc. as some
+ other pod(s)).
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ The scheduler will prefer to schedule pods to nodes that satisfy
+ the affinity expressions specified by this field, but it may choose
+ a node that violates one or more of the expressions. The node that is
+ most preferred is the one with the greatest sum of weights, i.e.
+ for each node that meets all of the scheduling requirements (resource
+ request, requiredDuringScheduling affinity expressions, etc.),
+ compute a sum by iterating through the elements of this field and adding
+ "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ node(s) with the highest sum are the most preferred.
+ items:
+ description: The weights of all of the matched WeightedPodAffinityTerm
+ fields are added per-node to find the most preferred
+ node(s)
+ properties:
+ podAffinityTerm:
+ description: Required. A pod affinity term, associated
+ with the corresponding weight.
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ weight:
+ description: |-
+ weight associated with matching the corresponding podAffinityTerm,
+ in the range 1-100.
+ format: int32
+ type: integer
+ required:
+ - podAffinityTerm
+ - weight
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ requiredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ If the affinity requirements specified by this field are not met at
+ scheduling time, the pod will not be scheduled onto the node.
+ If the affinity requirements specified by this field cease to be met
+ at some point during pod execution (e.g. due to a pod label update), the
+ system may or may not try to eventually evict the pod from its node.
+ When there are multiple elements, the lists of nodes corresponding to each
+ podAffinityTerm are intersected, i.e. all terms must be satisfied.
+ items:
+ description: |-
+ Defines a set of pods (namely those matching the labelSelector
+ relative to the given namespace(s)) that this pod should be
+ co-located (affinity) or not co-located (anti-affinity) with,
+ where co-located is defined as running on a node whose value of
+ the label with key matches that of any node on which
+ a pod of the set of pods is running
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ podAntiAffinity:
+ description: Describes pod anti-affinity scheduling rules
+ (e.g. avoid putting this pod in the same node, zone, etc.
+ as some other pod(s)).
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ The scheduler will prefer to schedule pods to nodes that satisfy
+ the anti-affinity expressions specified by this field, but it may choose
+ a node that violates one or more of the expressions. The node that is
+ most preferred is the one with the greatest sum of weights, i.e.
+ for each node that meets all of the scheduling requirements (resource
+ request, requiredDuringScheduling anti-affinity expressions, etc.),
+ compute a sum by iterating through the elements of this field and adding
+ "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the
+ node(s) with the highest sum are the most preferred.
+ items:
+ description: The weights of all of the matched WeightedPodAffinityTerm
+ fields are added per-node to find the most preferred
+ node(s)
+ properties:
+ podAffinityTerm:
+ description: Required. A pod affinity term, associated
+ with the corresponding weight.
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list
+ of label selector requirements. The requirements
+ are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key
+ that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ weight:
+ description: |-
+ weight associated with matching the corresponding podAffinityTerm,
+ in the range 1-100.
+ format: int32
+ type: integer
+ required:
+ - podAffinityTerm
+ - weight
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ requiredDuringSchedulingIgnoredDuringExecution:
+ description: |-
+ If the anti-affinity requirements specified by this field are not met at
+ scheduling time, the pod will not be scheduled onto the node.
+ If the anti-affinity requirements specified by this field cease to be met
+ at some point during pod execution (e.g. due to a pod label update), the
+ system may or may not try to eventually evict the pod from its node.
+ When there are multiple elements, the lists of nodes corresponding to each
+ podAffinityTerm are intersected, i.e. all terms must be satisfied.
+ items:
+ description: |-
+ Defines a set of pods (namely those matching the labelSelector
+ relative to the given namespace(s)) that this pod should be
+ co-located (affinity) or not co-located (anti-affinity) with,
+ where co-located is defined as running on a node whose value of
+ the label with key matches that of any node on which
+ a pod of the set of pods is running
+ properties:
+ labelSelector:
+ description: |-
+ A label query over a set of resources, in this case pods.
+ If it's null, this PodAffinityTerm matches with no Pods.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ matchLabelKeys:
+ description: |-
+ MatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both matchLabelKeys and labelSelector.
+ Also, matchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ mismatchLabelKeys:
+ description: |-
+ MismatchLabelKeys is a set of pod label keys to select which pods will
+ be taken into consideration. The keys are used to lookup values from the
+ incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)`
+ to select the group of existing pods which pods will be taken into consideration
+ for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming
+ pod labels will be ignored. The default value is empty.
+ The same key is forbidden to exist in both mismatchLabelKeys and labelSelector.
+ Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
+ This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ namespaceSelector:
+ description: |-
+ A label query over the set of namespaces that the term applies to.
+ The term is applied to the union of the namespaces selected by this field
+ and the ones listed in the namespaces field.
+ null selector and null or empty namespaces list means "this pod's namespace".
+ An empty selector ({}) matches all namespaces.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are
+ ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that
+ the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ namespaces:
+ description: |-
+ namespaces specifies a static list of namespace names that the term applies to.
+ The term is applied to the union of the namespaces listed in this field
+ and the ones selected by namespaceSelector.
+ null or empty namespaces list and null namespaceSelector means "this pod's namespace".
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ topologyKey:
+ description: |-
+ This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
+ the labelSelector in the specified namespaces, where co-located is defined as running on a node
+ whose value of the label with key topologyKey matches that of any node on which any of the
+ selected pods is running.
+ Empty topologyKey is not allowed.
+ type: string
+ required:
+ - topologyKey
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ type: object
+ nodeSelector:
+ additionalProperties:
+ type: string
+ description: |-
+ nodeSelector is the node selector applied to the relevant kind of pods
+ It specifies a map of key-value pairs: for the pod to be eligible to run on a node,
+ the node must have each of the indicated key-value pairs as labels
+ (it can have additional labels as well).
+ See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
+ type: object
+ tolerations:
+ description: |-
+ tolerations is a list of tolerations applied to the relevant kind of pods
+ See https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ for more info.
+ These are additional tolerations other than default ones.
+ items:
+ description: |-
+ The pod this Toleration is attached to tolerates any taint that matches
+ the triple using the matching operator .
+ properties:
+ effect:
+ description: |-
+ Effect indicates the taint effect to match. Empty means match all taint effects.
+ When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.
+ type: string
+ key:
+ description: |-
+ Key is the taint key that the toleration applies to. Empty means match all taint keys.
+ If the key is empty, operator must be Exists; this combination means to match all values and all keys.
+ type: string
+ operator:
+ description: |-
+ Operator represents a key's relationship to the value.
+ Valid operators are Exists and Equal. Defaults to Equal.
+ Exists is equivalent to wildcard for value, so that a pod can
+ tolerate all taints of a particular category.
+ type: string
+ tolerationSeconds:
+ description: |-
+ TolerationSeconds represents the period of time the toleration (which must be
+ of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default,
+ it is not set, which means tolerate the taint forever (do not evict). Zero and
+ negative values will be treated as 0 (evict immediately) by the system.
+ format: int64
+ type: integer
+ value:
+ description: |-
+ Value is the taint value the toleration matches to.
+ If the operator is Exists, the value should be empty, otherwise just a regular string.
+ type: string
+ type: object
+ type: array
+ type: object
+ type: object
+ status:
+ description: CDIStatus defines the status of the installation
+ properties:
+ conditions:
+ description: A list of current conditions of the resource
+ items:
+ description: |-
+ Condition represents the state of the operator's
+ reconciliation functionality.
+ properties:
+ lastHeartbeatTime:
+ format: date-time
+ type: string
+ lastTransitionTime:
+ format: date-time
+ type: string
+ message:
+ type: string
+ reason:
+ type: string
+ status:
+ type: string
+ type:
+ description: ConditionType is the state of the operator's reconciliation
+ functionality.
+ type: string
+ required:
+ - status
+ - type
+ type: object
+ type: array
+ observedVersion:
+ description: The observed version of the resource
+ type: string
+ operatorVersion:
+ description: The version of the resource as defined by the operator
+ type: string
+ phase:
+ description: Phase is the current phase of the deployment
+ type: string
+ targetVersion:
+ description: The desired version of the resource
+ type: string
+ type: object
+ required:
+ - spec
+ type: object
+ served: true
+ storage: true
+ subresources: {}
diff --git a/cdi-chart/templates/NOTES.txt b/cdi-chart/templates/NOTES.txt
new file mode 100644
index 0000000..f6a43a4
--- /dev/null
+++ b/cdi-chart/templates/NOTES.txt
@@ -0,0 +1,2 @@
+Verify that all CDI components are installed correctly:
+ kubectl get all -n {{ .Release.Namespace }}
diff --git a/cdi-chart/templates/_helpers.tpl b/cdi-chart/templates/_helpers.tpl
new file mode 100644
index 0000000..5f2e091
--- /dev/null
+++ b/cdi-chart/templates/_helpers.tpl
@@ -0,0 +1,62 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "cdi.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "cdi.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "cdi.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "cdi.labels" -}}
+helm.sh/chart: {{ include "cdi.chart" . }}
+{{ include "cdi.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "cdi.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "cdi.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "cdi.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "cdi.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/cdi-chart/templates/_hooks.tpl b/cdi-chart/templates/_hooks.tpl
new file mode 100644
index 0000000..d857801
--- /dev/null
+++ b/cdi-chart/templates/_hooks.tpl
@@ -0,0 +1,47 @@
+{{/* Hook annotations */}}
+{{- define "cdi.hook.annotations" -}}
+ annotations:
+ "helm.sh/hook": {{ .hookType }}
+ "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
+ "helm.sh/hook-weight": {{ .hookWeight | quote }}
+{{- end -}}
+
+{{/* Namespace modifying hook annotations */}}
+{{- define "cdi.namespaceHook.annotations" -}}
+{{ template "cdi.hook.annotations" merge (dict "hookType" "pre-install") . }}
+{{- end -}}
+
+{{/* CRD upgrading hook annotations */}}
+{{- define "cdi.crdUpgradeHook.annotations" -}}
+{{ template "cdi.hook.annotations" merge (dict "hookType" "pre-upgrade") . }}
+{{- end -}}
+
+{{/* Custom resource uninstalling hook annotations */}}
+{{- define "cdi.crUninstallHook.annotations" -}}
+{{ template "cdi.hook.annotations" merge (dict "hookType" "pre-delete") . }}
+{{- end -}}
+
+{{/* CRD uninstalling hook annotations */}}
+{{- define "cdi.crdUninstallHook.annotations" -}}
+{{ template "cdi.hook.annotations" merge (dict "hookType" "post-delete") . }}
+{{- end -}}
+
+{{/* Namespace modifying hook name */}}
+{{- define "cdi.namespaceHook.name" -}}
+{{ include "cdi.fullname" . }}-namespace-modify
+{{- end }}
+
+{{/* CRD upgrading hook name */}}
+{{- define "cdi.crdUpgradeHook.name" -}}
+{{ include "cdi.fullname" . }}-crd-upgrade
+{{- end }}
+
+{{/* Custom resource uninstalling hook name */}}
+{{- define "cdi.crUninstallHook.name" -}}
+{{ include "cdi.fullname" . }}-uninstall
+{{- end }}
+
+{{/* CRD uninstalling hook name */}}
+{{- define "cdi.crdUninstallHook.name" -}}
+{{ include "cdi.fullname" . }}-crd-uninstall
+{{- end }}
diff --git a/cdi-chart/templates/cdi-operator.yaml b/cdi-chart/templates/cdi-operator.yaml
new file mode 100644
index 0000000..f6ab6fe
--- /dev/null
+++ b/cdi-chart/templates/cdi-operator.yaml
@@ -0,0 +1,671 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ labels:
+ operator.cdi.kubevirt.io: ""
+ name: cdi-operator-cluster
+rules:
+ - apiGroups:
+ - rbac.authorization.k8s.io
+ resources:
+ - clusterrolebindings
+ - clusterroles
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - delete
+ - apiGroups:
+ - security.openshift.io
+ resources:
+ - securitycontextconstraints
+ verbs:
+ - get
+ - list
+ - watch
+ - update
+ - create
+ - apiGroups:
+ - apiextensions.k8s.io
+ resources:
+ - customresourcedefinitions
+ - customresourcedefinitions/status
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - delete
+ - apiGroups:
+ - cdi.kubevirt.io
+ - upload.cdi.kubevirt.io
+ resources:
+ - '*'
+ verbs:
+ - '*'
+ - apiGroups:
+ - admissionregistration.k8s.io
+ resources:
+ - validatingwebhookconfigurations
+ - mutatingwebhookconfigurations
+ verbs:
+ - create
+ - list
+ - watch
+ - apiGroups:
+ - admissionregistration.k8s.io
+ resourceNames:
+ - cdi-api-dataimportcron-validate
+ - cdi-api-populator-validate
+ - cdi-api-datavolume-validate
+ - cdi-api-validate
+ - objecttransfer-api-validate
+ resources:
+ - validatingwebhookconfigurations
+ verbs:
+ - get
+ - update
+ - delete
+ - apiGroups:
+ - admissionregistration.k8s.io
+ resourceNames:
+ - cdi-api-datavolume-mutate
+ - cdi-api-pvc-mutate
+ resources:
+ - mutatingwebhookconfigurations
+ verbs:
+ - get
+ - update
+ - delete
+ - apiGroups:
+ - apiregistration.k8s.io
+ resources:
+ - apiservices
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - delete
+ - apiGroups:
+ - authorization.k8s.io
+ resources:
+ - subjectaccessreviews
+ verbs:
+ - create
+ - apiGroups:
+ - ""
+ resources:
+ - configmaps
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - ""
+ resources:
+ - persistentvolumeclaims
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - ""
+ resources:
+ - persistentvolumes
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - storage.k8s.io
+ resources:
+ - storageclasses
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - ""
+ resources:
+ - namespaces
+ verbs:
+ - get
+ - apiGroups:
+ - snapshot.storage.k8s.io
+ resources:
+ - volumesnapshots
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - cdi.kubevirt.io
+ resources:
+ - datavolumes
+ verbs:
+ - list
+ - get
+ - apiGroups:
+ - cdi.kubevirt.io
+ resources:
+ - datasources
+ verbs:
+ - get
+ - apiGroups:
+ - cdi.kubevirt.io
+ resources:
+ - volumeclonesources
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - cdi.kubevirt.io
+ resources:
+ - storageprofiles
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - cdi.kubevirt.io
+ resources:
+ - cdis
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - cdi.kubevirt.io
+ resources:
+ - cdiconfigs
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - cdi.kubevirt.io
+ resources:
+ - cdis/finalizers
+ verbs:
+ - update
+ - apiGroups:
+ - ""
+ resources:
+ - events
+ verbs:
+ - create
+ - patch
+ - apiGroups:
+ - ""
+ resources:
+ - persistentvolumeclaims
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - delete
+ - deletecollection
+ - patch
+ - apiGroups:
+ - ""
+ resources:
+ - persistentvolumes
+ verbs:
+ - get
+ - list
+ - watch
+ - update
+ - apiGroups:
+ - ""
+ resources:
+ - persistentvolumeclaims/finalizers
+ - pods/finalizers
+ verbs:
+ - update
+ - apiGroups:
+ - ""
+ resources:
+ - pods
+ - services
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - delete
+ - apiGroups:
+ - ""
+ resources:
+ - configmaps
+ verbs:
+ - get
+ - create
+ - apiGroups:
+ - storage.k8s.io
+ resources:
+ - storageclasses
+ - csidrivers
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - config.openshift.io
+ resources:
+ - proxies
+ - infrastructures
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - config.openshift.io
+ resources:
+ - clusterversions
+ verbs:
+ - get
+ - apiGroups:
+ - cdi.kubevirt.io
+ resources:
+ - '*'
+ verbs:
+ - '*'
+ - apiGroups:
+ - snapshot.storage.k8s.io
+ resources:
+ - volumesnapshots
+ - volumesnapshotclasses
+ - volumesnapshotcontents
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - delete
+ - apiGroups:
+ - snapshot.storage.k8s.io
+ resources:
+ - volumesnapshots
+ verbs:
+ - update
+ - deletecollection
+ - apiGroups:
+ - apiextensions.k8s.io
+ resources:
+ - customresourcedefinitions
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - scheduling.k8s.io
+ resources:
+ - priorityclasses
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - image.openshift.io
+ resources:
+ - imagestreams
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - ""
+ resources:
+ - secrets
+ verbs:
+ - create
+ - apiGroups:
+ - kubevirt.io
+ resources:
+ - virtualmachines/finalizers
+ verbs:
+ - update
+ - apiGroups:
+ - forklift.cdi.kubevirt.io
+ resources:
+ - ovirtvolumepopulators
+ - openstackvolumepopulators
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - ""
+ resources:
+ - persistentvolumeclaims
+ verbs:
+ - get
+ - apiGroups:
+ - cdi.kubevirt.io
+ resources:
+ - dataimportcrons
+ verbs:
+ - get
+ - list
+ - update
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ labels:
+ operator.cdi.kubevirt.io: ""
+ name: cdi-operator
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: cdi-operator-cluster
+subjects:
+ - kind: ServiceAccount
+ name: cdi-operator
+ namespace: {{ .Release.Namespace }}
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ labels:
+ operator.cdi.kubevirt.io: ""
+ name: cdi-operator
+ namespace: {{ .Release.Namespace }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ labels:
+ app: containerized-data-importer
+ app.kubernetes.io/component: storage
+ app.kubernetes.io/managed-by: cdi-operator
+ cdi.kubevirt.io: ""
+ name: cdi-operator
+ namespace: {{ .Release.Namespace }}
+rules:
+ - apiGroups:
+ - rbac.authorization.k8s.io
+ resources:
+ - rolebindings
+ - roles
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - delete
+ - apiGroups:
+ - ""
+ resources:
+ - serviceaccounts
+ - configmaps
+ - events
+ - secrets
+ - services
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - patch
+ - delete
+ - apiGroups:
+ - apps
+ resources:
+ - deployments
+ - deployments/finalizers
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - delete
+ - apiGroups:
+ - route.openshift.io
+ resources:
+ - routes
+ - routes/custom-host
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - apiGroups:
+ - config.openshift.io
+ resources:
+ - proxies
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - monitoring.coreos.com
+ resources:
+ - servicemonitors
+ - prometheusrules
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - delete
+ - update
+ - patch
+ - apiGroups:
+ - coordination.k8s.io
+ resources:
+ - leases
+ verbs:
+ - get
+ - create
+ - update
+ - apiGroups:
+ - ""
+ resources:
+ - secrets
+ - configmaps
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - apiGroups:
+ - ""
+ resources:
+ - configmaps
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - delete
+ - apiGroups:
+ - ""
+ resources:
+ - secrets
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - batch
+ resources:
+ - cronjobs
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - deletecollection
+ - apiGroups:
+ - batch
+ resources:
+ - jobs
+ verbs:
+ - create
+ - deletecollection
+ - list
+ - watch
+ - apiGroups:
+ - coordination.k8s.io
+ resources:
+ - leases
+ verbs:
+ - get
+ - create
+ - update
+ - apiGroups:
+ - networking.k8s.io
+ resources:
+ - ingresses
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - route.openshift.io
+ resources:
+ - routes
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - ""
+ resources:
+ - configmaps
+ verbs:
+ - get
+ - apiGroups:
+ - ""
+ resources:
+ - services
+ - endpoints
+ - pods
+ verbs:
+ - get
+ - list
+ - watch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ labels:
+ app: containerized-data-importer
+ app.kubernetes.io/component: storage
+ app.kubernetes.io/managed-by: cdi-operator
+ cdi.kubevirt.io: ""
+ name: cdi-operator
+ namespace: {{ .Release.Namespace }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: cdi-operator
+subjects:
+ - kind: ServiceAccount
+ name: cdi-operator
+ namespace: {{ .Release.Namespace }}
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ cdi.kubevirt.io: cdi-operator
+ name: cdi-operator
+ operator.cdi.kubevirt.io: ""
+ prometheus.cdi.kubevirt.io: "true"
+ name: cdi-operator
+ namespace: {{ .Release.Namespace }}
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ name: cdi-operator
+ operator.cdi.kubevirt.io: ""
+ strategy: {}
+ template:
+ metadata:
+ labels:
+ cdi.kubevirt.io: cdi-operator
+ name: cdi-operator
+ operator.cdi.kubevirt.io: ""
+ prometheus.cdi.kubevirt.io: "true"
+ spec:
+ affinity:
+ podAffinity:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ - podAffinityTerm:
+ labelSelector:
+ matchExpressions:
+ - key: cdi.kubevirt.io
+ operator: In
+ values:
+ - cdi-operator
+ topologyKey: kubernetes.io/hostname
+ weight: 1
+ containers:
+ - env:
+ - name: DEPLOY_CLUSTER_RESOURCES
+ value: "true"
+ - name: OPERATOR_VERSION
+ value: {{ .Values.deployment.version }}
+ - name: CONTROLLER_IMAGE
+ value: {{ .Values.deployment.controllerImage }}:{{ .Values.deployment.version }}
+ - name: IMPORTER_IMAGE
+ value: {{ .Values.deployment.importerImage }}:{{ .Values.deployment.version }}
+ - name: CLONER_IMAGE
+ value: {{ .Values.deployment.clonerImage }}:{{ .Values.deployment.version }}
+ - name: OVIRT_POPULATOR_IMAGE
+ value: {{ .Values.deployment.importerImage }}:{{ .Values.deployment.version }}
+ - name: APISERVER_IMAGE
+ value: {{ .Values.deployment.apiserverImage }}:{{ .Values.deployment.version }}
+ - name: UPLOAD_SERVER_IMAGE
+ value: {{ .Values.deployment.uploadserverImage }}:{{ .Values.deployment.version }}
+ - name: UPLOAD_PROXY_IMAGE
+ value: {{ .Values.deployment.uploadproxyImage }}:{{ .Values.deployment.version }}
+ - name: VERBOSITY
+ value: "1"
+ - name: PULL_POLICY
+ value: {{ .Values.deployment.pullPolicy }}
+ - name: MONITORING_NAMESPACE
+ image: {{ .Values.deployment.operatorImage }}:{{ .Values.deployment.version }}
+ imagePullPolicy: {{ .Values.deployment.pullPolicy }}
+ name: cdi-operator
+ ports:
+ - containerPort: 8080
+ name: metrics
+ protocol: TCP
+ resources:
+ requests:
+ cpu: 100m
+ memory: 150Mi
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
+ runAsNonRoot: true
+ seccompProfile:
+ type: RuntimeDefault
+ nodeSelector:
+ kubernetes.io/os: linux
+ securityContext:
+ runAsNonRoot: true
+ serviceAccountName: cdi-operator
+ tolerations:
+ - key: CriticalAddonsOnly
+ operator: Exists
diff --git a/cdi-chart/templates/cdi-uninstall-hooks.yaml b/cdi-chart/templates/cdi-uninstall-hooks.yaml
new file mode 100644
index 0000000..d737539
--- /dev/null
+++ b/cdi-chart/templates/cdi-uninstall-hooks.yaml
@@ -0,0 +1,69 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ namespace: {{ .Release.Namespace }}
+ name: {{ template "cdi.crUninstallHook.name" . }}
+ {{ template "cdi.crUninstallHook.annotations" (dict "hookWeight" 1) }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ template "cdi.crUninstallHook.name" . }}
+ {{ template "cdi.crUninstallHook.annotations" (dict "hookWeight" 1) }}
+rules:
+ - apiGroups: [ "cdi.kubevirt.io" ]
+ resources: [ "cdis" ]
+ resourceNames:
+ - "cdi"
+ verbs: [ "delete" ]
+ - apiGroups: [ "apps" ]
+ resources: [ "deployments" ]
+ verbs: [ "get", "list" ]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ template "cdi.crUninstallHook.name" . }}
+ {{ template "cdi.crUninstallHook.annotations" (dict "hookWeight" 2) }}
+subjects:
+ - kind: ServiceAccount
+ namespace: {{ .Release.Namespace }}
+ name: {{ template "cdi.crUninstallHook.name" . }}
+roleRef:
+ kind: ClusterRole
+ name: {{ template "cdi.crUninstallHook.name" . }}
+ apiGroup: rbac.authorization.k8s.io
+---
+apiVersion: batch/v1
+kind: Job
+metadata:
+ namespace: {{ .Release.Namespace }}
+ name: {{ template "cdi.crUninstallHook.name" . }}
+ {{ template "cdi.crUninstallHook.annotations" (dict "hookWeight" 3) }}
+spec:
+ template:
+ metadata:
+ name: {{ template "cdi.crUninstallHook.name" . }}
+ spec:
+ serviceAccountName: {{ template "cdi.crUninstallHook.name" . }}
+ restartPolicy: {{ .Values.hookRestartPolicy }}
+ containers:
+ - name: {{ template "cdi.crUninstallHook.name" . }}
+ image: {{ .Values.hookImage }}
+ securityContext:
+ {{- toYaml .Values.hookSecurityContext | nindent 12 }}
+ args:
+ - delete
+ - cdi
+ - cdi
+ - name: {{ template "cdi.crUninstallHook.name" . }}-cleanup
+ image: {{ .Values.hookImage }}
+ securityContext:
+ {{- toYaml .Values.hookSecurityContext | nindent 12 }}
+ args:
+ - wait
+ - --for=delete
+ - deployments/cdi-apiserver
+ - deployments/cdi-deployment
+ - deployments/cdi-uploadproxy
+ - --timeout=60s
diff --git a/cdi-chart/templates/cdi.yaml b/cdi-chart/templates/cdi.yaml
new file mode 100644
index 0000000..b3e476d
--- /dev/null
+++ b/cdi-chart/templates/cdi.yaml
@@ -0,0 +1,21 @@
+apiVersion: cdi.kubevirt.io/v1beta1
+kind: CDI
+metadata:
+ name: cdi
+spec:
+ {{- with .Values.cdi.config }}
+ config:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ imagePullPolicy: {{ .Values.cdi.imagePullPolicy }}
+ {{- with .Values.cdi.infra }}
+ infra:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- if .Values.cdi.uninstallStrategy }}
+ uninstallStrategy: {{ .Values.cdi.uninstallStrategy }}
+ {{- end }}
+ {{- with .Values.cdi.workload }}
+ workload:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
diff --git a/cdi-chart/templates/crd-uninstall-hooks.yaml b/cdi-chart/templates/crd-uninstall-hooks.yaml
new file mode 100644
index 0000000..19bdaf2
--- /dev/null
+++ b/cdi-chart/templates/crd-uninstall-hooks.yaml
@@ -0,0 +1,55 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ namespace: {{ .Release.Namespace }}
+ name: {{ template "cdi.crdUninstallHook.name" . }}
+ {{ template "cdi.crdUninstallHook.annotations" (dict "hookWeight" 1) }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ template "cdi.crdUninstallHook.name" . }}
+ {{ template "cdi.crdUninstallHook.annotations" (dict "hookWeight" 1) }}
+rules:
+ - apiGroups: [ "apiextensions.k8s.io" ]
+ resources: [ "customresourcedefinitions" ]
+ resourceNames:
+ - "cdis.cdi.kubevirt.io"
+ verbs: [ "delete" ]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ template "cdi.crdUninstallHook.name" . }}
+ {{ template "cdi.crdUninstallHook.annotations" (dict "hookWeight" 2) }}
+subjects:
+ - kind: ServiceAccount
+ namespace: {{ .Release.Namespace }}
+ name: {{ template "cdi.crdUninstallHook.name" . }}
+roleRef:
+ kind: ClusterRole
+ name: {{ template "cdi.crdUninstallHook.name" . }}
+ apiGroup: rbac.authorization.k8s.io
+---
+apiVersion: batch/v1
+kind: Job
+metadata:
+ namespace: {{ .Release.Namespace }}
+ name: {{ template "cdi.crdUninstallHook.name" . }}
+ {{ template "cdi.crdUninstallHook.annotations" (dict "hookWeight" 3) }}
+spec:
+ template:
+ metadata:
+ name: {{ template "cdi.crdUninstallHook.name" . }}
+ spec:
+ serviceAccountName: {{ template "cdi.crdUninstallHook.name" . }}
+ restartPolicy: {{ .Values.hookRestartPolicy }}
+ containers:
+ - name: {{ template "cdi.crdUninstallHook.name" . }}
+ image: {{ .Values.hookImage }}
+ args:
+ - delete
+ - customresourcedefinitions
+ - cdis.cdi.kubevirt.io
+ securityContext:
+ {{- toYaml .Values.hookSecurityContext | nindent 12 }}
diff --git a/cdi-chart/templates/crd-upgrade-hooks.yaml b/cdi-chart/templates/crd-upgrade-hooks.yaml
new file mode 100644
index 0000000..f650adc
--- /dev/null
+++ b/cdi-chart/templates/crd-upgrade-hooks.yaml
@@ -0,0 +1,80 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ namespace: {{ .Release.Namespace }}
+ name: cdi-crd-manifest
+ {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 1) }}
+data:
+ crd: |-
+ {{ $.Files.Get "crds/cdi.yaml" | nindent 4 }}
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ namespace: {{ .Release.Namespace }}
+ name: {{ template "cdi.crdUpgradeHook.name" . }}
+ {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 2) }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ template "cdi.crdUpgradeHook.name" . }}
+ {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 2) }}
+rules:
+ - apiGroups: [ "" ]
+ resources: [ "configmaps" ]
+ resourceNames:
+ - "cdi-crd-manifest"
+ verbs: [ "get" ]
+ - apiGroups: [ "apiextensions.k8s.io" ]
+ resources: [ "customresourcedefinitions" ]
+ resourceNames:
+ - "cdis.cdi.kubevirt.io"
+ verbs: [ "get", "patch" ]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ template "cdi.crdUpgradeHook.name" . }}
+ {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 3) }}
+subjects:
+ - kind: ServiceAccount
+ namespace: {{ .Release.Namespace }}
+ name: {{ template "cdi.crdUpgradeHook.name" . }}
+roleRef:
+ kind: ClusterRole
+ name: {{ template "cdi.crdUpgradeHook.name" . }}
+ apiGroup: rbac.authorization.k8s.io
+---
+apiVersion: batch/v1
+kind: Job
+metadata:
+ namespace: {{ .Release.Namespace }}
+ name: {{ template "cdi.crdUpgradeHook.name" . }}
+ {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 4) }}
+spec:
+ template:
+ metadata:
+ name: {{ template "cdi.crdUpgradeHook.name" . }}
+ spec:
+ serviceAccountName: {{ template "cdi.crdUpgradeHook.name" . }}
+ restartPolicy: {{ .Values.hookRestartPolicy }}
+ containers:
+ - name: {{ template "cdi.crdUpgradeHook.name" . }}
+ image: {{ .Values.hookImage }}
+ args:
+ - apply
+ - -f
+ - /etc/manifests/crd.yaml
+ securityContext:
+ {{- toYaml .Values.hookSecurityContext | nindent 12 }}
+ volumeMounts:
+ - name: crd-volume
+ mountPath: /etc/manifests
+ volumes:
+ - name: crd-volume
+ configMap:
+ name: cdi-crd-manifest
+ items:
+ - key: crd
+ path: crd.yaml
diff --git a/cdi-chart/templates/namespace-hooks.yaml b/cdi-chart/templates/namespace-hooks.yaml
new file mode 100644
index 0000000..30d16a4
--- /dev/null
+++ b/cdi-chart/templates/namespace-hooks.yaml
@@ -0,0 +1,56 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ namespace: {{ .Release.Namespace }}
+ name: {{ template "cdi.namespaceHook.name" . }}
+ {{ template "cdi.namespaceHook.annotations" (dict "hookWeight" 1) }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ template "cdi.namespaceHook.name" . }}
+ {{ template "cdi.namespaceHook.annotations" (dict "hookWeight" 1) }}
+rules:
+ - apiGroups: [ "" ]
+ resources: [ "namespaces" ]
+ resourceNames:
+ - {{ .Release.Namespace | quote }}
+ verbs: [ "get", "patch" ]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ template "cdi.namespaceHook.name" . }}
+ {{ template "cdi.namespaceHook.annotations" (dict "hookWeight" 2) }}
+subjects:
+ - kind: ServiceAccount
+ namespace: {{ .Release.Namespace }}
+ name: {{ template "cdi.namespaceHook.name" . }}
+roleRef:
+ kind: ClusterRole
+ name: {{ template "cdi.namespaceHook.name" . }}
+ apiGroup: rbac.authorization.k8s.io
+---
+apiVersion: batch/v1
+kind: Job
+metadata:
+ namespace: {{ .Release.Namespace }}
+ name: {{ template "cdi.namespaceHook.name" . }}
+ {{ template "cdi.namespaceHook.annotations" (dict "hookWeight" 3) }}
+spec:
+ template:
+ metadata:
+ name: {{ template "cdi.namespaceHook.name" . }}
+ spec:
+ serviceAccountName: {{ template "cdi.namespaceHook.name" . }}
+ restartPolicy: {{ .Values.hookRestartPolicy }}
+ containers:
+ - name: {{ template "cdi.namespaceHook.name" . }}
+ securityContext:
+ {{- toYaml .Values.hookSecurityContext | nindent 12 }}
+ image: {{ .Values.hookImage }}
+ args:
+ - label
+ - namespace
+ - {{ .Release.Namespace }}
+ - cdi.kubevirt.io=
diff --git a/cdi-chart/values.yaml b/cdi-chart/values.yaml
new file mode 100644
index 0000000..b4c1fef
--- /dev/null
+++ b/cdi-chart/values.yaml
@@ -0,0 +1,38 @@
+deployment:
+ version: 1.60.1-150600.3.9.1
+ operatorImage: registry.suse.com/suse/sles/15.6/cdi-operator
+ controllerImage: registry.suse.com/suse/sles/15.6/cdi-controller
+ importerImage: registry.suse.com/suse/sles/15.6/cdi-importer
+ clonerImage: registry.suse.com/suse/sles/15.6/cdi-cloner
+ apiserverImage: registry.suse.com/suse/sles/15.6/cdi-apiserver
+ uploadserverImage: registry.suse.com/suse/sles/15.6/cdi-uploadserver
+ uploadproxyImage: registry.suse.com/suse/sles/15.6/cdi-uploadproxy
+ pullPolicy: IfNotPresent
+
+cdi:
+ config:
+ featureGates:
+ - HonorWaitForFirstConsumer
+ imagePullPolicy: "IfNotPresent"
+ infra:
+ nodeSelector:
+ kubernetes.io/os: linux
+ tolerations:
+ - key: CriticalAddonsOnly
+ operator: Exists
+ uninstallStrategy: ""
+ workload:
+ nodeSelector:
+ kubernetes.io/os: linux
+
+hookImage: rancher/kubectl:v1.30.2
+hookRestartPolicy: OnFailure
+hookSecurityContext:
+ seccompProfile:
+ type: RuntimeDefault
+ runAsNonRoot: true
+ runAsUser: 1000
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
diff --git a/cluster-api-controller-image/Dockerfile b/cluster-api-controller-image/Dockerfile
new file mode 100644
index 0000000..758da5e
--- /dev/null
+++ b/cluster-api-controller-image/Dockerfile
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: Apache-2.0
+#!BuildTag: %%IMG_PREFIX%%cluster-api-controller:v%%cluster-api_version%%
+#!BuildTag: %%IMG_PREFIX%%cluster-api-controller:%%cluster-api_version%%
+#!BuildTag: %%IMG_PREFIX%%cluster-api-controller:%%cluster-api_version%%-%RELEASE%
+#!BuildVersion: 15.6
+ARG SLE_VERSION
+FROM registry.suse.com/bci/bci-micro:$SLE_VERSION AS micro
+
+FROM registry.suse.com/bci/bci-base:$SLE_VERSION AS base
+COPY --from=micro / /installroot/
+RUN zypper --installroot /installroot --non-interactive install --no-recommends cluster-api shadow; zypper -n clean; rm -rf /var/log/*
+
+FROM micro AS final
+# Define labels according to https://en.opensuse.org/Building_derived_containers
+# labelprefix=com.suse.application.cluster-api
+LABEL org.opencontainers.image.authors="SUSE LLC (https://www.suse.com/)"
+LABEL org.opencontainers.image.title="SLE cluster-api Container Image"
+LABEL org.opencontainers.image.description="cluster-api based on the SLE Base Container Image."
+LABEL org.opencontainers.image.version="%%cluster-api_version%%"
+LABEL org.opencontainers.image.url="https://www.suse.com/products/server/"
+LABEL org.opencontainers.image.created="%BUILDTIME%"
+LABEL org.opencontainers.image.vendor="SUSE LLC"
+LABEL org.opensuse.reference="%%IMG_REPO%%/%%IMG_PREFIX%%cluster-api:%%cluster-api_version%%-%RELEASE%"
+LABEL org.openbuildservice.disturl="%DISTURL%"
+LABEL com.suse.supportlevel="l3"
+LABEL com.suse.eula="SUSE Combined EULA February 2024"
+LABEL com.suse.lifecycle-url="https://www.suse.com/lifecycle"
+LABEL com.suse.image-type="application"
+LABEL com.suse.release-stage="released"
+# endlabelprefix
+
+COPY --from=base /installroot /
+RUN mv /usr/bin/cluster-api-controller /manager
+# Use uid of nonroot user (65532) because kubernetes expects numeric user when applying pod security policies
+USER 65532
+ENTRYPOINT [ "/manager" ]
diff --git a/cluster-api-controller-image/_service b/cluster-api-controller-image/_service
new file mode 100644
index 0000000..05f906c
--- /dev/null
+++ b/cluster-api-controller-image/_service
@@ -0,0 +1,17 @@
+
+
+
+
+ Dockerfile
+ %%cluster-api_version%%
+ cluster-api
+ patch
+
+
+ Dockerfile
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+
diff --git a/cluster-api-operator-image/Dockerfile b/cluster-api-operator-image/Dockerfile
new file mode 100644
index 0000000..b6fbc89
--- /dev/null
+++ b/cluster-api-operator-image/Dockerfile
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: Apache-2.0
+#!BuildTag: %%IMG_PREFIX%%cluster-api-operator:%%cluster-api-operator_version%%
+#!BuildTag: %%IMG_PREFIX%%cluster-api-operator:%%cluster-api-operator_version%%-%RELEASE%
+#!BuildVersion: 15.6
+ARG SLE_VERSION
+FROM registry.suse.com/bci/bci-micro:$SLE_VERSION AS micro
+
+FROM registry.suse.com/bci/bci-base:$SLE_VERSION AS base
+COPY --from=micro / /installroot/
+RUN zypper --installroot /installroot --non-interactive install --no-recommends cluster-api-operator shadow; zypper -n clean; rm -rf /var/log/*
+
+FROM micro AS final
+# Define labels according to https://en.opensuse.org/Building_derived_containers
+# labelprefix=com.suse.application.cluster-api-operator
+LABEL org.opencontainers.image.authors="SUSE LLC (https://www.suse.com/)"
+LABEL org.opencontainers.image.title="SLE cluster-api-operator Container Image"
+LABEL org.opencontainers.image.description="cluster-api-operator based on the SLE Base Container Image."
+LABEL org.opencontainers.image.version="%%cluster-api-operator_version%%"
+LABEL org.opencontainers.image.url="https://www.suse.com/products/server/"
+LABEL org.opencontainers.image.created="%BUILDTIME%"
+LABEL org.opencontainers.image.vendor="SUSE LLC"
+LABEL org.opensuse.reference="%%IMG_REPO%%/%%IMG_PREFIX%%cluster-api-operator:%%cluster-api-operator_version%%-%RELEASE%"
+LABEL org.openbuildservice.disturl="%DISTURL%"
+LABEL com.suse.supportlevel="l3"
+LABEL com.suse.eula="SUSE Combined EULA February 2024"
+LABEL com.suse.lifecycle-url="https://www.suse.com/lifecycle"
+LABEL com.suse.image-type="application"
+LABEL com.suse.release-stage="released"
+# endlabelprefix
+
+COPY --from=base /installroot /
+RUN mv /usr/bin/cluster-api-operator-controller /manager
+# Use uid of nonroot user (65532) because kubernetes expects numeric user when applying pod security policies
+USER 65532
+ENTRYPOINT [ "/manager" ]
diff --git a/cluster-api-operator-image/_service b/cluster-api-operator-image/_service
new file mode 100644
index 0000000..1edc617
--- /dev/null
+++ b/cluster-api-operator-image/_service
@@ -0,0 +1,17 @@
+
+
+
+
+ Dockerfile
+ %%cluster-api-operator_version%%
+ cluster-api-operator
+ patch
+
+
+ Dockerfile
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+
diff --git a/cluster-api-provider-metal3-image/Dockerfile b/cluster-api-provider-metal3-image/Dockerfile
new file mode 100644
index 0000000..727007d
--- /dev/null
+++ b/cluster-api-provider-metal3-image/Dockerfile
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: Apache-2.0
+#!BuildTag: %%IMG_PREFIX%%cluster-api-provider-metal3:v%%cluster-api-provider-metal3_version%%
+#!BuildTag: %%IMG_PREFIX%%cluster-api-provider-metal3:%%cluster-api-provider-metal3_version%%
+#!BuildTag: %%IMG_PREFIX%%cluster-api-provider-metal3:%%cluster-api-provider-metal3_version%%-%RELEASE%
+#!BuildVersion: 15.6
+ARG SLE_VERSION
+FROM registry.suse.com/bci/bci-micro:$SLE_VERSION AS micro
+
+FROM registry.suse.com/bci/bci-base:$SLE_VERSION AS base
+COPY --from=micro / /installroot/
+RUN zypper --installroot /installroot --non-interactive install --no-recommends cluster-api-provider-metal3 shadow; zypper -n clean; rm -rf /var/log/*
+
+FROM micro AS final
+# Define labels according to https://en.opensuse.org/Building_derived_containers
+# labelprefix=com.suse.application.cluster-api-provider-metal3
+LABEL org.opencontainers.image.authors="SUSE LLC (https://www.suse.com/)"
+LABEL org.opencontainers.image.title="SLE cluster-api-provider-metal3 Container Image"
+LABEL org.opencontainers.image.description="cluster-api-provider-metal3 based on the SLE Base Container Image."
+LABEL org.opencontainers.image.version="%%cluster-api-provider-metal3_version%%"
+LABEL org.opencontainers.image.url="https://www.suse.com/products/server/"
+LABEL org.opencontainers.image.created="%BUILDTIME%"
+LABEL org.opencontainers.image.vendor="SUSE LLC"
+LABEL org.opensuse.reference="%%IMG_REPO%%/%%IMG_PREFIX%%cluster-api-provider-metal3:%%cluster-api-provider-metal3_version%%-%RELEASE%"
+LABEL org.openbuildservice.disturl="%DISTURL%"
+LABEL com.suse.supportlevel="l3"
+LABEL com.suse.eula="SUSE Combined EULA February 2024"
+LABEL com.suse.lifecycle-url="https://www.suse.com/lifecycle"
+LABEL com.suse.image-type="application"
+LABEL com.suse.release-stage="released"
+# endlabelprefix
+
+COPY --from=base /installroot /
+RUN mv /usr/bin/cluster-api-provider-metal3 /manager
+# Use uid of nonroot user (65532) because kubernetes expects numeric user when applying pod security policies
+USER 65532
+ENTRYPOINT [ "/manager" ]
diff --git a/cluster-api-provider-metal3-image/_service b/cluster-api-provider-metal3-image/_service
new file mode 100644
index 0000000..ec4e439
--- /dev/null
+++ b/cluster-api-provider-metal3-image/_service
@@ -0,0 +1,17 @@
+
+
+
+
+ Dockerfile
+ %%cluster-api-provider-metal3_version%%
+ cluster-api-provider-metal3
+ patch
+
+
+ Dockerfile
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+
diff --git a/cluster-api-provider-rke2-bootstrap-image/Dockerfile b/cluster-api-provider-rke2-bootstrap-image/Dockerfile
new file mode 100644
index 0000000..6f3be33
--- /dev/null
+++ b/cluster-api-provider-rke2-bootstrap-image/Dockerfile
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: Apache-2.0
+#!BuildTag: %%IMG_PREFIX%%cluster-api-provider-rke2-bootstrap:v%%cluster-api-provider-rke2_version%%
+#!BuildTag: %%IMG_PREFIX%%cluster-api-provider-rke2-bootstrap:%%cluster-api-provider-rke2_version%%
+#!BuildTag: %%IMG_PREFIX%%cluster-api-provider-rke2-bootstrap:%%cluster-api-provider-rke2_version%%-%RELEASE%
+#!BuildVersion: 15.6
+ARG SLE_VERSION
+FROM registry.suse.com/bci/bci-micro:$SLE_VERSION AS micro
+
+FROM registry.suse.com/bci/bci-base:$SLE_VERSION AS base
+COPY --from=micro / /installroot/
+RUN zypper --installroot /installroot --non-interactive install --no-recommends cluster-api-provider-rke2-bootstrap shadow; zypper -n clean; rm -rf /var/log/*
+
+FROM micro AS final
+# Define labels according to https://en.opensuse.org/Building_derived_containers
+# labelprefix=com.suse.application.cluster-api-provider-rke2
+LABEL org.opencontainers.image.authors="SUSE LLC (https://www.suse.com/)"
+LABEL org.opencontainers.image.title="SLE cluster-api-provider-rke2 Container Image"
+LABEL org.opencontainers.image.description="cluster-api-provider-rke2 based on the SLE Base Container Image."
+LABEL org.opencontainers.image.version="%%cluster-api-provider-rke2_version%%"
+LABEL org.opencontainers.image.url="https://www.suse.com/products/server/"
+LABEL org.opencontainers.image.created="%BUILDTIME%"
+LABEL org.opencontainers.image.vendor="SUSE LLC"
+LABEL org.opensuse.reference="%%IMG_REPO%%/%%IMG_PREFIX%%cluster-api-provider-rke2-bootstrap:%%cluster-api-provider-rke2_version%%-%RELEASE%"
+LABEL org.openbuildservice.disturl="%DISTURL%"
+LABEL com.suse.supportlevel="l3"
+LABEL com.suse.eula="SUSE Combined EULA February 2024"
+LABEL com.suse.lifecycle-url="https://www.suse.com/lifecycle"
+LABEL com.suse.image-type="application"
+LABEL com.suse.release-stage="released"
+# endlabelprefix
+
+COPY --from=base /installroot /
+RUN mv /usr/bin/rke2-bootstrap-manager /manager
+# Use uid of nonroot user (65532) because kubernetes expects numeric user when applying pod security policies
+USER 65532
+ENTRYPOINT [ "/manager" ]
diff --git a/cluster-api-provider-rke2-bootstrap-image/_service b/cluster-api-provider-rke2-bootstrap-image/_service
new file mode 100644
index 0000000..430aa7c
--- /dev/null
+++ b/cluster-api-provider-rke2-bootstrap-image/_service
@@ -0,0 +1,17 @@
+
+
+
+
+ Dockerfile
+ %%cluster-api-provider-rke2_version%%
+ cluster-api-provider-rke2-bootstrap
+ patch
+
+
+ Dockerfile
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+
diff --git a/cluster-api-provider-rke2-controlplane-image/Dockerfile b/cluster-api-provider-rke2-controlplane-image/Dockerfile
new file mode 100644
index 0000000..011bc75
--- /dev/null
+++ b/cluster-api-provider-rke2-controlplane-image/Dockerfile
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: Apache-2.0
+#!BuildTag: %%IMG_PREFIX%%cluster-api-provider-rke2-controlplane:v%%cluster-api-provider-rke2_version%%
+#!BuildTag: %%IMG_PREFIX%%cluster-api-provider-rke2-controlplane:%%cluster-api-provider-rke2_version%%
+#!BuildTag: %%IMG_PREFIX%%cluster-api-provider-rke2-controlplane:%%cluster-api-provider-rke2_version%%-%RELEASE%
+#!BuildVersion: 15.6
+ARG SLE_VERSION
+FROM registry.suse.com/bci/bci-micro:$SLE_VERSION AS micro
+
+FROM registry.suse.com/bci/bci-base:$SLE_VERSION AS base
+COPY --from=micro / /installroot/
+RUN zypper --installroot /installroot --non-interactive install --no-recommends cluster-api-provider-rke2-control-plane shadow; zypper -n clean; rm -rf /var/log/*
+
+FROM micro AS final
+# Define labels according to https://en.opensuse.org/Building_derived_containers
+# labelprefix=com.suse.application.cluster-api-provider-rke2
+LABEL org.opencontainers.image.authors="SUSE LLC (https://www.suse.com/)"
+LABEL org.opencontainers.image.title="SLE cluster-api-provider-rke2 Container Image"
+LABEL org.opencontainers.image.description="cluster-api-provider-rke2 based on the SLE Base Container Image."
+LABEL org.opencontainers.image.version="%%cluster-api-provider-rke2_version%%"
+LABEL org.opencontainers.image.url="https://www.suse.com/products/server/"
+LABEL org.opencontainers.image.created="%BUILDTIME%"
+LABEL org.opencontainers.image.vendor="SUSE LLC"
+LABEL org.opensuse.reference="%%IMG_REPO%%/%%IMG_PREFIX%%cluster-api-provider-rke2-controlplane:%%cluster-api-provider-rke2_version%%-%RELEASE%"
+LABEL org.openbuildservice.disturl="%DISTURL%"
+LABEL com.suse.supportlevel="l3"
+LABEL com.suse.eula="SUSE Combined EULA February 2024"
+LABEL com.suse.lifecycle-url="https://www.suse.com/lifecycle"
+LABEL com.suse.image-type="application"
+LABEL com.suse.release-stage="released"
+# endlabelprefix
+
+COPY --from=base /installroot /
+RUN mv /usr/bin/rke2-control-plane-manager /manager
+# Use uid of nonroot user (65532) because kubernetes expects numeric user when applying pod security policies
+USER 65532
+ENTRYPOINT [ "/manager" ]
diff --git a/cluster-api-provider-rke2-controlplane-image/_service b/cluster-api-provider-rke2-controlplane-image/_service
new file mode 100644
index 0000000..1fbc59e
--- /dev/null
+++ b/cluster-api-provider-rke2-controlplane-image/_service
@@ -0,0 +1,17 @@
+
+
+
+
+ Dockerfile
+ %%cluster-api-provider-rke2_version%%
+ cluster-api-provider-rke2-control-plane
+ patch
+
+
+ Dockerfile
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+
diff --git a/edge-image-builder-image/Dockerfile b/edge-image-builder-image/Dockerfile
new file mode 100644
index 0000000..60ac9b6
--- /dev/null
+++ b/edge-image-builder-image/Dockerfile
@@ -0,0 +1,40 @@
+#!BuildTag: %%IMG_PREFIX%%edge-image-builder:1.1.0
+#!BuildTag: %%IMG_PREFIX%%edge-image-builder:1.1.0-%RELEASE%
+#!BuildVersion: 15.6
+ARG SLE_VERSION
+FROM registry.suse.com/bci/bci-base:$SLE_VERSION
+MAINTAINER SUSE LLC (https://www.suse.com/)
+
+COPY artifacts.yaml artifacts.yaml
+
+RUN sed -i -e 's%^# rpm.install.excludedocs = no.*%rpm.install.excludedocs = yes%g' /etc/zypp/zypp.conf
+RUN zypper --non-interactive install --no-recommends edge-image-builder qemu-x86 qemu-uefi-aarch64 cni-plugins; zypper -n clean; rm -rf /var/log/*
+
+# Define labels according to https://en.opensuse.org/Building_derived_containers
+# labelprefix=com.suse.application.edge-image-builder
+LABEL org.opencontainers.image.authors="SUSE LLC (https://www.suse.com/)"
+LABEL org.opencontainers.image.title="SLE edge-image-builder Container Image"
+LABEL org.opencontainers.image.description="edge-image-builder based on the SLE Base Container Image."
+LABEL org.opencontainers.image.version="1.1.0"
+LABEL org.opencontainers.image.url="https://www.suse.com/products/server/"
+LABEL org.opencontainers.image.created="%BUILDTIME%"
+LABEL org.opencontainers.image.vendor="SUSE LLC"
+LABEL org.opensuse.reference="%%IMG_REPO%%/%%IMG_PREFIX%%edge-image-builder:1.1.0-%RELEASE%"
+LABEL org.openbuildservice.disturl="%DISTURL%"
+LABEL com.suse.supportlevel="l3"
+LABEL com.suse.eula="SUSE Combined EULA February 2024"
+LABEL com.suse.lifecycle-url="https://www.suse.com/lifecycle"
+LABEL com.suse.image-type="application"
+LABEL com.suse.release-stage="released"
+# endlabelprefix
+
+# Make adjustments for running guestfish and image modifications on aarch64
+# guestfish looks for very specific locations on the filesystem for UEFI firmware
+# and also expects the boot kernel to be a portable executable (PE), not ELF.
+RUN mkdir -p /usr/share/edk2/aarch64 && \
+ cp /usr/share/qemu/aavmf-aarch64-code.bin /usr/share/edk2/aarch64/QEMU_EFI-pflash.raw && \
+ cp /usr/share/qemu/aavmf-aarch64-vars.bin /usr/share/edk2/aarch64/vars-template-pflash.raw && \
+ mv /boot/vmlinux* /boot/backup-vmlinux
+
+ENTRYPOINT ["/usr/bin/eib"]
+
diff --git a/edge-image-builder-image/_service b/edge-image-builder-image/_service
new file mode 100644
index 0000000..3990297
--- /dev/null
+++ b/edge-image-builder-image/_service
@@ -0,0 +1,14 @@
+
+
+
+ Dockerfile
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+ artifacts.yaml
+ CHART_REPO=$(rpm --macros=/root/.rpmmacros -E %chart_repo)
+ CHART_REPO
+
+
+
diff --git a/edge-image-builder-image/artifacts.yaml b/edge-image-builder-image/artifacts.yaml
new file mode 100644
index 0000000..c1c06f3
--- /dev/null
+++ b/edge-image-builder-image/artifacts.yaml
@@ -0,0 +1,16 @@
+metallb:
+ chart: metallb-chart
+ repository: %%CHART_REPO%%/3.1
+ version: 0.14.9
+endpoint-copier-operator:
+ chart: endpoint-copier-operator-chart
+ repository: %%CHART_REPO%%/3.1
+ version: 0.2.1
+kubernetes:
+ k3s:
+ selinuxPackage: k3s-selinux-1.6-1.slemicro.noarch
+ selinuxRepository: https://rpm.rancher.io/k3s/stable/common/slemicro/noarch
+ rke2:
+ selinuxPackage: rke2-selinux
+ selinuxRepository: https://rpm.rancher.io/rke2/stable/common/slemicro/noarch
+
diff --git a/ip-address-manager-image/Dockerfile b/ip-address-manager-image/Dockerfile
new file mode 100644
index 0000000..af19182
--- /dev/null
+++ b/ip-address-manager-image/Dockerfile
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: Apache-2.0
+#!BuildTag: %%IMG_PREFIX%%ip-address-manager:v%%ip-address-manager_version%%
+#!BuildTag: %%IMG_PREFIX%%ip-address-manager:%%ip-address-manager_version%%
+#!BuildTag: %%IMG_PREFIX%%ip-address-manager:%%ip-address-manager_version%%-%RELEASE%
+#!BuildVersion: 15.6
+ARG SLE_VERSION
+FROM registry.suse.com/bci/bci-micro:$SLE_VERSION AS micro
+
+FROM registry.suse.com/bci/bci-base:$SLE_VERSION AS base
+COPY --from=micro / /installroot/
+RUN zypper --installroot /installroot --non-interactive install --no-recommends ip-address-manager shadow; zypper -n clean; rm -rf /var/log/*
+
+FROM micro AS final
+# Define labels according to https://en.opensuse.org/Building_derived_containers
+# labelprefix=com.suse.application.ip-address-manager
+LABEL org.opencontainers.image.authors="SUSE LLC (https://www.suse.com/)"
+LABEL org.opencontainers.image.title="SLE ip-address-manager Container Image"
+LABEL org.opencontainers.image.description="ip-address-manager based on the SLE Base Container Image."
+LABEL org.opencontainers.image.version="%%ip-address-manager_version%%"
+LABEL org.opencontainers.image.url="https://www.suse.com/products/server/"
+LABEL org.opencontainers.image.created="%BUILDTIME%"
+LABEL org.opencontainers.image.vendor="SUSE LLC"
+LABEL org.opensuse.reference="%%IMG_REPO%%/%%IMG_PREFIX%%ip-address-manager:%%ip-address-manager_version%%-%RELEASE%"
+LABEL org.openbuildservice.disturl="%DISTURL%"
+LABEL com.suse.supportlevel="l3"
+LABEL com.suse.eula="SUSE Combined EULA February 2024"
+LABEL com.suse.lifecycle-url="https://www.suse.com/lifecycle"
+LABEL com.suse.image-type="application"
+LABEL com.suse.release-stage="released"
+# endlabelprefix
+
+COPY --from=base /installroot /
+RUN mv /usr/bin/ip-address-manager /manager
+# Use uid of nonroot user (65532) because kubernetes expects numeric user when applying pod security policies
+USER 65532
+ENTRYPOINT [ "/manager" ]
diff --git a/ip-address-manager-image/_service b/ip-address-manager-image/_service
new file mode 100644
index 0000000..56cf294
--- /dev/null
+++ b/ip-address-manager-image/_service
@@ -0,0 +1,17 @@
+
+
+
+
+ Dockerfile
+ %%ip-address-manager_version%%
+ ip-address-manager
+ patch
+
+
+ Dockerfile
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+
diff --git a/ironic-image/Dockerfile b/ironic-image/Dockerfile
new file mode 100644
index 0000000..830d31f
--- /dev/null
+++ b/ironic-image/Dockerfile
@@ -0,0 +1,91 @@
+# SPDX-License-Identifier: Apache-2.0
+#!BuildTag: %%IMG_PREFIX%%ironic:24.1.2.0
+#!BuildTag: %%IMG_PREFIX%%ironic:24.1.2.0-%RELEASE%
+#!BuildVersion: 15.6
+
+ARG SLE_VERSION
+FROM registry.suse.com/bci/bci-micro:$SLE_VERSION AS micro
+
+FROM registry.suse.com/bci/bci-base:$SLE_VERSION AS base
+
+RUN set -euo pipefail; zypper -n in --no-recommends gcc git make xz-devel shim dosfstools mtools glibc-extra grub2-x86_64-efi grub2; zypper -n clean; rm -rf /var/log/*
+WORKDIR /tmp
+COPY prepare-efi.sh /bin/
+RUN set -euo pipefail; chmod +x /bin/prepare-efi.sh
+RUN /bin/prepare-efi.sh
+
+COPY --from=micro / /installroot/
+RUN sed -i -e 's%^# rpm.install.excludedocs = no.*%rpm.install.excludedocs = yes%g' /etc/zypp/zypp.conf
+RUN zypper --installroot /installroot --non-interactive install --no-recommends python311-devel python311 python311-pip python-dracclient python311-sushy-oem-idrac python311-proliantutils python311-sushy python3-ironicclient git curl sles-release tar gzip vim gawk dnsmasq dosfstools apache2 apache2-mod_wsgi inotify-tools ipcalc ipmitool iproute2 procps qemu-tools sqlite3 util-linux xorriso tftp syslinux ipxe-bootimgs python311-sushy-tools crudini openstack-ironic openstack-ironic-inspector-api
+
+FROM micro AS final
+MAINTAINER SUSE LLC (https://www.suse.com/)
+# Define labels according to https://en.opensuse.org/Building_derived_containers
+LABEL org.opencontainers.image.title="SLE Openstack Ironic Container Image"
+LABEL org.opencontainers.image.description="Openstack Ironic based on the SLE Base Container Image."
+LABEL org.opencontainers.image.url="https://www.suse.com/products/server/"
+LABEL org.opencontainers.image.created="%BUILDTIME%"
+LABEL org.opencontainers.image.vendor="SUSE LLC"
+LABEL org.opencontainers.image.version="24.1.2.0"
+LABEL org.opensuse.reference="%%IMG_REPO%%/%%IMG_PREFIX%%ironic:24.1.2.0-%RELEASE%"
+LABEL org.openbuildservice.disturl="%DISTURL%"
+LABEL com.suse.supportlevel="l3"
+LABEL com.suse.eula="SUSE Combined EULA February 2024"
+LABEL com.suse.lifecycle-url="https://www.suse.com/lifecycle"
+LABEL com.suse.image-type="application"
+LABEL com.suse.release-stage="released"
+# endlabelprefix
+
+COPY --from=base /installroot /
+
+RUN set -euo pipefail; ln -s /usr/bin/python3.11 /usr/local/bin/python3; \
+ ln -s /usr/bin/pydoc3.11 /usr/local/bin/pydoc
+
+ENV GRUB_DIR=/tftpboot/boot/grub
+
+# workaround for mkisofs command failing
+RUN echo 'alias mkisofs="xorriso -as mkisofs"' >> ~/.bashrc
+COPY mkisofs_wrapper /usr/bin/mkisofs
+RUN set -euo pipefail; chmod +x /usr/bin/mkisofs
+
+COPY auth-common.sh configure-ironic.sh ironic-common.sh rundnsmasq runhttpd runironic runironic-api runironic-conductor runironic-exporter runironic-inspector runlogwatch.sh tls-common.sh configure-nonroot.sh /bin/
+RUN set -euo pipefail; chmod +x /bin/auth-common.sh; chmod +x /bin/configure-ironic.sh; chmod +x /bin/ironic-common.sh; chmod +x /bin/rundnsmasq; chmod +x /bin/runhttpd; chmod +x /bin/runironic; chmod +x /bin/runironic-api; chmod +x /bin/runironic-conductor; chmod +x /bin/runironic-exporter; chmod +x /bin/runironic-inspector; chmod +x /bin/runlogwatch.sh; chmod +x /bin/tls-common.sh; chmod +x /bin/configure-nonroot.sh;
+RUN mkdir -p /tftpboot
+RUN mkdir -p $GRUB_DIR
+
+# No need to support the Legacy BIOS boot
+#RUN cp /usr/share/syslinux/pxelinux.0 /tftpboot
+#RUN cp /usr/share/syslinux/chain.c32 /tftpboot/
+
+# IRONIC #
+RUN cp /usr/share/ipxe/undionly.kpxe /tftpboot/undionly.kpxe
+RUN cp /usr/share/ipxe/ipxe-x86_64.efi /tftpboot/ipxe.efi
+COPY --from=base /tmp/esp.img /tmp/uefi_esp.img
+
+COPY ironic.conf.j2 /etc/ironic/
+COPY inspector.ipxe.j2 httpd-ironic-api.conf.j2 /tmp/
+COPY network-data-schema-empty.json /etc/ironic/
+
+# DNSMASQ
+COPY dnsmasq.conf.j2 /etc/
+
+# Custom httpd config, removes all but the bare minimum needed modules
+COPY httpd.conf.j2 /etc/httpd/conf/
+COPY httpd-modules.conf /etc/httpd/conf.modules.d/
+COPY apache2-vmedia.conf.j2 /etc/httpd-vmedia.conf.j2
+
+# IRONIC-INSPECTOR #
+RUN mkdir -p /var/lib/ironic /var/lib/ironic-inspector && \
+ sqlite3 /var/lib/ironic/ironic.db "pragma journal_mode=wal" && \
+ sqlite3 /var/lib/ironic-inspector/ironic-inspector.db "pragma journal_mode=wal"
+
+COPY ironic-inspector.conf.j2 /etc/ironic-inspector/
+COPY inspector-apache.conf.j2 /etc/httpd/conf.d/
+
+# Workaround
+# Removing the 010-ironic.conf file that comes with the package
+RUN rm /etc/ironic/ironic.conf.d/010-ironic.conf
+
+# configure non-root user and set relevant permissions
+RUN configure-nonroot.sh && \
+ rm -f /bin/configure-nonroot.sh
diff --git a/ironic-image/_service b/ironic-image/_service
new file mode 100644
index 0000000..219c79f
--- /dev/null
+++ b/ironic-image/_service
@@ -0,0 +1,17 @@
+
+
+
+
+ Dockerfile
+ %%openstack-ironic_version%%
+ openstack-ironic
+ patch
+
+
+ Dockerfile
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+
diff --git a/ironic-image/apache2-vmedia.conf.j2 b/ironic-image/apache2-vmedia.conf.j2
new file mode 100644
index 0000000..1d7ad21
--- /dev/null
+++ b/ironic-image/apache2-vmedia.conf.j2
@@ -0,0 +1,27 @@
+Listen {{ env.VMEDIA_TLS_PORT }}
+
+
+ ErrorLog /dev/stderr
+ LogLevel debug
+ CustomLog /dev/stdout combined
+
+ SSLEngine on
+ SSLProtocol {{ env.IRONIC_VMEDIA_SSL_PROTOCOL }}
+ SSLCertificateFile {{ env.IRONIC_VMEDIA_CERT_FILE }}
+ SSLCertificateKeyFile {{ env.IRONIC_VMEDIA_KEY_FILE }}
+
+
+ AllowOverride None
+ Require all granted
+
+
+
+ Options Indexes FollowSymLinks
+ AllowOverride None
+ Require all granted
+
+
+
+
+ SSLRequireSSL
+
diff --git a/ironic-image/auth-common.sh b/ironic-image/auth-common.sh
new file mode 100644
index 0000000..9906776
--- /dev/null
+++ b/ironic-image/auth-common.sh
@@ -0,0 +1,71 @@
+#!/usr/bin/bash
+
+set -euxo pipefail
+
+export IRONIC_HTPASSWD=${IRONIC_HTPASSWD:-${HTTP_BASIC_HTPASSWD:-}}
+export INSPECTOR_HTPASSWD=${INSPECTOR_HTPASSWD:-${HTTP_BASIC_HTPASSWD:-}}
+export IRONIC_DEPLOYMENT="${IRONIC_DEPLOYMENT:-}"
+export IRONIC_REVERSE_PROXY_SETUP=${IRONIC_REVERSE_PROXY_SETUP:-false}
+export INSPECTOR_REVERSE_PROXY_SETUP=${INSPECTOR_REVERSE_PROXY_SETUP:-false}
+
+IRONIC_HTPASSWD_FILE=/etc/ironic/htpasswd
+INSPECTOR_HTPASSWD_FILE=/etc/ironic-inspector/htpasswd
+
+configure_client_basic_auth()
+{
+ local auth_config_file="/auth/$1/auth-config"
+ local dest="${2:-/etc/ironic/ironic.conf}"
+ if [[ -f "${auth_config_file}" ]]; then
+ # Merge configurations in the "auth" directory into the default ironic configuration file because there is no way to choose the configuration file
+ # when running the api as a WSGI app.
+ crudini --merge "${dest}" < "${auth_config_file}"
+ fi
+}
+
+configure_json_rpc_auth()
+{
+ export JSON_RPC_AUTH_STRATEGY="noauth"
+ if [[ -n "${IRONIC_HTPASSWD}" ]]; then
+ if [[ "${IRONIC_DEPLOYMENT}" == "Conductor" ]]; then
+ export JSON_RPC_AUTH_STRATEGY="http_basic"
+ printf "%s\n" "${IRONIC_HTPASSWD}" > "${IRONIC_HTPASSWD_FILE}-rpc"
+ else
+ printf "%s\n" "${IRONIC_HTPASSWD}" > "${IRONIC_HTPASSWD_FILE}"
+ fi
+ fi
+}
+
+configure_ironic_auth()
+{
+ local config=/etc/ironic/ironic.conf
+ # Configure HTTP basic auth for API server
+ if [[ -n "${IRONIC_HTPASSWD}" ]]; then
+ printf "%s\n" "${IRONIC_HTPASSWD}" > "${IRONIC_HTPASSWD_FILE}"
+ if [[ "${IRONIC_REVERSE_PROXY_SETUP}" == "false" ]]; then
+ crudini --set "${config}" DEFAULT auth_strategy http_basic
+ crudini --set "${config}" DEFAULT http_basic_auth_user_file "${IRONIC_HTPASSWD_FILE}"
+ fi
+ fi
+}
+
+configure_inspector_auth()
+{
+ local config=/etc/ironic-inspector/ironic-inspector.conf
+ if [[ -n "${INSPECTOR_HTPASSWD}" ]]; then
+ printf "%s\n" "${INSPECTOR_HTPASSWD}" > "${INSPECTOR_HTPASSWD_FILE}"
+ if [[ "${INSPECTOR_REVERSE_PROXY_SETUP}" == "false" ]]; then
+ crudini --set "${config}" DEFAULT auth_strategy http_basic
+ crudini --set "${config}" DEFAULT http_basic_auth_user_file "${INSPECTOR_HTPASSWD_FILE}"
+ fi
+ fi
+}
+
+write_htpasswd_files()
+{
+ if [[ -n "${IRONIC_HTPASSWD:-}" ]]; then
+ printf "%s\n" "${IRONIC_HTPASSWD}" > "${IRONIC_HTPASSWD_FILE}"
+ fi
+ if [[ -n "${INSPECTOR_HTPASSWD:-}" ]]; then
+ printf "%s\n" "${INSPECTOR_HTPASSWD}" > "${INSPECTOR_HTPASSWD_FILE}"
+ fi
+}
diff --git a/ironic-image/configure-ironic.sh b/ironic-image/configure-ironic.sh
new file mode 100644
index 0000000..fa07f43
--- /dev/null
+++ b/ironic-image/configure-ironic.sh
@@ -0,0 +1,102 @@
+#!/usr/bin/bash
+
+set -euxo pipefail
+
+IRONIC_DEPLOYMENT="${IRONIC_DEPLOYMENT:-}"
+IRONIC_EXTERNAL_IP="${IRONIC_EXTERNAL_IP:-}"
+
+# Define the VLAN interfaces to be included in introspection report, e.g.
+# all - all VLANs on all interfaces using LLDP information
+# - all VLANs on a particular interface using LLDP information
+# - a particular VLAN on an interface, not relying on LLDP
+export IRONIC_INSPECTOR_VLAN_INTERFACES=${IRONIC_INSPECTOR_VLAN_INTERFACES:-all}
+
+# shellcheck disable=SC1091
+. /bin/tls-common.sh
+# shellcheck disable=SC1091
+. /bin/ironic-common.sh
+# shellcheck disable=SC1091
+. /bin/auth-common.sh
+
+export HTTP_PORT=${HTTP_PORT:-80}
+
+MARIADB_PASSWORD=${MARIADB_PASSWORD}
+MARIADB_DATABASE=${MARIADB_DATABASE:-ironic}
+MARIADB_USER=${MARIADB_USER:-ironic}
+MARIADB_HOST=${MARIADB_HOST:-127.0.0.1}
+export MARIADB_CONNECTION="mysql+pymysql://${MARIADB_USER}:${MARIADB_PASSWORD}@${MARIADB_HOST}/${MARIADB_DATABASE}?charset=utf8"
+if [[ "$MARIADB_TLS_ENABLED" == "true" ]]; then
+ export MARIADB_CONNECTION="${MARIADB_CONNECTION}&ssl=on&ssl_ca=${MARIADB_CACERT_FILE}"
+fi
+
+# TODO(dtantsur): remove the explicit default once we get
+# https://review.opendev.org/761185 in the repositories
+NUMPROC="$(grep -c "^processor" /proc/cpuinfo)"
+if [[ "$NUMPROC" -lt 4 ]]; then
+ NUMPROC=4
+fi
+export NUMWORKERS=${NUMWORKERS:-$NUMPROC}
+
+export IRONIC_USE_MARIADB=${IRONIC_USE_MARIADB:-true}
+export IRONIC_EXPOSE_JSON_RPC=${IRONIC_EXPOSE_JSON_RPC:-true}
+
+# Whether to enable fast_track provisioning or not
+export IRONIC_FAST_TRACK=${IRONIC_FAST_TRACK:-true}
+
+# Whether cleaning disks before and after deployment
+export IRONIC_AUTOMATED_CLEAN=${IRONIC_AUTOMATED_CLEAN:-true}
+
+# Wheter to enable the sensor data collection
+export SEND_SENSOR_DATA=${SEND_SENSOR_DATA:-false}
+
+# Set of collectors that should be used with IPA inspection
+export IRONIC_IPA_COLLECTORS=${IRONIC_IPA_COLLECTORS:-default,logs}
+
+wait_for_interface_or_ip
+
+# Hostname to use for the current conductor instance.
+export IRONIC_CONDUCTOR_HOST=${IRONIC_CONDUCTOR_HOST:-${IRONIC_URL_HOST}}
+
+export IRONIC_BASE_URL=${IRONIC_BASE_URL:-"${IRONIC_SCHEME}://${IRONIC_URL_HOST}:${IRONIC_ACCESS_PORT}"}
+export IRONIC_INSPECTOR_BASE_URL=${IRONIC_INSPECTOR_BASE_URL:-"${IRONIC_INSPECTOR_SCHEME}://${IRONIC_URL_HOST}:${IRONIC_INSPECTOR_ACCESS_PORT}"}
+
+if [[ -n "$IRONIC_EXTERNAL_IP" ]]; then
+ export IRONIC_EXTERNAL_CALLBACK_URL="${IRONIC_SCHEME}://${IRONIC_EXTERNAL_IP}:${IRONIC_ACCESS_PORT}"
+ if [[ "$IRONIC_VMEDIA_TLS_SETUP" == "true" ]]; then
+ export IRONIC_EXTERNAL_HTTP_URL="https://${IRONIC_EXTERNAL_IP}:${VMEDIA_TLS_PORT}"
+ else
+ export IRONIC_EXTERNAL_HTTP_URL="http://${IRONIC_EXTERNAL_IP}:${HTTP_PORT}"
+ fi
+ export IRONIC_INSPECTOR_CALLBACK_ENDPOINT_OVERRIDE="https://${IRONIC_EXTERNAL_IP}:${IRONIC_INSPECTOR_ACCESS_PORT}"
+fi
+
+IMAGE_CACHE_PREFIX=/shared/html/images/ironic-python-agent
+if [[ -f "${IMAGE_CACHE_PREFIX}.kernel" ]] && [[ -f "${IMAGE_CACHE_PREFIX}.initramfs" ]]; then
+ export IRONIC_DEFAULT_KERNEL="${IMAGE_CACHE_PREFIX}.kernel"
+ export IRONIC_DEFAULT_RAMDISK="${IMAGE_CACHE_PREFIX}.initramfs"
+fi
+
+if [[ -f /etc/ironic/ironic.conf ]]; then
+ # Make a copy of the original supposed empty configuration file
+ cp /etc/ironic/ironic.conf /etc/ironic/ironic.conf_orig
+fi
+
+# oslo.config also supports Config Opts From Environment, log them to stdout
+echo 'Options set from Environment variables'
+env | grep "^OS_" || true
+
+mkdir -p /shared/html
+mkdir -p /shared/ironic_prometheus_exporter
+
+configure_json_rpc_auth
+
+# The original ironic.conf is empty, and can be found in ironic.conf_orig
+render_j2_config /etc/ironic/ironic.conf.j2 /etc/ironic/ironic.conf
+
+if [[ "${USE_IRONIC_INSPECTOR}" == "true" ]]; then
+ configure_client_basic_auth ironic-inspector
+fi
+configure_client_basic_auth ironic-rpc
+
+# Make sure ironic traffic bypasses any proxies
+export NO_PROXY="${NO_PROXY:-},$IRONIC_IP"
diff --git a/ironic-image/configure-nonroot.sh b/ironic-image/configure-nonroot.sh
new file mode 100644
index 0000000..caeec02
--- /dev/null
+++ b/ironic-image/configure-nonroot.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/bash
+
+NONROOT_UID=10475
+NONROOT_GID=10475
+USER="ironic-suse"
+
+groupadd -r -g ${NONROOT_GID} ${USER}
+useradd -r -g ${NONROOT_GID} \
+ -u ${NONROOT_UID} \
+ -d /var/lib/ironic \
+ -s /sbin/nologin \
+ ${USER}
+
+# create ironic's http_root directory
+mkdir -p /shared/html
+chown "${NONROOT_UID}":"${NONROOT_GID}" /shared/html
+
+# we'll bind mount shared ca and ironic/inspector certificate dirs here
+# that need to have correct ownership as the entire ironic in BMO
+# deployment shares a single fsGroup in manifest's securityContext
+mkdir -p /certs/ca
+chown "${NONROOT_UID}":"${NONROOT_GID}" /certs{,/ca}
+chmod 2775 /certs{,/ca}
+
+# apache2 permission changes
+chown -R "${NONROOT_UID}":"${NONROOT_GID}" /etc/apache2
+chown -R "${NONROOT_UID}":"${NONROOT_GID}" /run
+
+# ironic, inspector and httpd related changes
+chown -R "${NONROOT_UID}":"${NONROOT_GID}" /etc/ironic /etc/httpd /etc/httpd
+chown -R "${NONROOT_UID}":"${NONROOT_GID}" /etc/ironic-inspector
+chown -R "${NONROOT_UID}":"${NONROOT_GID}" /var/log
+chmod 2775 /etc/ironic /etc/ironic-inspector /etc/httpd/conf /etc/httpd/conf.d
+chmod 664 /etc/ironic/* /etc/ironic-inspector/* /etc/httpd/conf/* /etc/httpd/conf.d/*
+
+chown -R "${NONROOT_UID}":"${NONROOT_GID}" /var/lib/ironic
+chown -R "${NONROOT_UID}":"${NONROOT_GID}" /var/lib/ironic-inspector
+chmod 2775 /var/lib/ironic /var/lib/ironic-inspector
+chmod 664 /var/lib/ironic/ironic.db /var/lib/ironic-inspector/ironic-inspector.db
+
+# dnsmasq, and the capabilities required to run it as non-root user
+chown -R "${NONROOT_UID}":"${NONROOT_GID}" /etc/dnsmasq.conf /var/lib/dnsmasq
+chmod 2775 /var/lib/dnsmasq
+touch /var/lib/dnsmasq/dnsmasq.leases
+chmod 664 /etc/dnsmasq.conf /var/lib/dnsmasq/dnsmasq.leases
+
+# ca-certificates permission changes
+touch /var/lib/ca-certificates/ca-bundle.pem.new
+chown -R "${NONROOT_UID}":"${NONROOT_GID}" /var/lib/ca-certificates/
+chmod -R +w /var/lib/ca-certificates/
diff --git a/ironic-image/dnsmasq.conf.j2 b/ironic-image/dnsmasq.conf.j2
new file mode 100644
index 0000000..502de9a
--- /dev/null
+++ b/ironic-image/dnsmasq.conf.j2
@@ -0,0 +1,79 @@
+interface={{ env.PROVISIONING_INTERFACE }}
+bind-dynamic
+enable-tftp
+tftp-root=/shared/tftpboot
+log-queries
+
+# Configure listening for DNS (0 disables DNS)
+port={{ env.DNS_PORT }}
+
+{%- if env.DHCP_RANGE | length %}
+log-dhcp
+dhcp-range={{ env.DHCP_RANGE }}
+
+# It can be used when setting DNS or GW variables.
+{%- if env["GATEWAY_IP"] is undefined %}
+# Disable default router(s)
+dhcp-option=3
+{% else %}
+dhcp-option=option{% if ":" in env["GATEWAY_IP"] %}6{% endif %}:router,{{ env["GATEWAY_IP"] }}
+{% endif %}
+{%- if env["DNS_IP"] is undefined %}
+# Disable DNS over provisioning network
+dhcp-option=6
+{% else %}
+dhcp-option=option{% if ":" in env["DNS_IP"] %}6{% endif %}:dns-server,{{ env["DNS_IP"] }}
+{% endif %}
+
+{%- if env.IPV == "4" or env.IPV is undefined %}
+# IPv4 Configuration:
+dhcp-match=ipxe,175
+# Client is already running iPXE; move to next stage of chainloading
+dhcp-boot=tag:ipxe,http://{{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }}/boot.ipxe
+
+# Note: Need to test EFI booting
+dhcp-match=set:efi,option:client-arch,7
+dhcp-match=set:efi,option:client-arch,9
+dhcp-match=set:efi,option:client-arch,11
+# Client is PXE booting over EFI without iPXE ROM; send EFI version of iPXE chainloader
+dhcp-boot=tag:efi,tag:!ipxe,snponly.efi
+
+# Client is running PXE over BIOS; send BIOS version of iPXE chainloader
+dhcp-boot=/undionly.kpxe,{{ env.IRONIC_IP }}
+{% endif %}
+
+{% if env.IPV == "6" %}
+# IPv6 Configuration:
+enable-ra
+ra-param={{ env.PROVISIONING_INTERFACE }},0,0
+
+dhcp-vendorclass=set:pxe6,enterprise:343,PXEClient
+dhcp-userclass=set:ipxe6,iPXE
+dhcp-option=tag:pxe6,option6:bootfile-url,tftp://{{ env.IRONIC_URL_HOST }}/snponly.efi
+dhcp-option=tag:ipxe6,option6:bootfile-url,http://{{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }}/boot.ipxe
+
+# It can be used when setting DNS or GW variables.
+{%- if env["GATEWAY_IP"] is undefined %}
+# Disable default router(s)
+dhcp-option=3
+{% else %}
+dhcp-option=3,{{ env["GATEWAY_IP"] }}
+{% endif %}
+{%- if env["DNS_IP"] is undefined %}
+# Disable DNS over provisioning network
+dhcp-option=6
+{% else %}
+dhcp-option=6,{{ env["DNS_IP"] }}
+{% endif %}
+{% endif %}
+{% endif %}
+
+{%- if env.DHCP_IGNORE | length %}
+dhcp-ignore={{ env.DHCP_IGNORE }}
+{% endif %}
+
+{%- if env.DHCP_HOSTS | length %}
+{%- for item in env.DHCP_HOSTS.split(";") %}
+dhcp-host={{ item }}
+{%- endfor %}
+{% endif %}
diff --git a/ironic-image/httpd-ironic-api.conf.j2 b/ironic-image/httpd-ironic-api.conf.j2
new file mode 100644
index 0000000..2132c9f
--- /dev/null
+++ b/ironic-image/httpd-ironic-api.conf.j2
@@ -0,0 +1,85 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+{% if env.LISTEN_ALL_INTERFACES | lower == "true" %}
+Listen {{ env.IRONIC_LISTEN_PORT }}
+
+{% else %}
+Listen {{ env.IRONIC_URL_HOST }}:{{ env.IRONIC_LISTEN_PORT }}
+
+{% endif %}
+
+ {% if env.IRONIC_REVERSE_PROXY_SETUP | lower == "true" %}
+
+ {% if env.IRONIC_PRIVATE_PORT == "unix" %}
+ ProxyPass "/" "unix:/shared/ironic.sock|http://127.0.0.1/"
+ ProxyPassReverse "/" "unix:/shared/ironic.sock|http://127.0.0.1/"
+ {% else %}
+ ProxyPass "/" "http://127.0.0.1:{{ env.IRONIC_PRIVATE_PORT }}/"
+ ProxyPassReverse "/" "http://127.0.0.1:{{ env.IRONIC_PRIVATE_PORT }}/"
+ {% endif %}
+
+ {% else %}
+ WSGIDaemonProcess ironic user=ironic group=ironic threads=10 display-name=%{GROUP}
+ WSGIScriptAlias / /usr/bin/ironic-api-wsgi
+ {% endif %}
+
+ SetEnv APACHE_RUN_USER ironic-suse
+ SetEnv APACHE_RUN_GROUP ironic-suse
+ WSGIProcessGroup ironic-suse
+
+ ErrorLog /dev/stderr
+ LogLevel debug
+ CustomLog /dev/stdout combined
+
+{% if env.IRONIC_TLS_SETUP == "true" %}
+ SSLEngine on
+ SSLProtocol {{ env.IRONIC_SSL_PROTOCOL }}
+ SSLCertificateFile {{ env.IRONIC_CERT_FILE }}
+ SSLCertificateKeyFile {{ env.IRONIC_KEY_FILE }}
+{% endif %}
+
+ {% if env.IRONIC_REVERSE_PROXY_SETUP | lower == "true" %}
+
+ {% if "IRONIC_HTPASSWD" in env and env.IRONIC_HTPASSWD | length %}
+ AuthType Basic
+ AuthName "Restricted area"
+ AuthUserFile "/etc/ironic/htpasswd"
+ Require valid-user
+ {% endif %}
+
+ {% else %}
+
+ WSGIProcessGroup ironic
+ WSGIApplicationGroup %{GLOBAL}
+ AllowOverride None
+
+ {% if "IRONIC_HTPASSWD" in env and env.IRONIC_HTPASSWD | length %}
+ AuthType Basic
+ AuthName "Restricted WSGI area"
+ AuthUserFile "/etc/ironic/htpasswd"
+ Require valid-user
+ {% else %}
+ Require all granted
+ {% endif %}
+
+ {% endif %}
+
+
+ Require all granted
+
+
+
+ Require all granted
+
+
diff --git a/ironic-image/httpd-modules.conf b/ironic-image/httpd-modules.conf
new file mode 100644
index 0000000..c1c5aaa
--- /dev/null
+++ b/ironic-image/httpd-modules.conf
@@ -0,0 +1,21 @@
+# Bare minimum set of modules
+LoadModule log_config_module /usr/lib64/apache2/mod_log_config.so
+LoadModule mime_module /usr/lib64/apache2/mod_mime.so
+LoadModule dir_module /usr/lib64/apache2/mod_dir.so
+LoadModule authz_core_module /usr/lib64/apache2/mod_authz_core.so
+#LoadModule unixd_module modules/mod_unixd.so
+#LoadModule mpm_event_module modules/mod_mpm_event.so
+LoadModule wsgi_module /usr/lib64/apache2/mod_wsgi.so
+LoadModule ssl_module /usr/lib64/apache2/mod_ssl.so
+LoadModule env_module /usr/lib64/apache2/mod_env.so
+LoadModule proxy_module /usr/lib64/apache2/mod_proxy.so
+LoadModule proxy_ajp_module /usr/lib64/apache2/mod_proxy_ajp.so
+LoadModule proxy_balancer_module /usr/lib64/apache2/mod_proxy_balancer.so
+LoadModule proxy_http_module /usr/lib64/apache2/mod_proxy_http.so
+LoadModule slotmem_shm_module /usr/lib64/apache2/mod_slotmem_shm.so
+LoadModule headers_module /usr/lib64/apache2/mod_headers.so
+LoadModule authn_core_module /usr/lib64/apache2/mod_authn_core.so
+LoadModule auth_basic_module /usr/lib64/apache2/mod_auth_basic.so
+LoadModule authn_file_module /usr/lib64/apache2/mod_authn_file.so
+LoadModule authz_user_module /usr/lib64/apache2/mod_authz_user.so
+LoadModule access_compat_module /usr/lib64/apache2/mod_access_compat.so
diff --git a/ironic-image/httpd.conf.j2 b/ironic-image/httpd.conf.j2
new file mode 100644
index 0000000..16f5470
--- /dev/null
+++ b/ironic-image/httpd.conf.j2
@@ -0,0 +1,84 @@
+ServerRoot "/etc/httpd"
+{%- if env.LISTEN_ALL_INTERFACES | lower == "true" %}
+Listen [::]:{{ env.HTTP_PORT }}
+{% else %}
+Listen {{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }}
+{% endif %}
+Include conf.modules.d/*.conf
+User ironic-suse
+Group ironic-suse
+
+
+ AllowOverride none
+ Require all denied
+
+
+DocumentRoot "/shared/html"
+
+
+ Options Indexes FollowSymLinks
+ AllowOverride None
+ Require all granted
+
+
+{%- if env.HTTPD_SERVE_NODE_IMAGES | lower == "true" %}
+
+ Options Indexes FollowSymLinks
+ AllowOverride None
+ Require all granted
+
+{% endif %}
+
+
+ DirectoryIndex index.html
+
+
+
+ Require all denied
+
+
+ErrorLog "/dev/stderr"
+
+LogLevel warn
+
+
+ LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+ LogFormat "%h %l %u %t \"%r\" %>s %b" common
+
+ LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
+
+ CustomLog "/dev/stderr" combined
+
+
+
+ TypesConfig /etc/mime.types
+ AddType application/x-compress .Z
+ AddType application/x-gzip .gz .tgz
+ AddType text/html .shtml
+ AddOutputFilter INCLUDES .shtml
+
+
+AddDefaultCharset UTF-8
+
+
+ MIMEMagicFile conf/magic
+
+
+PidFile /var/tmp/httpd.pid
+
+# EnableSendfile directive could speed up deployments but it could also cause
+# issues depending on the underlying file system, to learn more:
+# https://httpd.apache.org/docs/current/mod/core.html#enablesendfile
+{%- if env.HTTPD_ENABLE_SENDFILE | lower == "true" %}
+EnableSendfile on
+{% endif %}
+
+# http TRACE can be subjected to abuse and should be disabled
+TraceEnable off
+
+# provide minimal server information
+ServerTokens Prod
+ServerSignature Off
+
+IncludeOptional conf.d/*.conf
+
diff --git a/ironic-image/inspector-apache.conf.j2 b/ironic-image/inspector-apache.conf.j2
new file mode 100644
index 0000000..b0a9d7f
--- /dev/null
+++ b/ironic-image/inspector-apache.conf.j2
@@ -0,0 +1,57 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+{% if env.LISTEN_ALL_INTERFACES | lower == "true" %}
+Listen {{ env.IRONIC_INSPECTOR_LISTEN_PORT }}
+
+{% else %}
+Listen {{ env.IRONIC_URL_HOST }}:{{ env.IRONIC_INSPECTOR_LISTEN_PORT }}
+
+{% endif %}
+ {% if env.IRONIC_INSPECTOR_PRIVATE_PORT == "unix" %}
+ ProxyPass "/" "unix:/shared/inspector.sock|http://127.0.0.1/"
+ ProxyPassReverse "/" "unix:/shared/inspector.sock|http://127.0.0.1/"
+ {% else %}
+ ProxyPass "/" "http://127.0.0.1:{{ env.IRONIC_INSPECTOR_PRIVATE_PORT }}/"
+ ProxyPassReverse "/" "http://127.0.0.1:{{ env.IRONIC_INSPECTOR_PRIVATE_PORT }}/"
+ {% endif %}
+
+ SetEnv APACHE_RUN_USER ironic-suse
+ SetEnv APACHE_RUN_GROUP ironic-suse
+
+ ErrorLog /dev/stdout
+ LogLevel debug
+ CustomLog /dev/stdout combined
+
+ SSLEngine On
+ SSLProtocol {{ env.IRONIC_SSL_PROTOCOL }}
+ SSLCertificateFile {{ env.IRONIC_INSPECTOR_CERT_FILE }}
+ SSLCertificateKeyFile {{ env.IRONIC_INSPECTOR_KEY_FILE }}
+
+ {% if "INSPECTOR_HTPASSWD" in env and env.INSPECTOR_HTPASSWD | length %}
+
+ AuthType Basic
+ AuthName "Restricted area"
+ AuthUserFile "/etc/ironic-inspector/htpasswd"
+ Require valid-user
+
+
+
+ Require all granted
+
+
+
+ Require all granted
+
+ {% endif %}
+
diff --git a/ironic-image/inspector.ipxe.j2 b/ironic-image/inspector.ipxe.j2
new file mode 100644
index 0000000..93f8c75
--- /dev/null
+++ b/ironic-image/inspector.ipxe.j2
@@ -0,0 +1,10 @@
+#!ipxe
+
+:retry_boot
+echo In inspector.ipxe
+imgfree
+# NOTE(dtantsur): keep inspection kernel params in [mdns]params in
+# ironic-inspector-image and configuration in configure-ironic.sh
+kernel --timeout 60000 http://{{ env.IRONIC_IP }}:{{ env.HTTP_PORT }}/images/ironic-python-agent.kernel ipa-insecure=1 ipa-inspection-collectors={{ env.IRONIC_IPA_COLLECTORS }} systemd.journald.forward_to_console=yes BOOTIF=${mac} ipa-debug=1 ipa-enable-vlan-interfaces={{ env.IRONIC_INSPECTOR_VLAN_INTERFACES }} ipa-inspection-dhcp-all-interfaces=1 ipa-collect-lldp=1 {{ env.INSPECTOR_EXTRA_ARGS }} initrd=ironic-python-agent.initramfs {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} || goto retry_boot
+initrd --timeout 60000 http://{{ env.IRONIC_IP }}:{{ env.HTTP_PORT }}/images/ironic-python-agent.initramfs || goto retry_boot
+boot
diff --git a/ironic-image/ironic-common.sh b/ironic-image/ironic-common.sh
new file mode 100644
index 0000000..f388c6b
--- /dev/null
+++ b/ironic-image/ironic-common.sh
@@ -0,0 +1,110 @@
+#!/usr/bin/bash
+
+set -euxo pipefail
+
+IRONIC_IP="${IRONIC_IP:-}"
+PROVISIONING_INTERFACE="${PROVISIONING_INTERFACE:-}"
+PROVISIONING_IP="${PROVISIONING_IP:-}"
+PROVISIONING_MACS="${PROVISIONING_MACS:-}"
+
+get_provisioning_interface()
+{
+ if [[ -n "$PROVISIONING_INTERFACE" ]]; then
+ # don't override the PROVISIONING_INTERFACE if one is provided
+ echo "$PROVISIONING_INTERFACE"
+ return
+ fi
+
+ local interface="provisioning"
+
+ if [[ -n "${PROVISIONING_IP}" ]]; then
+ if ip -br addr show | grep -qi " ${PROVISIONING_IP}/"; then
+ interface="$(ip -br addr show | grep -i " ${PROVISIONING_IP}/" | cut -f 1 -d ' ' | cut -f 1 -d '@')"
+ fi
+ fi
+
+ for mac in ${PROVISIONING_MACS//,/ }; do
+ if ip -br link show up | grep -qi "$mac"; then
+ interface="$(ip -br link show up | grep -i "$mac" | cut -f 1 -d ' ' | cut -f 1 -d '@')"
+ break
+ fi
+ done
+
+ echo "$interface"
+}
+
+PROVISIONING_INTERFACE="$(get_provisioning_interface)"
+export PROVISIONING_INTERFACE
+
+export LISTEN_ALL_INTERFACES="${LISTEN_ALL_INTERFACES:-true}"
+
+# Wait for the interface or IP to be up, sets $IRONIC_IP
+wait_for_interface_or_ip()
+{
+ # If $PROVISIONING_IP is specified, then we wait for that to become available on an interface, otherwise we look at $PROVISIONING_INTERFACE for an IP
+ if [[ -n "$PROVISIONING_IP" ]]; then
+ # Convert the address using ipcalc which strips out the subnet. For IPv6 addresses, this will give the short-form address
+ IRONIC_IP="$(ipcalc "${PROVISIONING_IP}" | grep "^Address:" | awk '{print $2}')"
+ export IRONIC_IP
+ until grep -F " ${IRONIC_IP}/" <(ip -br addr show); do
+ echo "Waiting for ${IRONIC_IP} to be configured on an interface"
+ sleep 1
+ done
+ else
+ until [[ -n "$IRONIC_IP" ]]; do
+ echo "Waiting for ${PROVISIONING_INTERFACE} interface to be configured"
+ IRONIC_IP="$(ip -br add show scope global up dev "${PROVISIONING_INTERFACE}" | awk '{print $3}' | sed -e 's%/.*%%' | head -n 1)"
+ export IRONIC_IP
+ sleep 1
+ done
+ fi
+
+ # If the IP contains a colon, then it's an IPv6 address, and the HTTP
+ # host needs surrounding with brackets
+ if [[ "$IRONIC_IP" =~ .*:.* ]]; then
+ export IPV=6
+ export IRONIC_URL_HOST="[$IRONIC_IP]"
+ else
+ export IPV=4
+ export IRONIC_URL_HOST="$IRONIC_IP"
+ fi
+}
+
+render_j2_config()
+{
+ python3 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' < "$1" > "$2"
+}
+
+run_ironic_dbsync()
+{
+ if [[ "${IRONIC_USE_MARIADB:-true}" == "true" ]]; then
+ # It's possible for the dbsync to fail if mariadb is not up yet, so
+ # retry until success
+ until ironic-dbsync --config-file /etc/ironic/ironic.conf upgrade; do
+ echo "WARNING: ironic-dbsync failed, retrying"
+ sleep 1
+ done
+ else
+ # SQLite does not support some statements. Fortunately, we can just create
+ # the schema in one go instead of going through an upgrade.
+ ironic-dbsync --config-file /etc/ironic/ironic.conf create_schema
+ fi
+}
+
+# Use the special value "unix" for unix sockets
+export IRONIC_PRIVATE_PORT=${IRONIC_PRIVATE_PORT:-6388}
+export IRONIC_INSPECTOR_PRIVATE_PORT=${IRONIC_INSPECTOR_PRIVATE_PORT:-5049}
+
+export IRONIC_ACCESS_PORT=${IRONIC_ACCESS_PORT:-6385}
+export IRONIC_LISTEN_PORT=${IRONIC_LISTEN_PORT:-$IRONIC_ACCESS_PORT}
+
+export IRONIC_INSPECTOR_ACCESS_PORT=${IRONIC_INSPECTOR_ACCESS_PORT:-5050}
+export IRONIC_INSPECTOR_LISTEN_PORT=${IRONIC_INSPECTOR_LISTEN_PORT:-$IRONIC_INSPECTOR_ACCESS_PORT}
+
+# If this is false, built-in inspection is used.
+export USE_IRONIC_INSPECTOR=${USE_IRONIC_INSPECTOR:-true}
+export IRONIC_INSPECTOR_ENABLE_DISCOVERY=${IRONIC_INSPECTOR_ENABLE_DISCOVERY:-false}
+if [[ "${USE_IRONIC_INSPECTOR}" != "true" ]] && [[ "${IRONIC_INSPECTOR_ENABLE_DISCOVERY}" == "true" ]]; then
+ echo "Discovery is only supported with ironic-inspector at this point"
+ exit 1
+fi
diff --git a/ironic-image/ironic-inspector.conf.j2 b/ironic-image/ironic-inspector.conf.j2
new file mode 100644
index 0000000..9932980
--- /dev/null
+++ b/ironic-image/ironic-inspector.conf.j2
@@ -0,0 +1,68 @@
+[DEFAULT]
+auth_strategy = noauth
+debug = true
+transport_url = fake://
+use_stderr = true
+{% if env.INSPECTOR_REVERSE_PROXY_SETUP == "true" %}
+{% if env.IRONIC_INSPECTOR_PRIVATE_PORT == "unix" %}
+listen_unix_socket = /shared/inspector.sock
+# NOTE(dtantsur): this is not ideal, but since the socket is accessed from
+# another container, we need to make it world-writeable.
+listen_unix_socket_mode = 0666
+{% else %}
+listen_port = {{ env.IRONIC_INSPECTOR_PRIVATE_PORT }}
+listen_address = 127.0.0.1
+{% endif %}
+{% elif env.LISTEN_ALL_INTERFACES | lower == "true" %}
+listen_port = {{ env.IRONIC_INSPECTOR_LISTEN_PORT }}
+listen_address = ::
+{% else %}
+listen_port = {{ env.IRONIC_INSPECTOR_LISTEN_PORT }}
+listen_address = {{ env.IRONIC_IP }}
+{% endif %}
+host = {{ env.IRONIC_IP }}
+{% if env.IRONIC_INSPECTOR_TLS_SETUP == "true" and env.INSPECTOR_REVERSE_PROXY_SETUP == "false" %}
+use_ssl = true
+{% endif %}
+
+[database]
+connection = sqlite:////var/lib/ironic-inspector/ironic-inspector.db
+
+{% if env.IRONIC_INSPECTOR_ENABLE_DISCOVERY == "true" %}
+[discovery]
+enroll_node_driver = ipmi
+{% endif %}
+
+[ironic]
+auth_type = none
+endpoint_override = {{ env.IRONIC_BASE_URL }}
+{% if env.IRONIC_TLS_SETUP == "true" %}
+cafile = {{ env.IRONIC_CACERT_FILE }}
+insecure = {{ env.IRONIC_INSECURE }}
+{% endif %}
+
+[processing]
+add_ports = all
+always_store_ramdisk_logs = true
+keep_ports = present
+{% if env.IRONIC_INSPECTOR_ENABLE_DISCOVERY == "true" %}
+node_not_found_hook = enroll
+{% endif %}
+permit_active_introspection = true
+power_off = false
+processing_hooks = $default_processing_hooks,lldp_basic
+ramdisk_logs_dir = /shared/log/ironic-inspector/ramdisk
+store_data = database
+
+[pxe_filter]
+driver = noop
+
+[service_catalog]
+auth_type = none
+endpoint_override = {{ env.IRONIC_INSPECTOR_BASE_URL }}
+
+{% if env.IRONIC_INSPECTOR_TLS_SETUP == "true" and env.INSPECTOR_REVERSE_PROXY_SETUP == "false" %}
+[ssl]
+cert_file = {{ env.IRONIC_INSPECTOR_CERT_FILE }}
+key_file = {{ env.IRONIC_INSPECTOR_KEY_FILE }}
+{% endif %}
diff --git a/ironic-image/ironic.conf.j2 b/ironic-image/ironic.conf.j2
new file mode 100644
index 0000000..5bce6d2
--- /dev/null
+++ b/ironic-image/ironic.conf.j2
@@ -0,0 +1,253 @@
+[DEFAULT]
+{% if env.AUTH_STRATEGY is defined %}
+auth_strategy = {{ env.AUTH_STRATEGY }}
+{% if env.AUTH_STRATEGY == "http_basic" %}
+http_basic_auth_user_file=/etc/ironic/htpasswd
+{% endif %}
+{% else %}
+auth_strategy = noauth
+{% endif %}
+debug = true
+default_deploy_interface = direct
+default_inspect_interface = {% if env.USE_IRONIC_INSPECTOR == "true" %}inspector{% else %}agent{% endif %}
+default_network_interface = noop
+enabled_bios_interfaces = idrac-wsman,no-bios,redfish,idrac-redfish,irmc,ilo
+enabled_boot_interfaces = ipxe,ilo-ipxe,pxe,ilo-pxe,fake,redfish-virtual-media,idrac-redfish-virtual-media,ilo-virtual-media
+enabled_deploy_interfaces = direct,fake,ramdisk,custom-agent
+# NOTE(dtantsur): when changing this, make sure to update the driver
+# dependencies in Dockerfile.
+enabled_hardware_types = ipmi,idrac,irmc,fake-hardware,redfish,manual-management,ilo,ilo5
+enabled_inspect_interfaces = {% if env.USE_IRONIC_INSPECTOR == "true" %}inspector{% else %}agent{% endif %},idrac-wsman,irmc,fake,redfish,ilo
+enabled_management_interfaces = ipmitool,idrac-wsman,irmc,fake,redfish,idrac-redfish,ilo,ilo5,noop
+enabled_power_interfaces = ipmitool,idrac-wsman,irmc,fake,redfish,idrac-redfish,ilo
+enabled_raid_interfaces = no-raid,irmc,agent,fake,idrac-wsman,redfish,idrac-redfish,ilo5
+enabled_vendor_interfaces = no-vendor,ipmitool,idrac-wsman,idrac-redfish,redfish,ilo,fake
+enabled_firmware_interfaces = no-firmware,fake,redfish
+{% if env.IRONIC_EXPOSE_JSON_RPC | lower == "true" %}
+rpc_transport = json-rpc
+{% else %}
+rpc_transport = none
+{% endif %}
+use_stderr = true
+# NOTE(dtantsur): the default md5 is not compatible with FIPS mode
+hash_ring_algorithm = sha256
+my_ip = {{ env.IRONIC_IP }}
+{% if env.IRONIC_DEPLOYMENT == "Conductor" and env.JSON_RPC_AUTH_STRATEGY == "noauth" %}
+# if access is unauthenticated, we bind only to localhost - use that as the
+# host name also, so that the client can find the server
+# If we run both API and conductor in the same pod, use localhost
+host = localhost
+{% else %}
+host = {{ env.IRONIC_CONDUCTOR_HOST }}
+{% endif %}
+
+# If a path to a certificate is defined, use that first for webserver
+{% if env.WEBSERVER_CACERT_FILE %}
+webserver_verify_ca = {{ env.WEBSERVER_CACERT_FILE }}
+{% elif env.IRONIC_INSECURE == "true" %}
+webserver_verify_ca = false
+{% endif %}
+
+isolinux_bin = /usr/share/syslinux/isolinux.bin
+
+# NOTE(dtantsur): this path is specific to the GRUB image that is built into
+# the ESP provided in [conductor]bootloader.
+grub_config_path = EFI/BOOT/grub.cfg
+
+[agent]
+deploy_logs_collect = always
+deploy_logs_local_path = /shared/log/ironic/deploy
+# NOTE(dtantsur): in some environments temporary networking issues can cause
+# the whole deployment to fail on inability to reach the ramdisk. Increasing
+# retries here works around such problems without affecting the normal path.
+# See https://bugzilla.redhat.com/show_bug.cgi?id=1822763
+max_command_attempts = 30
+
+[api]
+{% if env.IRONIC_REVERSE_PROXY_SETUP == "true" %}
+{% if env.IRONIC_PRIVATE_PORT == "unix" %}
+unix_socket = /shared/ironic.sock
+# NOTE(dtantsur): this is not ideal, but since the socket is accessed from
+# another container, we need to make it world-writeable.
+unix_socket_mode = 0666
+{% else %}
+host_ip = 127.0.0.1
+port = {{ env.IRONIC_PRIVATE_PORT }}
+{% endif %}
+public_endpoint = {{ env.IRONIC_BASE_URL }}
+{% else %}
+host_ip = {% if env.LISTEN_ALL_INTERFACES | lower == "true" %}::{% else %}{{ env.IRONIC_IP }}{% endif %}
+port = {{ env.IRONIC_LISTEN_PORT }}
+{% if env.IRONIC_TLS_SETUP == "true" %}
+enable_ssl_api = true
+{% endif %}
+{% endif %}
+api_workers = {{ env.NUMWORKERS }}
+
+# Disable schema validation so we can pass nmstate format
+network_data_schema = /etc/ironic/network-data-schema-empty.json
+
+[conductor]
+automated_clean = {{ env.IRONIC_AUTOMATED_CLEAN }}
+# NOTE(dtantsur): keep aligned with [pxe]boot_retry_timeout below.
+deploy_callback_timeout = 4800
+send_sensor_data = {{ env.SEND_SENSOR_DATA }}
+# NOTE(TheJulia): Do not lower this value below 120 seconds.
+# Power state is checked every 60 seconds and BMC activity should
+# be avoided more often than once every sixty seconds.
+send_sensor_data_interval = 160
+bootloader = {{ env.IRONIC_BOOT_BASE_URL }}/uefi_esp.img
+verify_step_priority_override = management.clear_job_queue:90
+# We don't use this feature, and it creates an additional load on the database
+node_history = False
+# Provide for a timeout longer than 60 seconds for certain vendor's hardware
+power_state_change_timeout = 120
+{% if env.IRONIC_DEFAULT_KERNEL is defined %}
+deploy_kernel = file://{{ env.IRONIC_DEFAULT_KERNEL }}
+{% endif %}
+{% if env.IRONIC_DEFAULT_RAMDISK is defined %}
+deploy_ramdisk = file://{{ env.IRONIC_DEFAULT_RAMDISK }}
+{% endif %}
+
+[database]
+{% if env.IRONIC_USE_MARIADB | lower == "false" %}
+connection = sqlite:////var/lib/ironic/ironic.sqlite
+# Synchronous mode is required for data integrity in case of operating system
+# crash. In our case we restart the container from scratch, so we can save some
+# IO by not doing syncs all the time.
+sqlite_synchronous = False
+{% else %}
+connection = {{ env.MARIADB_CONNECTION }}
+{% endif %}
+
+[deploy]
+default_boot_option = local
+erase_devices_metadata_priority = 10
+erase_devices_priority = 0
+http_root = /shared/html/
+http_url = {{ env.IRONIC_BOOT_BASE_URL }}
+fast_track = {{ env.IRONIC_FAST_TRACK }}
+{% if env.IRONIC_BOOT_ISO_SOURCE %}
+ramdisk_image_download_source = {{ env.IRONIC_BOOT_ISO_SOURCE }}
+{% endif %}
+{% if env.IRONIC_EXTERNAL_HTTP_URL %}
+external_http_url = {{ env.IRONIC_EXTERNAL_HTTP_URL }}
+{% elif env.IRONIC_VMEDIA_TLS_SETUP == "true" %}
+external_http_url = https://{{ env.IRONIC_URL_HOST }}:{{ env.VMEDIA_TLS_PORT }}
+{% endif %}
+{% if env.IRONIC_EXTERNAL_CALLBACK_URL %}
+external_callback_url = {{ env.IRONIC_EXTERNAL_CALLBACK_URL }}
+{% endif %}
+
+[dhcp]
+dhcp_provider = none
+
+[inspector]
+power_off = {{ false if env.IRONIC_FAST_TRACK == "true" else true }}
+# NOTE(dtantsur): keep inspection arguments synchronized with inspector.ipxe
+# Also keep in mind that only parameters unique for inspection go here.
+# No need to duplicate pxe_append_params/kernel_append_params.
+extra_kernel_params = ipa-inspection-collectors={{ env.IRONIC_IPA_COLLECTORS }} ipa-enable-vlan-interfaces={{ env.IRONIC_INSPECTOR_VLAN_INTERFACES }} ipa-inspection-dhcp-all-interfaces=1 ipa-collect-lldp=1 net.ifnames={{ '0' if env.PREDICTABLE_NIC_NAMES == 'false' else '1' }}
+
+{% if env.USE_IRONIC_INSPECTOR == "true" %}
+endpoint_override = {{ env.IRONIC_INSPECTOR_BASE_URL }}
+{% if env.IRONIC_INSPECTOR_TLS_SETUP == "true" %}
+cafile = {{ env.IRONIC_INSPECTOR_CACERT_FILE }}
+insecure = {{ env.IRONIC_INSPECTOR_INSECURE }}
+{% endif %}
+{% if env.IRONIC_INSPECTOR_CALLBACK_ENDPOINT_OVERRIDE %}
+callback_endpoint_override = {{ env.IRONIC_INSPECTOR_CALLBACK_ENDPOINT_OVERRIDE }}
+{% endif %}
+{% else %}
+hooks = $default_hooks,parse-lldp
+add_ports = all
+keep_ports = present
+{% endif %}
+
+[ipmi]
+# use_ipmitool_retries transfers the responsibility of retrying to ipmitool
+# when supported. If set to false, then ipmitool is called as follows :
+# $ipmitool -R 1 -N 1 ...
+# and Ironic handles the retry loop.
+use_ipmitool_retries = false
+# The following parameters are the defaults in Ironic. They are used in the
+# following way if use_ipmitool_retries is set to true:
+# $ipmitool -R -N ...
+# where :
+# X = command_retry_timeout / min_command_interval
+# Y = min_command_interval
+# If use_ipmitool_retries is false, then ironic retries X times, with an
+# interval of Y in between each tries.
+min_command_interval = 5
+command_retry_timeout = 60
+# List of possible cipher suites versions that can be
+# supported by the hardware in case the field `cipher_suite`
+# is not set for the node. (list value)
+cipher_suite_versions = 3,17
+
+{% if env.IRONIC_EXPOSE_JSON_RPC | lower == "true" %}
+[json_rpc]
+# We assume that when we run API and conductor in the same container, they use
+# authentication over localhost, using the same credentials as API, to prevent
+# unauthenticated connections from other processes in the same host since the
+# containers are in host networking.
+auth_strategy = {{ env.JSON_RPC_AUTH_STRATEGY }}
+http_basic_auth_user_file = /etc/ironic/htpasswd-rpc
+{% if env.IRONIC_DEPLOYMENT == "Conductor" and env.JSON_RPC_AUTH_STRATEGY == "noauth" %}
+# if access is unauthenticated, we bind only to localhost - use that as the
+# host name also, so that the client can find the server
+host_ip = localhost
+{% else %}
+host_ip = {% if env.LISTEN_ALL_INTERFACES | lower == "true" %}::{% else %}{{ env.IRONIC_IP }}{% endif %}
+{% endif %}
+{% if env.IRONIC_TLS_SETUP == "true" %}
+use_ssl = true
+cafile = {{ env.IRONIC_CACERT_FILE }}
+insecure = {{ env.IRONIC_INSECURE }}
+{% endif %}
+{% endif %}
+
+[nova]
+send_power_notifications = false
+
+[oslo_messaging_notifications]
+driver = prometheus_exporter
+location = /shared/ironic_prometheus_exporter
+transport_url = fake://
+
+[pxe]
+# NOTE(dtantsur): keep this value at least 3x lower than
+# [conductor]deploy_callback_timeout so that at least some retries happen.
+# The default settings enable 3 retries after 20 minutes each.
+boot_retry_timeout = 1200
+images_path = /shared/html/tmp
+instance_master_path = /shared/html/master_images
+tftp_master_path = /shared/tftpboot/master_images
+tftp_root = /shared/tftpboot
+kernel_append_params = nofb nomodeset vga=normal ipa-insecure={{ env.IPA_INSECURE }} {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} systemd.journald.forward_to_console=yes
+# This makes networking boot templates generated even for nodes using local
+# boot (the default), ensuring that they boot correctly even if they start
+# netbooting for some reason (e.g. with the noop management interface).
+enable_netboot_fallback = true
+# Enable the fallback path to in-band inspection
+ipxe_fallback_script = inspector.ipxe
+
+[redfish]
+use_swift = false
+kernel_append_params = nofb nomodeset vga=normal ipa-insecure={{ env.IPA_INSECURE }} {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} systemd.journald.forward_to_console=yes
+
+[ilo]
+kernel_append_params = nofb nomodeset vga=normal ipa-insecure={{ env.IPA_INSECURE }} {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} systemd.journald.forward_to_console=yes
+use_web_server_for_images = true
+
+[irmc]
+kernel_append_params = nofb nomodeset vga=normal ipa-insecure={{ env.IPA_INSECURE }} {% if env.IRONIC_RAMDISK_SSH_KEY %}sshkey="{{ env.IRONIC_RAMDISK_SSH_KEY|trim }}"{% endif %} {{ env.IRONIC_KERNEL_PARAMS|trim }} systemd.journald.forward_to_console=yes
+
+[service_catalog]
+endpoint_override = {{ env.IRONIC_BASE_URL }}
+
+{% if env.IRONIC_TLS_SETUP == "true" %}
+[ssl]
+cert_file = {{ env.IRONIC_CERT_FILE }}
+key_file = {{ env.IRONIC_KEY_FILE }}
+{% endif %}
diff --git a/ironic-image/mkisofs_wrapper b/ironic-image/mkisofs_wrapper
new file mode 100644
index 0000000..d1d1a3c
--- /dev/null
+++ b/ironic-image/mkisofs_wrapper
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+xorriso -as mkisofs "${@}"
\ No newline at end of file
diff --git a/ironic-image/network-data-schema-empty.json b/ironic-image/network-data-schema-empty.json
new file mode 100644
index 0000000..d31a3bc
--- /dev/null
+++ b/ironic-image/network-data-schema-empty.json
@@ -0,0 +1 @@
+{}
diff --git a/ironic-image/prepare-efi.sh b/ironic-image/prepare-efi.sh
new file mode 100644
index 0000000..84e0808
--- /dev/null
+++ b/ironic-image/prepare-efi.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+set -euxo pipefail
+
+ARCH=$(uname -m)
+DEST=${2:-/tmp/esp.img}
+OS=${1:-sles}
+
+BOOTEFI=BOOTX64.efi
+GRUBEFI=grubx64.efi
+
+dd bs=1024 count=6400 if=/dev/zero of=$DEST
+mkfs.msdos -F 12 -n 'ESP_IMAGE' $DEST
+
+mkdir -p /boot/efi/EFI/BOOT
+cp -L /usr/lib64/efi/shim.efi /boot/efi/EFI/BOOT/$BOOTEFI
+mkdir -p /boot/efi/EFI/$OS
+#cp /usr/share/grub2/x86_64-efi/grub.efi /boot/efi/EFI/$OS/$GRUBEFI
+cp /usr/share/grub2/x86_64-efi/grub.efi /boot/efi/EFI/$OS/grub.efi
+
+mmd -i $DEST EFI
+mmd -i $DEST EFI/BOOT
+mcopy -i $DEST -v /boot/efi/EFI/BOOT/$BOOTEFI ::EFI/BOOT
+#mcopy -i $DEST -v /boot/efi/EFI/$OS/$GRUBEFI ::EFI/BOOT
+mcopy -i $DEST -v /boot/efi/EFI/$OS/grub.efi ::EFI/BOOT
+mdir -i $DEST ::EFI/BOOT;
+
diff --git a/ironic-image/rundnsmasq b/ironic-image/rundnsmasq
new file mode 100644
index 0000000..92af2eb
--- /dev/null
+++ b/ironic-image/rundnsmasq
@@ -0,0 +1,35 @@
+#!/usr/bin/bash
+
+set -eux
+
+# shellcheck disable=SC1091
+. /bin/ironic-common.sh
+
+export HTTP_PORT=${HTTP_PORT:-80}
+DNSMASQ_EXCEPT_INTERFACE=${DNSMASQ_EXCEPT_INTERFACE:-lo}
+export DNS_PORT=${DNS_PORT:-0}
+
+wait_for_interface_or_ip
+if [[ "${DNS_IP:-}" == "provisioning" ]]; then
+ export DNS_IP="$IRONIC_URL_HOST"
+fi
+
+mkdir -p /shared/tftpboot
+mkdir -p /shared/html/images
+mkdir -p /shared/html/pxelinux.cfg
+
+# Copy files to shared mount
+cp /tftpboot/undionly.kpxe /tftpboot/snponly.efi /shared/tftpboot
+
+# Template and write dnsmasq.conf
+# we template via /tmp as sed otherwise creates temp files in /etc directory
+# where we can't write
+python3 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' /tmp/dnsmasq.conf
+
+for iface in $(echo "$DNSMASQ_EXCEPT_INTERFACE" | tr ',' ' '); do
+ sed -i -e "/^interface=.*/ a\except-interface=${iface}" /tmp/dnsmasq.conf
+done
+cat /tmp/dnsmasq.conf > /etc/dnsmasq.conf
+rm /tmp/dnsmasq.conf
+
+exec /usr/sbin/dnsmasq -d -q -C /etc/dnsmasq.conf
diff --git a/ironic-image/runhttpd b/ironic-image/runhttpd
new file mode 100644
index 0000000..57e7c97
--- /dev/null
+++ b/ironic-image/runhttpd
@@ -0,0 +1,101 @@
+#!/usr/bin/bash
+
+# shellcheck disable=SC1091
+. /bin/tls-common.sh
+. /bin/ironic-common.sh
+. /bin/auth-common.sh
+
+export HTTP_PORT=${HTTP_PORT:-80}
+export VMEDIA_TLS_PORT=${VMEDIA_TLS_PORT:-8083}
+
+INSPECTOR_ORIG_HTTPD_CONFIG=/etc/httpd/conf.d/inspector-apache.conf.j2
+INSPECTOR_RESULT_HTTPD_CONFIG=/etc/httpd/conf.d/ironic-inspector.conf
+export IRONIC_REVERSE_PROXY_SETUP=${IRONIC_REVERSE_PROXY_SETUP:-false}
+export INSPECTOR_REVERSE_PROXY_SETUP=${INSPECTOR_REVERSE_PROXY_SETUP:-false}
+
+# In Metal3 context they are called node images in Ironic context they are
+# called user images.
+export HTTPD_SERVE_NODE_IMAGES="${HTTPD_SERVE_NODE_IMAGES:-true}"
+
+# Whether to enable fast_track provisioning or not
+IRONIC_FAST_TRACK=${IRONIC_FAST_TRACK:-true}
+
+# Whether to activate the EnableSendfile apache directive for httpd
+HTTPD_ENABLE_SENDFILE="${HTTPD_ENABLE_SENDFILE:-false}"
+
+# Set of collectors that should be used with IPA inspection
+export IRONIC_IPA_COLLECTORS=${IRONIC_IPA_COLLECTORS:-default,logs}
+
+wait_for_interface_or_ip
+
+mkdir -p /shared/html
+chmod 0777 /shared/html
+
+IRONIC_BASE_URL="${IRONIC_SCHEME}://${IRONIC_URL_HOST}"
+
+if [[ "${USE_IRONIC_INSPECTOR}" == "true" ]]; then
+ INSPECTOR_EXTRA_ARGS=" ipa-inspection-callback-url=${IRONIC_BASE_URL}:${IRONIC_INSPECTOR_ACCESS_PORT}/v1/continue"
+else
+ INSPECTOR_EXTRA_ARGS=" ipa-inspection-callback-url=${IRONIC_BASE_URL}:${IRONIC_ACCESS_PORT}/v1/continue_inspection"
+fi
+
+if [[ "$IRONIC_FAST_TRACK" == "true" ]]; then
+ INSPECTOR_EXTRA_ARGS+=" ipa-api-url=${IRONIC_BASE_URL}:${IRONIC_ACCESS_PORT}"
+fi
+export INSPECTOR_EXTRA_ARGS
+
+# Copy files to shared mount
+render_j2_config /tmp/inspector.ipxe.j2 /shared/html/inspector.ipxe
+cp /tmp/uefi_esp.img /shared/html/uefi_esp.img
+
+# Render the core httpd config
+render_j2_config /etc/httpd/conf/httpd.conf.j2 /etc/httpd/conf/httpd.conf
+
+if [[ "$USE_IRONIC_INSPECTOR" == "true" ]] && [[ "$IRONIC_INSPECTOR_TLS_SETUP" == "true" ]]; then
+ if [[ "${INSPECTOR_REVERSE_PROXY_SETUP}" == "true" ]]; then
+ render_j2_config "$INSPECTOR_ORIG_HTTPD_CONFIG" "$INSPECTOR_RESULT_HTTPD_CONFIG"
+ fi
+else
+ export INSPECTOR_REVERSE_PROXY_SETUP="false" # If TLS is not used, we have no reason to use the reverse proxy
+fi
+
+if [[ "$IRONIC_TLS_SETUP" == "true" ]]; then
+ if [[ "${IRONIC_REVERSE_PROXY_SETUP}" == "true" ]]; then
+ render_j2_config /tmp/httpd-ironic-api.conf.j2 /etc/httpd/conf.d/ironic.conf
+ fi
+else
+ export IRONIC_REVERSE_PROXY_SETUP="false" # If TLS is not used, we have no reason to use the reverse proxy
+fi
+
+write_htpasswd_files
+
+# Render httpd TLS configuration for /shared/html/
+if [[ "$IRONIC_VMEDIA_TLS_SETUP" == "true" ]]; then
+ render_j2_config /etc/httpd-vmedia.conf.j2 /etc/httpd/conf.d/vmedia.conf
+fi
+
+# Set up inotify to kill the container (restart) whenever cert files for ironic inspector change
+if [[ "$IRONIC_INSPECTOR_TLS_SETUP" == "true" ]] && [[ "${RESTART_CONTAINER_CERTIFICATE_UPDATED}" == "true" ]]; then
+ # shellcheck disable=SC2034
+ inotifywait -m -e delete_self "${IRONIC_INSPECTOR_CERT_FILE}" | while read -r file event; do
+ kill -WINCH $(pgrep httpd)
+ done &
+fi
+
+# Set up inotify to kill the container (restart) whenever cert files for ironic api change
+if [[ "$IRONIC_TLS_SETUP" == "true" ]] && [[ "${RESTART_CONTAINER_CERTIFICATE_UPDATED}" == "true" ]]; then
+ # shellcheck disable=SC2034
+ inotifywait -m -e delete_self "${IRONIC_CERT_FILE}" | while read -r file event; do
+ kill -WINCH $(pgrep httpd)
+ done &
+fi
+
+# Set up inotify to kill the container (restart) whenever cert of httpd for /shared/html/ path change
+if [[ "$IRONIC_VMEDIA_TLS_SETUP" == "true" ]] && [[ "${RESTART_CONTAINER_CERTIFICATE_UPDATED}" == "true" ]]; then
+ # shellcheck disable=SC2034
+ inotifywait -m -e delete_self "${IRONIC_VMEDIA_CERT_FILE}" | while read -r file event; do
+ kill -WINCH $(pgrep httpd)
+ done &
+fi
+
+exec /usr/sbin/httpd -DFOREGROUND -f /etc/httpd/conf/httpd.conf
diff --git a/ironic-image/runironic b/ironic-image/runironic
new file mode 100644
index 0000000..5dd6ef2
--- /dev/null
+++ b/ironic-image/runironic
@@ -0,0 +1,25 @@
+#!/usr/bin/bash
+
+# These settings must go before configure-ironic since it has different
+# defaults.
+export IRONIC_USE_MARIADB=${IRONIC_USE_MARIADB:-false}
+export IRONIC_EXPOSE_JSON_RPC=${IRONIC_EXPOSE_JSON_RPC:-false}
+
+# shellcheck disable=SC1091
+. /bin/configure-ironic.sh
+
+# Ramdisk logs
+mkdir -p /shared/log/ironic/deploy
+
+run_ironic_dbsync
+
+if [[ "$IRONIC_TLS_SETUP" == "true" ]] && [[ "${RESTART_CONTAINER_CERTIFICATE_UPDATED}" == "true" ]]; then
+ # shellcheck disable=SC2034
+ inotifywait -m -e delete_self "${IRONIC_CERT_FILE}" | while read -r file event; do
+ kill $(pgrep ironic)
+ done &
+fi
+
+configure_ironic_auth
+
+exec /usr/bin/ironic
diff --git a/ironic-image/runironic-api b/ironic-image/runironic-api
new file mode 100644
index 0000000..9deb9ac
--- /dev/null
+++ b/ironic-image/runironic-api
@@ -0,0 +1,13 @@
+#!/usr/bin/bash
+
+export IRONIC_DEPLOYMENT="API"
+
+# shellcheck disable=SC1091
+. /bin/configure-ironic.sh
+
+export IRONIC_REVERSE_PROXY_SETUP=false
+
+python3 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' < /tmp/httpd-ironic-api.conf.j2 > /etc/httpd/conf.d/ironic.conf
+
+# shellcheck disable=SC1091
+. /bin/runhttpd
diff --git a/ironic-image/runironic-conductor b/ironic-image/runironic-conductor
new file mode 100644
index 0000000..64b2c82
--- /dev/null
+++ b/ironic-image/runironic-conductor
@@ -0,0 +1,20 @@
+#!/usr/bin/bash
+
+export IRONIC_DEPLOYMENT="Conductor"
+
+# shellcheck disable=SC1091
+. /bin/configure-ironic.sh
+
+# Ramdisk logs
+mkdir -p /shared/log/ironic/deploy
+
+run_ironic_dbsync
+
+if [[ "$IRONIC_TLS_SETUP" == "true" ]] && [[ "${RESTART_CONTAINER_CERTIFICATE_UPDATED}" == "true" ]]; then
+ # shellcheck disable=SC2034
+ inotifywait -m -e delete_self "${IRONIC_CERT_FILE}" | while read -r file event; do
+ kill $(pgrep ironic)
+ done &
+fi
+
+exec /usr/bin/ironic-conductor
diff --git a/ironic-image/runironic-exporter b/ironic-image/runironic-exporter
new file mode 100644
index 0000000..f2f60f2
--- /dev/null
+++ b/ironic-image/runironic-exporter
@@ -0,0 +1,12 @@
+#!/usr/bin/bash
+
+# shellcheck disable=SC1091
+. /bin/configure-ironic.sh
+
+FLASK_RUN_HOST=${FLASK_RUN_HOST:-0.0.0.0}
+FLASK_RUN_PORT=${FLASK_RUN_PORT:-9608}
+
+export IRONIC_CONFIG="/etc/ironic/ironic.conf"
+
+exec gunicorn -b "${FLASK_RUN_HOST}:${FLASK_RUN_PORT}" -w 4 \
+ ironic_prometheus_exporter.app.wsgi:application
diff --git a/ironic-image/runironic-inspector b/ironic-image/runironic-inspector
new file mode 100644
index 0000000..c43782d
--- /dev/null
+++ b/ironic-image/runironic-inspector
@@ -0,0 +1,62 @@
+#!/usr/bin/bash
+
+set -euxo pipefail
+
+CONFIG=/etc/ironic-inspector/ironic-inspector.conf
+
+export IRONIC_INSPECTOR_ENABLE_DISCOVERY=${IRONIC_INSPECTOR_ENABLE_DISCOVERY:-false}
+export INSPECTOR_REVERSE_PROXY_SETUP=${INSPECTOR_REVERSE_PROXY_SETUP:-false}
+
+# shellcheck disable=SC1091
+. /bin/tls-common.sh
+# shellcheck disable=SC1091
+. /bin/ironic-common.sh
+# shellcheck disable=SC1091
+. /bin/auth-common.sh
+
+if [[ "$USE_IRONIC_INSPECTOR" == "false" ]]; then
+ echo "FATAL: ironic-inspector is disabled via USE_IRONIC_INSPECTOR"
+ exit 1
+fi
+
+wait_for_interface_or_ip
+
+IRONIC_INSPECTOR_PORT=${IRONIC_INSPECTOR_ACCESS_PORT}
+if [[ "$IRONIC_INSPECTOR_TLS_SETUP" == "true" ]]; then
+ if [[ "${INSPECTOR_REVERSE_PROXY_SETUP}" == "true" ]] && [[ "${IRONIC_INSPECTOR_PRIVATE_PORT}" != "unix" ]]; then
+ IRONIC_INSPECTOR_PORT=$IRONIC_INSPECTOR_PRIVATE_PORT
+ fi
+else
+ export INSPECTOR_REVERSE_PROXY_SETUP="false" # If TLS is not used, we have no reason to use the reverse proxy
+fi
+
+export IRONIC_INSPECTOR_BASE_URL="${IRONIC_INSPECTOR_SCHEME}://${IRONIC_URL_HOST}:${IRONIC_INSPECTOR_PORT}"
+export IRONIC_BASE_URL="${IRONIC_SCHEME}://${IRONIC_URL_HOST}:${IRONIC_ACCESS_PORT}"
+
+build_j2_config()
+{
+ local CONFIG_FILE="$1"
+ python3 -c 'import os; import sys; import jinja2; sys.stdout.write(jinja2.Template(sys.stdin.read()).render(env=os.environ))' < "$CONFIG_FILE.j2"
+}
+
+# Merge with the original configuration file from the package.
+build_j2_config "$CONFIG" | crudini --merge "$CONFIG"
+
+configure_inspector_auth
+
+configure_client_basic_auth ironic "${CONFIG}"
+
+ironic-inspector-dbsync --config-file "${CONFIG}" upgrade
+
+if [[ "$INSPECTOR_REVERSE_PROXY_SETUP" == "false" ]] && [[ "${RESTART_CONTAINER_CERTIFICATE_UPDATED}" == "true" ]]; then
+ # shellcheck disable=SC2034
+ inotifywait -m -e delete_self "${IRONIC_INSPECTOR_CERT_FILE}" | while read -r file event; do
+ kill $(pgrep ironic)
+ done &
+fi
+
+# Make sure ironic traffic bypasses any proxies
+export NO_PROXY="${NO_PROXY:-},$IRONIC_IP"
+
+# shellcheck disable=SC2086
+exec /usr/bin/ironic-inspector
diff --git a/ironic-image/runlogwatch.sh b/ironic-image/runlogwatch.sh
new file mode 100644
index 0000000..8b2124e
--- /dev/null
+++ b/ironic-image/runlogwatch.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/bash
+
+# Ramdisk logs path
+LOG_DIRS=("/shared/log/ironic/deploy" "/shared/log/ironic-inspector/ramdisk")
+
+while :; do
+ for LOG_DIR in "${LOG_DIRS[@]}"; do
+ if ! ls "${LOG_DIR}"/*.tar.gz 1> /dev/null 2>&1; then
+ continue
+ fi
+
+ for fn in "${LOG_DIR}"/*.tar.gz; do
+ echo "************ Contents of $fn ramdisk log file bundle **************"
+ tar -xOzvvf "$fn" | sed -e "s/^/$(basename "$fn"): /"
+ rm -f "$fn"
+ done
+ done
+
+ sleep 5
+done
diff --git a/ironic-image/tls-common.sh b/ironic-image/tls-common.sh
new file mode 100644
index 0000000..992f475
--- /dev/null
+++ b/ironic-image/tls-common.sh
@@ -0,0 +1,101 @@
+#!/bin/bash
+
+export IRONIC_CERT_FILE=/certs/ironic/tls.crt
+export IRONIC_KEY_FILE=/certs/ironic/tls.key
+export IRONIC_CACERT_FILE=/certs/ca/ironic/tls.crt
+export IRONIC_INSECURE=${IRONIC_INSECURE:-false}
+export IRONIC_SSL_PROTOCOL=${IRONIC_SSL_PROTOCOL:-"-ALL +TLSv1.2 +TLSv1.3"}
+export IRONIC_VMEDIA_SSL_PROTOCOL=${IRONIC_VMEDIA_SSL_PROTOCOL:-"ALL"}
+
+export IRONIC_INSPECTOR_CERT_FILE=/certs/ironic-inspector/tls.crt
+export IRONIC_INSPECTOR_KEY_FILE=/certs/ironic-inspector/tls.key
+export IRONIC_INSPECTOR_CACERT_FILE=/certs/ca/ironic-inspector/tls.crt
+export IRONIC_INSPECTOR_INSECURE=${IRONIC_INSPECTOR_INSECURE:-$IRONIC_INSECURE}
+
+export IRONIC_VMEDIA_CERT_FILE=/certs/vmedia/tls.crt
+export IRONIC_VMEDIA_KEY_FILE=/certs/vmedia/tls.key
+
+export RESTART_CONTAINER_CERTIFICATE_UPDATED=${RESTART_CONTAINER_CERTIFICATE_UPDATED:-"false"}
+
+export MARIADB_CACERT_FILE=/certs/ca/mariadb/tls.crt
+
+mkdir -p /certs/ironic
+mkdir -p /certs/ironic-inspector
+mkdir -p /certs/ca/ironic
+mkdir -p /certs/ca/ironic-inspector
+
+if [[ -f "$IRONIC_CERT_FILE" ]] && [[ ! -f "$IRONIC_KEY_FILE" ]]; then
+ echo "Missing TLS Certificate key file $IRONIC_KEY_FILE"
+ exit 1
+fi
+if [[ ! -f "$IRONIC_CERT_FILE" ]] && [[ -f "$IRONIC_KEY_FILE" ]]; then
+ echo "Missing TLS Certificate file $IRONIC_CERT_FILE"
+ exit 1
+fi
+
+if [[ -f "$IRONIC_INSPECTOR_CERT_FILE" ]] && [[ ! -f "$IRONIC_INSPECTOR_KEY_FILE" ]]; then
+ echo "Missing TLS Certificate key file $IRONIC_INSPECTOR_KEY_FILE"
+ exit 1
+fi
+if [[ ! -f "$IRONIC_INSPECTOR_CERT_FILE" ]] && [[ -f "$IRONIC_INSPECTOR_KEY_FILE" ]]; then
+ echo "Missing TLS Certificate file $IRONIC_INSPECTOR_CERT_FILE"
+ exit 1
+fi
+
+if [[ -f "$IRONIC_VMEDIA_CERT_FILE" ]] && [[ ! -f "$IRONIC_VMEDIA_KEY_FILE" ]]; then
+ echo "Missing TLS Certificate key file $IRONIC_VMEDIA_KEY_FILE"
+ exit 1
+fi
+if [[ ! -f "$IRONIC_VMEDIA_CERT_FILE" ]] && [[ -f "$IRONIC_VMEDIA_KEY_FILE" ]]; then
+ echo "Missing TLS Certificate file $IRONIC_VMEDIA_CERT_FILE"
+ exit 1
+fi
+
+copy_atomic()
+{
+ local src="$1"
+ local dest="$2"
+ local tmpdest
+
+ tmpdest=$(mktemp "$dest.XXX")
+ cp "$src" "$tmpdest"
+ # Hard linking is atomic, but only works on the same volume
+ ln -f "$tmpdest" "$dest"
+ rm -f "$tmpdest"
+}
+
+if [[ -f "$IRONIC_CERT_FILE" ]] || [[ -f "$IRONIC_CACERT_FILE" ]]; then
+ export IRONIC_TLS_SETUP="true"
+ export IRONIC_SCHEME="https"
+ if [[ ! -f "$IRONIC_CACERT_FILE" ]]; then
+ copy_atomic "$IRONIC_CERT_FILE" "$IRONIC_CACERT_FILE"
+ fi
+else
+ export IRONIC_TLS_SETUP="false"
+ export IRONIC_SCHEME="http"
+fi
+
+if [[ -f "$IRONIC_INSPECTOR_CERT_FILE" ]] || [[ -f "$IRONIC_INSPECTOR_CACERT_FILE" ]]; then
+ export IRONIC_INSPECTOR_TLS_SETUP="true"
+ export IRONIC_INSPECTOR_SCHEME="https"
+ if [[ ! -f "$IRONIC_INSPECTOR_CACERT_FILE" ]]; then
+ copy_atomic "$IRONIC_INSPECTOR_CERT_FILE" "$IRONIC_INSPECTOR_CACERT_FILE"
+ fi
+else
+ export IRONIC_INSPECTOR_TLS_SETUP="false"
+ export IRONIC_INSPECTOR_SCHEME="http"
+fi
+
+if [[ -f "$IRONIC_VMEDIA_CERT_FILE" ]]; then
+ export IRONIC_VMEDIA_SCHEME="https"
+ export IRONIC_VMEDIA_TLS_SETUP="true"
+else
+ export IRONIC_VMEDIA_SCHEME="http"
+ export IRONIC_VMEDIA_TLS_SETUP="false"
+fi
+
+if [[ -f "$MARIADB_CACERT_FILE" ]]; then
+ export MARIADB_TLS_ENABLED="true"
+else
+ export MARIADB_TLS_ENABLED="false"
+fi
diff --git a/ironic-ipa-downloader-image/Dockerfile b/ironic-ipa-downloader-image/Dockerfile
new file mode 100644
index 0000000..bb061bc
--- /dev/null
+++ b/ironic-ipa-downloader-image/Dockerfile
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: Apache-2.0
+#!BuildTag: %%IMG_PREFIX%%ironic-ipa-downloader:2.0.0
+#!BuildTag: %%IMG_PREFIX%%ironic-ipa-downloader:2.0.0-%RELEASE%
+#!BuildVersion: 15.6
+ARG SLE_VERSION
+FROM registry.suse.com/bci/bci-micro:$SLE_VERSION AS micro
+
+FROM registry.suse.com/bci/bci-base:$SLE_VERSION AS base
+COPY --from=micro / /installroot/
+RUN sed -i -e 's%^# rpm.install.excludedocs = no.*%rpm.install.excludedocs = yes%g' /etc/zypp/zypp.conf
+RUN zypper --installroot /installroot --non-interactive install --no-recommends openstack-ironic-image-x86_64 python311-devel python311 python311-pip tar gawk git curl xz fakeroot shadow sed cpio; zypper -n clean; rm -rf /var/log/*
+#RUN zypper --installroot /installroot --non-interactive install --no-recommends sles-release;
+RUN cp /usr/bin/getopt /installroot/
+
+FROM micro AS final
+
+# Define labels according to https://en.opensuse.org/Building_derived_containers
+# labelprefix=com.suse.application.ironic
+LABEL org.opencontainers.image.authors="SUSE LLC (https://www.suse.com/)"
+LABEL org.opencontainers.image.title="SLE Based Ironic IPA Downloader Container Image"
+LABEL org.opencontainers.image.description="ironic-ipa-downloader based on the SLE Base Container Image."
+LABEL org.opencontainers.image.version="2.0.0"
+LABEL org.opencontainers.image.url="https://www.suse.com/solutions/edge-computing/"
+LABEL org.opencontainers.image.created="%BUILDTIME%"
+LABEL org.opencontainers.image.vendor="SUSE LLC"
+LABEL org.opensuse.reference="%%IMG_REPO%%/%%IMG_PREFIX%%ironic-ipa-downloader:2.0.0-%RELEASE%"
+LABEL org.openbuildservice.disturl="%DISTURL%"
+LABEL com.suse.supportlevel="l3"
+LABEL com.suse.eula="SUSE Combined EULA February 2024"
+LABEL com.suse.lifecycle-url="https://www.suse.com/lifecycle"
+LABEL com.suse.image-type="application"
+LABEL com.suse.release-stage="released"
+# endlabelprefix
+
+COPY --from=base /installroot /
+RUN cp /getopt /usr/bin/
+RUN cp /srv/tftpboot/openstack-ironic-image/initrd.xz /tmp
+RUN cp /srv/tftpboot/openstack-ironic-image/openstack-ironic-image*.kernel /tmp
+# configure non-root user
+COPY configure-nonroot.sh /bin/
+RUN set -euo pipefail; chmod +x /bin/configure-nonroot.sh
+RUN set -euo pipefail; /bin/configure-nonroot.sh && rm -f /bin/configure-nonroot.sh
+COPY get-resource.sh /usr/local/bin/get-resource.sh
+
+RUN set -euo pipefail; chmod +x /usr/local/bin/get-resource.sh
diff --git a/ironic-ipa-downloader-image/_service b/ironic-ipa-downloader-image/_service
new file mode 100644
index 0000000..3480bd2
--- /dev/null
+++ b/ironic-ipa-downloader-image/_service
@@ -0,0 +1,17 @@
+
+
+
+
+ Dockerfile
+ %%openstack-ironic-image-x86_64_version%%
+ openstack-ironic-image-x86_64
+ patch
+
+
+ Dockerfile
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+
diff --git a/ironic-ipa-downloader-image/configure-nonroot.sh b/ironic-ipa-downloader-image/configure-nonroot.sh
new file mode 100644
index 0000000..e85754f
--- /dev/null
+++ b/ironic-ipa-downloader-image/configure-nonroot.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/bash
+
+NONROOT_UID=10475
+NONROOT_GID=10475
+USER="ironic-suse"
+
+groupadd -r -g ${NONROOT_GID} ${USER}
+useradd -r -g ${NONROOT_GID} \
+ -u ${NONROOT_UID} \
+ -d /home \
+ -s /sbin/nologin \
+ ${USER}
diff --git a/ironic-ipa-downloader-image/get-resource.sh b/ironic-ipa-downloader-image/get-resource.sh
new file mode 100644
index 0000000..373553f
--- /dev/null
+++ b/ironic-ipa-downloader-image/get-resource.sh
@@ -0,0 +1,71 @@
+#!/bin/bash -xe
+#CACHEURL=http://172.22.0.1/images
+
+# Check and set http(s)_proxy. Required for cURL to use a proxy
+export http_proxy=${http_proxy:-$HTTP_PROXY}
+export https_proxy=${https_proxy:-$HTTPS_PROXY}
+export no_proxy=${no_proxy:-$NO_PROXY}
+
+# Which image should we use
+if [ -z "${IPA_BASEURI}" ]; then
+ # SLES BASED IPA - openstack-ironic-image-x86_64 package
+ mkdir -p /shared/html/images
+ cp /tmp/initrd.xz /shared/html/images/ironic-python-agent.initramfs
+ cp /tmp/openstack-ironic-image*.x86_64*.kernel /shared/html/images/ironic-python-agent.kernel
+else
+ FILENAME=ironic-python-agent
+ FILENAME_EXT=.tar
+ FFILENAME=$FILENAME$FILENAME_EXT
+
+ mkdir -p /shared/html/images /shared/tmp
+ cd /shared/html/images
+
+ TMPDIR=$(mktemp -d -p /shared/tmp)
+
+ # If we have a CACHEURL and nothing has yet been downloaded
+ # get header info from the cache
+ ls -l
+ if [ -n "$CACHEURL" -a ! -e $FFILENAME.headers ] ; then
+ curl -g --verbose --fail -O "$CACHEURL/$FFILENAME.headers" || true
+ fi
+
+ # Download the most recent version of IPA
+ if [ -e $FFILENAME.headers ] ; then
+ ETAG=$(awk '/ETag:/ {print $2}' $FFILENAME.headers | tr -d "\r")
+ cd $TMPDIR
+ curl -g --verbose --dump-header $FFILENAME.headers -O $IPA_BASEURI/$FFILENAME --header "If-None-Match: $ETAG" || cp /shared/html/images/$FFILENAME.headers .
+ # curl didn't download anything because we have the ETag already
+ # but we don't have it in the images directory
+ # Its in the cache, go get it
+ ETAG=$(awk '/ETag:/ {print $2}' $FFILENAME.headers | tr -d "\"\r")
+ if [ ! -s $FFILENAME -a ! -e /shared/html/images/$FILENAME-$ETAG/$FFILENAME ] ; then
+ mv /shared/html/images/$FFILENAME.headers .
+ curl -g --verbose -O "$CACHEURL/$FILENAME-$ETAG/$FFILENAME"
+ fi
+ else
+ cd $TMPDIR
+ curl -g --verbose --dump-header $FFILENAME.headers -O $IPA_BASEURI/$FFILENAME
+ fi
+
+ if [ -s $FFILENAME ] ; then
+ tar -xf $FFILENAME
+
+ ETAG=$(awk '/ETag:/ {print $2}' $FFILENAME.headers | tr -d "\"\r")
+ cd -
+ chmod 755 $TMPDIR
+ mv $TMPDIR $FILENAME-$ETAG
+ ln -sf $FILENAME-$ETAG/$FFILENAME.headers $FFILENAME.headers
+ ln -sf $FILENAME-$ETAG/$FILENAME.initramfs $FILENAME.initramfs
+ ln -sf $FILENAME-$ETAG/$FILENAME.kernel $FILENAME.kernel
+ else
+ rm -rf $TMPDIR
+ fi
+fi
+
+if [ -d "/tmp/ironic-certificates" ]; then
+ mkdir -p /tmp/ca/tmp-initrd && cd /tmp/ca/tmp-initrd
+ xz -d -c -k --fast /shared/html/images/ironic-python-agent.initramfs | fakeroot -s ../initrd.fakeroot cpio -i
+ mkdir -p etc/ironic-python-agent.d/ca-certs
+ cp /tmp/ironic-certificates/* etc/ironic-python-agent.d/ca-certs/
+ find . | fakeroot -i ../initrd.fakeroot cpio -o -H newc | xz --check=crc32 --x86 --lzma2 --fast > /shared/html/images/ironic-python-agent.initramfs
+fi
\ No newline at end of file
diff --git a/metal3-chart/Chart.yaml b/metal3-chart/Chart.yaml
new file mode 100644
index 0000000..50f2777
--- /dev/null
+++ b/metal3-chart/Chart.yaml
@@ -0,0 +1,27 @@
+#!BuildTag: %%IMG_PREFIX%%metal3-chart:0.8.1
+#!BuildTag: %%IMG_PREFIX%%metal3-chart:0.8.1-%RELEASE%
+apiVersion: v2
+appVersion: 1.16.0
+dependencies:
+- alias: metal3-baremetal-operator
+ name: baremetal-operator
+ repository: file://./charts/baremetal-operator
+ version: 0.5.0
+- alias: metal3-ironic
+ name: ironic
+ repository: file://./charts/ironic
+ version: 0.7.0
+- alias: metal3-mariadb
+ name: mariadb
+ repository: file://./charts/mariadb
+ version: 0.5.4
+- alias: metal3-media
+ condition: global.enable_metal3_media_server
+ name: media
+ repository: file://./charts/media
+ version: 0.5.0
+description: A Helm chart that installs all of the dependencies needed for Metal3
+icon: https://github.com/cncf/artwork/raw/master/projects/metal3/icon/color/metal3-icon-color.svg
+name: metal3
+type: application
+version: 0.8.1
diff --git a/metal3-chart/README.md b/metal3-chart/README.md
new file mode 100644
index 0000000..c6ccadd
--- /dev/null
+++ b/metal3-chart/README.md
@@ -0,0 +1,100 @@
+# Prerequisites
+There are two dependencies that are not managed through the metal3 chart because are related to applications that have a cluster-wide scope: `cert-manager` and a LoadBalancer Service provider such as `metallb` or `kube-vip`.
+
+## Cert Manager
+In order to successfully deploy metal3 the cluster must have already installed the `cert-manager`.
+
+You can install it through `helm` with:
+```bash
+helm repo add jetstack https://charts.jetstack.io
+helm repo update
+helm install \
+ cert-manager jetstack/cert-manager \
+ --namespace cert-manager \
+ --create-namespace \
+ --set installCRDs=true
+```
+, or via `kubectl` with:
+```bash
+kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.11.1/cert-manager.yaml
+```
+
+## MetalLB (Optional)
+Ironic currently requires a staticIP address and MetalLB is one option to achieve that.
+
+1. If K3s is used as Kubernetes distribution, then it should be started with `--disable=servicelb` flag. Ref https://metallb.universe.tf/configuration/k3s/
+2. Find 1 free IP address in the network.
+3. Install `MetalLB` through `helm` with:
+
+```bash
+helm repo add suse-edge https://suse-edge.github.io/charts
+helm install \
+ metallb suse-edge/metallb \
+ --namespace metallb-system \
+ --create-namespace
+```
+
+4. Provide the IP pool configuration with:
+
+```bash
+export STATIC_IRONIC_IP=
+
+cat <<-EOF | kubectl apply -f -
+apiVersion: metallb.io/v1beta1
+kind: IPAddressPool
+metadata:
+ name: ironic-ip-pool
+ namespace: metallb-system
+spec:
+ addresses:
+ - ${STATIC_IRONIC_IP}/32
+ serviceAllocation:
+ priority: 100
+ serviceSelectors:
+ - matchExpressions:
+ - {key: app.kubernetes.io/name, operator: In, values: [metal3-ironic]}
+EOF
+
+cat <<-EOF | kubectl apply -f -
+apiVersion: metallb.io/v1beta1
+kind: L2Advertisement
+metadata:
+ name: ironic-ip-pool-l2-adv
+ namespace: metallb-system
+spec:
+ ipAddressPools:
+ - ironic-ip-pool
+EOF
+```
+
+5. Create new values.yaml file that will override some of the default properties:
+
+```bash
+TMP_DIR=$(mktemp -d)
+cat > ${TMP_DIR}/values.yaml << EOF
+global:
+ ironicIP: ""
+EOF
+```
+
+# Install
+
+```bash
+helm install \
+ metal3 suse-edge/metal3 \
+ --namespace metal3-system \
+ --create-namespace
+ -f ${TMP_DIR}/values.yaml
+```
+
+# How to upgrade the chart
+1. Run `helm dependency update .` in this chart to download/update the dependent charts.
+
+2. Identify the appropriate subchart values settings and create an appropriate override values YAML file.
+ * Ensure that the relevant ironic and baremetal-operator settings match.
+
+3. Install the chart using a command like the following:
+
+```console
+$ helm upgrade heavy-metal . --namespace metal-cubed --create-namespace --install --values ~/overrides.yaml
+```
diff --git a/metal3-chart/_service b/metal3-chart/_service
new file mode 100644
index 0000000..c3f6878
--- /dev/null
+++ b/metal3-chart/_service
@@ -0,0 +1,15 @@
+
+
+
+ values.yaml
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+
+ Chart.yaml
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+
+
diff --git a/metal3-chart/app-readme.md b/metal3-chart/app-readme.md
new file mode 100644
index 0000000..a7572b9
--- /dev/null
+++ b/metal3-chart/app-readme.md
@@ -0,0 +1 @@
+The metal3 chart is a parent chart that installs all of the other charts that a metal3 deployment needs, but doesn't actually deploy any services itself.
\ No newline at end of file
diff --git a/metal3-chart/charts/baremetal-operator/.helmignore b/metal3-chart/charts/baremetal-operator/.helmignore
new file mode 100644
index 0000000..1b9a9cc
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/metal3-chart/charts/baremetal-operator/Chart.yaml b/metal3-chart/charts/baremetal-operator/Chart.yaml
new file mode 100644
index 0000000..1900441
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/Chart.yaml
@@ -0,0 +1,6 @@
+apiVersion: v2
+appVersion: 0.6.1
+description: A Helm chart for baremetal-operator, used by Metal3
+name: baremetal-operator
+type: application
+version: 0.5.0
diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-baremetalhosts.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-baremetalhosts.yaml
new file mode 100644
index 0000000..6406700
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/crds/customresource-baremetalhosts.yaml
@@ -0,0 +1,1148 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ cert-manager.io/inject-ca-from: baremetal-operator-system/baremetal-operator-serving-cert
+ controller-gen.kubebuilder.io/version: v0.12.1
+ labels:
+ clusterctl.cluster.x-k8s.io: ""
+ name: baremetalhosts.metal3.io
+spec:
+ group: metal3.io
+ names:
+ kind: BareMetalHost
+ listKind: BareMetalHostList
+ plural: baremetalhosts
+ shortNames:
+ - bmh
+ - bmhost
+ singular: baremetalhost
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - description: Operational status
+ jsonPath: .status.operationalStatus
+ name: Status
+ priority: 1
+ type: string
+ - description: Provisioning status
+ jsonPath: .status.provisioning.state
+ name: State
+ type: string
+ - description: Consumer using this host
+ jsonPath: .spec.consumerRef.name
+ name: Consumer
+ type: string
+ - description: Address of management controller
+ jsonPath: .spec.bmc.address
+ name: BMC
+ priority: 1
+ type: string
+ - description: The type of hardware detected
+ jsonPath: .status.hardwareProfile
+ name: Hardware_Profile
+ priority: 1
+ type: string
+ - description: Whether the host is online or not
+ jsonPath: .spec.online
+ name: Online
+ type: string
+ - description: Type of the most recent error
+ jsonPath: .status.errorType
+ name: Error
+ type: string
+ - description: Time duration since creation of BaremetalHost
+ jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: BareMetalHost is the Schema for the baremetalhosts API
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: BareMetalHostSpec defines the desired state of BareMetalHost.
+ properties:
+ architecture:
+ description: CPU architecture of the host, e.g. "x86_64" or "aarch64".
+ If unset, eventually populated by inspection.
+ type: string
+ automatedCleaningMode:
+ default: metadata
+ description: When set to disabled, automated cleaning will be avoided
+ during provisioning and deprovisioning.
+ enum:
+ - metadata
+ - disabled
+ type: string
+ bmc:
+ description: How do we connect to the BMC?
+ properties:
+ address:
+ description: Address holds the URL for accessing the controller
+ on the network.
+ type: string
+ credentialsName:
+ description: The name of the secret containing the BMC credentials
+ (requires keys "username" and "password").
+ type: string
+ disableCertificateVerification:
+ description: DisableCertificateVerification disables verification
+ of server certificates when using HTTPS to connect to the BMC.
+ This is required when the server certificate is self-signed,
+ but is insecure because it allows a man-in-the-middle to intercept
+ the connection.
+ type: boolean
+ required:
+ - address
+ - credentialsName
+ type: object
+ bootMACAddress:
+ description: Which MAC address will PXE boot? This is optional for
+ some types, but required for libvirt VMs driven by vbmc.
+ pattern: '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'
+ type: string
+ bootMode:
+ description: Select the method of initializing the hardware during
+ boot. Defaults to UEFI.
+ enum:
+ - UEFI
+ - UEFISecureBoot
+ - legacy
+ type: string
+ consumerRef:
+ description: ConsumerRef can be used to store information about something
+ that is using a host. When it is not empty, the host is considered
+ "in use".
+ properties:
+ apiVersion:
+ description: API version of the referent.
+ type: string
+ fieldPath:
+ description: 'If referring to a piece of an object instead of
+ an entire object, this string should contain a valid JSON/Go
+ field access statement, such as desiredState.manifest.containers[2].
+ For example, if the object reference is to a container within
+ a pod, this would take on a value like: "spec.containers{name}"
+ (where "name" refers to the name of the container that triggered
+ the event) or if no container name is specified "spec.containers[2]"
+ (container with index 2 in this pod). This syntax is chosen
+ only to have some well-defined way of referencing a part of
+ an object. TODO: this design is not final and this field is
+ subject to change in the future.'
+ type: string
+ kind:
+ description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ name:
+ description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+ type: string
+ namespace:
+ description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+ type: string
+ resourceVersion:
+ description: 'Specific resourceVersion to which this reference
+ is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
+ type: string
+ uid:
+ description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
+ type: string
+ type: object
+ x-kubernetes-map-type: atomic
+ customDeploy:
+ description: A custom deploy procedure.
+ properties:
+ method:
+ description: Custom deploy method name. This name is specific
+ to the deploy ramdisk used. If you don't have a custom deploy
+ ramdisk, you shouldn't use CustomDeploy.
+ type: string
+ required:
+ - method
+ type: object
+ description:
+ description: Description is a human-entered text used to help identify
+ the host
+ type: string
+ externallyProvisioned:
+ description: ExternallyProvisioned means something else is managing
+ the image running on the host and the operator should only manage
+ the power status and hardware inventory inspection. If the Image
+ field is filled in, this field is ignored.
+ type: boolean
+ firmware:
+ description: BIOS configuration for bare metal server
+ properties:
+ simultaneousMultithreadingEnabled:
+ description: 'Allows a single physical processor core to appear
+ as several logical processors. This supports following options:
+ true, false.'
+ enum:
+ - true
+ - false
+ type: boolean
+ sriovEnabled:
+ description: 'SR-IOV support enables a hypervisor to create virtual
+ instances of a PCI-express device, potentially increasing performance.
+ This supports following options: true, false.'
+ enum:
+ - true
+ - false
+ type: boolean
+ virtualizationEnabled:
+ description: 'Supports the virtualization of platform hardware.
+ This supports following options: true, false.'
+ enum:
+ - true
+ - false
+ type: boolean
+ type: object
+ hardwareProfile:
+ description: What is the name of the hardware profile for this host?
+ Hardware profiles are deprecated and should not be used. Use the
+ separate fields Architecture and RootDeviceHints instead. Set to
+ "empty" to prepare for the future version of the API without hardware
+ profiles.
+ type: string
+ image:
+ description: Image holds the details of the image to be provisioned.
+ properties:
+ checksum:
+ description: Checksum is the checksum for the image.
+ type: string
+ checksumType:
+ description: ChecksumType is the checksum algorithm for the image,
+ e.g md5, sha256 or sha512. The special value "auto" can be used
+ to detect the algorithm from the checksum. If missing, MD5 is
+ used. If in doubt, use "auto".
+ enum:
+ - md5
+ - sha256
+ - sha512
+ - auto
+ type: string
+ format:
+ description: DiskFormat contains the format of the image (raw,
+ qcow2, ...). Needs to be set to raw for raw images streaming.
+ Note live-iso means an iso referenced by the url will be live-booted
+ and not deployed to disk, and in this case the checksum options
+ are not required and if specified will be ignored.
+ enum:
+ - raw
+ - qcow2
+ - vdi
+ - vmdk
+ - live-iso
+ type: string
+ url:
+ description: URL is a location of an image to deploy.
+ type: string
+ required:
+ - url
+ type: object
+ metaData:
+ description: MetaData holds the reference to the Secret containing
+ host metadata (e.g. meta_data.json) which is passed to the Config
+ Drive.
+ properties:
+ name:
+ description: name is unique within a namespace to reference a
+ secret resource.
+ type: string
+ namespace:
+ description: namespace defines the space within which the secret
+ name must be unique.
+ type: string
+ type: object
+ x-kubernetes-map-type: atomic
+ networkData:
+ description: NetworkData holds the reference to the Secret containing
+ network configuration (e.g content of network_data.json) which is
+ passed to the Config Drive.
+ properties:
+ name:
+ description: name is unique within a namespace to reference a
+ secret resource.
+ type: string
+ namespace:
+ description: namespace defines the space within which the secret
+ name must be unique.
+ type: string
+ type: object
+ x-kubernetes-map-type: atomic
+ online:
+ description: Should the server be online?
+ type: boolean
+ preprovisioningNetworkDataName:
+ description: PreprovisioningNetworkDataName is the name of the Secret
+ in the local namespace containing network configuration (e.g content
+ of network_data.json) which is passed to the preprovisioning image,
+ and to the Config Drive if not overridden by specifying NetworkData.
+ type: string
+ raid:
+ description: RAID configuration for bare metal server
+ properties:
+ hardwareRAIDVolumes:
+ description: The list of logical disks for hardware RAID, if rootDeviceHints
+ isn't used, first volume is root volume. You can set the value
+ of this field to `[]` to clear all the hardware RAID configurations.
+ items:
+ description: HardwareRAIDVolume defines the desired configuration
+ of volume in hardware RAID.
+ properties:
+ controller:
+ description: The name of the RAID controller to use
+ type: string
+ level:
+ description: 'RAID level for the logical disk. The following
+ levels are supported: 0;1;2;5;6;1+0;5+0;6+0.'
+ enum:
+ - "0"
+ - "1"
+ - "2"
+ - "5"
+ - "6"
+ - 1+0
+ - 5+0
+ - 6+0
+ type: string
+ name:
+ description: Name of the volume. Should be unique within
+ the Node. If not specified, volume name will be auto-generated.
+ maxLength: 64
+ type: string
+ numberOfPhysicalDisks:
+ description: Integer, number of physical disks to use for
+ the logical disk. Defaults to minimum number of disks
+ required for the particular RAID level.
+ minimum: 1
+ type: integer
+ physicalDisks:
+ description: Optional list of physical disk names to be
+ used for the Hardware RAID volumes. The disk names are
+ interpreted by the Hardware RAID controller, and the format
+ is hardware specific.
+ items:
+ type: string
+ type: array
+ rotational:
+ description: Select disks with only rotational or solid-state
+ storage
+ type: boolean
+ sizeGibibytes:
+ description: Size (Integer) of the logical disk to be created
+ in GiB. If unspecified or set be 0, the maximum capacity
+ of disk will be used for logical disk.
+ minimum: 0
+ type: integer
+ required:
+ - level
+ type: object
+ nullable: true
+ type: array
+ softwareRAIDVolumes:
+ description: The list of logical disks for software RAID, if rootDeviceHints
+ isn't used, first volume is root volume. If HardwareRAIDVolumes
+ is set this item will be invalid. The number of created Software
+ RAID devices must be 1 or 2. If there is only one Software RAID
+ device, it has to be a RAID-1. If there are two, the first one
+ has to be a RAID-1, while the RAID level for the second one
+ can be 0, 1, or 1+0. As the first RAID device will be the deployment
+ device, enforcing a RAID-1 reduces the risk of ending up with
+ a non-booting node in case of a disk failure. Software RAID
+ will always be deleted.
+ items:
+ description: SoftwareRAIDVolume defines the desired configuration
+ of volume in software RAID.
+ properties:
+ level:
+ description: 'RAID level for the logical disk. The following
+ levels are supported: 0;1;1+0.'
+ enum:
+ - "0"
+ - "1"
+ - 1+0
+ type: string
+ physicalDisks:
+ description: A list of device hints, the number of items
+ should be greater than or equal to 2.
+ items:
+ description: RootDeviceHints holds the hints for specifying
+ the storage location for the root filesystem for the
+ image.
+ properties:
+ deviceName:
+ description: A Linux device name like "/dev/vda",
+ or a by-path link to it like "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0".
+ The hint must match the actual value exactly.
+ type: string
+ hctl:
+ description: A SCSI bus address like 0:0:0:0. The
+ hint must match the actual value exactly.
+ type: string
+ minSizeGigabytes:
+ description: The minimum size of the device in Gigabytes.
+ minimum: 0
+ type: integer
+ model:
+ description: A vendor-specific device identifier.
+ The hint can be a substring of the actual value.
+ type: string
+ rotational:
+ description: True if the device should use spinning
+ media, false otherwise.
+ type: boolean
+ serialNumber:
+ description: Device serial number. The hint must match
+ the actual value exactly.
+ type: string
+ vendor:
+ description: The name of the vendor or manufacturer
+ of the device. The hint can be a substring of the
+ actual value.
+ type: string
+ wwn:
+ description: Unique storage identifier. The hint must
+ match the actual value exactly.
+ type: string
+ wwnVendorExtension:
+ description: Unique vendor storage identifier. The
+ hint must match the actual value exactly.
+ type: string
+ wwnWithExtension:
+ description: Unique storage identifier with the vendor
+ extension appended. The hint must match the actual
+ value exactly.
+ type: string
+ type: object
+ minItems: 2
+ type: array
+ sizeGibibytes:
+ description: Size (Integer) of the logical disk to be created
+ in GiB. If unspecified or set be 0, the maximum capacity
+ of disk will be used for logical disk.
+ minimum: 0
+ type: integer
+ required:
+ - level
+ type: object
+ maxItems: 2
+ nullable: true
+ type: array
+ type: object
+ rootDeviceHints:
+ description: Provide guidance about how to choose the device for the
+ image being provisioned.
+ properties:
+ deviceName:
+ description: A Linux device name like "/dev/vda", or a by-path
+ link to it like "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0".
+ The hint must match the actual value exactly.
+ type: string
+ hctl:
+ description: A SCSI bus address like 0:0:0:0. The hint must match
+ the actual value exactly.
+ type: string
+ minSizeGigabytes:
+ description: The minimum size of the device in Gigabytes.
+ minimum: 0
+ type: integer
+ model:
+ description: A vendor-specific device identifier. The hint can
+ be a substring of the actual value.
+ type: string
+ rotational:
+ description: True if the device should use spinning media, false
+ otherwise.
+ type: boolean
+ serialNumber:
+ description: Device serial number. The hint must match the actual
+ value exactly.
+ type: string
+ vendor:
+ description: The name of the vendor or manufacturer of the device.
+ The hint can be a substring of the actual value.
+ type: string
+ wwn:
+ description: Unique storage identifier. The hint must match the
+ actual value exactly.
+ type: string
+ wwnVendorExtension:
+ description: Unique vendor storage identifier. The hint must match
+ the actual value exactly.
+ type: string
+ wwnWithExtension:
+ description: Unique storage identifier with the vendor extension
+ appended. The hint must match the actual value exactly.
+ type: string
+ type: object
+ taints:
+ description: Taints is the full, authoritative list of taints to apply
+ to the corresponding Machine. This list will overwrite any modifications
+ made to the Machine on an ongoing basis.
+ items:
+ description: The node this Taint is attached to has the "effect"
+ on any pod that does not tolerate the Taint.
+ properties:
+ effect:
+ description: Required. The effect of the taint on pods that
+ do not tolerate the taint. Valid effects are NoSchedule, PreferNoSchedule
+ and NoExecute.
+ type: string
+ key:
+ description: Required. The taint key to be applied to a node.
+ type: string
+ timeAdded:
+ description: TimeAdded represents the time at which the taint
+ was added. It is only written for NoExecute taints.
+ format: date-time
+ type: string
+ value:
+ description: The taint value corresponding to the taint key.
+ type: string
+ required:
+ - effect
+ - key
+ type: object
+ type: array
+ userData:
+ description: UserData holds the reference to the Secret containing
+ the user data to be passed to the host before it boots.
+ properties:
+ name:
+ description: name is unique within a namespace to reference a
+ secret resource.
+ type: string
+ namespace:
+ description: namespace defines the space within which the secret
+ name must be unique.
+ type: string
+ type: object
+ x-kubernetes-map-type: atomic
+ required:
+ - online
+ type: object
+ status:
+ description: BareMetalHostStatus defines the observed state of BareMetalHost.
+ properties:
+ errorCount:
+ default: 0
+ description: ErrorCount records how many times the host has encoutered
+ an error since the last successful operation
+ type: integer
+ errorMessage:
+ description: the last error message reported by the provisioning subsystem
+ type: string
+ errorType:
+ description: ErrorType indicates the type of failure encountered when
+ the OperationalStatus is OperationalStatusError
+ enum:
+ - provisioned registration error
+ - registration error
+ - inspection error
+ - preparation error
+ - provisioning error
+ - power management error
+ type: string
+ goodCredentials:
+ description: the last credentials we were able to validate as working
+ properties:
+ credentials:
+ description: SecretReference represents a Secret Reference. It
+ has enough information to retrieve secret in any namespace
+ properties:
+ name:
+ description: name is unique within a namespace to reference
+ a secret resource.
+ type: string
+ namespace:
+ description: namespace defines the space within which the
+ secret name must be unique.
+ type: string
+ type: object
+ x-kubernetes-map-type: atomic
+ credentialsVersion:
+ type: string
+ type: object
+ hardware:
+ description: The hardware discovered to exist on the host.
+ properties:
+ cpu:
+ description: CPU describes one processor on the host.
+ properties:
+ arch:
+ type: string
+ clockMegahertz:
+ description: ClockSpeed is a clock speed in MHz
+ format: double
+ type: number
+ count:
+ type: integer
+ flags:
+ items:
+ type: string
+ type: array
+ model:
+ type: string
+ type: object
+ firmware:
+ description: Firmware describes the firmware on the host.
+ properties:
+ bios:
+ description: The BIOS for this firmware
+ properties:
+ date:
+ description: The release/build date for this BIOS
+ type: string
+ vendor:
+ description: The vendor name for this BIOS
+ type: string
+ version:
+ description: The version of the BIOS
+ type: string
+ type: object
+ type: object
+ hostname:
+ type: string
+ nics:
+ items:
+ description: NIC describes one network interface on the host.
+ properties:
+ ip:
+ description: The IP address of the interface. This will
+ be an IPv4 or IPv6 address if one is present. If both
+ IPv4 and IPv6 addresses are present in a dual-stack environment,
+ two nics will be output, one with each IP.
+ type: string
+ mac:
+ description: The device MAC address
+ pattern: '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'
+ type: string
+ model:
+ description: The vendor and product IDs of the NIC, e.g.
+ "0x8086 0x1572"
+ type: string
+ name:
+ description: The name of the network interface, e.g. "en0"
+ type: string
+ pxe:
+ description: Whether the NIC is PXE Bootable
+ type: boolean
+ speedGbps:
+ description: The speed of the device in Gigabits per second
+ type: integer
+ vlanId:
+ description: The untagged VLAN ID
+ format: int32
+ maximum: 4094
+ minimum: 0
+ type: integer
+ vlans:
+ description: The VLANs available
+ items:
+ description: VLAN represents the name and ID of a VLAN.
+ properties:
+ id:
+ description: VLANID is a 12-bit 802.1Q VLAN identifier
+ format: int32
+ maximum: 4094
+ minimum: 0
+ type: integer
+ name:
+ type: string
+ type: object
+ type: array
+ type: object
+ type: array
+ ramMebibytes:
+ type: integer
+ storage:
+ items:
+ description: Storage describes one storage device (disk, SSD,
+ etc.) on the host.
+ properties:
+ alternateNames:
+ description: A list of alternate Linux device names of the
+ disk, e.g. "/dev/sda". Note that this list is not exhaustive,
+ and names may not be stable across reboots.
+ items:
+ type: string
+ type: array
+ hctl:
+ description: The SCSI location of the device
+ type: string
+ model:
+ description: Hardware model
+ type: string
+ name:
+ description: A Linux device name of the disk, e.g. "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0".
+ This will be a name that is stable across reboots if one
+ is available.
+ type: string
+ rotational:
+ description: Whether this disk represents rotational storage.
+ This field is not recommended for usage, please prefer
+ using 'Type' field instead, this field will be deprecated
+ eventually.
+ type: boolean
+ serialNumber:
+ description: The serial number of the device
+ type: string
+ sizeBytes:
+ description: The size of the disk in Bytes
+ format: int64
+ type: integer
+ type:
+ description: 'Device type, one of: HDD, SSD, NVME.'
+ enum:
+ - HDD
+ - SSD
+ - NVME
+ type: string
+ vendor:
+ description: The name of the vendor of the device
+ type: string
+ wwn:
+ description: The WWN of the device
+ type: string
+ wwnVendorExtension:
+ description: The WWN Vendor extension of the device
+ type: string
+ wwnWithExtension:
+ description: The WWN with the extension
+ type: string
+ type: object
+ type: array
+ systemVendor:
+ description: HardwareSystemVendor stores details about the whole
+ hardware system.
+ properties:
+ manufacturer:
+ type: string
+ productName:
+ type: string
+ serialNumber:
+ type: string
+ type: object
+ type: object
+ hardwareProfile:
+ description: The name of the profile matching the hardware details.
+ type: string
+ lastUpdated:
+ description: LastUpdated identifies when this status was last observed.
+ format: date-time
+ type: string
+ operationHistory:
+ description: OperationHistory holds information about operations performed
+ on this host.
+ properties:
+ deprovision:
+ description: OperationMetric contains metadata about an operation
+ (inspection, provisioning, etc.) used for tracking metrics.
+ properties:
+ end:
+ format: date-time
+ nullable: true
+ type: string
+ start:
+ format: date-time
+ nullable: true
+ type: string
+ type: object
+ inspect:
+ description: OperationMetric contains metadata about an operation
+ (inspection, provisioning, etc.) used for tracking metrics.
+ properties:
+ end:
+ format: date-time
+ nullable: true
+ type: string
+ start:
+ format: date-time
+ nullable: true
+ type: string
+ type: object
+ provision:
+ description: OperationMetric contains metadata about an operation
+ (inspection, provisioning, etc.) used for tracking metrics.
+ properties:
+ end:
+ format: date-time
+ nullable: true
+ type: string
+ start:
+ format: date-time
+ nullable: true
+ type: string
+ type: object
+ register:
+ description: OperationMetric contains metadata about an operation
+ (inspection, provisioning, etc.) used for tracking metrics.
+ properties:
+ end:
+ format: date-time
+ nullable: true
+ type: string
+ start:
+ format: date-time
+ nullable: true
+ type: string
+ type: object
+ type: object
+ operationalStatus:
+ description: OperationalStatus holds the status of the host
+ enum:
+ - ""
+ - OK
+ - discovered
+ - error
+ - delayed
+ - detached
+ type: string
+ poweredOn:
+ description: indicator for whether or not the host is powered on
+ type: boolean
+ provisioning:
+ description: Information tracked by the provisioner.
+ properties:
+ ID:
+ description: The machine's UUID from the underlying provisioning
+ tool
+ type: string
+ bootMode:
+ description: BootMode indicates the boot mode used to provision
+ the node
+ enum:
+ - UEFI
+ - UEFISecureBoot
+ - legacy
+ type: string
+ customDeploy:
+ description: Custom deploy procedure applied to the host.
+ properties:
+ method:
+ description: Custom deploy method name. This name is specific
+ to the deploy ramdisk used. If you don't have a custom deploy
+ ramdisk, you shouldn't use CustomDeploy.
+ type: string
+ required:
+ - method
+ type: object
+ firmware:
+ description: The Bios set by the user
+ properties:
+ simultaneousMultithreadingEnabled:
+ description: 'Allows a single physical processor core to appear
+ as several logical processors. This supports following options:
+ true, false.'
+ enum:
+ - true
+ - false
+ type: boolean
+ sriovEnabled:
+ description: 'SR-IOV support enables a hypervisor to create
+ virtual instances of a PCI-express device, potentially increasing
+ performance. This supports following options: true, false.'
+ enum:
+ - true
+ - false
+ type: boolean
+ virtualizationEnabled:
+ description: 'Supports the virtualization of platform hardware.
+ This supports following options: true, false.'
+ enum:
+ - true
+ - false
+ type: boolean
+ type: object
+ image:
+ description: Image holds the details of the last image successfully
+ provisioned to the host.
+ properties:
+ checksum:
+ description: Checksum is the checksum for the image.
+ type: string
+ checksumType:
+ description: ChecksumType is the checksum algorithm for the
+ image, e.g md5, sha256 or sha512. The special value "auto"
+ can be used to detect the algorithm from the checksum. If
+ missing, MD5 is used. If in doubt, use "auto".
+ enum:
+ - md5
+ - sha256
+ - sha512
+ - auto
+ type: string
+ format:
+ description: DiskFormat contains the format of the image (raw,
+ qcow2, ...). Needs to be set to raw for raw images streaming.
+ Note live-iso means an iso referenced by the url will be
+ live-booted and not deployed to disk, and in this case the
+ checksum options are not required and if specified will
+ be ignored.
+ enum:
+ - raw
+ - qcow2
+ - vdi
+ - vmdk
+ - live-iso
+ type: string
+ url:
+ description: URL is a location of an image to deploy.
+ type: string
+ required:
+ - url
+ type: object
+ raid:
+ description: The Raid set by the user
+ properties:
+ hardwareRAIDVolumes:
+ description: The list of logical disks for hardware RAID,
+ if rootDeviceHints isn't used, first volume is root volume.
+ You can set the value of this field to `[]` to clear all
+ the hardware RAID configurations.
+ items:
+ description: HardwareRAIDVolume defines the desired configuration
+ of volume in hardware RAID.
+ properties:
+ controller:
+ description: The name of the RAID controller to use
+ type: string
+ level:
+ description: 'RAID level for the logical disk. The following
+ levels are supported: 0;1;2;5;6;1+0;5+0;6+0.'
+ enum:
+ - "0"
+ - "1"
+ - "2"
+ - "5"
+ - "6"
+ - 1+0
+ - 5+0
+ - 6+0
+ type: string
+ name:
+ description: Name of the volume. Should be unique within
+ the Node. If not specified, volume name will be auto-generated.
+ maxLength: 64
+ type: string
+ numberOfPhysicalDisks:
+ description: Integer, number of physical disks to use
+ for the logical disk. Defaults to minimum number of
+ disks required for the particular RAID level.
+ minimum: 1
+ type: integer
+ physicalDisks:
+ description: Optional list of physical disk names to
+ be used for the Hardware RAID volumes. The disk names
+ are interpreted by the Hardware RAID controller, and
+ the format is hardware specific.
+ items:
+ type: string
+ type: array
+ rotational:
+ description: Select disks with only rotational or solid-state
+ storage
+ type: boolean
+ sizeGibibytes:
+ description: Size (Integer) of the logical disk to be
+ created in GiB. If unspecified or set be 0, the maximum
+ capacity of disk will be used for logical disk.
+ minimum: 0
+ type: integer
+ required:
+ - level
+ type: object
+ nullable: true
+ type: array
+ softwareRAIDVolumes:
+ description: The list of logical disks for software RAID,
+ if rootDeviceHints isn't used, first volume is root volume.
+ If HardwareRAIDVolumes is set this item will be invalid.
+ The number of created Software RAID devices must be 1 or
+ 2. If there is only one Software RAID device, it has to
+ be a RAID-1. If there are two, the first one has to be a
+ RAID-1, while the RAID level for the second one can be 0,
+ 1, or 1+0. As the first RAID device will be the deployment
+ device, enforcing a RAID-1 reduces the risk of ending up
+ with a non-booting node in case of a disk failure. Software
+ RAID will always be deleted.
+ items:
+ description: SoftwareRAIDVolume defines the desired configuration
+ of volume in software RAID.
+ properties:
+ level:
+ description: 'RAID level for the logical disk. The following
+ levels are supported: 0;1;1+0.'
+ enum:
+ - "0"
+ - "1"
+ - 1+0
+ type: string
+ physicalDisks:
+ description: A list of device hints, the number of items
+ should be greater than or equal to 2.
+ items:
+ description: RootDeviceHints holds the hints for specifying
+ the storage location for the root filesystem for
+ the image.
+ properties:
+ deviceName:
+ description: A Linux device name like "/dev/vda",
+ or a by-path link to it like "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0".
+ The hint must match the actual value exactly.
+ type: string
+ hctl:
+ description: A SCSI bus address like 0:0:0:0.
+ The hint must match the actual value exactly.
+ type: string
+ minSizeGigabytes:
+ description: The minimum size of the device in
+ Gigabytes.
+ minimum: 0
+ type: integer
+ model:
+ description: A vendor-specific device identifier.
+ The hint can be a substring of the actual value.
+ type: string
+ rotational:
+ description: True if the device should use spinning
+ media, false otherwise.
+ type: boolean
+ serialNumber:
+ description: Device serial number. The hint must
+ match the actual value exactly.
+ type: string
+ vendor:
+ description: The name of the vendor or manufacturer
+ of the device. The hint can be a substring of
+ the actual value.
+ type: string
+ wwn:
+ description: Unique storage identifier. The hint
+ must match the actual value exactly.
+ type: string
+ wwnVendorExtension:
+ description: Unique vendor storage identifier.
+ The hint must match the actual value exactly.
+ type: string
+ wwnWithExtension:
+ description: Unique storage identifier with the
+ vendor extension appended. The hint must match
+ the actual value exactly.
+ type: string
+ type: object
+ minItems: 2
+ type: array
+ sizeGibibytes:
+ description: Size (Integer) of the logical disk to be
+ created in GiB. If unspecified or set be 0, the maximum
+ capacity of disk will be used for logical disk.
+ minimum: 0
+ type: integer
+ required:
+ - level
+ type: object
+ maxItems: 2
+ nullable: true
+ type: array
+ type: object
+ rootDeviceHints:
+ description: The RootDevicehints set by the user
+ properties:
+ deviceName:
+ description: A Linux device name like "/dev/vda", or a by-path
+ link to it like "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0".
+ The hint must match the actual value exactly.
+ type: string
+ hctl:
+ description: A SCSI bus address like 0:0:0:0. The hint must
+ match the actual value exactly.
+ type: string
+ minSizeGigabytes:
+ description: The minimum size of the device in Gigabytes.
+ minimum: 0
+ type: integer
+ model:
+ description: A vendor-specific device identifier. The hint
+ can be a substring of the actual value.
+ type: string
+ rotational:
+ description: True if the device should use spinning media,
+ false otherwise.
+ type: boolean
+ serialNumber:
+ description: Device serial number. The hint must match the
+ actual value exactly.
+ type: string
+ vendor:
+ description: The name of the vendor or manufacturer of the
+ device. The hint can be a substring of the actual value.
+ type: string
+ wwn:
+ description: Unique storage identifier. The hint must match
+ the actual value exactly.
+ type: string
+ wwnVendorExtension:
+ description: Unique vendor storage identifier. The hint must
+ match the actual value exactly.
+ type: string
+ wwnWithExtension:
+ description: Unique storage identifier with the vendor extension
+ appended. The hint must match the actual value exactly.
+ type: string
+ type: object
+ state:
+ description: An indiciator for what the provisioner is doing with
+ the host.
+ type: string
+ required:
+ - ID
+ - state
+ type: object
+ triedCredentials:
+ description: the last credentials we sent to the provisioning backend
+ properties:
+ credentials:
+ description: SecretReference represents a Secret Reference. It
+ has enough information to retrieve secret in any namespace
+ properties:
+ name:
+ description: name is unique within a namespace to reference
+ a secret resource.
+ type: string
+ namespace:
+ description: namespace defines the space within which the
+ secret name must be unique.
+ type: string
+ type: object
+ x-kubernetes-map-type: atomic
+ credentialsVersion:
+ type: string
+ type: object
+ required:
+ - errorCount
+ - errorMessage
+ - hardwareProfile
+ - operationalStatus
+ - poweredOn
+ - provisioning
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-bmceventsubscriptions.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-bmceventsubscriptions.yaml
new file mode 100644
index 0000000..c0dc2bf
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/crds/customresource-bmceventsubscriptions.yaml
@@ -0,0 +1,85 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.12.1
+ labels:
+ clusterctl.cluster.x-k8s.io: ""
+ name: bmceventsubscriptions.metal3.io
+spec:
+ group: metal3.io
+ names:
+ kind: BMCEventSubscription
+ listKind: BMCEventSubscriptionList
+ plural: bmceventsubscriptions
+ shortNames:
+ - bes
+ - bmcevent
+ singular: bmceventsubscription
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - description: The most recent error message
+ jsonPath: .status.error
+ name: Error
+ type: string
+ - description: Time duration since creation of BMCEventSubscription
+ jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: BMCEventSubscription is the Schema for the fast eventing API
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ properties:
+ context:
+ description: Arbitrary user-provided context for the event
+ type: string
+ destination:
+ description: A webhook URL to send events to
+ type: string
+ hostName:
+ description: A reference to a BareMetalHost
+ type: string
+ httpHeadersRef:
+ description: A secret containing HTTP headers which should be passed
+ along to the Destination when making a request
+ properties:
+ name:
+ description: name is unique within a namespace to reference a
+ secret resource.
+ type: string
+ namespace:
+ description: namespace defines the space within which the secret
+ name must be unique.
+ type: string
+ type: object
+ x-kubernetes-map-type: atomic
+ type: object
+ status:
+ properties:
+ error:
+ type: string
+ subscriptionID:
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-dataimages.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-dataimages.yaml
new file mode 100644
index 0000000..c1bb7b0
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/crds/customresource-dataimages.yaml
@@ -0,0 +1,75 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.12.1
+ name: dataimages.metal3.io
+spec:
+ group: metal3.io
+ names:
+ kind: DataImage
+ listKind: DataImageList
+ plural: dataimages
+ singular: dataimage
+ scope: Namespaced
+ versions:
+ - name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: DataImage is the Schema for the dataimages API.
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: DataImageSpec defines the desired state of DataImage.
+ properties:
+ url:
+ description: Url is the address of the dataImage that we want to attach
+ to a BareMetalHost
+ type: string
+ required:
+ - url
+ type: object
+ status:
+ description: DataImageStatus defines the observed state of DataImage.
+ properties:
+ attachedImage:
+ description: Currently attached DataImage
+ properties:
+ url:
+ type: string
+ required:
+ - url
+ type: object
+ error:
+ description: Error count and message when attaching/detaching
+ properties:
+ count:
+ type: integer
+ message:
+ type: string
+ required:
+ - count
+ - message
+ type: object
+ lastReconciled:
+ description: Time of last reconciliation
+ format: date-time
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-firmwareschemas.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-firmwareschemas.yaml
new file mode 100644
index 0000000..3b3c4fe
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/crds/customresource-firmwareschemas.yaml
@@ -0,0 +1,90 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.12.1
+ labels:
+ clusterctl.cluster.x-k8s.io: ""
+ name: firmwareschemas.metal3.io
+spec:
+ group: metal3.io
+ names:
+ kind: FirmwareSchema
+ listKind: FirmwareSchemaList
+ plural: firmwareschemas
+ singular: firmwareschema
+ scope: Namespaced
+ versions:
+ - name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: FirmwareSchema is the Schema for the firmwareschemas API.
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: FirmwareSchemaSpec defines the desired state of FirmwareSchema.
+ properties:
+ hardwareModel:
+ description: The hardware model associated with this schema
+ type: string
+ hardwareVendor:
+ description: The hardware vendor associated with this schema
+ type: string
+ schema:
+ additionalProperties:
+ description: Additional data describing the firmware setting.
+ properties:
+ allowable_values:
+ description: The allowable value for an Enumeration type setting.
+ items:
+ type: string
+ type: array
+ attribute_type:
+ description: The type of setting.
+ enum:
+ - Enumeration
+ - String
+ - Integer
+ - Boolean
+ - Password
+ type: string
+ lower_bound:
+ description: The lowest value for an Integer type setting.
+ type: integer
+ max_length:
+ description: Maximum length for a String type setting.
+ type: integer
+ min_length:
+ description: Minimum length for a String type setting.
+ type: integer
+ read_only:
+ description: Whether or not this setting is read only.
+ type: boolean
+ unique:
+ description: Whether or not this setting's value is unique to
+ this node, e.g. a serial number.
+ type: boolean
+ upper_bound:
+ description: The highest value for an Integer type setting.
+ type: integer
+ type: object
+ description: Map of firmware name to schema
+ type: object
+ required:
+ - schema
+ type: object
+ type: object
+ served: true
+ storage: true
diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-hardwaredata.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-hardwaredata.yaml
new file mode 100644
index 0000000..7a39068
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/crds/customresource-hardwaredata.yaml
@@ -0,0 +1,211 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.12.1
+ labels:
+ clusterctl.cluster.x-k8s.io: ""
+ name: hardwaredata.metal3.io
+spec:
+ group: metal3.io
+ names:
+ kind: HardwareData
+ listKind: HardwareDataList
+ plural: hardwaredata
+ shortNames:
+ - hd
+ singular: hardwaredata
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - description: Time duration since creation of HardwareData
+ jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: HardwareData is the Schema for the hardwaredata API.
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: HardwareDataSpec defines the desired state of HardwareData.
+ properties:
+ hardware:
+ description: The hardware discovered on the host during its inspection.
+ properties:
+ cpu:
+ description: CPU describes one processor on the host.
+ properties:
+ arch:
+ type: string
+ clockMegahertz:
+ description: ClockSpeed is a clock speed in MHz
+ format: double
+ type: number
+ count:
+ type: integer
+ flags:
+ items:
+ type: string
+ type: array
+ model:
+ type: string
+ type: object
+ firmware:
+ description: Firmware describes the firmware on the host.
+ properties:
+ bios:
+ description: The BIOS for this firmware
+ properties:
+ date:
+ description: The release/build date for this BIOS
+ type: string
+ vendor:
+ description: The vendor name for this BIOS
+ type: string
+ version:
+ description: The version of the BIOS
+ type: string
+ type: object
+ type: object
+ hostname:
+ type: string
+ nics:
+ items:
+ description: NIC describes one network interface on the host.
+ properties:
+ ip:
+ description: The IP address of the interface. This will
+ be an IPv4 or IPv6 address if one is present. If both
+ IPv4 and IPv6 addresses are present in a dual-stack environment,
+ two nics will be output, one with each IP.
+ type: string
+ mac:
+ description: The device MAC address
+ pattern: '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'
+ type: string
+ model:
+ description: The vendor and product IDs of the NIC, e.g.
+ "0x8086 0x1572"
+ type: string
+ name:
+ description: The name of the network interface, e.g. "en0"
+ type: string
+ pxe:
+ description: Whether the NIC is PXE Bootable
+ type: boolean
+ speedGbps:
+ description: The speed of the device in Gigabits per second
+ type: integer
+ vlanId:
+ description: The untagged VLAN ID
+ format: int32
+ maximum: 4094
+ minimum: 0
+ type: integer
+ vlans:
+ description: The VLANs available
+ items:
+ description: VLAN represents the name and ID of a VLAN.
+ properties:
+ id:
+ description: VLANID is a 12-bit 802.1Q VLAN identifier
+ format: int32
+ maximum: 4094
+ minimum: 0
+ type: integer
+ name:
+ type: string
+ type: object
+ type: array
+ type: object
+ type: array
+ ramMebibytes:
+ type: integer
+ storage:
+ items:
+ description: Storage describes one storage device (disk, SSD,
+ etc.) on the host.
+ properties:
+ alternateNames:
+ description: A list of alternate Linux device names of the
+ disk, e.g. "/dev/sda". Note that this list is not exhaustive,
+ and names may not be stable across reboots.
+ items:
+ type: string
+ type: array
+ hctl:
+ description: The SCSI location of the device
+ type: string
+ model:
+ description: Hardware model
+ type: string
+ name:
+ description: A Linux device name of the disk, e.g. "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0".
+ This will be a name that is stable across reboots if one
+ is available.
+ type: string
+ rotational:
+ description: Whether this disk represents rotational storage.
+ This field is not recommended for usage, please prefer
+ using 'Type' field instead, this field will be deprecated
+ eventually.
+ type: boolean
+ serialNumber:
+ description: The serial number of the device
+ type: string
+ sizeBytes:
+ description: The size of the disk in Bytes
+ format: int64
+ type: integer
+ type:
+ description: 'Device type, one of: HDD, SSD, NVME.'
+ enum:
+ - HDD
+ - SSD
+ - NVME
+ type: string
+ vendor:
+ description: The name of the vendor of the device
+ type: string
+ wwn:
+ description: The WWN of the device
+ type: string
+ wwnVendorExtension:
+ description: The WWN Vendor extension of the device
+ type: string
+ wwnWithExtension:
+ description: The WWN with the extension
+ type: string
+ type: object
+ type: array
+ systemVendor:
+ description: HardwareSystemVendor stores details about the whole
+ hardware system.
+ properties:
+ manufacturer:
+ type: string
+ productName:
+ type: string
+ serialNumber:
+ type: string
+ type: object
+ type: object
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources: {}
diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwarecomponents.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwarecomponents.yaml
new file mode 100644
index 0000000..2962d52
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwarecomponents.yaml
@@ -0,0 +1,178 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.12.1
+ name: hostfirmwarecomponents.metal3.io
+spec:
+ group: metal3.io
+ names:
+ kind: HostFirmwareComponents
+ listKind: HostFirmwareComponentsList
+ plural: hostfirmwarecomponents
+ singular: hostfirmwarecomponents
+ scope: Namespaced
+ versions:
+ - name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: HostFirmwareComponents is the Schema for the hostfirmwarecomponents
+ API.
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: HostFirmwareComponentsSpec defines the desired state of HostFirmwareComponents.
+ properties:
+ updates:
+ items:
+ description: FirmwareUpdate defines a firmware update specification.
+ properties:
+ component:
+ type: string
+ url:
+ type: string
+ required:
+ - component
+ - url
+ type: object
+ type: array
+ required:
+ - updates
+ type: object
+ status:
+ description: HostFirmwareComponentsStatus defines the observed state of
+ HostFirmwareComponents.
+ properties:
+ components:
+ description: Components is the list of all available firmware components
+ and their information.
+ items:
+ description: FirmwareComponentStatus defines the status of a firmware
+ component.
+ properties:
+ component:
+ type: string
+ currentVersion:
+ type: string
+ initialVersion:
+ type: string
+ lastVersionFlashed:
+ type: string
+ updatedAt:
+ format: date-time
+ type: string
+ required:
+ - component
+ - initialVersion
+ type: object
+ type: array
+ conditions:
+ description: Track whether updates stored in the spec are valid based
+ on the schema
+ items:
+ description: "Condition contains details for one aspect of the current
+ state of this API Resource. --- This struct is intended for direct
+ use as an array at the field path .status.conditions. For example,
+ \n type FooStatus struct{ // Represents the observations of a
+ foo's current state. // Known .status.conditions.type are: \"Available\",
+ \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
+ // +listType=map // +listMapKey=type Conditions []metav1.Condition
+ `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
+ protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition
+ transitioned from one status to another. This should be when
+ the underlying condition changed. If that is not known, then
+ using the time when the API field changed is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating
+ details about the transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation
+ that the condition was set based upon. For instance, if .metadata.generation
+ is currently 12, but the .status.conditions[x].observedGeneration
+ is 9, the condition is out of date with respect to the current
+ state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier indicating
+ the reason for the condition's last transition. Producers
+ of specific condition types may define expected values and
+ meanings for this field, and whether the values are considered
+ a guaranteed API. The value should be a CamelCase string.
+ This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase.
+ --- Many .condition.type values are consistent across resources
+ like Available, but because arbitrary conditions can be useful
+ (see .node.status.conditions), the ability to deconflict is
+ important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ type: array
+ x-kubernetes-list-map-keys:
+ - type
+ x-kubernetes-list-type: map
+ lastUpdated:
+ description: Time that the status was last updated
+ format: date-time
+ type: string
+ updates:
+ description: Updates is the list of all firmware components that should
+ be updated they are specified via name and url fields.
+ items:
+ description: FirmwareUpdate defines a firmware update specification.
+ properties:
+ component:
+ type: string
+ url:
+ type: string
+ required:
+ - component
+ - url
+ type: object
+ type: array
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwaresettings.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwaresettings.yaml
new file mode 100644
index 0000000..62679cf
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwaresettings.yaml
@@ -0,0 +1,164 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.12.1
+ labels:
+ clusterctl.cluster.x-k8s.io: ""
+ name: hostfirmwaresettings.metal3.io
+spec:
+ group: metal3.io
+ names:
+ kind: HostFirmwareSettings
+ listKind: HostFirmwareSettingsList
+ plural: hostfirmwaresettings
+ shortNames:
+ - hfs
+ singular: hostfirmwaresettings
+ scope: Namespaced
+ versions:
+ - name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: HostFirmwareSettings is the Schema for the hostfirmwaresettings
+ API.
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: HostFirmwareSettingsSpec defines the desired state of HostFirmwareSettings.
+ properties:
+ settings:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ description: Settings are the desired firmware settings stored as
+ name/value pairs.
+ type: object
+ required:
+ - settings
+ type: object
+ status:
+ description: HostFirmwareSettingsStatus defines the observed state of
+ HostFirmwareSettings.
+ properties:
+ conditions:
+ description: Track whether settings stored in the spec are valid based
+ on the schema
+ items:
+ description: "Condition contains details for one aspect of the current
+ state of this API Resource. --- This struct is intended for direct
+ use as an array at the field path .status.conditions. For example,
+ \n type FooStatus struct{ // Represents the observations of a
+ foo's current state. // Known .status.conditions.type are: \"Available\",
+ \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
+ // +listType=map // +listMapKey=type Conditions []metav1.Condition
+ `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
+ protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition
+ transitioned from one status to another. This should be when
+ the underlying condition changed. If that is not known, then
+ using the time when the API field changed is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating
+ details about the transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation
+ that the condition was set based upon. For instance, if .metadata.generation
+ is currently 12, but the .status.conditions[x].observedGeneration
+ is 9, the condition is out of date with respect to the current
+ state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier indicating
+ the reason for the condition's last transition. Producers
+ of specific condition types may define expected values and
+ meanings for this field, and whether the values are considered
+ a guaranteed API. The value should be a CamelCase string.
+ This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase.
+ --- Many .condition.type values are consistent across resources
+ like Available, but because arbitrary conditions can be useful
+ (see .node.status.conditions), the ability to deconflict is
+ important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ type: array
+ x-kubernetes-list-map-keys:
+ - type
+ x-kubernetes-list-type: map
+ lastUpdated:
+ description: Time that the status was last updated
+ format: date-time
+ type: string
+ schema:
+ description: FirmwareSchema is a reference to the Schema used to describe
+ each FirmwareSetting. By default, this will be a Schema in the same
+ Namespace as the settings but it can be overwritten in the Spec
+ properties:
+ name:
+ description: '`name` is the reference to the schema.'
+ type: string
+ namespace:
+ description: '`namespace` is the namespace of the where the schema
+ is stored.'
+ type: string
+ required:
+ - name
+ - namespace
+ type: object
+ settings:
+ additionalProperties:
+ type: string
+ description: Settings are the firmware settings stored as name/value
+ pairs
+ type: object
+ required:
+ - settings
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-preprovisioningimages.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-preprovisioningimages.yaml
new file mode 100644
index 0000000..f743a89
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/crds/customresource-preprovisioningimages.yaml
@@ -0,0 +1,183 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.12.1
+ labels:
+ clusterctl.cluster.x-k8s.io: ""
+ name: preprovisioningimages.metal3.io
+spec:
+ group: metal3.io
+ names:
+ kind: PreprovisioningImage
+ listKind: PreprovisioningImageList
+ plural: preprovisioningimages
+ shortNames:
+ - ppimg
+ singular: preprovisioningimage
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - description: Whether the image is ready
+ jsonPath: .status.conditions[?(@.type=='Ready')].status
+ name: Ready
+ type: string
+ - description: The reason for the image readiness status
+ jsonPath: .status.conditions[?(@.type=='Ready')].reason
+ name: Reason
+ type: string
+ name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: PreprovisioningImage is the Schema for the preprovisioningimages
+ API.
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: PreprovisioningImageSpec defines the desired state of PreprovisioningImage.
+ properties:
+ acceptFormats:
+ description: acceptFormats is a list of acceptable image formats.
+ items:
+ description: ImageFormat enumerates the allowed image formats
+ enum:
+ - iso
+ - initrd
+ type: string
+ type: array
+ architecture:
+ description: architecture is the processor architecture for which
+ to build the image.
+ type: string
+ networkDataName:
+ description: networkDataName is the name of a Secret in the local
+ namespace that contains network data to build in to the image.
+ type: string
+ type: object
+ status:
+ description: PreprovisioningImageStatus defines the observed state of
+ PreprovisioningImage.
+ properties:
+ architecture:
+ description: architecture is the processor architecture for which
+ the image is built
+ type: string
+ conditions:
+ description: conditions describe the state of the built image
+ items:
+ description: "Condition contains details for one aspect of the current
+ state of this API Resource. --- This struct is intended for direct
+ use as an array at the field path .status.conditions. For example,
+ \n type FooStatus struct{ // Represents the observations of a
+ foo's current state. // Known .status.conditions.type are: \"Available\",
+ \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
+ // +listType=map // +listMapKey=type Conditions []metav1.Condition
+ `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
+ protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition
+ transitioned from one status to another. This should be when
+ the underlying condition changed. If that is not known, then
+ using the time when the API field changed is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating
+ details about the transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation
+ that the condition was set based upon. For instance, if .metadata.generation
+ is currently 12, but the .status.conditions[x].observedGeneration
+ is 9, the condition is out of date with respect to the current
+ state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier indicating
+ the reason for the condition's last transition. Producers
+ of specific condition types may define expected values and
+ meanings for this field, and whether the values are considered
+ a guaranteed API. The value should be a CamelCase string.
+ This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase.
+ --- Many .condition.type values are consistent across resources
+ like Available, but because arbitrary conditions can be useful
+ (see .node.status.conditions), the ability to deconflict is
+ important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ type: array
+ x-kubernetes-list-map-keys:
+ - type
+ x-kubernetes-list-type: map
+ extraKernelParams:
+ description: extraKernelParams is a string with extra parameters to
+ pass to the kernel when booting the image over network. Only makes
+ sense for initrd images.
+ type: string
+ format:
+ description: 'format is the type of image that is available at the
+ download url: either iso or initrd.'
+ enum:
+ - iso
+ - initrd
+ type: string
+ imageUrl:
+ description: imageUrl is the URL from which the built image can be
+ downloaded.
+ type: string
+ kernelUrl:
+ description: kernelUrl is the URL from which the kernel of the image
+ can be downloaded. Only makes sense for initrd images.
+ type: string
+ networkData:
+ description: networkData is a reference to the version of the Secret
+ containing the network data used to build the image.
+ properties:
+ name:
+ type: string
+ version:
+ type: string
+ type: object
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/metal3-chart/charts/baremetal-operator/templates/NOTES.txt b/metal3-chart/charts/baremetal-operator/templates/NOTES.txt
new file mode 100644
index 0000000..a46dc2b
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/NOTES.txt
@@ -0,0 +1,16 @@
+1. Get the application URL by running these commands:
+{{- if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "baremetal-operator.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "baremetal-operator.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "baremetal-operator.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+ echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "baremetal-operator.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
diff --git a/metal3-chart/charts/baremetal-operator/templates/_helpers.tpl b/metal3-chart/charts/baremetal-operator/templates/_helpers.tpl
new file mode 100644
index 0000000..08dc581
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/_helpers.tpl
@@ -0,0 +1,63 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "baremetal-operator.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "baremetal-operator.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "baremetal-operator.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "baremetal-operator.labels" -}}
+helm.sh/chart: {{ include "baremetal-operator.chart" . }}
+{{ include "baremetal-operator.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "baremetal-operator.selectorLabels" -}}
+app.kubernetes.io/component: baremetal-operator
+app.kubernetes.io/name: {{ include "baremetal-operator.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "baremetal-operator.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "baremetal-operator.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/metal3-chart/charts/baremetal-operator/templates/certificate.yaml b/metal3-chart/charts/baremetal-operator/templates/certificate.yaml
new file mode 100644
index 0000000..ad0fd88
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/certificate.yaml
@@ -0,0 +1,14 @@
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: {{ include "baremetal-operator.fullname" . }}-serving-cert
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+spec:
+ dnsNames:
+ - baremetal-operator-webhook-service.{{ .Release.Namespace }}.svc
+ - baremetal-operator-webhook-service.{{ .Release.Namespace }}.svc.cluster.local
+ issuerRef:
+ kind: Issuer
+ name: {{ include "baremetal-operator.fullname" . }}-selfsigned-issuer
+ secretName: bmo-webhook-server-cert
diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrole-manager.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrole-manager.yaml
new file mode 100644
index 0000000..e55cb06
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/clusterrole-manager.yaml
@@ -0,0 +1,186 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ creationTimestamp: null
+ name: {{ include "baremetal-operator.fullname" . }}-manager-role
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - events
+ verbs:
+ - create
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - ""
+ resources:
+ - secrets
+ verbs:
+ - get
+ - list
+ - update
+ - watch
+- apiGroups:
+ - metal3.io
+ resources:
+ - baremetalhosts
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - metal3.io
+ resources:
+ - baremetalhosts/status
+ verbs:
+ - get
+ - patch
+ - update
+- apiGroups:
+ - metal3.io
+ resources:
+ - bmceventsubscriptions
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - metal3.io
+ resources:
+ - bmceventsubscriptions/status
+ verbs:
+ - get
+ - patch
+ - update
+- apiGroups:
+ - metal3.io
+ resources:
+ - firmwareschemas
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - metal3.io
+ resources:
+ - firmwareschemas/status
+ verbs:
+ - get
+ - patch
+ - update
+- apiGroups:
+ - metal3.io
+ resources:
+ - hardware/finalizers
+ verbs:
+ - update
+- apiGroups:
+ - metal3.io
+ resources:
+ - hardwaredata
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - metal3.io
+ resources:
+ - hostfirmwaresettings
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - metal3.io
+ resources:
+ - hostfirmwaresettings/status
+ verbs:
+ - get
+ - patch
+ - update
+- apiGroups:
+ - metal3.io
+ resources:
+ - preprovisioningimages
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - metal3.io
+ resources:
+ - preprovisioningimages/status
+ verbs:
+ - get
+ - patch
+ - update
+- apiGroups:
+ - metal3.io
+ resources:
+ - dataimages
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - metal3.io
+ resources:
+ - dataimages/status
+ verbs:
+ - get
+ - patch
+ - update
+- apiGroups:
+ - metal3.io
+ resources:
+ - hostfirmwarecomponents
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - metal3.io
+ resources:
+ - hostfirmwarecomponents/status
+ verbs:
+ - get
+ - patch
+ - update
diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrole-metrics-reader.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrole-metrics-reader.yaml
new file mode 100644
index 0000000..cad7903
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/clusterrole-metrics-reader.yaml
@@ -0,0 +1,11 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ include "baremetal-operator.fullname" . }}-metrics-reader
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+rules:
+- nonResourceURLs:
+ - /metrics
+ verbs:
+ - get
diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrole-proxy.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrole-proxy.yaml
new file mode 100644
index 0000000..db6d71d
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/clusterrole-proxy.yaml
@@ -0,0 +1,19 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ include "baremetal-operator.fullname" . }}-proxy-role
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+rules:
+- apiGroups:
+ - authentication.k8s.io
+ resources:
+ - tokenreviews
+ verbs:
+ - create
+- apiGroups:
+ - authorization.k8s.io
+ resources:
+ - subjectaccessreviews
+ verbs:
+ - create
diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-manager.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-manager.yaml
new file mode 100644
index 0000000..bfce20a
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-manager.yaml
@@ -0,0 +1,14 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ include "baremetal-operator.fullname" . }}-manager-rolebinding
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ include "baremetal-operator.fullname" . }}-manager-role
+subjects:
+- kind: ServiceAccount
+ name: {{ include "baremetal-operator.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace }}
diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-proxy.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-proxy.yaml
new file mode 100644
index 0000000..5207b62
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-proxy.yaml
@@ -0,0 +1,14 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ include "baremetal-operator.fullname" . }}-proxy-rolebinding
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ include "baremetal-operator.fullname" . }}-proxy-role
+subjects:
+- kind: ServiceAccount
+ name: {{ include "baremetal-operator.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace }}
diff --git a/metal3-chart/charts/baremetal-operator/templates/configmap-ironic.yaml b/metal3-chart/charts/baremetal-operator/templates/configmap-ironic.yaml
new file mode 100644
index 0000000..20d3b8c
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/configmap-ironic.yaml
@@ -0,0 +1,30 @@
+ {{- $enableTLS := .Values.global.enable_tls }}
+ {{- $enableVMediaTLS := .Values.global.enable_vmedia_tls }}
+ {{- $protocol := ternary "https" "http" $enableTLS }}
+ {{- $ironicIP := .Values.global.ironicIP | default "" }}
+ {{- $ironicApiHost := print $ironicIP ":6385" }}
+ {{- $ironicInspectorHost := print $ironicIP ":5050" }}
+ {{- $ironicBootHost := print $ironicIP ":6180" }}
+ {{- $ironicCacheHost := print $ironicIP ":6180" }}
+
+apiVersion: v1
+data:
+ IRONIC_ENDPOINT: "{{ $protocol }}://{{ $ironicApiHost }}/v1/"
+ IRONIC_INSPECTOR_ENDPOINT: "{{ $protocol }}://{{ $ironicInspectorHost }}/v1/"
+ RESTART_CONTAINER_CERTIFICATE_UPDATED: "false"
+ # Switch VMedia to HTTP if enable_vmedia_tls is false
+ {{- if and $enableTLS $enableVMediaTLS }}
+ {{- $ironicBootHost = print $ironicIP ":" .Values.global.vmediaTLSPort }}
+ {{- $ironicCacheHost = print $ironicIP ":" .Values.global.vmediaTLSPort }}
+ {{- $protocol = "https" }}
+ {{- else }}
+ {{- $protocol = "http" }}
+ {{- end }}
+ CACHEURL: "{{ $protocol }}://{{ $ironicCacheHost }}/images"
+ DEPLOY_KERNEL_URL: "{{ $protocol }}://{{ $ironicBootHost }}/images/ironic-python-agent.kernel"
+ DEPLOY_RAMDISK_URL: "{{ $protocol }}://{{ $ironicBootHost }}/images/ironic-python-agent.initramfs"
+kind: ConfigMap
+metadata:
+ name: baremetal-operator-ironic
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
diff --git a/metal3-chart/charts/baremetal-operator/templates/configmap.yaml b/metal3-chart/charts/baremetal-operator/templates/configmap.yaml
new file mode 100644
index 0000000..b22579a
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/configmap.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+data:
+ controller_manager_config.yaml: |
+ apiVersion: controller-runtime.sigs.k8s.io/v1alpha1
+ kind: ControllerManagerConfig
+ health:
+ healthProbeBindAddress: :9440
+ metrics:
+ bindAddress: 127.0.0.1:8085
+ webhook:
+ port: 9443
+ leaderElection:
+ leaderElect: true
+ resourceName: a9498140.metal3.io
+kind: ConfigMap
+metadata:
+ name: baremetal-operator-manager-config
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
diff --git a/metal3-chart/charts/baremetal-operator/templates/deployment.yaml b/metal3-chart/charts/baremetal-operator/templates/deployment.yaml
new file mode 100644
index 0000000..877c714
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/deployment.yaml
@@ -0,0 +1,131 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+ control-plane: controller-manager
+ webhook: metal3-io-v1alpha1-baremetalhost
+ name: {{ include "baremetal-operator.fullname" . }}-controller-manager
+spec:
+ minReadySeconds: 10
+ {{- if not .Values.autoscaling.enabled }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "baremetal-operator.selectorLabels" . | nindent 6 }}
+ control-plane: controller-manager
+ template:
+ metadata:
+ labels:
+ {{- include "baremetal-operator.selectorLabels" . | nindent 8 }}
+ control-plane: controller-manager
+ webhook: metal3-io-v1alpha1-baremetalhost
+ spec:
+ containers:
+ - args:
+ - --metrics-addr=127.0.0.1:8085
+ - --enable-leader-election
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: POD_NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ envFrom:
+ - configMapRef:
+ name: {{ include "baremetal-operator.fullname" . }}-ironic
+ image: "{{ .Values.images.baremetalOperator.repository }}:{{ .Values.images.baremetalOperator.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.images.baremetalOperator.pullPolicy }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 10 }}
+ livenessProbe:
+ failureThreshold: 10
+ httpGet:
+ path: /healthz
+ port: 9440
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 2
+ name: manager
+ ports:
+ - containerPort: 9443
+ name: webhook-server
+ protocol: TCP
+ readinessProbe:
+ failureThreshold: 10
+ httpGet:
+ path: /readyz
+ port: 9440
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 2
+ volumeMounts:
+ - mountPath: /tmp/k8s-webhook-server/serving-certs
+ name: cert
+ readOnly: true
+ {{- if .Values.global.enable_basicAuth }}
+ - name: ironic-basic-auth
+ mountPath: "/opt/metal3/auth/ironic/username"
+ subPath: username
+ readOnly: true
+ - name: ironic-basic-auth
+ mountPath: "/opt/metal3/auth/ironic/password"
+ subPath: password
+ readOnly: true
+ - name: ironic-inspector-basic-auth
+ mountPath: "/opt/metal3/auth/ironic-inspector/username"
+ subPath: username
+ readOnly: true
+ - name: ironic-inspector-basic-auth
+ mountPath: "/opt/metal3/auth/ironic-inspector/password"
+ subPath: password
+ readOnly: true
+ {{- end }}
+ {{- if .Values.global.enable_tls }}
+ - name: cacert
+ mountPath: "/opt/metal3/certs/ca"
+ readOnly: true
+ {{- end }}
+ - args:
+ - --secure-listen-address=0.0.0.0:8443
+ - --upstream=http://127.0.0.1:8085/
+ - --logtostderr=true
+ - --v=10
+ image: "{{ .Values.images.rbacProxy.repository }}:{{ .Values.images.rbacProxy.tag }}"
+ imagePullPolicy: {{ .Values.images.rbacProxy.pullPolicy }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 10 }}
+ name: kube-rbac-proxy
+ ports:
+ - containerPort: 8443
+ name: https
+ serviceAccountName: {{ include "baremetal-operator.serviceAccountName" . }}
+ terminationGracePeriodSeconds: 10
+ volumes:
+ - name: cert
+ secret:
+ defaultMode: 420
+ secretName: bmo-webhook-server-cert
+ {{- if .Values.global.enable_basicAuth }}
+ - name: ironic-basic-auth
+ secret:
+ secretName: ironic-basic-auth
+ - name: ironic-inspector-basic-auth
+ secret:
+ secretName: ironic-inspector-basic-auth
+ {{- end }}
+ {{- if .Values.global.enable_tls }}
+ - name: cacert
+ secret:
+ secretName: ironic-cacert
+ {{- end }}
+ {{- with .Values.global.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
diff --git a/metal3-chart/charts/baremetal-operator/templates/issuer.yaml b/metal3-chart/charts/baremetal-operator/templates/issuer.yaml
new file mode 100644
index 0000000..c9d1522
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/issuer.yaml
@@ -0,0 +1,8 @@
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+ name: {{ include "baremetal-operator.fullname" . }}-selfsigned-issuer
+spec:
+ selfSigned: {}
diff --git a/metal3-chart/charts/baremetal-operator/templates/role.yaml b/metal3-chart/charts/baremetal-operator/templates/role.yaml
new file mode 100644
index 0000000..d56496f
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/role.yaml
@@ -0,0 +1,45 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ include "baremetal-operator.fullname" . }}-leader-election-role
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - configmaps
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - patch
+ - delete
+- apiGroups:
+ - ""
+ resources:
+ - configmaps/status
+ verbs:
+ - get
+ - update
+ - patch
+- apiGroups:
+ - ""
+ resources:
+ - events
+ verbs:
+ - create
+- apiGroups:
+ - coordination.k8s.io
+ resources:
+ - leases
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - patch
+ - delete
diff --git a/metal3-chart/charts/baremetal-operator/templates/rolebinding.yaml b/metal3-chart/charts/baremetal-operator/templates/rolebinding.yaml
new file mode 100644
index 0000000..5704c6a
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/rolebinding.yaml
@@ -0,0 +1,13 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ include "baremetal-operator.fullname" . }}-leader-election-rolebinding
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: {{ include "baremetal-operator.fullname" . }}-leader-election-role
+subjects:
+- kind: ServiceAccount
+ name: {{ include "baremetal-operator.serviceAccountName" . }}
diff --git a/metal3-chart/charts/baremetal-operator/templates/service-controller-manager.yaml b/metal3-chart/charts/baremetal-operator/templates/service-controller-manager.yaml
new file mode 100644
index 0000000..64f39a6
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/service-controller-manager.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+ control-plane: controller-manager
+ name: {{ include "baremetal-operator.fullname" . }}-controller-manager-metrics-service
+spec:
+ ports:
+ - name: https
+ port: 8443
+ targetPort: https
+ selector:
+ control-plane: controller-manager
diff --git a/metal3-chart/charts/baremetal-operator/templates/service-webhook.yaml b/metal3-chart/charts/baremetal-operator/templates/service-webhook.yaml
new file mode 100644
index 0000000..67fea7f
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/service-webhook.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+ name: {{ include "baremetal-operator.fullname" . }}-webhook-service
+spec:
+ ports:
+ - port: 443
+ targetPort: 9443
+ selector:
+ control-plane: controller-manager
+ webhook: metal3-io-v1alpha1-baremetalhost
diff --git a/metal3-chart/charts/baremetal-operator/templates/serviceaccount.yaml b/metal3-chart/charts/baremetal-operator/templates/serviceaccount.yaml
new file mode 100644
index 0000000..14376e8
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/serviceaccount.yaml
@@ -0,0 +1,12 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "baremetal-operator.serviceAccountName" . }}
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/metal3-chart/charts/baremetal-operator/templates/tests/test-connection.yaml b/metal3-chart/charts/baremetal-operator/templates/tests/test-connection.yaml
new file mode 100644
index 0000000..28715fe
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/tests/test-connection.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: "{{ include "baremetal-operator.fullname" . }}-test-connection"
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+ annotations:
+ "helm.sh/hook": test
+spec:
+ containers:
+ - name: wget
+ image: busybox
+ command: ['wget']
+ args: ['{{ include "baremetal-operator.fullname" . }}:{{ .Values.service.port }}']
+ restartPolicy: Never
diff --git a/metal3-chart/charts/baremetal-operator/templates/validatingwebhookconfiguration.yaml b/metal3-chart/charts/baremetal-operator/templates/validatingwebhookconfiguration.yaml
new file mode 100644
index 0000000..1cefe78
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/templates/validatingwebhookconfiguration.yaml
@@ -0,0 +1,51 @@
+apiVersion: admissionregistration.k8s.io/v1
+kind: ValidatingWebhookConfiguration
+metadata:
+ labels:
+ {{- include "baremetal-operator.labels" . | nindent 4 }}
+ annotations:
+ cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "baremetal-operator.fullname" . }}-serving-cert
+ name: {{ include "baremetal-operator.fullname" . }}-validating-webhook-configuration
+webhooks:
+- admissionReviewVersions:
+ - v1
+ - v1beta
+ clientConfig:
+ service:
+ name: {{ include "baremetal-operator.fullname" . }}-webhook-service
+ namespace: {{ .Release.Namespace }}
+ path: /validate-metal3-io-v1alpha1-baremetalhost
+ failurePolicy: Fail
+ name: baremetalhost.metal3.io
+ rules:
+ - apiGroups:
+ - metal3.io
+ apiVersions:
+ - v1alpha1
+ operations:
+ - CREATE
+ - UPDATE
+ resources:
+ - baremetalhosts
+ sideEffects: None
+- admissionReviewVersions:
+ - v1
+ - v1beta
+ clientConfig:
+ service:
+ name: {{ include "baremetal-operator.fullname" . }}-webhook-service
+ namespace: {{ .Release.Namespace }}
+ path: /validate-metal3-io-v1alpha1-bmceventsubscription
+ failurePolicy: Fail
+ name: bmceventsubscription.metal3.io
+ rules:
+ - apiGroups:
+ - metal3.io
+ apiVersions:
+ - v1alpha1
+ operations:
+ - CREATE
+ - UPDATE
+ resources:
+ - bmceventsubscriptions
+ sideEffects: None
diff --git a/metal3-chart/charts/baremetal-operator/values.yaml b/metal3-chart/charts/baremetal-operator/values.yaml
new file mode 100644
index 0000000..cf7fad4
--- /dev/null
+++ b/metal3-chart/charts/baremetal-operator/values.yaml
@@ -0,0 +1,90 @@
+# Default values for baremetal-operator.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+global:
+ # specify comma serparate beginning and end of the range of IP
+ # addresses the DHCP server will manage.
+ dhcpRange: 192.168.20.20,192.168.20.80
+
+ # Network interface on which provisioning network can be accessed
+ provisioningInterface: ens4
+
+ # IP Address assigned to network interface on provisioning network
+ provisioningIP: 192.168.20.5
+
+ # If running in a multi-node kubernetes cluster, "pin" the baremtal container
+ # to the same host where the ironic and media containers
+ # arerunning. Uncomment the nodeSelector and update the hostname accordingly.
+ #nodeSelector:
+ #kubernetes.io/hostname: "my-hostname"
+
+ # Comment this out when pinning the baremetal-operator container to a specfic host.
+ nodeSelector: {}
+
+replicaCount: 1
+
+images:
+ baremetalOperator:
+ repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/baremetal-operator
+ pullPolicy: IfNotPresent
+ tag: "0.6.1"
+ rbacProxy:
+ repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/kube-rbac-proxy
+ pullPolicy: IfNotPresent
+ tag: "v0.14.2"
+
+imagePullSecrets: []
+nameOverride: "manger"
+fullnameOverride: "baremetal-operator"
+
+serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: "baremetal-operator-controller-manager"
+
+podAnnotations: {}
+
+securityContext:
+ runAsUser: 11000
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
+ seccompProfile:
+ type: RuntimeDefault
+ runAsNonRoot: true
+
+service:
+ type: ClusterIP
+ port: 80
+
+resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+autoscaling:
+ enabled: false
+ minReplicas: 1
+ maxReplicas: 100
+ targetCPUUtilizationPercentage: 80
+ # targetMemoryUtilizationPercentage: 80
+
+tolerations: []
+
+affinity: {}
+
+baremetaloperator:
+ httpPort: "6180"
diff --git a/metal3-chart/charts/ironic/.helmignore b/metal3-chart/charts/ironic/.helmignore
new file mode 100644
index 0000000..1b9a9cc
--- /dev/null
+++ b/metal3-chart/charts/ironic/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/metal3-chart/charts/ironic/Chart.yaml b/metal3-chart/charts/ironic/Chart.yaml
new file mode 100644
index 0000000..a9d39ec
--- /dev/null
+++ b/metal3-chart/charts/ironic/Chart.yaml
@@ -0,0 +1,6 @@
+apiVersion: v2
+appVersion: 24.1.2
+description: A Helm chart for Ironic, used by Metal3
+name: ironic
+type: application
+version: 0.7.0
diff --git a/metal3-chart/charts/ironic/README.md b/metal3-chart/charts/ironic/README.md
new file mode 100644
index 0000000..d88fccc
--- /dev/null
+++ b/metal3-chart/charts/ironic/README.md
@@ -0,0 +1,24 @@
+## How to Enable Provisioning Network
+
+By default PXE boot functionality is disabled, so deployments via e.g redfish-virtualmedia may
+be performed without any dedicated provisioning network.
+
+For PXE boot a dedicated network is required, in this case we run a dnsmasq instance to provide
+DHCP and require a dedicated NIC for connectivity to the provisioning network on each host.
+
+To enable this mode you must provide the following additional configuration (note the values are
+examples and will depend on your environment):
+
+```
+global:
+ enable_dnsmasq: true
+ enable_pxe_boot: true
+ dnsmasqDefaultRouter: 192.168.21.254
+ dnsmasqDNSServer: 192.168.20.5
+ dhcpRange: 192.168.20.20,192.168.20.80
+ provisioningInterface: ens4
+ provisioningIP: 192.168.20.5
+```
+
+Note that these values *must not* conflict with your controlplane or other networks otherwise unexpected
+behavior is likely - a dedicated physical network is required in this configuration.
diff --git a/metal3-chart/charts/ironic/templates/NOTES.txt b/metal3-chart/charts/ironic/templates/NOTES.txt
new file mode 100644
index 0000000..acc38ed
--- /dev/null
+++ b/metal3-chart/charts/ironic/templates/NOTES.txt
@@ -0,0 +1,16 @@
+1. Get the application URL by running these commands:
+{{- if eq .Values.service.type "NodePort" }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ironic.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if eq .Values.service.type "LoadBalancer" }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ironic.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ironic.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+ echo http://$SERVICE_IP:6385
+{{- else if eq .Values.service.type "ClusterIP" }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ironic.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
diff --git a/metal3-chart/charts/ironic/templates/_helpers.tpl b/metal3-chart/charts/ironic/templates/_helpers.tpl
new file mode 100644
index 0000000..eb97966
--- /dev/null
+++ b/metal3-chart/charts/ironic/templates/_helpers.tpl
@@ -0,0 +1,88 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "ironic.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "ironic.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "ironic.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "ironic.labels" -}}
+helm.sh/chart: {{ include "ironic.chart" . }}
+{{ include "ironic.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "ironic.selectorLabels" -}}
+app.kubernetes.io/component: ironic
+app.kubernetes.io/name: {{ include "ironic.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "ironic.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "ironic.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
+
+{{/*
+Shared directory volumeMount
+*/}}
+{{- define "ironic.sharedVolumeMount" -}}
+- mountPath: /shared
+ name: ironic-data-volume
+{{- end }}
+
+{{/*
+Get ironic CA volumeMounts
+*/}}
+{{- define "ironic.CAVolumeMounts" -}}
+- name: cert-ironic-ca
+ mountPath: "/certs/ca/ironic"
+ readOnly: true
+- name: cert-ironic-inspector-ca
+ mountPath: "/certs/ca/ironic-inspector"
+ readOnly: true
+{{- if .Values.global.enable_vmedia_tls }}
+- name: cert-ironic-vmedia-ca
+ mountPath: "/certs/ca/vmedia"
+ readOnly: true
+{{- end }}
+{{- end }}
diff --git a/metal3-chart/charts/ironic/templates/certificates.yaml b/metal3-chart/charts/ironic/templates/certificates.yaml
new file mode 100644
index 0000000..f745c34
--- /dev/null
+++ b/metal3-chart/charts/ironic/templates/certificates.yaml
@@ -0,0 +1,56 @@
+{{- if .Values.global.enable_tls -}}
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: ironic-cacert
+spec:
+ commonName: ironic-ca
+ isCA: true
+ ipAddresses:
+ - {{ .Values.global.ironicIP }}
+ issuerRef:
+ kind: Issuer
+ name: selfsigned-issuer
+ secretName: ironic-cacert
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: ironic-cert
+spec:
+ commonName: ironic-cert
+ ipAddresses:
+ - {{ .Values.global.ironicIP }}
+ issuerRef:
+ kind: Issuer
+ name: ca-issuer
+ secretName: ironic-cert
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: ironic-inspector-cert
+spec:
+ commonName: ironic-inspector-cert
+ ipAddresses:
+ - {{ .Values.global.ironicIP }}
+ issuerRef:
+ kind: Issuer
+ name: ca-issuer
+ secretName: ironic-inspector-cert
+{{- if .Values.global.enable_vmedia_tls }}
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: ironic-vmedia-cert
+spec:
+ commonName: ironic-vmedia-cert
+ ipAddresses:
+ - {{ .Values.global.ironicIP }}
+ issuerRef:
+ kind: Issuer
+ name: ca-issuer
+ secretName: ironic-vmedia-cert
+{{- end }}
+{{- end }}
diff --git a/metal3-chart/charts/ironic/templates/configmap-ipa-downloader.yaml b/metal3-chart/charts/ironic/templates/configmap-ipa-downloader.yaml
new file mode 100644
index 0000000..3636717
--- /dev/null
+++ b/metal3-chart/charts/ironic/templates/configmap-ipa-downloader.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: ironic-ipa-downloader
+ labels:
+ {{- include "ironic.labels" . | nindent 4 }}
+data:
+ {{- with .Values.baremetaloperator }}
+ {{ if .ipaBaseUri }}
+ IPA_BASEURI: {{ .ipaBaseUri }}
+ {{ end }}
+ {{ end }}
diff --git a/metal3-chart/charts/ironic/templates/configmap.yaml b/metal3-chart/charts/ironic/templates/configmap.yaml
new file mode 100644
index 0000000..3a66c9d
--- /dev/null
+++ b/metal3-chart/charts/ironic/templates/configmap.yaml
@@ -0,0 +1,86 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: ironic-bmo
+ labels:
+ {{- include "ironic.labels" . | nindent 4 }}
+data:
+ {{- $enableTLS := .Values.global.enable_tls }}
+ {{- $enableVMediaTLS := .Values.global.enable_vmedia_tls }}
+ {{- $protocol := ternary "https" "http" $enableTLS }}
+ {{- $ironicIP := .Values.global.ironicIP | default "" }}
+ {{- $ironicApiHost := print $ironicIP ":6385" }}
+ {{- $ironicInspectorHost := print $ironicIP ":5050" }}
+ {{- $ironicBootHost := print $ironicIP ":6180" }}
+ {{- $ironicCacheHost := print $ironicIP ":6180" }}
+
+ {{- if ( .Values.global.enable_dnsmasq ) }}
+ DNSMASQ_BOOT_SERVER_ADDRESS: {{ $ironicBootHost }}
+ DNSMASQ_DNS_SERVER_ADDRESS: {{ .Values.global.dnsmasqDNSServer }}
+ DNSMASQ_DEFAULT_ROUTER: {{ .Values.global.dnsmasqDefaultRouter }}
+ DHCP_RANGE: {{ .Values.global.dhcpRange }}
+ {{- end }}
+ {{- if .Values.debug.ironicRamdiskSshKey }}
+ IRONIC_RAMDISK_SSH_KEY: {{ .Values.debug.ironicRamdiskSshKey }}
+ {{- end }}
+ HTTP_PORT: "6180"
+ PREDICTABLE_NIC_NAMES: "{{ .Values.global.predictableNicNames }}"
+ USE_IRONIC_INSPECTOR: "true"
+ IRONIC_API_BASE_URL: {{ $protocol }}://{{ $ironicApiHost }}
+ IRONIC_API_HOST: {{ $ironicApiHost }}
+ IRONIC_API_HTTPD_SERVER_NAME: {{ $ironicApiHost }}
+ IRONIC_ENDPOINT: {{ $protocol }}://{{ $ironicApiHost }}/v1/
+ IRONIC_INSPECTOR_BASE_URL: {{ $protocol }}://{{ $ironicInspectorHost }}
+ IRONIC_INSPECTOR_ENDPOINT: {{ $protocol }}://{{ $ironicInspectorHost }}/v1/
+ IRONIC_INSPECTOR_HOST: {{ $ironicInspectorHost }}
+ IRONIC_INSPECTOR_HTTPD_SERVER_NAME: {{ $ironicInspectorHost }}
+ # Switch VMedia to HTTP if enable_vmedia_tls is false
+ {{- if and $enableTLS $enableVMediaTLS }}
+ {{- $ironicBootHost = print $ironicIP ":" .Values.global.vmediaTLSPort }}
+ {{- $ironicCacheHost = print $ironicIP ":" .Values.global.vmediaTLSPort }}
+ {{- $protocol = "https" }}
+ {{- else }}
+ {{- $protocol = "http" }}
+ {{- end }}
+ IRONIC_EXTERNAL_HTTP_URL: {{ $protocol }}://{{ $ironicCacheHost }}
+ CACHEURL: {{ $protocol }}://{{ $ironicCacheHost }}/images
+ DEPLOY_KERNEL_URL: {{ $protocol }}://{{ $ironicBootHost }}/images/ironic-python-agent.kernel
+ DEPLOY_RAMDISK_URL: {{ $protocol }}://{{ $ironicBootHost }}/images/ironic-python-agent.initramfs
+ IRONIC_BOOT_BASE_URL: {{ $protocol }}://{{ $ironicBootHost }}
+ IRONIC_VMEDIA_HTTPD_SERVER_NAME: {{ $ironicBootHost }}
+ ENABLE_PXE_BOOT: "{{ .Values.global.enable_pxe_boot }}"
+ {{- if .Values.global.provisioningInterface }}
+ PROVISIONING_INTERFACE: {{ .Values.global.provisioningInterface }}
+ {{- end }}
+ {{- if .Values.global.provisioningIP }}
+ PROVISIONING_IP: {{ .Values.global.provisioningIP }}
+ {{- end }}
+ IRONIC_INSPECTOR_VLAN_INTERFACES: all
+ IRONIC_ILO_USE_SWIFT: "false"
+ IRONIC_ILO_USE_WEB_SERVER_FOR_IMAGES: "true"
+ IRONIC_FAST_TRACK: "true"
+ IRONIC_USE_MARIADB: "true"
+ LISTEN_ALL_INTERFACES: "true"
+ {{- if .Values.global.ironicIP }}
+ IRONIC_IP: {{ .Values.global.ironicIP }}
+ {{- end }}
+ {{- if ( .Values.global.enable_tls ) }}
+ RESTART_CONTAINER_CERTIFICATE_UPDATED: "true"
+ IRONIC_KERNEL_PARAMS: {{ .Values.global.ironicKernelParams }} tls.enabled=true
+ IPA_INSECURE: "0"
+ IRONIC_REVERSE_PROXY_SETUP: "true"
+ INSPECTOR_REVERSE_PROXY_SETUP: "true"
+ {{- if ( .Values.global.enable_vmedia_tls ) }}
+ VMEDIA_TLS_PORT: "{{ .Values.global.vmediaTLSPort }}"
+ {{- end }}
+ {{- else }}
+ RESTART_CONTAINER_CERTIFICATE_UPDATED: "false"
+ IRONIC_KERNEL_PARAMS: {{ .Values.global.ironicKernelParams }}
+ IPA_INSECURE: "1"
+ IRONIC_REVERSE_PROXY_SETUP: "false"
+ {{- end }}
+ {{- if ( .Values.global.enable_basicAuth ) }}
+ AUTH_STRATEGY: "http_basic"
+ INSPECTOR_AUTH_STRATEGY: "http_basic"
+ {{- end }}
+ MARIADB_HOST: {{ .Values.global.databaseServiceName }}.{{ .Release.Namespace }}.svc.cluster.local
diff --git a/metal3-chart/charts/ironic/templates/deployment.yaml b/metal3-chart/charts/ironic/templates/deployment.yaml
new file mode 100644
index 0000000..7f5e39d
--- /dev/null
+++ b/metal3-chart/charts/ironic/templates/deployment.yaml
@@ -0,0 +1,367 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "ironic.fullname" . }}
+ labels:
+ {{- include "ironic.labels" . | nindent 4 }}
+spec:
+ minReadySeconds: 10
+ replicas: {{ .Values.replicaCount }}
+ selector:
+ matchLabels:
+ {{- include "ironic.selectorLabels" . | nindent 6 }}
+ strategy:
+ type: Recreate
+ template:
+ metadata:
+ {{- with .Values.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "ironic.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- if .Values.podSecurityContext }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ {{- end }}
+ {{- if .Values.baremetaloperator.ironichostNetwork }}
+ hostNetwork: {{ .Values.baremetaloperator.ironichostNetwork }}
+ {{- end }}
+ containers:
+ - name: ironic-httpd
+ image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }}
+ imagePullPolicy: {{ .Values.images.ironic.pullPolicy }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 10 }}
+ command:
+ - /bin/runhttpd
+ envFrom:
+ - configMapRef:
+ name: ironic-bmo
+ livenessProbe:
+ exec:
+ command:
+ - /bin/sh
+ - -c
+ - curl {{ if and .Values.global.enable_tls .Values.global.enable_vmedia_tls }}-sSfk https://127.0.0.1:{{ .Values.global.vmediaTLSPort }}/boot.ipxe {{ else }}-sSf http://127.0.0.1:6180/boot.ipxe{{ end }}
+ failureThreshold: 10
+ initialDelaySeconds: 30
+ periodSeconds: 30
+ successThreshold: 1
+ timeoutSeconds: 10
+ ports:
+ {{- if and .Values.global.enable_tls .Values.global.enable_vmedia_tls }}
+ - containerPort: {{ .Values.global.vmediaTLSPort }}
+ name: httpd-tls
+ protocol: TCP
+ {{- else }}
+ - containerPort: 6180
+ name: httpd
+ protocol: TCP
+ {{- end }}
+ readinessProbe:
+ exec:
+ command:
+ - /bin/sh
+ - -c
+ - curl {{ if and .Values.global.enable_tls .Values.global.enable_vmedia_tls }}-sSfk https://127.0.0.1:{{ .Values.global.vmediaTLSPort }}/boot.ipxe {{ else }}-sSf http://127.0.0.1:6180/boot.ipxe{{ end }}
+ failureThreshold: 10
+ initialDelaySeconds: 30
+ periodSeconds: 30
+ successThreshold: 1
+ timeoutSeconds: 10
+ volumeMounts:
+ {{- include "ironic.sharedVolumeMount" . | nindent 10 }}
+ {{- if .Values.global.enable_tls }}
+ {{- include "ironic.CAVolumeMounts" . | nindent 10 }}
+ - name: cert-ironic
+ mountPath: "/certs/ironic"
+ readOnly: true
+ - name: cert-ironic-inspector
+ mountPath: "/certs/ironic-inspector"
+ readOnly: true
+ {{- if .Values.global.enable_vmedia_tls }}
+ - name: cert-ironic-vmedia
+ mountPath: "/certs/vmedia"
+ readOnly: true
+ {{- end }}
+ - mountPath: /shared/html/tstcerts
+ name: cert-ironic-ca
+ readOnly: true
+ {{- end }}
+ - name: ironic-inspector
+ image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }}
+ imagePullPolicy: {{ .Values.images.ironic.pullPolicy }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 10 }}
+ command:
+ - /bin/runironic-inspector
+ envFrom:
+ - configMapRef:
+ name: ironic-bmo
+ env:
+ {{- if .Values.global.enable_basicAuth }}
+ - name: INSPECTOR_HTPASSWD
+ valueFrom:
+ secretKeyRef:
+ name: ironic-inspector-basic-auth
+ key: htpasswd
+ {{- end }}
+ - name: MARIADB_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ key: password
+ name: ironic-mariadb
+ livenessProbe:
+ exec:
+ command:
+ - /bin/sh
+ - -c
+ - curl -sSf http://127.0.0.1:{{ if .Values.global.enable_tls }}5049{{ else }}5050{{ end }}
+ failureThreshold: 10
+ initialDelaySeconds: 30
+ periodSeconds: 30
+ successThreshold: 1
+ timeoutSeconds: 10
+ ports:
+ - containerPort: 5050
+ name: inspector
+ protocol: TCP
+ readinessProbe:
+ exec:
+ command:
+ - /bin/sh
+ - -c
+ - curl -sSf http://127.0.0.1:{{ if .Values.global.enable_tls }}5049{{ else }}5050{{ end }}
+ failureThreshold: 10
+ initialDelaySeconds: 30
+ periodSeconds: 30
+ successThreshold: 1
+ timeoutSeconds: 10
+ volumeMounts:
+ {{- include "ironic.sharedVolumeMount" . | nindent 10 }}
+ {{- if .Values.global.enable_basicAuth }}
+ - mountPath: "/auth/ironic/auth-config"
+ name: ironic-basic-auth
+ subPath: auth-config
+ readOnly: true
+ - mountPath: "/auth/ironic-inspector/auth-config"
+ name: ironic-inspector-basic-auth
+ subPath: auth-config
+ readOnly: true
+ {{- end }}
+ {{- if .Values.global.enable_tls }}
+ {{- include "ironic.CAVolumeMounts" . | nindent 10 }}
+ - name: cert-ironic-inspector
+ mountPath: "/certs/ironic-inspector"
+ readOnly: true
+ {{- end }}
+ - name: ironic-log-watch
+ image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }}
+ imagePullPolicy: {{ .Values.images.ironic.pullPolicy }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 10 }}
+ command:
+ - /bin/runlogwatch.sh
+ volumeMounts:
+ {{- include "ironic.sharedVolumeMount" . | nindent 10 }}
+ - name: ironic
+ image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }}
+ imagePullPolicy: {{ .Values.images.ironic.pullPolicy }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 10 }}
+ command:
+ - /bin/runironic
+ envFrom:
+ - configMapRef:
+ name: ironic-bmo
+ env:
+ {{- if .Values.global.enable_basicAuth }}
+ - name: IRONIC_HTPASSWD
+ valueFrom:
+ secretKeyRef:
+ name: ironic-basic-auth
+ key: htpasswd
+ {{- end }}
+ - name: MARIADB_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ key: password
+ name: ironic-mariadb
+ livenessProbe:
+ exec:
+ command:
+ - /bin/sh
+ - -c
+ - curl -sSf http://127.0.0.1:{{ if .Values.global.enable_tls }}6388{{ else }}6385{{ end }}
+ failureThreshold: 10
+ initialDelaySeconds: 30
+ periodSeconds: 30
+ successThreshold: 1
+ timeoutSeconds: 10
+ ports:
+ - containerPort: 6385
+ name: api
+ protocol: TCP
+ readinessProbe:
+ exec:
+ command:
+ - /bin/sh
+ - -c
+ - curl -sSf http://127.0.0.1:{{ if .Values.global.enable_tls }}6388{{ else }}6385{{ end }}
+ failureThreshold: 10
+ initialDelaySeconds: 30
+ periodSeconds: 30
+ successThreshold: 1
+ timeoutSeconds: 10
+ volumeMounts:
+ {{- include "ironic.sharedVolumeMount" . | nindent 10 }}
+ {{- if .Values.global.enable_basicAuth }}
+ - mountPath: "/auth/ironic/auth-config"
+ name: ironic-basic-auth
+ subPath: auth-config
+ readOnly: true
+ - mountPath: "/auth/ironic-inspector/auth-config"
+ name: ironic-inspector-basic-auth
+ subPath: auth-config
+ readOnly: true
+ {{- end }}
+ {{- if .Values.global.enable_tls }}
+ {{- include "ironic.CAVolumeMounts" . | nindent 10 }}
+ - name: cert-ironic
+ mountPath: "/certs/ironic"
+ readOnly: true
+ - mountPath: /etc/pki/trust/anchors
+ name: trusted-certs
+ readOnly: true
+ lifecycle:
+ postStart:
+ exec:
+ command:
+ - update-ca-certificates
+ {{- end }}
+ {{- if .Values.global.enable_dnsmasq }}
+ - name: ironic-dnsmasq
+ image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }}
+ imagePullPolicy: {{ .Values.images.ironic.pullPolicy }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 10 }}
+ securityContext:
+ capabilities:
+ add:
+ - NET_ADMIN
+ - NET_RAW
+ command:
+ - /bin/rundnsmasq
+ envFrom:
+ - configMapRef:
+ name: ironic-bmo
+ livenessProbe:
+ exec:
+ command:
+ - sh
+ - -c
+ - ss -lun | grep :67 && ss -lun | grep :69
+ failureThreshold: 10
+ initialDelaySeconds: 30
+ periodSeconds: 30
+ successThreshold: 1
+ timeoutSeconds: 10
+ ports:
+ - containerPort: 67
+ name: dhcp
+ protocol: UDP
+ - containerPort: 69
+ name: tftp
+ protocol: UDP
+ readinessProbe:
+ exec:
+ command:
+ - sh
+ - -c
+ - ss -lun | grep :67 && ss -lun | grep :69
+ failureThreshold: 10
+ initialDelaySeconds: 30
+ periodSeconds: 30
+ successThreshold: 1
+ timeoutSeconds: 10
+ volumeMounts:
+ {{- include "ironic.sharedVolumeMount" . | nindent 10 }}
+ {{- end }}
+ initContainers:
+ - name: ironic-ipa-downloader
+ image: {{ .Values.images.ironicIPADownloader.repository }}:{{ .Values.images.ironicIPADownloader.tag }}
+ imagePullPolicy: {{ .Values.images.ironicIPADownloader.pullPolicy }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 10 }}
+ command:
+ - /usr/local/bin/get-resource.sh
+ envFrom:
+ - configMapRef:
+ name: ironic-ipa-downloader
+ volumeMounts:
+ {{- include "ironic.sharedVolumeMount" . | nindent 10 }}
+ {{- if .Values.global.enable_tls }}
+ - mountPath: /tmp/ironic-certificates
+ name: trusted-certs
+ {{- end }}
+ volumes:
+ - name: ironic-data-volume
+ persistentVolumeClaim:
+ claimName: ironic-shared-volume
+ {{- if .Values.global.enable_basicAuth }}
+ - name: ironic-basic-auth
+ secret:
+ secretName: ironic-basic-auth
+ - name: ironic-inspector-basic-auth
+ secret:
+ secretName: ironic-inspector-basic-auth
+ {{- if .Values.global.enable_tls }}
+ - name: trusted-certs
+ projected:
+ sources:
+ - secret:
+ name: ironic-cacert
+ {{- if .Values.global.additionalTrustedCAs }}
+ - secret:
+ name: tls-ca-additional
+ {{- end }}
+ - name: cert-ironic-ca
+ secret:
+ secretName: ironic-cacert
+ - name: cert-ironic
+ secret:
+ secretName: ironic-cert
+ - name: cert-ironic-inspector-ca
+ secret:
+ secretName: ironic-cacert
+ - name: cert-ironic-inspector
+ secret:
+ secretName: ironic-inspector-cert
+ {{- if .Values.global.enable_vmedia_tls }}
+ - name: cert-ironic-vmedia-ca
+ secret:
+ secretName: ironic-cacert
+ - name: cert-ironic-vmedia
+ secret:
+ secretName: ironic-vmedia-cert
+ {{- end }}
+ {{- end }}
+ {{- end }}
+ {{- with .Values.global.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.global.dnsPolicy }}
+ dnsPolicy:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
diff --git a/metal3-chart/charts/ironic/templates/issuers.yaml b/metal3-chart/charts/ironic/templates/issuers.yaml
new file mode 100644
index 0000000..b03cbcc
--- /dev/null
+++ b/metal3-chart/charts/ironic/templates/issuers.yaml
@@ -0,0 +1,16 @@
+{{- if .Values.global.enable_tls -}}
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: selfsigned-issuer
+spec:
+ selfSigned: {}
+---
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: ca-issuer
+spec:
+ ca:
+ secretName: ironic-cacert
+{{- end }}
diff --git a/metal3-chart/charts/ironic/templates/pvc.yaml b/metal3-chart/charts/ironic/templates/pvc.yaml
new file mode 100644
index 0000000..e50c856
--- /dev/null
+++ b/metal3-chart/charts/ironic/templates/pvc.yaml
@@ -0,0 +1,24 @@
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: ironic-shared-volume
+ {{- if .Values.persistence.ironic.keep }}
+ annotations:
+ "helm.sh/resource-policy": keep
+ {{- end }}
+spec:
+ accessModes:
+ {{- if .Values.persistence.ironic.accessMode }}
+ - {{ .Values.persistence.ironic.accessMode }}
+ {{- else if eq (int .Values.replicaCount) 1 }}
+ - ReadWriteOnce
+ {{- else }}
+ - ReadWriteMany
+ {{- end }}
+ resources:
+ requests:
+ storage: {{ .Values.persistence.ironic.size }}
+ {{- if .Values.persistence.ironic.storageClass }}
+ storageClassName: {{ .Values.persistence.ironic.storageClass }}
+ {{- end }}
+ volumeMode: Filesystem
diff --git a/metal3-chart/charts/ironic/templates/secret-tls.yaml b/metal3-chart/charts/ironic/templates/secret-tls.yaml
new file mode 100644
index 0000000..173d2fb
--- /dev/null
+++ b/metal3-chart/charts/ironic/templates/secret-tls.yaml
@@ -0,0 +1,16 @@
+{{- if and (.Values.global.enable_tls)
+ (ne .Values.tlscerts.crt "")
+ (ne .Values.tlscerts.key "")
+ (ne .Values.tlscerts.cacert "") -}}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: ironic-cacert
+ labels:
+ {{- include "ironic.labels" . | nindent 4 }}
+type: Opaque
+data:
+ tls.crt: {{ .Values.tlscerts.crt | toString | b64enc }}
+ tls.key: {{ .Values.tlscerts.key | toString | b64enc }}
+ ca.crt: {{ .Values.tlscerts.cacert | toString | b64enc }}
+{{- end }}
diff --git a/metal3-chart/charts/ironic/templates/secrets-basic-auth.yaml b/metal3-chart/charts/ironic/templates/secrets-basic-auth.yaml
new file mode 100644
index 0000000..aa5736d
--- /dev/null
+++ b/metal3-chart/charts/ironic/templates/secrets-basic-auth.yaml
@@ -0,0 +1,62 @@
+{{- if .Values.global.enable_basicAuth }}
+
+{{- $ironicUsername := "" -}}
+{{- $ironicPassword := "" -}}
+{{- $ironicSecretName := "ironic-basic-auth" -}}
+
+# Check if the secret is deployed and has a password
+{{- $oldIronicSecret := lookup "v1" "Secret" .Release.Namespace $ironicSecretName }}
+{{- if and $oldIronicSecret (index $oldIronicSecret.data "username") (index $oldIronicSecret.data "password") }}
+{{- $ironicUsername = b64dec (index $oldIronicSecret.data "username" | toString) -}}
+{{- $ironicPassword = b64dec (index $oldIronicSecret.data "password" | toString) -}}
+# If not, check if a username and password are provided in values.yaml
+{{- else if and (.Values.global.auth.ironicUsername) (.Values.global.auth.ironicPassword) }}
+{{- $ironicUsername = .Values.global.auth.ironicUsername -}}
+{{- $ironicPassword = .Values.global.auth.ironicPassword -}}
+{{- else }}
+# If no username and password are provided in values.yaml, generate new ones
+{{- $ironicUsername = "ironic" -}}
+{{- $ironicPassword = (randAlphaNum 20) -}}
+{{- end }}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ $ironicSecretName }}
+type: Opaque
+data:
+ username: {{ $ironicUsername | b64enc }}
+ password: {{ $ironicPassword | b64enc }}
+ htpasswd: {{ b64enc (htpasswd $ironicUsername $ironicPassword) }}
+ auth-config: |
+ {{- printf "[ironic]\nauth_type=http_basic\nusername: %s\npassword: %s" $ironicUsername $ironicPassword | b64enc | nindent 4 }}
+---
+{{- $ironicInspectorUsername := "" -}}
+{{- $ironicInspectorPassword := "" -}}
+{{- $inspectorSecretName := "ironic-inspector-basic-auth" -}}
+
+# Check if the secret is deployed and has a password
+{{- $oldInspectorSecret := lookup "v1" "Secret" .Release.Namespace $inspectorSecretName }}
+{{- if and $oldInspectorSecret (index $oldInspectorSecret.data "username") (index $oldInspectorSecret.data "password") }}
+{{- $ironicInspectorUsername = b64dec (index $oldInspectorSecret.data "username" | toString) -}}
+{{- $ironicInspectorPassword = b64dec (index $oldInspectorSecret.data "password" | toString) -}}
+# If not, check if a username and password are provided in values.yaml
+{{- else if and (.Values.global.auth.ironicInspectorUsername) (.Values.global.auth.ironicInspectorPassword) }}
+{{- $ironicInspectorUsername = .Values.global.auth.ironicInspectorUsername -}}
+{{- $ironicInspectorPassword = .Values.global.auth.ironicInspectorPassword -}}
+{{- else }}
+# If no username and password are provided in values.yaml, generate new ones
+{{- $ironicInspectorUsername = "ironic" -}}
+{{- $ironicInspectorPassword = (randAlphaNum 20) -}}
+{{- end }}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ $inspectorSecretName }}
+type: Opaque
+data:
+ username: {{ $ironicInspectorUsername | b64enc }}
+ password: {{ $ironicInspectorPassword | b64enc }}
+ htpasswd: {{ b64enc (htpasswd $ironicInspectorUsername $ironicInspectorPassword) }}
+ auth-config: |
+ {{- printf "[inspector]\nauth_type=http_basic\nusername: %s\npassword: %s" $ironicInspectorUsername $ironicInspectorPassword | b64enc | nindent 4 }}
+{{- end }}
diff --git a/metal3-chart/charts/ironic/templates/service.yaml b/metal3-chart/charts/ironic/templates/service.yaml
new file mode 100644
index 0000000..f3f0b51
--- /dev/null
+++ b/metal3-chart/charts/ironic/templates/service.yaml
@@ -0,0 +1,39 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "ironic.fullname" . }}
+ labels:
+ {{- include "ironic.labels" . | nindent 4 }}
+ {{- with .Values.service.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ {{- $enableTLS := .Values.global.enable_tls }}
+ {{- $enableVMediaTLS := .Values.global.enable_vmedia_tls }}
+ {{- range .Values.service.ports }}
+ {{- if and (eq .name "httpd") (or (not $enableTLS) (not $enableVMediaTLS)) }}
+ - name: {{ .name }}
+ port: {{ .port }}
+ protocol: {{ .protocol }}
+ targetPort: {{ .targetPort }}
+ {{- else if and (eq .name "httpd-tls") ($enableTLS) ($enableVMediaTLS) }}
+ - name: {{ .name }}
+ port: {{ .port }}
+ protocol: {{ .protocol }}
+ targetPort: {{ .targetPort }}
+ {{- else if and (ne .name "httpd") (ne .name "httpd-tls") }}
+ - name: {{ .name }}
+ port: {{ .port }}
+ protocol: {{ .protocol }}
+ targetPort: {{ .targetPort }}
+ {{- end }}
+ {{- end }}
+ selector:
+ {{- include "ironic.selectorLabels" . | nindent 4 }}
+ {{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }}
+ externalIPs:
+ {{- toYaml .Values.service.externalIPs | nindent 4 }}
+ {{- end }}
diff --git a/metal3-chart/charts/ironic/templates/serviceaccount.yaml b/metal3-chart/charts/ironic/templates/serviceaccount.yaml
new file mode 100644
index 0000000..c94a90f
--- /dev/null
+++ b/metal3-chart/charts/ironic/templates/serviceaccount.yaml
@@ -0,0 +1,12 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "ironic.serviceAccountName" . }}
+ labels:
+ {{- include "ironic.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/metal3-chart/charts/ironic/values.yaml b/metal3-chart/charts/ironic/values.yaml
new file mode 100644
index 0000000..2ffb69a
--- /dev/null
+++ b/metal3-chart/charts/ironic/values.yaml
@@ -0,0 +1,153 @@
+# Default values for ironic.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+global:
+ # whether to enable dnsmasq on the provisioning network (for PXE boot)
+ enable_dnsmasq: false
+
+ # whether to enable PXE boot capability
+ # NOTE: enable_dnsmasq must set to 'true' in order for this option to be effective.
+ enable_pxe_boot: false
+
+ # DNS Policy of the Ironic pod
+ dnsPolicy: "ClusterFirstWithHostNet"
+
+ # IP address of the router associated with the specified DHCP
+ # address range
+ dnsmasqDefaultRouter: ""
+
+ # IP address of the dns server to be provided with DHCP
+ # response
+ dnsmasqDNSServer: ""
+
+ # specify comma-delimited xrange of IP addresses the DHCP server will manage.
+ # e.g 192.168.20.20,192.168.20.80
+ dhcpRange: ""
+
+ # Network interface on which provisioning network can be accessed
+ # Note this must be a dedicated NIC separate from the controlplane network
+ provisioningInterface: ""
+
+ # IP Address assigned to network interface on provisioning network
+ provisioningIP: ""
+
+ # Whether the NIC names should be predictable or not
+ predictableNicNames: "true"
+
+ # The kernel params for Ironic
+ ironicKernelParams: "console=ttyS0"
+
+ databaseServiceName: "metal3-mariadb"
+
+ # In a multi-node kubernetes cluster, we need to "pin" the
+ # ironic containers to the given host where the
+ # provisioningIP exists. Uncomment the nodeSelector
+ # here and update the hostname accordingly.
+ #nodeSelector:
+ #kubernetes.io/hostname: "csrancher-n1"
+
+ # Comment this out when pinning the pdns containers to a specfic host.
+ nodeSelector: {}
+
+replicaCount: 1
+
+images:
+ ironic:
+ repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/ironic
+ pullPolicy: IfNotPresent
+ tag: 24.1.2.0
+ ironicIPADownloader:
+ repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/ironic-ipa-downloader
+ pullPolicy: IfNotPresent
+ tag: 2.0.0
+
+nameOverride: ""
+fullnameOverride: ""
+
+serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: ""
+
+podAnnotations: {}
+
+podSecurityContext:
+ runAsUser: 10475
+ fsGroup: 10475
+
+securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
+ seccompProfile:
+ type: RuntimeDefault
+ runAsNonRoot: true
+
+service:
+ type: LoadBalancer
+ annotations: {}
+ externalIPs: []
+ ports:
+ - name: httpd
+ port: 6180
+ protocol: TCP
+ targetPort: 6180
+ - name: httpd-tls
+ port: 6185
+ protocol: TCP
+ targetPort: 6185
+ - name: inspector
+ port: 5050
+ protocol: TCP
+ targetPort: 5050
+ - name: api
+ port: 6385
+ protocol: TCP
+ targetPort: 6385
+
+resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+tolerations: []
+
+affinity: {}
+
+baremetaloperator:
+ cloudflareApiToken: "foo"
+ ironichostNetwork: true
+
+debug:
+ ironicRamdiskSshKey: ""
+
+tlscerts:
+ cacert: ""
+ key: ""
+ crt: ""
+
+persistence:
+ ironic:
+ # storageClass for the ironic shared volume
+ # Ensure the storageClass is defined
+ storageClass: ""
+ # size of the ironic shared volume
+ size: "1Gi"
+ # accessMode of the ironic shared volume PVC
+ # If empty defaults to ReadWriteOnce when replicaCount=1 otherwise ReadWriteMany
+ accessMode: ""
+ # flag to indicate to keep pvc upon helm uninstall
+ keep: false
diff --git a/metal3-chart/charts/mariadb/.helmignore b/metal3-chart/charts/mariadb/.helmignore
new file mode 100644
index 0000000..f0907ec
--- /dev/null
+++ b/metal3-chart/charts/mariadb/.helmignore
@@ -0,0 +1,24 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
+
diff --git a/metal3-chart/charts/mariadb/Chart.yaml b/metal3-chart/charts/mariadb/Chart.yaml
new file mode 100644
index 0000000..df93690
--- /dev/null
+++ b/metal3-chart/charts/mariadb/Chart.yaml
@@ -0,0 +1,6 @@
+apiVersion: v2
+appVersion: 10.6.7
+description: A Helm chart for MariaDB, used by Metal3
+name: mariadb
+type: application
+version: 0.5.4
diff --git a/metal3-chart/charts/mariadb/templates/_helpers.tpl b/metal3-chart/charts/mariadb/templates/_helpers.tpl
new file mode 100644
index 0000000..d3d47e4
--- /dev/null
+++ b/metal3-chart/charts/mariadb/templates/_helpers.tpl
@@ -0,0 +1,64 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "mariadb.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "mariadb.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "mariadb.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "mariadb.labels" -}}
+helm.sh/chart: {{ include "mariadb.chart" . }}
+{{ include "mariadb.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "mariadb.selectorLabels" -}}
+app.kubernetes.io/component: mariadb
+app.kubernetes.io/name: {{ include "mariadb.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "mariadb.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "mariadb.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
+
diff --git a/metal3-chart/charts/mariadb/templates/configmap.yaml b/metal3-chart/charts/mariadb/templates/configmap.yaml
new file mode 100644
index 0000000..59a2cc1
--- /dev/null
+++ b/metal3-chart/charts/mariadb/templates/configmap.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: mariadb-cm
+ labels:
+ {{- include "mariadb.labels" . | nindent 4 }}
+data:
+ RESTART_CONTAINER_CERTIFICATE_UPDATED: "false"
diff --git a/metal3-chart/charts/mariadb/templates/deployment.yaml b/metal3-chart/charts/mariadb/templates/deployment.yaml
new file mode 100644
index 0000000..070c2fb
--- /dev/null
+++ b/metal3-chart/charts/mariadb/templates/deployment.yaml
@@ -0,0 +1,85 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "mariadb.fullname" . }}
+ labels:
+ {{- include "mariadb.labels" . | nindent 4 }}
+spec:
+ replicas: {{.Values.replicaCount}}
+ selector:
+ matchLabels:
+ {{- include "mariadb.selectorLabels" . | nindent 6 }}
+ strategy:
+ type: Recreate
+ template:
+ metadata:
+ {{- with .Values.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "mariadb.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- $volmounts := toYaml .Values.volumeMounts | trim | nindent 12 }}
+ {{- $volumes := toYaml .Values.volumes | trim | nindent 8 }}
+ serviceAccountName: {{ include "mariadb.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ containers:
+ - name: mariadb
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
+ env:
+ - name: MARIADB_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ key: password
+ name: ironic-mariadb
+ - name: RESTART_CONTAINER_CERTIFICATE_UPDATED
+ valueFrom:
+ configMapKeyRef:
+ name: mariadb-cm
+ key: RESTART_CONTAINER_CERTIFICATE_UPDATED
+ lifecycle:
+ preStop:
+ exec:
+ command:
+ - sh
+ - -c
+ - mysqladmin shutdown -uironic -p$(printenv MARIADB_PASSWORD)
+ livenessProbe:
+ exec:
+ command:
+ - sh
+ - -c
+ - mysqladmin status -uironic -p$(printenv MARIADB_PASSWORD)
+ failureThreshold: 10
+ initialDelaySeconds: 30
+ periodSeconds: 30
+ successThreshold: 1
+ timeoutSeconds: 10
+ ports:
+ - containerPort: 3306
+ name: mariadb
+ protocol: TCP
+ readinessProbe:
+ exec:
+ command:
+ - sh
+ - -c
+ - mysqladmin status -uironic -p$(printenv MARIADB_PASSWORD)
+ failureThreshold: 10
+ initialDelaySeconds: 30
+ periodSeconds: 30
+ successThreshold: 1
+ timeoutSeconds: 10
+ volumeMounts:
+ {{- $volmounts }}
+ {{- with .Values.global.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ volumes:
+ {{- $volumes }}
diff --git a/metal3-chart/charts/mariadb/templates/pvc.yaml b/metal3-chart/charts/mariadb/templates/pvc.yaml
new file mode 100644
index 0000000..fa0a176
--- /dev/null
+++ b/metal3-chart/charts/mariadb/templates/pvc.yaml
@@ -0,0 +1,24 @@
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: mariadb-volume-claim
+ {{- if .Values.persistence.keep }}
+ annotations:
+ "helm.sh/resource-policy": keep
+ {{- end }}
+spec:
+ accessModes:
+ {{- if .Values.persistence.accessMode }}
+ - {{ .Values.persistence.accessMode }}
+ {{- else if eq (int .Values.replicaCount) 1 }}
+ - ReadWriteOnce
+ {{- else }}
+ - ReadWriteMany
+ {{- end }}
+ resources:
+ requests:
+ storage: {{ .Values.persistence.size }}
+ {{- if .Values.persistence.storageClass }}
+ storageClassName: {{ .Values.persistence.storageClass }}
+ {{- end }}
+ volumeMode: Filesystem
diff --git a/metal3-chart/charts/mariadb/templates/secret.yaml b/metal3-chart/charts/mariadb/templates/secret.yaml
new file mode 100644
index 0000000..d4b2318
--- /dev/null
+++ b/metal3-chart/charts/mariadb/templates/secret.yaml
@@ -0,0 +1,21 @@
+{{- $secret_name := "ironic-mariadb" -}}
+
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ $secret_name }}
+ labels:
+ {{- include "mariadb.labels" . | nindent 4 }}
+type: Opaque
+data:
+ # Check if the secret is deployed and has a password
+ {{- $old_sec := lookup "v1" "Secret" .Release.Namespace $secret_name }}
+ {{- if and $old_sec (index $old_sec.data "password") }}
+ password: {{ index $old_sec.data "password" }}
+ {{- else if .Values.password }}
+ # If not, check if a password is provided in values.yaml
+ password: {{ .Values.password | toString | b64enc }}
+ {{- else }}
+ # If no secret and no password in values.yaml, generate a new password
+ password: {{ randAlphaNum 20 | b64enc }}
+ {{- end }}
\ No newline at end of file
diff --git a/metal3-chart/charts/mariadb/templates/service-account.yaml b/metal3-chart/charts/mariadb/templates/service-account.yaml
new file mode 100644
index 0000000..5101f01
--- /dev/null
+++ b/metal3-chart/charts/mariadb/templates/service-account.yaml
@@ -0,0 +1,13 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "mariadb.serviceAccountName" . }}
+ labels:
+ {{- include "mariadb.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
+
diff --git a/metal3-chart/charts/mariadb/templates/service.yaml b/metal3-chart/charts/mariadb/templates/service.yaml
new file mode 100644
index 0000000..5d0d75d
--- /dev/null
+++ b/metal3-chart/charts/mariadb/templates/service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ .Values.global.databaseServiceName }}
+ labels:
+ {{- include "mariadb.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ selector:
+ {{- include "mariadb.selectorLabels" . | nindent 4 }}
+ ports:
+ {{- with .Values.service.ports }}
+ {{- toYaml . | nindent 2 }}
+ {{- end }}
\ No newline at end of file
diff --git a/metal3-chart/charts/mariadb/values.yaml b/metal3-chart/charts/mariadb/values.yaml
new file mode 100644
index 0000000..7d2fbce
--- /dev/null
+++ b/metal3-chart/charts/mariadb/values.yaml
@@ -0,0 +1,67 @@
+global:
+ databaseServiceName: "metal3-mariadb"
+ nodeSelector: {}
+
+replicaCount: 1
+
+service:
+ type: ClusterIP
+ ports:
+ - protocol: TCP
+ port: 3306
+ targetPort: 3306
+
+image:
+ repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/suse/mariadb
+ pullPolicy: IfNotPresent
+ tag: 10.6.15.1
+
+nameOverride: ""
+fullnameOverride: ""
+
+serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: ""
+
+podAnnotations: {}
+
+podSecurityContext:
+ runAsUser: 10060
+ fsGroup: 10060
+
+securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
+ seccompProfile:
+ type: RuntimeDefault
+ runAsNonRoot: true
+
+# Password for the mariadb ironic user
+password: ""
+
+persistence:
+ # storageClass for the mariadb data volume
+ storageClass: ""
+ # size of the mariadb data volume
+ size: "1Gi"
+ # accessMode of the mariadb data volume PVC
+ # If empty defaults to ReadWriteOnce when replicaCount=1 otherwise ReadWriteMany
+ accessMode: ""
+ # flag to indicate to keep pvc upon helm uninstall
+ keep: false
+
+volumeMounts:
+ - name: mariadb-data-volume
+ mountPath: /var/lib/mysql
+
+volumes:
+ - name: mariadb-data-volume
+ persistentVolumeClaim:
+ claimName: mariadb-volume-claim
diff --git a/metal3-chart/charts/media/.helmignore b/metal3-chart/charts/media/.helmignore
new file mode 100644
index 0000000..1b9a9cc
--- /dev/null
+++ b/metal3-chart/charts/media/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/metal3-chart/charts/media/Chart.yaml b/metal3-chart/charts/media/Chart.yaml
new file mode 100644
index 0000000..544c704
--- /dev/null
+++ b/metal3-chart/charts/media/Chart.yaml
@@ -0,0 +1,6 @@
+apiVersion: v2
+appVersion: 1.16.0
+description: A Helm chart for Media, used by Metal3
+name: media
+type: application
+version: 0.5.0
diff --git a/metal3-chart/charts/media/templates/NOTES.txt b/metal3-chart/charts/media/templates/NOTES.txt
new file mode 100644
index 0000000..c6350f5
--- /dev/null
+++ b/metal3-chart/charts/media/templates/NOTES.txt
@@ -0,0 +1,22 @@
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+ {{- range .paths }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
+ {{- end }}
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "media.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "media.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "media.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+ echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "media.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
diff --git a/metal3-chart/charts/media/templates/_helpers.tpl b/metal3-chart/charts/media/templates/_helpers.tpl
new file mode 100644
index 0000000..37c5e87
--- /dev/null
+++ b/metal3-chart/charts/media/templates/_helpers.tpl
@@ -0,0 +1,63 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "media.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "media.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "media.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "media.labels" -}}
+helm.sh/chart: {{ include "media.chart" . }}
+{{ include "media.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "media.selectorLabels" -}}
+app.kubernetes.io/component: media
+app.kubernetes.io/name: {{ include "media.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "media.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "media.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/metal3-chart/charts/media/templates/deployment.yaml b/metal3-chart/charts/media/templates/deployment.yaml
new file mode 100644
index 0000000..9dccd57
--- /dev/null
+++ b/metal3-chart/charts/media/templates/deployment.yaml
@@ -0,0 +1,66 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "media.fullname" . }}
+ labels:
+ {{- include "media.labels" . | nindent 4 }}
+spec:
+ {{- if not .Values.autoscaling.enabled }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "media.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ annotations:
+ rollme: {{ randAlphaNum 5 | quote }}
+ {{- with .Values.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "media.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "media.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ {{- with .Values.volumes }}
+ volumes:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ containers:
+ - name: {{ .Chart.Name }}
+ command:
+ - /usr/sbin/httpd
+ args:
+ - -DFOREGROUND
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ ports:
+ - name: http
+ containerPort: 80
+ protocol: TCP
+ {{- with .Values.volumeMounts }}
+ volumeMounts:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ resources:
+ {{- toYaml .Values.resources | nindent 12 }}
+ {{- with .Values.global.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
diff --git a/metal3-chart/charts/media/templates/hpa.yaml b/metal3-chart/charts/media/templates/hpa.yaml
new file mode 100644
index 0000000..0bd8a10
--- /dev/null
+++ b/metal3-chart/charts/media/templates/hpa.yaml
@@ -0,0 +1,28 @@
+{{- if .Values.autoscaling.enabled }}
+apiVersion: autoscaling/v2beta1
+kind: HorizontalPodAutoscaler
+metadata:
+ name: {{ include "media.fullname" . }}
+ labels:
+ {{- include "media.labels" . | nindent 4 }}
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: {{ include "media.fullname" . }}
+ minReplicas: {{ .Values.autoscaling.minReplicas }}
+ maxReplicas: {{ .Values.autoscaling.maxReplicas }}
+ metrics:
+ {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: cpu
+ targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
+ {{- end }}
+ {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: memory
+ targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ {{- end }}
+{{- end }}
diff --git a/metal3-chart/charts/media/templates/ingress.yaml b/metal3-chart/charts/media/templates/ingress.yaml
new file mode 100644
index 0000000..576ecb9
--- /dev/null
+++ b/metal3-chart/charts/media/templates/ingress.yaml
@@ -0,0 +1,61 @@
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "media.fullname" . -}}
+{{- $svcPort := .Values.service.port -}}
+{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
+ {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
+ {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
+ {{- end }}
+{{- end }}
+{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1
+{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+ name: {{ $fullName }}
+ labels:
+ {{- include "media.labels" . | nindent 4 }}
+ {{- with $_ := merge .Values.ingress.annotations $.Values.global.ingress.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
+ ingressClassName: {{ .Values.ingress.className }}
+ {{- end }}
+ {{- if .Values.ingress.tls }}
+ tls:
+ {{- range .Values.ingress.tls }}
+ - hosts:
+ {{- range .hosts }}
+ - {{ . | quote }}
+ {{- end }}
+ secretName: {{ .secretName }}
+ {{- end }}
+ {{- end }}
+ rules:
+ {{- range .Values.ingress.hosts }}
+ - host: {{ tpl .host $ }}
+ http:
+ paths:
+ {{- range .paths }}
+ - path: {{ .path }}
+ {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
+ pathType: {{ .pathType }}
+ {{- end }}
+ backend:
+ {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
+ service:
+ name: {{ $fullName }}
+ port:
+ number: {{ $svcPort }}
+ {{- else }}
+ serviceName: {{ $fullName }}
+ servicePort: {{ $svcPort }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
+{{- end }}
diff --git a/metal3-chart/charts/media/templates/persistentvolume.yaml b/metal3-chart/charts/media/templates/persistentvolume.yaml
new file mode 100644
index 0000000..8ebf28c
--- /dev/null
+++ b/metal3-chart/charts/media/templates/persistentvolume.yaml
@@ -0,0 +1,18 @@
+{{- if eq .Values.mediaVolume.storageClassName "local" }}
+---
+kind: PersistentVolume
+apiVersion: v1
+metadata:
+ name: media
+ labels:
+ {{- include "media.labels" . | nindent 4 }}
+spec:
+ storageClassName: {{ .Values.mediaVolume.storageClassName }}
+ accessModes:
+ {{ toYaml .Values.mediaVolume.accessModes }}
+ capacity:
+ storage: {{ .Values.mediaVolume.storage }}
+ hostPath:
+ path: {{ .Values.mediaVolume.hostPath }}
+ type: DirectoryOrCreate
+{{- end }}
diff --git a/metal3-chart/charts/media/templates/persistentvolumeclaim.yaml b/metal3-chart/charts/media/templates/persistentvolumeclaim.yaml
new file mode 100644
index 0000000..7cb52f8
--- /dev/null
+++ b/metal3-chart/charts/media/templates/persistentvolumeclaim.yaml
@@ -0,0 +1,14 @@
+---
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+ name: media
+ labels:
+ {{- include "media.labels" . | nindent 4 }}
+spec:
+ storageClassName: {{ .Values.mediaVolume.storageClassName }}
+ accessModes:
+ {{ toYaml .Values.mediaVolume.accessModes }}
+ resources:
+ requests:
+ storage: {{ .Values.mediaVolume.storage }}
diff --git a/metal3-chart/charts/media/templates/service.yaml b/metal3-chart/charts/media/templates/service.yaml
new file mode 100644
index 0000000..93598e5
--- /dev/null
+++ b/metal3-chart/charts/media/templates/service.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "media.fullname" . }}
+ labels:
+ {{- include "media.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.port }}
+ targetPort: http
+ protocol: TCP
+ name: http
+ selector:
+ {{- include "media.selectorLabels" . | nindent 4 }}
diff --git a/metal3-chart/charts/media/templates/serviceaccount.yaml b/metal3-chart/charts/media/templates/serviceaccount.yaml
new file mode 100644
index 0000000..3badde4
--- /dev/null
+++ b/metal3-chart/charts/media/templates/serviceaccount.yaml
@@ -0,0 +1,12 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "media.serviceAccountName" . }}
+ labels:
+ {{- include "media.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/metal3-chart/charts/media/templates/storageclass.yaml b/metal3-chart/charts/media/templates/storageclass.yaml
new file mode 100644
index 0000000..6c491aa
--- /dev/null
+++ b/metal3-chart/charts/media/templates/storageclass.yaml
@@ -0,0 +1,9 @@
+---
+kind: StorageClass
+apiVersion: storage.k8s.io/v1
+metadata:
+ name: {{ include "media.fullname" . }}
+ labels:
+ {{- include "media.labels" . | nindent 4 }}
+provisioner: kubernetes.io/no-provisioner
+volumeBindingMode: WaitForFirstConsumer
diff --git a/metal3-chart/charts/media/templates/tests/test-connection.yaml b/metal3-chart/charts/media/templates/tests/test-connection.yaml
new file mode 100644
index 0000000..f96c62c
--- /dev/null
+++ b/metal3-chart/charts/media/templates/tests/test-connection.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: "{{ include "media.fullname" . }}-test-connection"
+ labels:
+ {{- include "media.labels" . | nindent 4 }}
+ annotations:
+ "helm.sh/hook": test
+spec:
+ containers:
+ - name: wget
+ image: busybox
+ command: ['wget']
+ args: ['{{ include "media.fullname" . }}:{{ .Values.service.port }}']
+ restartPolicy: Never
diff --git a/metal3-chart/charts/media/values.yaml b/metal3-chart/charts/media/values.yaml
new file mode 100644
index 0000000..9f46ebe
--- /dev/null
+++ b/metal3-chart/charts/media/values.yaml
@@ -0,0 +1,117 @@
+# Default values for media.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+global:
+ # Global ingress annotations that is shared by all the ingress services.
+ # For example, use it to override extern-dns records.
+ ingress:
+ annotations: {}
+ # The IP to register with external-dns for this service
+ #external-dns.alpha.kubernetes.io/target: 192.168.20.5
+
+ # If running in a multi-node kubernetes cluster, "pin" the media container
+ # to the given host where the /opt/media volume exists. Uncomment the
+ # nodeSelector and update the hostname accordingly.
+ #nodeSelector:
+ #kubernetes.io/hostname: "my-hostname"
+
+ # Comment this out when pinning the media container to a specfic host.
+ nodeSelector: {}
+
+replicaCount: 1
+
+image:
+ repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/ironic
+ pullPolicy: IfNotPresent
+ tag: 24.1.2.0
+
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+
+serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: ""
+
+podAnnotations: {}
+
+podSecurityContext:
+ runAsUser: 10475
+ fsGroup: 10475
+
+securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
+ seccompProfile:
+ type: RuntimeDefault
+ runAsNonRoot: true
+
+service:
+ type: ClusterIP
+ port: 80
+
+ingress:
+ enabled: true
+ className: ""
+ annotations: {}
+ # kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: "true"
+ hosts:
+ - host: media.suse.baremetal
+ paths:
+ - path: /
+ pathType: Prefix
+ tls: []
+ # - secretName: chart-example-tls
+ # hosts:
+ # - chart-example.local
+
+resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+autoscaling:
+ enabled: false
+ minReplicas: 1
+ maxReplicas: 100
+ targetCPUUtilizationPercentage: 80
+ # targetMemoryUtilizationPercentage: 80
+
+tolerations: []
+
+affinity: {}
+
+# volumes
+volumes:
+ - name: assets
+ persistentVolumeClaim:
+ claimName: media
+
+# volume mounts
+volumeMounts:
+ - mountPath: /srv/www/htdocs
+ name: assets
+
+# media volume settings
+mediaVolume:
+ storageClassName: local
+ accessModes:
+ - ReadOnlyMany
+ hostPath: /opt/media
+ storage: 5Gi
diff --git a/metal3-chart/templates/NOTES.txt b/metal3-chart/templates/NOTES.txt
new file mode 100644
index 0000000..acbebf0
--- /dev/null
+++ b/metal3-chart/templates/NOTES.txt
@@ -0,0 +1,3 @@
+TBD: Document the deployed application/service endpoints
+
+You should now be ready to install and configure ClusterAPI.
diff --git a/metal3-chart/templates/_helpers.tpl b/metal3-chart/templates/_helpers.tpl
new file mode 100644
index 0000000..67024dd
--- /dev/null
+++ b/metal3-chart/templates/_helpers.tpl
@@ -0,0 +1,62 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "metal3.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "metal3.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "metal3.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "metal3.labels" -}}
+helm.sh/chart: {{ include "metal3.chart" . }}
+{{ include "metal3.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "metal3.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "metal3.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "metal3.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "metal3.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/metal3-chart/values.yaml b/metal3-chart/values.yaml
new file mode 100644
index 0000000..48af6e4
--- /dev/null
+++ b/metal3-chart/values.yaml
@@ -0,0 +1,130 @@
+# The metal3 chart is a parent chart that installs
+# all of the other charts that a metal3 deployment needs,
+# but doesn't actually deploy any services itself.
+
+global:
+ # IP on which the Ironic services will be exposed
+ ironicIP: ""
+
+ # whether to enable media server.
+ enable_metal3_media_server: false
+
+ # whether to enable dnsmasq on the provisioning network (for PXE boot)
+ enable_dnsmasq: false
+
+ # whether to enable PXE boot capability
+ # NOTE: enable_dnsmasq must set to 'true' in order for this option to be effective.
+ enable_pxe_boot: false
+
+ # whether to enable tls
+ enable_tls: true
+
+ # whether to enable the TLS of the Virtual Media.
+ enable_vmedia_tls: true
+
+ # whether to enable basic auth
+ enable_basicAuth: true
+
+ auth:
+ ironicUsername: ""
+ ironicPassword: ""
+ ironicInspectorUsername: ""
+ ironicInspectorPassword: ""
+
+ # whether to have additional trusted CA
+ # NOTE: If enabled, a secret with name tls-ca-additional should be deployed
+ # The secret should be like this:
+ # data:
+ # ca-additional.crt:
+ additionalTrustedCAs: false
+
+ # Will be used when tls is enabled
+ vmediaTLSPort: 6185
+
+ # IP address of the router associated with the specified DHCP
+ # address range
+ dnsmasqDefaultRouter: ""
+
+ # IP address of the dns server to be provided with DHCP
+ # response
+ dnsmasqDNSServer: ""
+
+ # specify comma-delimited range of IP addresses the DHCP server will manage.
+ # e.g 192.168.20.20,192.168.20.80
+ dhcpRange: ""
+
+ # Network interface on which provisioning network can be accessed
+ provisioningInterface: ""
+
+ # IP Address assigned to network interface on provisioning network
+ provisioningIP: ""
+
+ # Name for the MariaDB service
+ databaseServiceName: metal3-mariadb
+
+ # In a multi-node cluster use the node selector to ensure the pods
+ # all run on the same host where the dnsmasqDNSServer and provisioningIP
+ # and /opt/media exist. Uncomment the nodeSelector and update the
+ # hostname accordingly.
+ #nodeSelector:
+ #kubernetes.io/hostname: "csrancher-n1"
+
+#
+# media service
+#
+
+# Override any settings for the metal3 media service here
+metal3-media:
+ # location where media files should be placed so that they are
+ # available to the Ironic deployment services.
+ mediaVolume:
+ hostPath: /opt/media
+ image:
+ repository: "%%IMG_REPO%%/%%IMG_PREFIX%%ironic"
+
+#
+# ironic service
+#
+
+# Override any settings for the metal3 ironic service here
+# Ensure the storageClass is defined
+metal3-ironic:
+ service:
+ type: LoadBalancer
+ persistence:
+ ironic:
+ # storageClass for the ironic shared volume
+ storageClass: ""
+ images:
+ ironic:
+ repository: "%%IMG_REPO%%/%%IMG_PREFIX%%ironic"
+ ironicIPADownloader:
+ repository: "%%IMG_REPO%%/%%IMG_PREFIX%%ironic-ipa-downloader"
+
+#
+# Database Service
+#
+
+# Override any settings for the metal3 mariadb service here
+metal3-mariadb:
+ # storageClass for the mysql datastore
+ persistence:
+ storageClass: ""
+ image:
+ repository: "registry.suse.com/edge/mariadb"
+ tag: "10.6.15.1"
+
+#
+# Baremetal Operator
+#
+
+# Override any settings for the metal3 baremetal-operator service here
+metal3-baremetal-operator:
+ images:
+ baremetalOperator:
+ repository: "%%IMG_REPO%%/%%IMG_PREFIX%%baremetal-operator"
+ rbacProxy:
+ repository: "%%IMG_REPO%%/%%IMG_PREFIX%%kube-rbac-proxy"
+ tag: "v0.18.0"
+
+
diff --git a/metallb-chart/Chart.yaml b/metallb-chart/Chart.yaml
new file mode 100644
index 0000000..6531cd1
--- /dev/null
+++ b/metallb-chart/Chart.yaml
@@ -0,0 +1,23 @@
+#!BuildTag: %%IMG_PREFIX%%metallb-chart:0.14.9
+#!BuildTag: %%IMG_PREFIX%%metallb-chart:0.14.9-%RELEASE%
+apiVersion: v2
+appVersion: v0.14.3
+dependencies:
+- condition: frrk8s.enabled
+ name: frr-k8s
+ repository: file://./charts/frr-k8s
+ version: 0.0.15
+- condition: crds.enabled
+ name: metallb-crds
+ repository: file://./charts/metallb-crds
+ version: 0.14.8
+description: A network load-balancer implementation for Kubernetes using standard
+ routing protocols
+home: https://metallb.universe.tf
+icon: https://metallb.universe.tf/images/logo/metallb-white.png
+kubeVersion: '>= 1.19.0-0'
+name: metallb
+sources:
+- https://github.com/metallb/metallb
+type: application
+version: 0.14.9
diff --git a/metallb-chart/README.md b/metallb-chart/README.md
new file mode 100644
index 0000000..68692d1
--- /dev/null
+++ b/metallb-chart/README.md
@@ -0,0 +1,169 @@
+# metallb
+
+![Version: 0.14.8](https://img.shields.io/badge/Version-0.14.8-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.14.8](https://img.shields.io/badge/AppVersion-v0.14.8-informational?style=flat-square)
+
+A network load-balancer implementation for Kubernetes using standard routing protocols
+
+**Homepage:**
+
+## Source Code
+
+*
+
+## Requirements
+
+Kubernetes: `>= 1.19.0-0`
+
+| Repository | Name | Version |
+|------------|------|---------|
+| | crds | 0.14.8 |
+| https://metallb.github.io/frr-k8s | frr-k8s | 0.0.14 |
+
+## Values
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| controller.affinity | object | `{}` | |
+| controller.enabled | bool | `true` | |
+| controller.extraContainers | list | `[]` | |
+| controller.image.pullPolicy | string | `nil` | |
+| controller.image.repository | string | `"registry.opensuse.org/isv/suse/edge/metallb/images/metallb-controller"` | |
+| controller.image.tag | string | `nil` | |
+| controller.labels | object | `{}` | |
+| controller.livenessProbe.enabled | bool | `true` | |
+| controller.livenessProbe.failureThreshold | int | `3` | |
+| controller.livenessProbe.initialDelaySeconds | int | `10` | |
+| controller.livenessProbe.periodSeconds | int | `10` | |
+| controller.livenessProbe.successThreshold | int | `1` | |
+| controller.livenessProbe.timeoutSeconds | int | `1` | |
+| controller.logLevel | string | `"info"` | Controller log level. Must be one of: `all`, `debug`, `info`, `warn`, `error` or `none` |
+| controller.nodeSelector | object | `{}` | |
+| controller.podAnnotations | object | `{}` | |
+| controller.priorityClassName | string | `""` | |
+| controller.readinessProbe.enabled | bool | `true` | |
+| controller.readinessProbe.failureThreshold | int | `3` | |
+| controller.readinessProbe.initialDelaySeconds | int | `10` | |
+| controller.readinessProbe.periodSeconds | int | `10` | |
+| controller.readinessProbe.successThreshold | int | `1` | |
+| controller.readinessProbe.timeoutSeconds | int | `1` | |
+| controller.resources | object | `{}` | |
+| controller.runtimeClassName | string | `""` | |
+| controller.securityContext.fsGroup | int | `65534` | |
+| controller.securityContext.runAsNonRoot | bool | `true` | |
+| controller.securityContext.runAsUser | int | `65534` | |
+| controller.serviceAccount.annotations | object | `{}` | |
+| controller.serviceAccount.create | bool | `true` | |
+| controller.serviceAccount.name | string | `""` | |
+| controller.strategy.type | string | `"RollingUpdate"` | |
+| controller.tlsCipherSuites | string | `""` | |
+| controller.tlsMinVersion | string | `"VersionTLS12"` | |
+| controller.tolerations | list | `[]` | |
+| crds.enabled | bool | `true` | |
+| crds.validationFailurePolicy | string | `"Fail"` | |
+| frrk8s.enabled | bool | `false` | |
+| frrk8s.external | bool | `false` | |
+| frrk8s.namespace | string | `""` | |
+| fullnameOverride | string | `""` | |
+| imagePullSecrets | list | `[]` | |
+| loadBalancerClass | string | `""` | |
+| nameOverride | string | `""` | |
+| prometheus.controllerMetricsTLSSecret | string | `""` | |
+| prometheus.metricsPort | int | `7472` | |
+| prometheus.namespace | string | `""` | |
+| prometheus.podMonitor.additionalLabels | object | `{}` | |
+| prometheus.podMonitor.annotations | object | `{}` | |
+| prometheus.podMonitor.enabled | bool | `false` | |
+| prometheus.podMonitor.interval | string | `nil` | |
+| prometheus.podMonitor.jobLabel | string | `"app.kubernetes.io/name"` | |
+| prometheus.podMonitor.metricRelabelings | list | `[]` | |
+| prometheus.podMonitor.relabelings | list | `[]` | |
+| prometheus.prometheusRule.additionalLabels | object | `{}` | |
+| prometheus.prometheusRule.addressPoolExhausted.enabled | bool | `true` | |
+| prometheus.prometheusRule.addressPoolExhausted.labels.severity | string | `"alert"` | |
+| prometheus.prometheusRule.addressPoolUsage.enabled | bool | `true` | |
+| prometheus.prometheusRule.addressPoolUsage.thresholds[0].labels.severity | string | `"warning"` | |
+| prometheus.prometheusRule.addressPoolUsage.thresholds[0].percent | int | `75` | |
+| prometheus.prometheusRule.addressPoolUsage.thresholds[1].labels.severity | string | `"warning"` | |
+| prometheus.prometheusRule.addressPoolUsage.thresholds[1].percent | int | `85` | |
+| prometheus.prometheusRule.addressPoolUsage.thresholds[2].labels.severity | string | `"alert"` | |
+| prometheus.prometheusRule.addressPoolUsage.thresholds[2].percent | int | `95` | |
+| prometheus.prometheusRule.annotations | object | `{}` | |
+| prometheus.prometheusRule.bgpSessionDown.enabled | bool | `true` | |
+| prometheus.prometheusRule.bgpSessionDown.labels.severity | string | `"alert"` | |
+| prometheus.prometheusRule.configNotLoaded.enabled | bool | `true` | |
+| prometheus.prometheusRule.configNotLoaded.labels.severity | string | `"warning"` | |
+| prometheus.prometheusRule.enabled | bool | `false` | |
+| prometheus.prometheusRule.extraAlerts | list | `[]` | |
+| prometheus.prometheusRule.staleConfig.enabled | bool | `true` | |
+| prometheus.prometheusRule.staleConfig.labels.severity | string | `"warning"` | |
+| prometheus.rbacPrometheus | bool | `true` | |
+| prometheus.rbacProxy.pullPolicy | string | `nil` | |
+| prometheus.rbacProxy.repository | string | `"registry.opensuse.org/isv/suse/edge/metallb/images/kube-rbac-proxy"` | |
+| prometheus.rbacProxy.tag | string | `"v0.12.0"` | |
+| prometheus.scrapeAnnotations | bool | `false` | |
+| prometheus.serviceAccount | string | `""` | |
+| prometheus.serviceMonitor.controller.additionalLabels | object | `{}` | |
+| prometheus.serviceMonitor.controller.annotations | object | `{}` | |
+| prometheus.serviceMonitor.controller.tlsConfig.insecureSkipVerify | bool | `true` | |
+| prometheus.serviceMonitor.enabled | bool | `false` | |
+| prometheus.serviceMonitor.interval | string | `nil` | |
+| prometheus.serviceMonitor.jobLabel | string | `"app.kubernetes.io/name"` | |
+| prometheus.serviceMonitor.metricRelabelings | list | `[]` | |
+| prometheus.serviceMonitor.relabelings | list | `[]` | |
+| prometheus.serviceMonitor.speaker.additionalLabels | object | `{}` | |
+| prometheus.serviceMonitor.speaker.annotations | object | `{}` | |
+| prometheus.serviceMonitor.speaker.tlsConfig.insecureSkipVerify | bool | `true` | |
+| prometheus.speakerMetricsTLSSecret | string | `""` | |
+| rbac.create | bool | `true` | |
+| speaker.affinity | object | `{}` | |
+| speaker.enabled | bool | `true` | |
+| speaker.excludeInterfaces.enabled | bool | `true` | |
+| speaker.extraContainers | list | `[]` | |
+| speaker.frr.enabled | bool | `true` | |
+| speaker.frr.image.pullPolicy | string | `nil` | |
+| speaker.frr.image.repository | string | `"registry.opensuse.org/isv/suse/edge/metallb/images/frr"` | |
+| speaker.frr.image.tag | string | `"8.4.2"` | |
+| speaker.frr.metricsPort | int | `7473` | |
+| speaker.frr.resources | object | `{}` | |
+| speaker.frrMetrics.resources | object | `{}` | |
+| speaker.ignoreExcludeLB | bool | `false` | |
+| speaker.image.pullPolicy | string | `nil` | |
+| speaker.image.repository | string | `"registry.opensuse.org/isv/suse/edge/metallb/images/metallb-speaker"` | |
+| speaker.image.tag | string | `nil` | |
+| speaker.labels | object | `{}` | |
+| speaker.livenessProbe.enabled | bool | `true` | |
+| speaker.livenessProbe.failureThreshold | int | `3` | |
+| speaker.livenessProbe.initialDelaySeconds | int | `10` | |
+| speaker.livenessProbe.periodSeconds | int | `10` | |
+| speaker.livenessProbe.successThreshold | int | `1` | |
+| speaker.livenessProbe.timeoutSeconds | int | `1` | |
+| speaker.logLevel | string | `"info"` | Speaker log level. Must be one of: `all`, `debug`, `info`, `warn`, `error` or `none` |
+| speaker.memberlist.enabled | bool | `true` | |
+| speaker.memberlist.mlBindAddrOverride | string | `""` | |
+| speaker.memberlist.mlBindPort | int | `7946` | |
+| speaker.memberlist.mlSecretKeyPath | string | `"/etc/ml_secret_key"` | |
+| speaker.nodeSelector | object | `{}` | |
+| speaker.podAnnotations | object | `{}` | |
+| speaker.priorityClassName | string | `""` | |
+| speaker.readinessProbe.enabled | bool | `true` | |
+| speaker.readinessProbe.failureThreshold | int | `3` | |
+| speaker.readinessProbe.initialDelaySeconds | int | `10` | |
+| speaker.readinessProbe.periodSeconds | int | `10` | |
+| speaker.readinessProbe.successThreshold | int | `1` | |
+| speaker.readinessProbe.timeoutSeconds | int | `1` | |
+| speaker.reloader.resources | object | `{}` | |
+| speaker.resources | object | `{}` | |
+| speaker.runtimeClassName | string | `""` | |
+| speaker.securityContext | object | `{}` | |
+| speaker.serviceAccount.annotations | object | `{}` | |
+| speaker.serviceAccount.create | bool | `true` | |
+| speaker.serviceAccount.name | string | `""` | |
+| speaker.startupProbe.enabled | bool | `true` | |
+| speaker.startupProbe.failureThreshold | int | `30` | |
+| speaker.startupProbe.periodSeconds | int | `5` | |
+| speaker.tolerateMaster | bool | `true` | |
+| speaker.tolerations | list | `[]` | |
+| speaker.updateStrategy.type | string | `"RollingUpdate"` | |
+
+----------------------------------------------
+Autogenerated from chart metadata using [helm-docs v1.10.0](https://github.com/norwoodj/helm-docs/releases/v1.10.0)
diff --git a/metallb-chart/_service b/metallb-chart/_service
new file mode 100644
index 0000000..c3f6878
--- /dev/null
+++ b/metallb-chart/_service
@@ -0,0 +1,15 @@
+
+
+
+ values.yaml
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+
+ Chart.yaml
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+
+
diff --git a/metallb-chart/charts/frr-k8s/Chart.yaml b/metallb-chart/charts/frr-k8s/Chart.yaml
new file mode 100644
index 0000000..2fa4501
--- /dev/null
+++ b/metallb-chart/charts/frr-k8s/Chart.yaml
@@ -0,0 +1,11 @@
+apiVersion: v2
+appVersion: v0.0.14
+description: A cloud native wrapper of FRR
+home: https://metallb.universe.tf
+icon: https://metallb.universe.tf/images/logo/metallb-white.png
+kubeVersion: '>= 1.19.0-0'
+name: frr-k8s
+sources:
+- https://github.com/metallb/frr-k8s
+type: application
+version: 0.0.15
diff --git a/metallb-chart/charts/frr-k8s/README.md b/metallb-chart/charts/frr-k8s/README.md
new file mode 100644
index 0000000..0418d64
--- /dev/null
+++ b/metallb-chart/charts/frr-k8s/README.md
@@ -0,0 +1,96 @@
+# frr-k8s
+
+![Version: 0.0.14](https://img.shields.io/badge/Version-0.0.14-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.0.14](https://img.shields.io/badge/AppVersion-v0.0.14-informational?style=flat-square)
+
+A cloud native wrapper of FRR
+
+**Homepage:**
+
+## Source Code
+
+*
+
+## Requirements
+
+Kubernetes: `>= 1.19.0-0`
+
+| Repository | Name | Version |
+|------------|------|---------|
+| | crds | 0.0.14 |
+
+## Values
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| crds.enabled | bool | `true` | |
+| crds.validationFailurePolicy | string | `"Fail"` | |
+| frrk8s.affinity | object | `{}` | |
+| frrk8s.alwaysBlock | string | `""` | |
+| frrk8s.disableCertRotation | bool | `false` | |
+| frrk8s.frr.image.pullPolicy | string | `nil` | |
+| frrk8s.frr.image.repository | string | `"quay.io/frrouting/frr"` | |
+| frrk8s.frr.image.tag | string | `"9.1.0"` | |
+| frrk8s.frr.metricsBindAddress | string | `"127.0.0.1"` | |
+| frrk8s.frr.metricsPort | int | `7573` | |
+| frrk8s.frr.resources | object | `{}` | |
+| frrk8s.frr.secureMetricsPort | int | `9141` | |
+| frrk8s.frrMetrics.resources | object | `{}` | |
+| frrk8s.healthPort | int | `8081` | |
+| frrk8s.image.pullPolicy | string | `nil` | |
+| frrk8s.image.repository | string | `"quay.io/metallb/frr-k8s"` | |
+| frrk8s.image.tag | string | `nil` | |
+| frrk8s.labels.app | string | `"frr-k8s"` | |
+| frrk8s.livenessProbe.enabled | bool | `true` | |
+| frrk8s.livenessProbe.failureThreshold | int | `3` | |
+| frrk8s.livenessProbe.initialDelaySeconds | int | `10` | |
+| frrk8s.livenessProbe.periodSeconds | int | `10` | |
+| frrk8s.livenessProbe.successThreshold | int | `1` | |
+| frrk8s.livenessProbe.timeoutSeconds | int | `1` | |
+| frrk8s.logLevel | string | `"info"` | Controller log level. Must be one of: `all`, `debug`, `info`, `warn`, `error` or `none` |
+| frrk8s.nodeSelector | object | `{}` | |
+| frrk8s.podAnnotations | object | `{}` | |
+| frrk8s.priorityClassName | string | `""` | |
+| frrk8s.readinessProbe.enabled | bool | `true` | |
+| frrk8s.readinessProbe.failureThreshold | int | `3` | |
+| frrk8s.readinessProbe.initialDelaySeconds | int | `10` | |
+| frrk8s.readinessProbe.periodSeconds | int | `10` | |
+| frrk8s.readinessProbe.successThreshold | int | `1` | |
+| frrk8s.readinessProbe.timeoutSeconds | int | `1` | |
+| frrk8s.reloader.resources | object | `{}` | |
+| frrk8s.resources | object | `{}` | |
+| frrk8s.restartOnRotatorSecretRefresh | bool | `false` | |
+| frrk8s.runtimeClassName | string | `""` | |
+| frrk8s.serviceAccount.annotations | object | `{}` | |
+| frrk8s.serviceAccount.create | bool | `true` | |
+| frrk8s.serviceAccount.name | string | `""` | |
+| frrk8s.startupProbe.enabled | bool | `true` | |
+| frrk8s.startupProbe.failureThreshold | int | `30` | |
+| frrk8s.startupProbe.periodSeconds | int | `5` | |
+| frrk8s.tolerateMaster | bool | `true` | |
+| frrk8s.tolerations | list | `[]` | |
+| frrk8s.updateStrategy.type | string | `"RollingUpdate"` | |
+| fullnameOverride | string | `""` | |
+| nameOverride | string | `""` | |
+| prometheus.metricsBindAddress | string | `"127.0.0.1"` | |
+| prometheus.metricsPort | int | `7572` | |
+| prometheus.metricsTLSSecret | string | `""` | |
+| prometheus.namespace | string | `""` | |
+| prometheus.rbacPrometheus | bool | `false` | |
+| prometheus.rbacProxy.pullPolicy | string | `nil` | |
+| prometheus.rbacProxy.repository | string | `"gcr.io/kubebuilder/kube-rbac-proxy"` | |
+| prometheus.rbacProxy.tag | string | `"v0.12.0"` | |
+| prometheus.scrapeAnnotations | bool | `false` | |
+| prometheus.secureMetricsPort | int | `9140` | |
+| prometheus.serviceAccount | string | `""` | |
+| prometheus.serviceMonitor.additionalLabels | object | `{}` | |
+| prometheus.serviceMonitor.annotations | object | `{}` | |
+| prometheus.serviceMonitor.enabled | bool | `false` | |
+| prometheus.serviceMonitor.interval | string | `nil` | |
+| prometheus.serviceMonitor.jobLabel | string | `"app.kubernetes.io/name"` | |
+| prometheus.serviceMonitor.metricRelabelings | list | `[]` | |
+| prometheus.serviceMonitor.relabelings | list | `[]` | |
+| prometheus.serviceMonitor.tlsConfig.insecureSkipVerify | bool | `true` | |
+| rbac.create | bool | `true` | |
+
+----------------------------------------------
+Autogenerated from chart metadata using [helm-docs v1.10.0](https://github.com/norwoodj/helm-docs/releases/v1.10.0)
diff --git a/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrconfigurations.yaml b/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrconfigurations.yaml
new file mode 100644
index 0000000..2813767
--- /dev/null
+++ b/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrconfigurations.yaml
@@ -0,0 +1,462 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: frrconfigurations.frrk8s.metallb.io
+spec:
+ group: frrk8s.metallb.io
+ names:
+ kind: FRRConfiguration
+ listKind: FRRConfigurationList
+ plural: frrconfigurations
+ singular: frrconfiguration
+ scope: Namespaced
+ versions:
+ - name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: FRRConfiguration is a piece of FRR configuration.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: FRRConfigurationSpec defines the desired state of FRRConfiguration.
+ properties:
+ bgp:
+ description: BGP is the configuration related to the BGP protocol.
+ properties:
+ bfdProfiles:
+ description: BFDProfiles is the list of bfd profiles to be used
+ when configuring the neighbors.
+ items:
+ description: |-
+ BFDProfile is the configuration related to the BFD protocol associated
+ to a BGP session.
+ properties:
+ detectMultiplier:
+ description: |-
+ Configures the detection multiplier to determine
+ packet loss. The remote transmission interval will be multiplied
+ by this value to determine the connection loss detection timer.
+ format: int32
+ maximum: 255
+ minimum: 2
+ type: integer
+ echoInterval:
+ description: |-
+ Configures the minimal echo receive transmission
+ interval that this system is capable of handling in milliseconds.
+ Defaults to 50ms
+ format: int32
+ maximum: 60000
+ minimum: 10
+ type: integer
+ echoMode:
+ description: |-
+ Enables or disables the echo transmission mode.
+ This mode is disabled by default, and not supported on multi
+ hops setups.
+ type: boolean
+ minimumTtl:
+ description: |-
+ For multi hop sessions only: configure the minimum
+ expected TTL for an incoming BFD control packet.
+ format: int32
+ maximum: 254
+ minimum: 1
+ type: integer
+ name:
+ description: |-
+ The name of the BFD Profile to be referenced in other parts
+ of the configuration.
+ type: string
+ passiveMode:
+ description: |-
+ Mark session as passive: a passive session will not
+ attempt to start the connection and will wait for control packets
+ from peer before it begins replying.
+ type: boolean
+ receiveInterval:
+ description: |-
+ The minimum interval that this system is capable of
+ receiving control packets in milliseconds.
+ Defaults to 300ms.
+ format: int32
+ maximum: 60000
+ minimum: 10
+ type: integer
+ transmitInterval:
+ description: |-
+ The minimum transmission interval (less jitter)
+ that this system wants to use to send BFD control packets in
+ milliseconds. Defaults to 300ms
+ format: int32
+ maximum: 60000
+ minimum: 10
+ type: integer
+ required:
+ - name
+ type: object
+ type: array
+ routers:
+ description: Routers is the list of routers we want FRR to configure
+ (one per VRF).
+ items:
+ description: Router represent a neighbor router we want FRR
+ to connect to.
+ properties:
+ asn:
+ description: ASN is the AS number to use for the local end
+ of the session.
+ format: int32
+ maximum: 4294967295
+ minimum: 0
+ type: integer
+ id:
+ description: ID is the BGP router ID
+ type: string
+ imports:
+ description: Imports is the list of imported VRFs we want
+ for this router / vrf.
+ items:
+ description: Import represents the possible imported VRFs
+ to a given router.
+ properties:
+ vrf:
+ description: Vrf is the vrf we want to import from
+ type: string
+ type: object
+ type: array
+ neighbors:
+ description: Neighbors is the list of neighbors we want
+ to establish BGP sessions with.
+ items:
+ description: Neighbor represents a BGP Neighbor we want
+ FRR to connect to.
+ properties:
+ address:
+ description: Address is the IP address to establish
+ the session with.
+ type: string
+ asn:
+ description: ASN is the AS number to use for the local
+ end of the session.
+ format: int32
+ maximum: 4294967295
+ minimum: 0
+ type: integer
+ bfdProfile:
+ description: |-
+ BFDProfile is the name of the BFD Profile to be used for the BFD session associated
+ to the BGP session. If not set, the BFD session won't be set up.
+ type: string
+ connectTime:
+ description: Requested BGP connect time, controls
+ how long BGP waits between connection attempts to
+ a neighbor.
+ type: string
+ x-kubernetes-validations:
+ - message: connect time should be between 1 seconds
+ to 65535
+ rule: duration(self).getSeconds() >= 1 && duration(self).getSeconds()
+ <= 65535
+ - message: connect time should contain a whole number
+ of seconds
+ rule: duration(self).getMilliseconds() % 1000 ==
+ 0
+ disableMP:
+ default: false
+ description: To set if we want to disable MP BGP that
+ will separate IPv4 and IPv6 route exchanges into
+ distinct BGP sessions.
+ type: boolean
+ ebgpMultiHop:
+ description: EBGPMultiHop indicates if the BGPPeer
+ is multi-hops away.
+ type: boolean
+ enableGracefulRestart:
+ description: |-
+ EnableGracefulRestart allows BGP peer to continue to forward data packets along
+ known routes while the routing protocol information is being restored. If
+ the session is already established, the configuration will have effect
+ after reconnecting to the peer
+ type: boolean
+ holdTime:
+ description: |-
+ HoldTime is the requested BGP hold time, per RFC4271.
+ Defaults to 180s.
+ type: string
+ keepaliveTime:
+ description: |-
+ KeepaliveTime is the requested BGP keepalive time, per RFC4271.
+ Defaults to 60s.
+ type: string
+ password:
+ description: |-
+ Password to be used for establishing the BGP session.
+ Password and PasswordSecret are mutually exclusive.
+ type: string
+ passwordSecret:
+ description: |-
+ PasswordSecret is name of the authentication secret for the neighbor.
+ the secret must be of type "kubernetes.io/basic-auth", and created in the
+ same namespace as the frr-k8s daemon. The password is stored in the
+ secret as the key "password".
+ Password and PasswordSecret are mutually exclusive.
+ properties:
+ name:
+ description: name is unique within a namespace
+ to reference a secret resource.
+ type: string
+ namespace:
+ description: namespace defines the space within
+ which the secret name must be unique.
+ type: string
+ type: object
+ x-kubernetes-map-type: atomic
+ port:
+ description: |-
+ Port is the port to dial when establishing the session.
+ Defaults to 179.
+ maximum: 16384
+ minimum: 0
+ type: integer
+ sourceaddress:
+ description: |-
+ SourceAddress is the IPv4 or IPv6 source address to use for the BGP
+ session to this neighbour, may be specified as either an IP address
+ directly or as an interface name
+ type: string
+ toAdvertise:
+ description: |-
+ ToAdvertise represents the list of prefixes to advertise to the given neighbor
+ and the associated properties.
+ properties:
+ allowed:
+ description: |-
+ Allowed is is the list of prefixes allowed to be propagated to
+ this neighbor. They must match the prefixes defined in the router.
+ properties:
+ mode:
+ default: filtered
+ description: |-
+ Mode is the mode to use when handling the prefixes.
+ When set to "filtered", only the prefixes in the given list will be allowed.
+ When set to "all", all the prefixes configured on the router will be allowed.
+ enum:
+ - all
+ - filtered
+ type: string
+ prefixes:
+ items:
+ type: string
+ type: array
+ type: object
+ withCommunity:
+ description: |-
+ PrefixesWithCommunity is a list of prefixes that are associated to a
+ bgp community when being advertised. The prefixes associated to a given local pref
+ must be in the prefixes allowed to be advertised.
+ items:
+ description: CommunityPrefixes is a list of
+ prefixes associated to a community.
+ properties:
+ community:
+ description: Community is the community
+ associated to the prefixes.
+ type: string
+ prefixes:
+ description: Prefixes is the list of prefixes
+ associated to the community.
+ format: cidr
+ items:
+ type: string
+ minItems: 1
+ type: array
+ type: object
+ type: array
+ withLocalPref:
+ description: |-
+ PrefixesWithLocalPref is a list of prefixes that are associated to a local
+ preference when being advertised. The prefixes associated to a given local pref
+ must be in the prefixes allowed to be advertised.
+ items:
+ description: LocalPrefPrefixes is a list of
+ prefixes associated to a local preference.
+ properties:
+ localPref:
+ description: LocalPref is the local preference
+ associated to the prefixes.
+ format: int32
+ type: integer
+ prefixes:
+ description: Prefixes is the list of prefixes
+ associated to the local preference.
+ format: cidr
+ items:
+ type: string
+ minItems: 1
+ type: array
+ type: object
+ type: array
+ type: object
+ toReceive:
+ description: ToReceive represents the list of prefixes
+ to receive from the given neighbor.
+ properties:
+ allowed:
+ description: |-
+ Allowed is the list of prefixes allowed to be received from
+ this neighbor.
+ properties:
+ mode:
+ default: filtered
+ description: |-
+ Mode is the mode to use when handling the prefixes.
+ When set to "filtered", only the prefixes in the given list will be allowed.
+ When set to "all", all the prefixes configured on the router will be allowed.
+ enum:
+ - all
+ - filtered
+ type: string
+ prefixes:
+ items:
+ description: PrefixSelector is a filter
+ of prefixes to receive.
+ properties:
+ ge:
+ description: |-
+ The prefix length modifier. This selector accepts any matching prefix with length
+ greater or equal the given value.
+ format: int32
+ maximum: 128
+ minimum: 1
+ type: integer
+ le:
+ description: |-
+ The prefix length modifier. This selector accepts any matching prefix with length
+ less or equal the given value.
+ format: int32
+ maximum: 128
+ minimum: 1
+ type: integer
+ prefix:
+ format: cidr
+ type: string
+ type: object
+ type: array
+ type: object
+ type: object
+ required:
+ - address
+ - asn
+ type: object
+ type: array
+ prefixes:
+ description: Prefixes is the list of prefixes we want to
+ advertise from this router instance.
+ items:
+ type: string
+ type: array
+ vrf:
+ description: VRF is the host vrf used to establish sessions
+ from this router.
+ type: string
+ required:
+ - asn
+ type: object
+ type: array
+ type: object
+ nodeSelector:
+ description: |-
+ NodeSelector limits the nodes that will attempt to apply this config.
+ When specified, the configuration will be considered only on nodes
+ whose labels match the specified selectors.
+ When it is not specified all nodes will attempt to apply this config.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label selector requirements.
+ The requirements are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the selector applies
+ to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ raw:
+ description: |-
+ Raw is a snippet of raw frr configuration that gets appended to the
+ one rendered translating the type safe API.
+ properties:
+ priority:
+ description: |-
+ Priority is the order with this configuration is appended to the
+ bottom of the rendered configuration. A higher value means the
+ raw config is appended later in the configuration file.
+ type: integer
+ rawConfig:
+ description: |-
+ Config is a raw FRR configuration to be appended to the configuration
+ rendered via the k8s api.
+ type: string
+ type: object
+ type: object
+ status:
+ description: FRRConfigurationStatus defines the observed state of FRRConfiguration.
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrnodestates.yaml b/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrnodestates.yaml
new file mode 100644
index 0000000..66f4196
--- /dev/null
+++ b/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrnodestates.yaml
@@ -0,0 +1,65 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: frrnodestates.frrk8s.metallb.io
+spec:
+ group: frrk8s.metallb.io
+ names:
+ kind: FRRNodeState
+ listKind: FRRNodeStateList
+ plural: frrnodestates
+ singular: frrnodestate
+ scope: Cluster
+ versions:
+ - name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: FRRNodeState exposes the status of the FRR instance running on
+ each node.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: FRRNodeStateSpec defines the desired state of FRRNodeState.
+ type: object
+ status:
+ description: FRRNodeStateStatus defines the observed state of FRRNodeState.
+ properties:
+ lastConversionResult:
+ description: LastConversionResult is the status of the last translation
+ between the `FRRConfiguration`s resources and FRR's configuration,
+ contains "success" or an error.
+ type: string
+ lastReloadResult:
+ description: LastReloadResult represents the status of the last configuration
+ update operation by FRR, contains "success" or an error.
+ type: string
+ runningConfig:
+ description: RunningConfig represents the current FRR running config,
+ which is the configuration the FRR instance is currently running
+ with.
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/metallb-chart/charts/frr-k8s/templates/NOTES.txt b/metallb-chart/charts/frr-k8s/templates/NOTES.txt
new file mode 100644
index 0000000..813ab8a
--- /dev/null
+++ b/metallb-chart/charts/frr-k8s/templates/NOTES.txt
@@ -0,0 +1,4 @@
+FRR-k8s is now running in the cluster.
+
+Now you can configure it via its CRs. Please refer to the frr-k8s official docs
+on how to use the CRs.
diff --git a/metallb-chart/charts/frr-k8s/templates/_helpers.tpl b/metallb-chart/charts/frr-k8s/templates/_helpers.tpl
new file mode 100644
index 0000000..8b728d2
--- /dev/null
+++ b/metallb-chart/charts/frr-k8s/templates/_helpers.tpl
@@ -0,0 +1,63 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "frrk8s.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "frrk8s.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "frrk8s.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "frrk8s.labels" -}}
+helm.sh/chart: {{ include "frrk8s.chart" . }}
+{{ include "frrk8s.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "frrk8s.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "frrk8s.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the frrk8s service account to use
+*/}}
+{{- define "frrk8s.serviceAccountName" -}}
+{{- if .Values.frrk8s.serviceAccount.create }}
+{{- default (printf "%s-controller" (include "frrk8s.fullname" .)) .Values.frrk8s.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.frrk8s.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/metallb-chart/charts/frr-k8s/templates/controller.yaml b/metallb-chart/charts/frr-k8s/templates/controller.yaml
new file mode 100644
index 0000000..50badde
--- /dev/null
+++ b/metallb-chart/charts/frr-k8s/templates/controller.yaml
@@ -0,0 +1,431 @@
+# FRR expects to have these files owned by frr:frr on startup.
+# Having them in a ConfigMap allows us to modify behaviors: for example enabling more daemons on startup.
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ template "frrk8s.fullname" . }}-frr-startup
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "frrk8s.labels" . | nindent 4 }}
+ app.kubernetes.io/component: frr-k8s
+data:
+ daemons: |
+ # This file tells the frr package which daemons to start.
+ #
+ # Sample configurations for these daemons can be found in
+ # /usr/share/doc/frr/examples/.
+ #
+ # ATTENTION:
+ #
+ # When activating a daemon for the first time, a config file, even if it is
+ # empty, has to be present *and* be owned by the user and group "frr", else
+ # the daemon will not be started by /etc/init.d/frr. The permissions should
+ # be u=rw,g=r,o=.
+ # When using "vtysh" such a config file is also needed. It should be owned by
+ # group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too.
+ #
+ # The watchfrr and zebra daemons are always started.
+ #
+ bgpd=yes
+ ospfd=no
+ ospf6d=no
+ ripd=no
+ ripngd=no
+ isisd=no
+ pimd=no
+ ldpd=no
+ nhrpd=no
+ eigrpd=no
+ babeld=no
+ sharpd=no
+ pbrd=no
+ bfdd=yes
+ fabricd=no
+ vrrpd=no
+
+ #
+ # If this option is set the /etc/init.d/frr script automatically loads
+ # the config via "vtysh -b" when the servers are started.
+ # Check /etc/pam.d/frr if you intend to use "vtysh"!
+ #
+ vtysh_enable=yes
+ zebra_options=" -A 127.0.0.1 -s 90000000"
+ bgpd_options=" -A 127.0.0.1"
+ ospfd_options=" -A 127.0.0.1"
+ ospf6d_options=" -A ::1"
+ ripd_options=" -A 127.0.0.1"
+ ripngd_options=" -A ::1"
+ isisd_options=" -A 127.0.0.1"
+ pimd_options=" -A 127.0.0.1"
+ ldpd_options=" -A 127.0.0.1"
+ nhrpd_options=" -A 127.0.0.1"
+ eigrpd_options=" -A 127.0.0.1"
+ babeld_options=" -A 127.0.0.1"
+ sharpd_options=" -A 127.0.0.1"
+ pbrd_options=" -A 127.0.0.1"
+ staticd_options="-A 127.0.0.1"
+ bfdd_options=" -A 127.0.0.1"
+ fabricd_options="-A 127.0.0.1"
+ vrrpd_options=" -A 127.0.0.1"
+
+ # configuration profile
+ #
+ #frr_profile="traditional"
+ #frr_profile="datacenter"
+
+ #
+ # This is the maximum number of FD's that will be available.
+ # Upon startup this is read by the control files and ulimit
+ # is called. Uncomment and use a reasonable value for your
+ # setup if you are expecting a large number of peers in
+ # say BGP.
+ #MAX_FDS=1024
+
+ # The list of daemons to watch is automatically generated by the init script.
+ #watchfrr_options=""
+
+ # for debugging purposes, you can specify a "wrap" command to start instead
+ # of starting the daemon directly, e.g. to use valgrind on ospfd:
+ # ospfd_wrap="/usr/bin/valgrind"
+ # or you can use "all_wrap" for all daemons, e.g. to use perf record:
+ # all_wrap="/usr/bin/perf record --call-graph -"
+ # the normal daemon command is added to this at the end.
+ vtysh.conf: |+
+ service integrated-vtysh-config
+ frr.conf: |+
+ ! This file gets overriden the first time the speaker renders a config.
+ ! So anything configured here is only temporary.
+ frr version 8.0
+ frr defaults traditional
+ hostname Router
+ line vty
+ log file /etc/frr/frr.log informational
+---
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+ name: {{ template "frrk8s.fullname" . }}
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "frrk8s.labels" . | nindent 4 }}
+ app.kubernetes.io/component: frr-k8s
+ {{- range $key, $value := .Values.frrk8s.labels }}
+ {{ $key }}: {{ $value | quote }}
+ {{- end }}
+spec:
+ {{- if .Values.frrk8s.updateStrategy }}
+ updateStrategy: {{- toYaml .Values.frrk8s.updateStrategy | nindent 4 }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "frrk8s.selectorLabels" . | nindent 6 }}
+ app.kubernetes.io/component: frr-k8s
+ template:
+ metadata:
+ labels:
+ {{- include "frrk8s.selectorLabels" . | nindent 8 }}
+ app.kubernetes.io/component: frr-k8s
+ {{- range $key, $value := .Values.frrk8s.labels }}
+ {{ $key }}: {{ $value | quote }}
+ {{- end }}
+ spec:
+ {{- if .Values.frrk8s.runtimeClassName }}
+ runtimeClassName: {{ .Values.frrk8s.runtimeClassName }}
+ {{- end }}
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ template "frrk8s.serviceAccountName" . }}
+ terminationGracePeriodSeconds: 0
+ hostNetwork: true
+ volumes:
+ - name: frr-sockets
+ emptyDir: {}
+ - name: frr-startup
+ configMap:
+ name: {{ template "frrk8s.fullname" . }}-frr-startup
+ - name: frr-conf
+ emptyDir: {}
+ - name: reloader
+ emptyDir: {}
+ - name: metrics
+ emptyDir: {}
+ {{- if .Values.prometheus.metricsTLSSecret }}
+ - name: metrics-certs
+ secret:
+ secretName: {{ .Values.prometheus.metricsTLSSecret }}
+ {{- end }}
+ initContainers:
+ # Copies the initial config files with the right permissions to the shared volume.
+ - name: cp-frr-files
+ image: {{ .Values.frrk8s.frr.image.repository }}:{{ .Values.frrk8s.frr.image.tag | default .Chart.AppVersion }}
+ securityContext:
+ runAsUser: 100
+ runAsGroup: 101
+ command: ["/bin/sh", "-c", "cp -rLf /tmp/frr/* /etc/frr/"]
+ volumeMounts:
+ - name: frr-startup
+ mountPath: /tmp/frr
+ - name: frr-conf
+ mountPath: /etc/frr
+ # Copies the reloader to the shared volume between the speaker and reloader.
+ - name: cp-reloader
+ image: {{ .Values.frrk8s.image.repository }}:{{ .Values.frrk8s.image.tag | default .Chart.AppVersion }}
+ command: ["/bin/sh", "-c", "cp -f /frr-reloader.sh /etc/frr_reloader/"]
+ volumeMounts:
+ - name: reloader
+ mountPath: /etc/frr_reloader
+ # Copies the metrics exporter
+ - name: cp-metrics
+ image: {{ .Values.frrk8s.image.repository }}:{{ .Values.frrk8s.image.tag | default .Chart.AppVersion }}
+ command: ["/bin/sh", "-c", "cp -f /frr-metrics /etc/frr_metrics/"]
+ volumeMounts:
+ - name: metrics
+ mountPath: /etc/frr_metrics
+ shareProcessNamespace: true
+ containers:
+ - name: controller
+ image: {{ .Values.frrk8s.image.repository }}:{{ .Values.frrk8s.image.tag | default .Chart.AppVersion }}
+ {{- if .Values.frrk8s.image.pullPolicy }}
+ imagePullPolicy: {{ .Values.frrk8s.image.pullPolicy }}
+ {{- end }}
+ command:
+ - /frr-k8s
+ args:
+ - "--node-name=$(NODE_NAME)"
+ - "--namespace=$(NAMESPACE)"
+ - "--metrics-bind-address={{.Values.prometheus.metricsBindAddress}}:{{ .Values.prometheus.metricsPort }}"
+ {{- with .Values.frrk8s.logLevel }}
+ - --log-level={{ . }}
+ {{- end }}
+ - --health-probe-bind-address={{.Values.prometheus.metricsBindAddress}}:{{ .Values.frrk8s.healthPort }}
+ {{- if .Values.frrk8s.alwaysBlock }}
+ - --always-block={{ .Values.frrk8s.alwaysBlock }}
+ {{- end }}
+ env:
+ - name: FRR_CONFIG_FILE
+ value: /etc/frr_reloader/frr.conf
+ - name: FRR_RELOADER_PID_FILE
+ value: /etc/frr_reloader/reloader.pid
+ - name: NODE_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: spec.nodeName
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ ports:
+ - containerPort: {{ .Values.prometheus.metricsPort }}
+ name: monitoring
+ {{- if .Values.frrk8s.livenessProbe.enabled }}
+ livenessProbe:
+ httpGet:
+ path: /healthz
+ port: {{ .Values.frrk8s.healthPort }}
+ host: {{ .Values.prometheus.metricsBindAddress }}
+ initialDelaySeconds: {{ .Values.frrk8s.livenessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.frrk8s.livenessProbe.periodSeconds }}
+ timeoutSeconds: {{ .Values.frrk8s.livenessProbe.timeoutSeconds }}
+ successThreshold: {{ .Values.frrk8s.livenessProbe.successThreshold }}
+ failureThreshold: {{ .Values.frrk8s.livenessProbe.failureThreshold }}
+ {{- end }}
+ {{- if .Values.frrk8s.readinessProbe.enabled }}
+ readinessProbe:
+ httpGet:
+ path: /healthz
+ port: {{ .Values.frrk8s.healthPort }}
+ host: {{ .Values.prometheus.metricsBindAddress }}
+ initialDelaySeconds: {{ .Values.frrk8s.readinessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.frrk8s.readinessProbe.periodSeconds }}
+ timeoutSeconds: {{ .Values.frrk8s.readinessProbe.timeoutSeconds }}
+ successThreshold: {{ .Values.frrk8s.readinessProbe.successThreshold }}
+ failureThreshold: {{ .Values.frrk8s.readinessProbe.failureThreshold }}
+ {{- end }}
+ {{- with .Values.frrk8s.resources }}
+ resources:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ securityContext:
+ allowPrivilegeEscalation: false
+ readOnlyRootFilesystem: true
+ capabilities:
+ drop:
+ - ALL
+ add:
+ - NET_RAW
+ volumeMounts:
+ - name: reloader
+ mountPath: /etc/frr_reloader
+ - name: frr
+ securityContext:
+ capabilities:
+ add:
+ - NET_ADMIN
+ - NET_RAW
+ - SYS_ADMIN
+ - NET_BIND_SERVICE
+ image: {{ .Values.frrk8s.frr.image.repository }}:{{ .Values.frrk8s.frr.image.tag | default .Chart.AppVersion }}
+ {{- if .Values.frrk8s.frr.image.pullPolicy }}
+ imagePullPolicy: {{ .Values.frrk8s.frr.image.pullPolicy }}
+ {{- end }}
+ env:
+ - name: TINI_SUBREAPER
+ value: "true"
+ volumeMounts:
+ - name: frr-sockets
+ mountPath: /var/run/frr
+ - name: frr-conf
+ mountPath: /etc/frr
+ # The command is FRR's default entrypoint & waiting for the log file to appear and tailing it.
+ # If the log file isn't created in 60 seconds the tail fails and the container is restarted.
+ # This workaround is needed to have the frr logs as part of kubectl logs -c frr < controller_pod_name >.
+ command:
+ - /bin/sh
+ - -c
+ - |
+ /sbin/tini -- /usr/lib/frr/docker-start &
+ attempts=0
+ until [[ -f /etc/frr/frr.log || $attempts -eq 60 ]]; do
+ sleep 1
+ attempts=$(( $attempts + 1 ))
+ done
+ tail -f /etc/frr/frr.log
+ {{- with .Values.frrk8s.frr.resources }}
+ resources:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ {{- if .Values.frrk8s.livenessProbe.enabled }}
+ livenessProbe:
+ httpGet:
+ path: /livez
+ port: {{ .Values.frrk8s.frr.metricsPort }}
+ host: {{ .Values.frrk8s.frr.metricsBindAddress }}
+ periodSeconds: {{ .Values.frrk8s.livenessProbe.periodSeconds }}
+ failureThreshold: {{ .Values.frrk8s.livenessProbe.failureThreshold }}
+ {{- end }}
+ {{- if .Values.frrk8s.startupProbe.enabled }}
+ startupProbe:
+ httpGet:
+ path: /livez
+ port: {{ .Values.frrk8s.frr.metricsPort }}
+ host: {{ .Values.frrk8s.frr.metricsBindAddress }}
+ failureThreshold: {{ .Values.frrk8s.startupProbe.failureThreshold }}
+ periodSeconds: {{ .Values.frrk8s.startupProbe.periodSeconds }}
+ {{- end }}
+ - name: reloader
+ image: {{ .Values.frrk8s.frr.image.repository }}:{{ .Values.frrk8s.frr.image.tag | default .Chart.AppVersion }}
+ {{- if .Values.frrk8s.frr.image.pullPolicy }}
+ imagePullPolicy: {{ .Values.frrk8s.frr.image.pullPolicy }}
+ {{- end }}
+ command: ["/etc/frr_reloader/frr-reloader.sh"]
+ volumeMounts:
+ - name: frr-sockets
+ mountPath: /var/run/frr
+ - name: frr-conf
+ mountPath: /etc/frr
+ - name: reloader
+ mountPath: /etc/frr_reloader
+ {{- with .Values.frrk8s.reloader.resources }}
+ resources:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ - name: frr-metrics
+ image: {{ .Values.frrk8s.frr.image.repository }}:{{ .Values.frrk8s.frr.image.tag | default .Chart.AppVersion }}
+ command: ["/etc/frr_metrics/frr-metrics"]
+ args:
+ - --metrics-port={{ .Values.frrk8s.frr.metricsPort }}
+ - --metrics-bind-address={{ .Values.frrk8s.frr.metricsBindAddress }}
+ ports:
+ - containerPort: {{ .Values.frrk8s.frr.metricsPort }}
+ name: monitoring
+ volumeMounts:
+ - name: frr-sockets
+ mountPath: /var/run/frr
+ - name: frr-conf
+ mountPath: /etc/frr
+ - name: metrics
+ mountPath: /etc/frr_metrics
+ {{- with .Values.frrk8s.frrMetrics.resources }}
+ resources:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ - name: kube-rbac-proxy
+ image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag }}
+ imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }}
+ args:
+ - --logtostderr
+ - --secure-listen-address=:{{ .Values.prometheus.secureMetricsPort }}
+ - --upstream=http://{{.Values.prometheus.metricsBindAddress}}:{{ .Values.prometheus.metricsPort }}/
+ - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ {{- if .Values.prometheus.metricsTLSSecret }}
+ - --tls-private-key-file=/etc/metrics/tls.key
+ - --tls-cert-file=/etc/metrics/tls.crt
+ {{- end }}
+ ports:
+ - containerPort: {{ .Values.prometheus.secureMetricsPort }}
+ name: metricshttps
+ resources:
+ requests:
+ cpu: 10m
+ memory: 20Mi
+ terminationMessagePolicy: FallbackToLogsOnError
+ {{- if .Values.prometheus.metricsTLSSecret }}
+ volumeMounts:
+ - name: metrics-certs
+ mountPath: /etc/metrics
+ readOnly: true
+ {{- end }}
+ - name: kube-rbac-proxy-frr
+ image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag | default .Chart.AppVersion }}
+ imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }}
+ args:
+ - --logtostderr
+ - --secure-listen-address=:{{ .Values.frrk8s.frr.secureMetricsPort }}
+ - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ - --upstream=http://{{ .Values.frrk8s.frr.metricsBindAddress }}:{{ .Values.frrk8s.frr.metricsPort }}/
+ {{- if .Values.prometheus.metricsTLSSecret }}
+ - --tls-private-key-file=/etc/metrics/tls.key
+ - --tls-cert-file=/etc/metrics/tls.crt
+ {{- end }}
+ ports:
+ - containerPort: {{ .Values.frrk8s.frr.secureMetricsPort }}
+ name: metricshttps
+ resources:
+ requests:
+ cpu: 10m
+ memory: 20Mi
+ terminationMessagePolicy: FallbackToLogsOnError
+ {{- if .Values.prometheus.metricsTLSSecret }}
+ volumeMounts:
+ - name: metrics-certs
+ mountPath: /etc/metrics
+ readOnly: true
+ {{- end }}
+ nodeSelector:
+ "kubernetes.io/os": linux
+ {{- with .Values.frrk8s.nodeSelector }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.frrk8s.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- if or .Values.frrk8s.tolerateMaster .Values.frrk8s.tolerations }}
+ tolerations:
+ {{- if .Values.frrk8s.tolerateMaster }}
+ - key: node-role.kubernetes.io/master
+ effect: NoSchedule
+ operator: Exists
+ - key: node-role.kubernetes.io/control-plane
+ effect: NoSchedule
+ operator: Exists
+ {{- end }}
+ {{- with .Values.frrk8s.tolerations }}
+ {{- toYaml . | nindent 6 }}
+ {{- end }}
+ {{- end }}
+ {{- with .Values.frrk8s.priorityClassName }}
+ priorityClassName: {{ . | quote }}
+ {{- end }}
diff --git a/metallb-chart/charts/frr-k8s/templates/rbac.yaml b/metallb-chart/charts/frr-k8s/templates/rbac.yaml
new file mode 100644
index 0000000..5c0b9d6
--- /dev/null
+++ b/metallb-chart/charts/frr-k8s/templates/rbac.yaml
@@ -0,0 +1,73 @@
+{{- if .Values.rbac.create -}}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ include "frrk8s.fullname" . }}-controller
+ labels: {{- include "frrk8s.labels" . | nindent 4 }}
+rules:
+- apiGroups: ["frrk8s.metallb.io"]
+ resources: ["frrconfigurations"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: ["frrk8s.metallb.io"]
+ resources: ["frrnodestates"]
+ verbs: ["get", "list", "watch", "create", "delete", "patch", "update"]
+- apiGroups: ["frrk8s.metallb.io"]
+ resources: ["frrnodestates/status"]
+ verbs: ["get", "patch", "update"]
+- apiGroups: [""]
+ resources: ["nodes"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: ["authentication.k8s.io"]
+ resources: ["tokenreviews"]
+ verbs: ["create"]
+- apiGroups: ["authorization.k8s.io"]
+ resources: ["subjectaccessreviews"]
+ verbs: ["create"]
+- apiGroups: ["admissionregistration.k8s.io"]
+ resources: ["validatingwebhookconfigurations"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: ["admissionregistration.k8s.io"]
+ resourceNames: ["frr-k8s-validating-webhook-configuration"]
+ resources: ["validatingwebhookconfigurations"]
+ verbs: ["update"]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ include "frrk8s.fullname" . }}-controller
+ labels: {{- include "frrk8s.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ include "frrk8s.fullname" . }}-controller
+subjects:
+- kind: ServiceAccount
+ name: {{ include "frrk8s.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace | quote }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ include "frrk8s.fullname" . }}-controller
+ namespace: {{ .Release.Namespace | quote }}
+ labels: {{- include "frrk8s.labels" . | nindent 4 }}
+rules:
+- apiGroups: [""]
+ resources: ["secrets"]
+ verbs: ["get", "list", "watch","update"]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ include "frrk8s.fullname" . }}-controller
+ namespace: {{ .Release.Namespace | quote }}
+ labels: {{- include "frrk8s.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: {{ include "frrk8s.fullname" . }}-controller
+subjects:
+- kind: ServiceAccount
+ name: {{ include "frrk8s.serviceAccountName" . }}
+{{ end -}}
diff --git a/metallb-chart/charts/frr-k8s/templates/service-accounts.yaml b/metallb-chart/charts/frr-k8s/templates/service-accounts.yaml
new file mode 100644
index 0000000..c3d7423
--- /dev/null
+++ b/metallb-chart/charts/frr-k8s/templates/service-accounts.yaml
@@ -0,0 +1,16 @@
+{{- if .Values.frrk8s.serviceAccount.create }}
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ template "frrk8s.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "frrk8s.labels" . | nindent 4 }}
+ app.kubernetes.io/component: controller
+ {{- with .Values.frrk8s.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
+
diff --git a/metallb-chart/charts/frr-k8s/templates/service-monitor.yaml b/metallb-chart/charts/frr-k8s/templates/service-monitor.yaml
new file mode 100644
index 0000000..323c442
--- /dev/null
+++ b/metallb-chart/charts/frr-k8s/templates/service-monitor.yaml
@@ -0,0 +1,128 @@
+{{- if .Values.prometheus.serviceMonitor.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+ name: {{ template "frrk8s.fullname" . }}-frr-k8s-monitor
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "frrk8s.labels" . | nindent 4 }}
+ app.kubernetes.io/component: frr-k8s
+ {{- if .Values.prometheus.serviceMonitor.additionalLabels }}
+{{ toYaml .Values.prometheus.serviceMonitor.additionalLabels | indent 4 }}
+ {{- end }}
+ {{- if .Values.prometheus.serviceMonitor.annotations }}
+ annotations:
+{{ toYaml .Values.prometheus.serviceMonitor.annotations | indent 4 }}
+ {{- end }}
+spec:
+ endpoints:
+ - port: "metricshttps"
+ honorLabels: true
+ {{- if .Values.prometheus.serviceMonitor.metricRelabelings }}
+ metricRelabelings:
+ {{- toYaml .Values.prometheus.serviceMonitor.metricRelabelings | nindent 8 }}
+ {{- end -}}
+ {{- if .Values.prometheus.serviceMonitor.relabelings }}
+ relabelings:
+ {{- toYaml .Values.prometheus.serviceMonitor.relabelings | nindent 8 }}
+ {{- end }}
+ {{- if .Values.prometheus.serviceMonitor.interval }}
+ interval: {{ .Values.prometheus.serviceMonitor.interval }}
+ {{- end -}}
+{{ if .Values.prometheus.secureMetricsPort }}
+ bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token"
+ scheme: "https"
+{{- if .Values.prometheus.serviceMonitor.tlsConfig }}
+ tlsConfig:
+{{ toYaml .Values.prometheus.serviceMonitor.tlsConfig | indent 8 }}
+{{- end }}
+{{ end }}
+{{ if .Values.frrk8s.frr.secureMetricsPort }}
+ - port: "frrmetricshttps"
+ honorLabels: true
+ {{- if .Values.prometheus.serviceMonitor.metricRelabelings }}
+ metricRelabelings:
+ {{- toYaml .Values.prometheus.serviceMonitor.metricRelabelings | nindent 8 }}
+ {{- end -}}
+ {{- if .Values.prometheus.serviceMonitor.relabelings }}
+ relabelings:
+ {{- toYaml .Values.prometheus.serviceMonitor.relabelings | nindent 8 }}
+ {{- end }}
+ {{- if .Values.prometheus.serviceMonitor.interval }}
+ interval: {{ .Values.prometheus.serviceMonitor.interval }}
+ {{- end }}
+ bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token"
+ scheme: "https"
+{{- if .Values.prometheus.serviceMonitor.tlsConfig }}
+ tlsConfig:
+{{ toYaml .Values.prometheus.serviceMonitor.tlsConfig | indent 8 }}
+{{- end }}
+{{- end }}
+ jobLabel: {{ .Values.prometheus.serviceMonitor.jobLabel | quote }}
+ namespaceSelector:
+ matchNames:
+ - {{ .Release.Namespace }}
+ selector:
+ matchLabels:
+ name: {{ template "frrk8s.fullname" . }}-frr-k8s-monitor-service
+---
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ prometheus.io/scrape: "true"
+ {{- if .Values.prometheus.serviceMonitor.annotations }}
+{{ toYaml .Values.prometheus.serviceMonitor.annotations | indent 4 }}
+ {{- end }}
+ labels:
+ name: {{ template "frrk8s.fullname" . }}-frr-k8s-monitor-service
+ name: {{ template "frrk8s.fullname" . }}-frr-k8s-monitor-service
+ namespace: {{ .Release.Namespace | quote }}
+spec:
+ selector:
+ {{- include "frrk8s.selectorLabels" . | nindent 4 }}
+ app.kubernetes.io/component: frr-k8s
+ clusterIP: None
+ ports:
+ - name: "metricshttps"
+ port: {{ .Values.prometheus.secureMetricsPort }}
+ targetPort: {{ .Values.prometheus.secureMetricsPort }}
+ - name: frrmetricshttps
+ port: {{ .Values.frrk8s.frr.secureMetricsPort }}
+ targetPort: {{ .Values.frrk8s.frr.secureMetricsPort }}
+ sessionAffinity: None
+ type: ClusterIP
+---
+{{- if .Values.prometheus.rbacPrometheus }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ template "frrk8s.fullname" . }}-prometheus
+ namespace: {{ .Release.Namespace | quote }}
+rules:
+ - apiGroups:
+ - ""
+ resources:
+ - pods
+ - services
+ - endpoints
+ verbs:
+ - get
+ - list
+ - watch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ template "frrk8s.fullname" . }}-prometheus
+ namespace: {{ .Release.Namespace | quote }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: {{ template "frrk8s.fullname" . }}-prometheus
+subjects:
+ - kind: ServiceAccount
+ name: {{ required ".Values.prometheus.serviceAccount must be defined when .Values.prometheus.serviceMonitor.enabled == true" .Values.prometheus.serviceAccount }}
+ namespace: {{ required ".Values.prometheus.namespace must be defined when .Values.prometheus.serviceMonitor.enabled == true" .Values.prometheus.namespace }}
+{{- end }}
+{{- end }}
diff --git a/metallb-chart/charts/frr-k8s/templates/webhooks.yaml b/metallb-chart/charts/frr-k8s/templates/webhooks.yaml
new file mode 100644
index 0000000..a84b3b6
--- /dev/null
+++ b/metallb-chart/charts/frr-k8s/templates/webhooks.yaml
@@ -0,0 +1,163 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ template "frrk8s.fullname" . }}-webhook-server
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "frrk8s.labels" . | nindent 4 }}
+ app.kubernetes.io/component: frr-k8s-webhook-server
+ {{- range $key, $value := .Values.frrk8s.labels }}
+ {{ $key }}: {{ $value | quote }}
+ {{- end }}
+spec:
+ selector:
+ matchLabels:
+ app.kubernetes.io/component: frr-k8s-webhook-server
+ template:
+ metadata:
+ annotations:
+ kubectl.kubernetes.io/default-container: frr-k8s-webhook-server
+ labels:
+ app.kubernetes.io/component: frr-k8s-webhook-server
+ spec:
+ {{- if .Values.frrk8s.runtimeClassName }}
+ runtimeClassName: {{ .Values.frrk8s.runtimeClassName }}
+ {{- end }}
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- if .Values.podSecurityContext }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ {{- end }}
+ containers:
+ - command:
+ - /frr-k8s
+ args:
+ {{- with .Values.frrk8s.logLevel }}
+ - --log-level={{ . }}
+ {{- end }}
+ - "--webhook-mode=onlywebhook"
+ {{- if .Values.frrk8s.disableCertRotation }}
+ - "--disable-cert-rotation=true"
+ {{- end }}
+ {{- if .Values.frrk8s.restartOnRotatorSecretRefresh }}
+ - "--restart-on-rotator-secret-refresh=true"
+ {{- end }}
+ - "--namespace=$(NAMESPACE)"
+ - --health-probe-bind-address=:8081
+ env:
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ image: {{ .Values.frrk8s.image.repository }}:{{ .Values.frrk8s.image.tag | default .Chart.AppVersion }}
+ {{- if .Values.frrk8s.image.pullPolicy }}
+ imagePullPolicy: {{ .Values.frrk8s.image.pullPolicy }}
+ {{- end }}
+ name: frr-k8s-webhook-server
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
+ readOnlyRootFilesystem: true
+ {{- if .Values.frrk8s.livenessProbe.enabled }}
+ livenessProbe:
+ httpGet:
+ path: /healthz
+ port: 8081
+ initialDelaySeconds: {{ .Values.frrk8s.livenessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.frrk8s.livenessProbe.periodSeconds }}
+ failureThreshold: {{ .Values.frrk8s.livenessProbe.failureThreshold }}
+ {{- end }}
+ {{- if .Values.frrk8s.readinessProbe.enabled }}
+ readinessProbe:
+ httpGet:
+ path: /readyz
+ port: 8081
+ initialDelaySeconds: {{ .Values.frrk8s.readinessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.frrk8s.readinessProbe.periodSeconds }}
+ failureThreshold: {{ .Values.frrk8s.readinessProbe.failureThreshold }}
+ {{- end }}
+ {{- with .Values.frrk8s.resources }}
+ resources:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ volumeMounts:
+ - name: cert
+ mountPath: /tmp/k8s-webhook-server/serving-certs
+ readOnly: true
+ {{- with .Values.frrk8s.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- if or .Values.frrk8s.tolerateMaster .Values.frrk8s.tolerations }}
+ tolerations:
+ {{- if .Values.frrk8s.tolerateMaster }}
+ - key: node-role.kubernetes.io/master
+ effect: NoSchedule
+ operator: Exists
+ - key: node-role.kubernetes.io/control-plane
+ effect: NoSchedule
+ operator: Exists
+ {{- end }}
+ {{- with .Values.frrk8s.tolerations }}
+ {{- toYaml . | nindent 6 }}
+ {{- end }}
+ {{- end }}
+ {{- with .Values.frrk8s.priorityClassName }}
+ priorityClassName: {{ . | quote }}
+ {{- end }}
+ volumes:
+ - name: cert
+ secret:
+ defaultMode: 420
+ secretName: frr-k8s-webhook-server-cert
+ serviceAccountName: {{ template "frrk8s.serviceAccountName" . }}
+ terminationGracePeriodSeconds: 10
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: frr-k8s-webhook-server-cert
+ namespace: {{ .Release.Namespace | quote }}
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: frr-k8s-webhook-service
+ namespace: {{ .Release.Namespace | quote }}
+spec:
+ ports:
+ - port: 443
+ targetPort: 9443
+ selector:
+ app.kubernetes.io/component: frr-k8s-webhook-server
+---
+apiVersion: admissionregistration.k8s.io/v1
+kind: ValidatingWebhookConfiguration
+metadata:
+ name: frr-k8s-validating-webhook-configuration
+webhooks:
+- admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: frr-k8s-webhook-service
+ namespace: {{ .Release.Namespace }}
+ path: /validate-frrk8s-metallb-io-v1beta1-frrconfiguration
+ failurePolicy: {{ .Values.crds.validationFailurePolicy }}
+ name: frrconfigurationsvalidationwebhook.metallb.io
+ rules:
+ - apiGroups:
+ - frrk8s.metallb.io
+ apiVersions:
+ - v1beta1
+ operations:
+ - CREATE
+ - UPDATE
+ resources:
+ - frrconfigurations
+ sideEffects: None
diff --git a/metallb-chart/charts/frr-k8s/values.schema.json b/metallb-chart/charts/frr-k8s/values.schema.json
new file mode 100644
index 0000000..67ec727
--- /dev/null
+++ b/metallb-chart/charts/frr-k8s/values.schema.json
@@ -0,0 +1,387 @@
+{
+ "$schema": "https://json-schema.org/draft-07/schema#",
+ "title": "Values",
+ "type": "object",
+ "definitions": {
+ "prometheusAlert": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "labels": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ }
+ },
+ "required": [
+ "enabled"
+ ]
+ },
+ "probe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ }
+ },
+ "required": [
+ "failureThreshold",
+ "initialDelaySeconds",
+ "periodSeconds",
+ "successThreshold",
+ "timeoutSeconds"
+ ]
+ },
+ "component": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "logLevel": {
+ "type": "string",
+ "enum": [
+ "all",
+ "debug",
+ "info",
+ "warn",
+ "error",
+ "none"
+ ]
+ },
+ "image": {
+ "type": "object",
+ "properties": {
+ "repository": {
+ "type": "string"
+ },
+ "tag": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "pullPolicy": {
+ "anyOf": [
+ {
+ "type": "null"
+ },
+ {
+ "type": "string",
+ "enum": [
+ "Always",
+ "IfNotPresent",
+ "Never"
+ ]
+ }
+ ]
+ }
+ }
+ },
+ "serviceAccount": {
+ "type": "object",
+ "properties": {
+ "create": {
+ "type": "boolean"
+ },
+ "name": {
+ "type": "string"
+ },
+ "annotations": {
+ "type": "object"
+ }
+ }
+ },
+ "resources": {
+ "type": "object"
+ },
+ "nodeSelector": {
+ "type": "object"
+ },
+ "tolerations": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "priorityClassName": {
+ "type": "string"
+ },
+ "runtimeClassName": {
+ "type": "string"
+ },
+ "affinity": {
+ "type": "object"
+ },
+ "podAnnotations": {
+ "type": "object"
+ },
+ "livenessProbe": {
+ "$ref": "#/definitions/probe"
+ },
+ "readinessProbe": {
+ "$ref": "#/definitions/probe"
+ }
+ },
+ "required": [
+ "image",
+ "serviceAccount"
+ ]
+ }
+ },
+ "properties": {
+ "imagePullSecrets": {
+ "description": "Secrets used for pulling images",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "nameOverride": {
+ "description": "Override chart name",
+ "type": "string"
+ },
+ "fullNameOverride": {
+ "description": "Override fully qualified app name",
+ "type": "string"
+ },
+ "rbac": {
+ "description": "RBAC configuration",
+ "type": "object",
+ "properties": {
+ "create": {
+ "description": "Enable RBAC",
+ "type": "boolean"
+ }
+ }
+ },
+ "prometheus": {
+ "description": "Prometheus monitoring config",
+ "type": "object",
+ "properties": {
+ "scrapeAnnotations": {
+ "type": "boolean"
+ },
+ "metricsPort": {
+ "type": "integer"
+ },
+ "secureMetricsPort": {
+ "type": "integer"
+ },
+ "rbacPrometheus": {
+ "type": "boolean"
+ },
+ "serviceAccount": {
+ "type": "string"
+ },
+ "namespace": {
+ "type": "string"
+ },
+ "rbacProxy": {
+ "description": "kube-rbac-proxy configuration",
+ "type": "object",
+ "properties": {
+ "repository": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ }
+ }
+ },
+ "serviceMonitor": {
+ "description": "Prometheus Operator ServiceMonitors",
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "jobLabel": {
+ "type": "string"
+ },
+ "interval": {
+ "anyOf": [
+ {
+ "type": "integer"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "metricRelabelings": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "relabelings": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "frrk8s": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/component"
+ },
+ {
+ "description": "FRR-K8s controller",
+ "type": "object",
+ "properties": {
+ "tolerateMaster": {
+ "type": "boolean"
+ },
+ "updateStrategy": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ]
+ },
+ "runtimeClassName": {
+ "type": "string"
+ },
+ "secretName": {
+ "type": "string"
+ },
+ "frr": {
+ "description": "The FRR properties in the controller",
+ "type": "object",
+ "properties": {
+ "image": {
+ "$ref": "#/definitions/component/properties/image"
+ },
+ "metricsPort": {
+ "type": "integer"
+ },
+ "secureMetricsPort": {
+ "type": "integer"
+ },
+ "resources:": {
+ "type": "object"
+ }
+ },
+ "required": [
+ "enabled"
+ ]
+ },
+ "command": {
+ "type": "string"
+ },
+ "reloader": {
+ "type": "object",
+ "properties": {
+ "resources": {
+ "type": "object"
+ }
+ }
+ },
+ "frrMetrics": {
+ "type": "object",
+ "properties": {
+ "resources": {
+ "type": "object"
+ }
+ }
+ }
+ },
+ "required": [
+ "tolerateMaster"
+ ]
+ }
+ ]
+ },
+ "crds": {
+ "description": "CRD configuration",
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "description": "Enable CRDs",
+ "type": "boolean"
+ },
+ "validationFailurePolicy": {
+ "description": "Failure policy to use with validating webhooks",
+ "type": "string",
+ "enum": [
+ "Ignore",
+ "Fail"
+ ]
+ }
+ }
+ }
+ },
+ "frrk8s": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/component"
+ },
+ {
+ "description": "FRRk8s Controller",
+ "type": "object",
+ "properties": {
+ "strategy": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ]
+ },
+ "command": {
+ "type": "string"
+ },
+ "webhookMode": {
+ "type": "string"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "required": [
+ "frrk8s"
+ ]
+}
\ No newline at end of file
diff --git a/metallb-chart/charts/frr-k8s/values.yaml b/metallb-chart/charts/frr-k8s/values.yaml
new file mode 100644
index 0000000..87731fe
--- /dev/null
+++ b/metallb-chart/charts/frr-k8s/values.yaml
@@ -0,0 +1,176 @@
+# Default values for frr-k8s.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+nameOverride: ""
+fullnameOverride: ""
+
+rbac:
+ # create specifies whether to install and use RBAC rules.
+ create: true
+
+podSecurityContext:
+ seccompProfile:
+ type: RuntimeDefault
+
+prometheus:
+ # scrape annotations specifies whether to add Prometheus metric
+ # auto-collection annotations to pods. See
+ # https://github.com/prometheus/prometheus/blob/release-2.1/documentation/examples/prometheus-kubernetes.yml
+ # for a corresponding Prometheus configuration. Alternatively, you
+ # may want to use the Prometheus Operator
+ # (https://github.com/coreos/prometheus-operator) for more powerful
+ # monitoring configuration. If you use the Prometheus operator, this
+ # can be left at false.
+ scrapeAnnotations: false
+
+ # bind addr frr-k8s will use for metrics
+ metricsBindAddress: 127.0.0.1
+
+ # port frr-k8s will listen on for metrics
+ metricsPort: 7572
+
+ # if set, enables rbac proxy on frr-k8s to expose
+ # the metrics via tls.
+ secureMetricsPort: 9140
+
+ # the name of the secret to be mounted in the frr-k8s pod
+ # to expose the metrics securely. If not present, a self signed
+ # certificate to be used.
+ metricsTLSSecret: ""
+
+ # prometheus doens't have the permission to scrape all namespaces so we give it permission to scrape metallb's one
+ rbacPrometheus: false
+
+ # the service account used by prometheus
+ # required when " .Values.prometheus.rbacPrometheus == true " and " prometheus.serviceMonitor.enabled=true "
+ serviceAccount: ""
+
+ # the namespace where prometheus is deployed
+ # required when " .Values.prometheus.rbacPrometheus == true " and " prometheus.serviceMonitor.enabled=true "
+ namespace: ""
+
+ # the image to be used for the kuberbacproxy container
+ rbacProxy:
+ repository: "registry.opensuse.org/isv/suse/edge/metallb/images/kube-rbac-proxy"
+ tag: "v0.18.0"
+ pullPolicy: IfNotPresent
+
+ # Prometheus Operator ServiceMonitors.
+ serviceMonitor:
+ # enable support for Prometheus Operator
+ enabled: false
+
+ additionalLabels: {}
+ # optional additional annotations for the controller serviceMonitor
+ annotations: {}
+ # optional tls configuration for the controller serviceMonitor, in case
+ # secure metrics are enabled.
+ tlsConfig:
+ insecureSkipVerify: true
+
+ # Job label for scrape target
+ jobLabel: "app.kubernetes.io/name"
+
+ # Scrape interval. If not set, the Prometheus default scrape interval is used.
+ interval:
+
+ # metric relabel configs to apply to samples before ingestion.
+ metricRelabelings: []
+ # - action: keep
+ # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'
+ # sourceLabels: [__name__]
+
+ # relabel configs to apply to samples before ingestion.
+ relabelings: []
+ # - sourceLabels: [__meta_kubernetes_pod_node_name]
+ # separator: ;
+ # regex: ^(.*)$
+ # target_label: nodename
+ # replacement: $1
+ # action: replace
+
+# controller contains configuration specific to the FRRK8s controller
+# daemonset.
+frrk8s:
+ # -- Controller log level. Must be one of: `all`, `debug`, `info`, `warn`, `error` or `none`
+ logLevel: info
+ tolerateMaster: true
+ image:
+ repository: "registry.opensuse.org/isv/suse/edge/metallb/images/frr-k8s"
+ tag: "v0.0.14"
+ pullPolicy: IfNotPresent
+ ## @param controller.updateStrategy.type FRR-K8s controller daemonset strategy type
+ ## ref: https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/
+ ##
+ updateStrategy:
+ ## StrategyType
+ ## Can be set to RollingUpdate or OnDelete
+ ##
+ type: RollingUpdate
+ serviceAccount:
+ # Specifies whether a ServiceAccount should be created
+ create: true
+ # The name of the ServiceAccount to use. If not set and create is
+ # true, a name is generated using the fullname template
+ name: ""
+ annotations: {}
+ ## Defines a secret name for the controller to generate a memberlist encryption secret
+ ## By default secretName: {{ "metallb.fullname" }}-memberlist
+ ##
+ # secretName:
+ resources: {}
+ # limits:
+ # cpu: 100m
+ # memory: 100Mi
+ nodeSelector: {}
+ tolerations: []
+ priorityClassName: ""
+ affinity: {}
+ ## Selects which runtime class will be used by the pod.
+ runtimeClassName: ""
+ podAnnotations: {}
+ labels:
+ app: frr-k8s
+ healthPort: 8081
+ livenessProbe:
+ enabled: true
+ failureThreshold: 3
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 1
+ readinessProbe:
+ enabled: true
+ failureThreshold: 3
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 1
+ startupProbe:
+ enabled: true
+ failureThreshold: 30
+ periodSeconds: 5
+ ## A comma separated list of cidrs we want always to block for incoming routes
+ alwaysBlock: ""
+ ## Specifies whether the cert rotator works as part of the webhook.
+ disableCertRotation: false
+ ## Specifies whether the pod restarts when the rotator refreshes the cert secret.
+ ## Enabling this proved useful for the webhook's stability when it is redeployed multiple times in succession.
+ restartOnRotatorSecretRefresh: false
+ # frr contains configuration specific to the FRR container,
+ frr:
+ image:
+ repository: "registry.opensuse.org/isv/suse/edge/metallb/images/frr"
+ tag: "8.4"
+ pullPolicy: IfNotPresent
+ metricsBindAddress: 127.0.0.1
+ metricsPort: 7573
+ resources: {}
+ secureMetricsPort: 9141
+ reloader:
+ resources: {}
+ frrMetrics:
+ resources: {}
+crds:
+ validationFailurePolicy: Fail
diff --git a/metallb-chart/charts/metallb-crds/.helmignore b/metallb-chart/charts/metallb-crds/.helmignore
new file mode 100644
index 0000000..1b9a9cc
--- /dev/null
+++ b/metallb-chart/charts/metallb-crds/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/metallb-chart/charts/metallb-crds/Chart.yaml b/metallb-chart/charts/metallb-crds/Chart.yaml
new file mode 100644
index 0000000..6d070fc
--- /dev/null
+++ b/metallb-chart/charts/metallb-crds/Chart.yaml
@@ -0,0 +1,10 @@
+apiVersion: v2
+appVersion: v0.14.9
+description: MetalLB CRDs
+home: https://metallb.universe.tf
+icon: https://metallb.universe.tf/images/logo/metallb-white.png
+name: metallb-crds
+sources:
+- https://github.com/metallb/metallb
+type: application
+version: 0.14.8
diff --git a/metallb-chart/charts/metallb-crds/README.md b/metallb-chart/charts/metallb-crds/README.md
new file mode 100644
index 0000000..58cf71b
--- /dev/null
+++ b/metallb-chart/charts/metallb-crds/README.md
@@ -0,0 +1,11 @@
+# crds
+
+![Version: 0.14.3](https://img.shields.io/badge/Version-0.14.3-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.14.3](https://img.shields.io/badge/AppVersion-v0.14.3-informational?style=flat-square)
+
+MetalLB CRDs
+
+**Homepage:**
+
+## Source Code
+
+*
diff --git a/metallb-chart/charts/metallb-crds/templates/crds.yaml b/metallb-chart/charts/metallb-crds/templates/crds.yaml
new file mode 100644
index 0000000..9341bb4
--- /dev/null
+++ b/metallb-chart/charts/metallb-crds/templates/crds.yaml
@@ -0,0 +1,1205 @@
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: bfdprofiles.metallb.io
+spec:
+ group: metallb.io
+ names:
+ kind: BFDProfile
+ listKind: BFDProfileList
+ plural: bfdprofiles
+ singular: bfdprofile
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .spec.passiveMode
+ name: Passive Mode
+ type: boolean
+ - jsonPath: .spec.transmitInterval
+ name: Transmit Interval
+ type: integer
+ - jsonPath: .spec.receiveInterval
+ name: Receive Interval
+ type: integer
+ - jsonPath: .spec.detectMultiplier
+ name: Multiplier
+ type: integer
+ name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: |-
+ BFDProfile represents the settings of the bfd session that can be
+ optionally associated with a BGP session.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: BFDProfileSpec defines the desired state of BFDProfile.
+ properties:
+ detectMultiplier:
+ description: |-
+ Configures the detection multiplier to determine
+ packet loss. The remote transmission interval will be multiplied
+ by this value to determine the connection loss detection timer.
+ format: int32
+ maximum: 255
+ minimum: 2
+ type: integer
+ echoInterval:
+ description: |-
+ Configures the minimal echo receive transmission
+ interval that this system is capable of handling in milliseconds.
+ Defaults to 50ms
+ format: int32
+ maximum: 60000
+ minimum: 10
+ type: integer
+ echoMode:
+ description: |-
+ Enables or disables the echo transmission mode.
+ This mode is disabled by default, and not supported on multi
+ hops setups.
+ type: boolean
+ minimumTtl:
+ description: |-
+ For multi hop sessions only: configure the minimum
+ expected TTL for an incoming BFD control packet.
+ format: int32
+ maximum: 254
+ minimum: 1
+ type: integer
+ passiveMode:
+ description: |-
+ Mark session as passive: a passive session will not
+ attempt to start the connection and will wait for control packets
+ from peer before it begins replying.
+ type: boolean
+ receiveInterval:
+ description: |-
+ The minimum interval that this system is capable of
+ receiving control packets in milliseconds.
+ Defaults to 300ms.
+ format: int32
+ maximum: 60000
+ minimum: 10
+ type: integer
+ transmitInterval:
+ description: |-
+ The minimum transmission interval (less jitter)
+ that this system wants to use to send BFD control packets in
+ milliseconds. Defaults to 300ms
+ format: int32
+ maximum: 60000
+ minimum: 10
+ type: integer
+ type: object
+ status:
+ description: BFDProfileStatus defines the observed state of BFDProfile.
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: bgpadvertisements.metallb.io
+spec:
+ group: metallb.io
+ names:
+ kind: BGPAdvertisement
+ listKind: BGPAdvertisementList
+ plural: bgpadvertisements
+ singular: bgpadvertisement
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .spec.ipAddressPools
+ name: IPAddressPools
+ type: string
+ - jsonPath: .spec.ipAddressPoolSelectors
+ name: IPAddressPool Selectors
+ type: string
+ - jsonPath: .spec.peers
+ name: Peers
+ type: string
+ - jsonPath: .spec.nodeSelectors
+ name: Node Selectors
+ priority: 10
+ type: string
+ name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: |-
+ BGPAdvertisement allows to advertise the IPs coming
+ from the selected IPAddressPools via BGP, setting the parameters of the
+ BGP Advertisement.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: BGPAdvertisementSpec defines the desired state of BGPAdvertisement.
+ properties:
+ aggregationLength:
+ default: 32
+ description: The aggregation-length advertisement option lets you “roll up” the /32s into a larger prefix. Defaults to 32. Works for IPv4 addresses.
+ format: int32
+ minimum: 1
+ type: integer
+ aggregationLengthV6:
+ default: 128
+ description: The aggregation-length advertisement option lets you “roll up” the /128s into a larger prefix. Defaults to 128. Works for IPv6 addresses.
+ format: int32
+ type: integer
+ communities:
+ description: |-
+ The BGP communities to be associated with the announcement. Each item can be a standard community of the
+ form 1234:1234, a large community of the form large:1234:1234:1234 or the name of an alias defined in the
+ Community CRD.
+ items:
+ type: string
+ type: array
+ ipAddressPoolSelectors:
+ description: |-
+ A selector for the IPAddressPools which would get advertised via this advertisement.
+ If no IPAddressPool is selected by this or by the list, the advertisement is applied to all the IPAddressPools.
+ items:
+ description: |-
+ A label selector is a label query over a set of resources. The result of matchLabels and
+ matchExpressions are ANDed. An empty label selector matches all objects. A null
+ label selector matches no objects.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ ipAddressPools:
+ description: The list of IPAddressPools to advertise via this advertisement, selected by name.
+ items:
+ type: string
+ type: array
+ localPref:
+ description: |-
+ The BGP LOCAL_PREF attribute which is used by BGP best path algorithm,
+ Path with higher localpref is preferred over one with lower localpref.
+ format: int32
+ type: integer
+ nodeSelectors:
+ description: NodeSelectors allows to limit the nodes to announce as next hops for the LoadBalancer IP. When empty, all the nodes having are announced as next hops.
+ items:
+ description: |-
+ A label selector is a label query over a set of resources. The result of matchLabels and
+ matchExpressions are ANDed. An empty label selector matches all objects. A null
+ label selector matches no objects.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ peers:
+ description: |-
+ Peers limits the bgppeer to advertise the ips of the selected pools to.
+ When empty, the loadbalancer IP is announced to all the BGPPeers configured.
+ items:
+ type: string
+ type: array
+ type: object
+ status:
+ description: BGPAdvertisementStatus defines the observed state of BGPAdvertisement.
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: bgppeers.metallb.io
+spec:
+ conversion:
+ strategy: Webhook
+ webhook:
+ clientConfig:
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGWlRDQ0EwMmdBd0lCQWdJVU5GRW1XcTM3MVpKdGkrMmlSQzk1WmpBV1MxZ3dEUVlKS29aSWh2Y05BUUVMDQpCUUF3UWpFTE1Ba0dBMVVFQmhNQ1dGZ3hGVEFUQmdOVkJBY01ERVJsWm1GMWJIUWdRMmwwZVRFY01Cb0dBMVVFDQpDZ3dUUkdWbVlYVnNkQ0JEYjIxd1lXNTVJRXgwWkRBZUZ3MHlNakEzTVRrd09UTXlNek5hRncweU1qQTRNVGd3DQpPVE15TXpOYU1FSXhDekFKQmdOVkJBWVRBbGhZTVJVd0V3WURWUVFIREF4RVpXWmhkV3gwSUVOcGRIa3hIREFhDQpCZ05WQkFvTUUwUmxabUYxYkhRZ1EyOXRjR0Z1ZVNCTWRHUXdnZ0lpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElDDQpEd0F3Z2dJS0FvSUNBUUNxVFpxMWZRcC9vYkdlenhES0o3OVB3Ny94azJwellualNzMlkzb1ZYSm5sRmM4YjVlDQpma2ZZQnY2bndscW1keW5PL2phWFBaQmRQSS82aFdOUDBkdVhadEtWU0NCUUpyZzEyOGNXb3F0MGNTN3pLb1VpDQpvcU1tQ0QvRXVBeFFNZjhRZDF2c1gvVllkZ0poVTZBRXJLZEpIaXpFOUJtUkNkTDBGMW1OVW55Rk82UnRtWFZUDQpidkxsTDVYeTc2R0FaQVBLOFB4aVlDa0NtbDdxN0VnTWNiOXlLWldCYmlxQ3VkTXE5TGJLNmdKNzF6YkZnSXV4DQo1L1pXK2JraTB2RlplWk9ZODUxb1psckFUNzJvMDI4NHNTWW9uN0pHZVZkY3NoUnh5R1VpSFpSTzdkaXZVTDVTDQpmM2JmSDFYbWY1ZDQzT0NWTWRuUUV2NWVaOG8zeWVLa3ZrbkZQUGVJMU9BbjdGbDlFRVNNR2dhOGFaSG1URSttDQpsLzlMSmdDYjBnQmtPT0M0WnV4bWh2aERKV1EzWnJCS3pMQlNUZXN0NWlLNVlwcXRWVVk2THRyRW9FelVTK1lsDQpwWndXY2VQWHlHeHM5ZURsR3lNVmQraW15Y3NTU1UvVno2Mmx6MnZCS21NTXBkYldDQWhud0RsRTVqU2dyMjRRDQp0eGNXLys2N3d5KzhuQlI3UXdqVTFITndVRjBzeERWdEwrZ1NHVERnSEVZSlhZelYvT05zMy94TkpoVFNPSkxNDQpoeXNVdyttaGdackdhbUdXcHVIVU1DUitvTWJzMTc1UkcrQjJnUFFHVytPTjJnUTRyOXN2b0ZBNHBBQm8xd1dLDQpRYjRhY3pmeVVscElBOVFoSmFsZEY3S3dPSHVlV3gwRUNrNXg0T2tvVDBvWVp0dzFiR0JjRGtaSmF3SURBUUFCDQpvMU13VVRBZEJnTlZIUTRFRmdRVW90UlNIUm9IWTEyRFZ4R0NCdEhpb1g2ZmVFQXdId1lEVlIwakJCZ3dGb0FVDQpvdFJTSFJvSFkxMkRWeEdDQnRIaW9YNmZlRUF3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCDQpBUXNGQUFPQ0FnRUFSbkpsWWRjMTFHd0VxWnh6RDF2R3BDR2pDN2VWTlQ3aVY1d3IybXlybHdPYi9aUWFEa0xYDQpvVStaOVVXT1VlSXJTdzUydDdmQUpvVVAwSm5iYkMveVIrU1lqUGhvUXNiVHduOTc2ZldBWTduM3FMOXhCd1Y0DQphek41OXNjeUp0dlhMeUtOL2N5ak1ReDRLajBIMFg0bWJ6bzVZNUtzWWtYVU0vOEFPdWZMcEd0S1NGVGgrSEFDDQpab1Q5YnZHS25adnNHd0tYZFF0Wnh0akhaUjVqK3U3ZGtQOTJBT051RFNabS8rWVV4b2tBK09JbzdSR3BwSHNXDQo1ZTdNY0FTVXRtb1FORXd6dVFoVkJaRWQ1OGtKYjUrV0VWbGNzanlXNnRTbzErZ25tTWNqR1BsMWgxR2hVbjV4DQpFY0lWRnBIWXM5YWo1NmpBSjk1MVQvZjhMaWxmTlVnanBLQ0c1bnl0SUt3emxhOHNtdGlPdm1UNEpYbXBwSkI2DQo4bmdHRVluVjUrUTYwWFJ2OEhSSGp1VG9CRHVhaERrVDA2R1JGODU1d09FR2V4bkZpMXZYWUxLVllWb1V2MXRKDQo4dVdUR1pwNllDSVJldlBqbzg5ZytWTlJSaVFYUThJd0dybXE5c0RoVTlqTjA0SjdVL1RvRDFpNHE3VnlsRUc5DQorV1VGNkNLaEdBeTJIaEhwVncyTGFoOS9lUzdZMUZ1YURrWmhPZG1laG1BOCtqdHNZamJadnR5Mm1SWlF0UUZzDQpUU1VUUjREbUR2bVVPRVRmeStpRHdzK2RkWXVNTnJGeVVYV2dkMnpBQU4ydVl1UHFGY2pRcFNPODFzVTJTU3R3DQoxVzAyeUtYOGJEYmZFdjBzbUh3UzliQnFlSGo5NEM1Mjg0YXpsdTBmaUdpTm1OUEM4ckJLRmhBPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==
+ service:
+ name: metallb-webhook-service
+ namespace: {{ .Release.Namespace }}
+ path: /convert
+ conversionReviewVersions:
+ - v1beta1
+ - v1beta2
+ group: metallb.io
+ names:
+ kind: BGPPeer
+ listKind: BGPPeerList
+ plural: bgppeers
+ singular: bgppeer
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .spec.peerAddress
+ name: Address
+ type: string
+ - jsonPath: .spec.peerASN
+ name: ASN
+ type: string
+ - jsonPath: .spec.bfdProfile
+ name: BFD Profile
+ type: string
+ - jsonPath: .spec.ebgpMultiHop
+ name: Multi Hops
+ type: string
+ name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: BGPPeer is the Schema for the peers API.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: BGPPeerSpec defines the desired state of Peer.
+ properties:
+ bfdProfile:
+ type: string
+ ebgpMultiHop:
+ description: EBGP peer is multi-hops away
+ type: boolean
+ holdTime:
+ description: Requested BGP hold time, per RFC4271.
+ type: string
+ keepaliveTime:
+ description: Requested BGP keepalive time, per RFC4271.
+ type: string
+ myASN:
+ description: AS number to use for the local end of the session.
+ format: int32
+ maximum: 4294967295
+ minimum: 0
+ type: integer
+ nodeSelectors:
+ description: |-
+ Only connect to this peer on nodes that match one of these
+ selectors.
+ items:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ minItems: 1
+ type: array
+ required:
+ - key
+ - operator
+ - values
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ type: array
+ password:
+ description: Authentication password for routers enforcing TCP MD5 authenticated sessions
+ type: string
+ peerASN:
+ description: AS number to expect from the remote end of the session.
+ format: int32
+ maximum: 4294967295
+ minimum: 0
+ type: integer
+ peerAddress:
+ description: Address to dial when establishing the session.
+ type: string
+ peerPort:
+ description: Port to dial when establishing the session.
+ maximum: 16384
+ minimum: 0
+ type: integer
+ routerID:
+ description: BGP router ID to advertise to the peer
+ type: string
+ sourceAddress:
+ description: Source address to use when establishing the session.
+ type: string
+ required:
+ - myASN
+ - peerASN
+ - peerAddress
+ type: object
+ status:
+ description: BGPPeerStatus defines the observed state of Peer.
+ type: object
+ type: object
+ served: true
+ storage: false
+ subresources:
+ status: {}
+ - additionalPrinterColumns:
+ - jsonPath: .spec.peerAddress
+ name: Address
+ type: string
+ - jsonPath: .spec.peerASN
+ name: ASN
+ type: string
+ - jsonPath: .spec.bfdProfile
+ name: BFD Profile
+ type: string
+ - jsonPath: .spec.ebgpMultiHop
+ name: Multi Hops
+ type: string
+ name: v1beta2
+ schema:
+ openAPIV3Schema:
+ description: BGPPeer is the Schema for the peers API.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: BGPPeerSpec defines the desired state of Peer.
+ properties:
+ bfdProfile:
+ description: The name of the BFD Profile to be used for the BFD session associated to the BGP session. If not set, the BFD session won't be set up.
+ type: string
+ connectTime:
+ description: Requested BGP connect time, controls how long BGP waits between connection attempts to a neighbor.
+ type: string
+ x-kubernetes-validations:
+ - message: connect time should be between 1 seconds to 65535
+ rule: duration(self).getSeconds() >= 1 && duration(self).getSeconds() <= 65535
+ - message: connect time should contain a whole number of seconds
+ rule: duration(self).getMilliseconds() % 1000 == 0
+ disableMP:
+ default: false
+ description: To set if we want to disable MP BGP that will separate IPv4 and IPv6 route exchanges into distinct BGP sessions.
+ type: boolean
+ ebgpMultiHop:
+ description: To set if the BGPPeer is multi-hops away. Needed for FRR mode only.
+ type: boolean
+ enableGracefulRestart:
+ description: |-
+ EnableGracefulRestart allows BGP peer to continue to forward data packets along
+ known routes while the routing protocol information is being restored.
+ This field is immutable because it requires restart of the BGP session
+ Supported for FRR mode only.
+ type: boolean
+ x-kubernetes-validations:
+ - message: EnableGracefulRestart cannot be changed after creation
+ rule: self == oldSelf
+ holdTime:
+ description: Requested BGP hold time, per RFC4271.
+ type: string
+ keepaliveTime:
+ description: Requested BGP keepalive time, per RFC4271.
+ type: string
+ myASN:
+ description: AS number to use for the local end of the session.
+ format: int32
+ maximum: 4294967295
+ minimum: 0
+ type: integer
+ nodeSelectors:
+ description: |-
+ Only connect to this peer on nodes that match one of these
+ selectors.
+ items:
+ description: |-
+ A label selector is a label query over a set of resources. The result of matchLabels and
+ matchExpressions are ANDed. An empty label selector matches all objects. A null
+ label selector matches no objects.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ password:
+ description: Authentication password for routers enforcing TCP MD5 authenticated sessions
+ type: string
+ passwordSecret:
+ description: |-
+ passwordSecret is name of the authentication secret for BGP Peer.
+ the secret must be of type "kubernetes.io/basic-auth", and created in the
+ same namespace as the MetalLB deployment. The password is stored in the
+ secret as the key "password".
+ properties:
+ name:
+ description: name is unique within a namespace to reference a secret resource.
+ type: string
+ namespace:
+ description: namespace defines the space within which the secret name must be unique.
+ type: string
+ type: object
+ x-kubernetes-map-type: atomic
+ peerASN:
+ description: AS number to expect from the remote end of the session.
+ format: int32
+ maximum: 4294967295
+ minimum: 0
+ type: integer
+ peerAddress:
+ description: Address to dial when establishing the session.
+ type: string
+ peerPort:
+ default: 179
+ description: Port to dial when establishing the session.
+ maximum: 16384
+ minimum: 0
+ type: integer
+ routerID:
+ description: BGP router ID to advertise to the peer
+ type: string
+ sourceAddress:
+ description: Source address to use when establishing the session.
+ type: string
+ vrf:
+ description: |-
+ To set if we want to peer with the BGPPeer using an interface belonging to
+ a host vrf
+ type: string
+ required:
+ - myASN
+ - peerASN
+ - peerAddress
+ type: object
+ status:
+ description: BGPPeerStatus defines the observed state of Peer.
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: communities.metallb.io
+spec:
+ group: metallb.io
+ names:
+ kind: Community
+ listKind: CommunityList
+ plural: communities
+ singular: community
+ scope: Namespaced
+ versions:
+ - name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: |-
+ Community is a collection of aliases for communities.
+ Users can define named aliases to be used in the BGPPeer CRD.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: CommunitySpec defines the desired state of Community.
+ properties:
+ communities:
+ items:
+ properties:
+ name:
+ description: The name of the alias for the community.
+ type: string
+ value:
+ description: |-
+ The BGP community value corresponding to the given name. Can be a standard community of the form 1234:1234
+ or a large community of the form large:1234:1234:1234.
+ type: string
+ type: object
+ type: array
+ type: object
+ status:
+ description: CommunityStatus defines the observed state of Community.
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: ipaddresspools.metallb.io
+spec:
+ group: metallb.io
+ names:
+ kind: IPAddressPool
+ listKind: IPAddressPoolList
+ plural: ipaddresspools
+ singular: ipaddresspool
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .spec.autoAssign
+ name: Auto Assign
+ type: boolean
+ - jsonPath: .spec.avoidBuggyIPs
+ name: Avoid Buggy IPs
+ type: boolean
+ - jsonPath: .spec.addresses
+ name: Addresses
+ type: string
+ name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: |-
+ IPAddressPool represents a pool of IP addresses that can be allocated
+ to LoadBalancer services.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: IPAddressPoolSpec defines the desired state of IPAddressPool.
+ properties:
+ addresses:
+ description: |-
+ A list of IP address ranges over which MetalLB has authority.
+ You can list multiple ranges in a single pool, they will all share the
+ same settings. Each range can be either a CIDR prefix, or an explicit
+ start-end range of IPs.
+ items:
+ type: string
+ type: array
+ autoAssign:
+ default: true
+ description: |-
+ AutoAssign flag used to prevent MetallB from automatic allocation
+ for a pool.
+ type: boolean
+ avoidBuggyIPs:
+ default: false
+ description: |-
+ AvoidBuggyIPs prevents addresses ending with .0 and .255
+ to be used by a pool.
+ type: boolean
+ serviceAllocation:
+ description: |-
+ AllocateTo makes ip pool allocation to specific namespace and/or service.
+ The controller will use the pool with lowest value of priority in case of
+ multiple matches. A pool with no priority set will be used only if the
+ pools with priority can't be used. If multiple matching IPAddressPools are
+ available it will check for the availability of IPs sorting the matching
+ IPAddressPools by priority, starting from the highest to the lowest. If
+ multiple IPAddressPools have the same priority, choice will be random.
+ properties:
+ namespaceSelectors:
+ description: |-
+ NamespaceSelectors list of label selectors to select namespace(s) for ip pool,
+ an alternative to using namespace list.
+ items:
+ description: |-
+ A label selector is a label query over a set of resources. The result of matchLabels and
+ matchExpressions are ANDed. An empty label selector matches all objects. A null
+ label selector matches no objects.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ namespaces:
+ description: Namespaces list of namespace(s) on which ip pool can be attached.
+ items:
+ type: string
+ type: array
+ priority:
+ description: Priority priority given for ip pool while ip allocation on a service.
+ type: integer
+ serviceSelectors:
+ description: |-
+ ServiceSelectors list of label selector to select service(s) for which ip pool
+ can be used for ip allocation.
+ items:
+ description: |-
+ A label selector is a label query over a set of resources. The result of matchLabels and
+ matchExpressions are ANDed. An empty label selector matches all objects. A null
+ label selector matches no objects.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ type: object
+ required:
+ - addresses
+ type: object
+ status:
+ description: IPAddressPoolStatus defines the observed state of IPAddressPool.
+ type: object
+ required:
+ - spec
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: l2advertisements.metallb.io
+spec:
+ group: metallb.io
+ names:
+ kind: L2Advertisement
+ listKind: L2AdvertisementList
+ plural: l2advertisements
+ singular: l2advertisement
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .spec.ipAddressPools
+ name: IPAddressPools
+ type: string
+ - jsonPath: .spec.ipAddressPoolSelectors
+ name: IPAddressPool Selectors
+ type: string
+ - jsonPath: .spec.interfaces
+ name: Interfaces
+ type: string
+ - jsonPath: .spec.nodeSelectors
+ name: Node Selectors
+ priority: 10
+ type: string
+ name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: |-
+ L2Advertisement allows to advertise the LoadBalancer IPs provided
+ by the selected pools via L2.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: L2AdvertisementSpec defines the desired state of L2Advertisement.
+ properties:
+ interfaces:
+ description: |-
+ A list of interfaces to announce from. The LB IP will be announced only from these interfaces.
+ If the field is not set, we advertise from all the interfaces on the host.
+ items:
+ type: string
+ type: array
+ ipAddressPoolSelectors:
+ description: |-
+ A selector for the IPAddressPools which would get advertised via this advertisement.
+ If no IPAddressPool is selected by this or by the list, the advertisement is applied to all the IPAddressPools.
+ items:
+ description: |-
+ A label selector is a label query over a set of resources. The result of matchLabels and
+ matchExpressions are ANDed. An empty label selector matches all objects. A null
+ label selector matches no objects.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ ipAddressPools:
+ description: The list of IPAddressPools to advertise via this advertisement, selected by name.
+ items:
+ type: string
+ type: array
+ nodeSelectors:
+ description: NodeSelectors allows to limit the nodes to announce as next hops for the LoadBalancer IP. When empty, all the nodes having are announced as next hops.
+ items:
+ description: |-
+ A label selector is a label query over a set of resources. The result of matchLabels and
+ matchExpressions are ANDed. An empty label selector matches all objects. A null
+ label selector matches no objects.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the selector applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ type: array
+ type: object
+ status:
+ description: L2AdvertisementStatus defines the observed state of L2Advertisement.
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: servicel2statuses.metallb.io
+spec:
+ group: metallb.io
+ names:
+ kind: ServiceL2Status
+ listKind: ServiceL2StatusList
+ plural: servicel2statuses
+ singular: servicel2status
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .status.node
+ name: Allocated Node
+ type: string
+ - jsonPath: .status.serviceName
+ name: Service Name
+ type: string
+ - jsonPath: .status.serviceNamespace
+ name: Service Namespace
+ type: string
+ name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: ServiceL2Status reveals the actual traffic status of loadbalancer services in layer2 mode.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: ServiceL2StatusSpec defines the desired state of ServiceL2Status.
+ type: object
+ status:
+ description: MetalLBServiceL2Status defines the observed state of ServiceL2Status.
+ properties:
+ interfaces:
+ description: Interfaces indicates the interfaces that receive the directed traffic
+ items:
+ description: InterfaceInfo defines interface info of layer2 announcement.
+ properties:
+ name:
+ description: Name the name of network interface card
+ type: string
+ type: object
+ type: array
+ node:
+ description: Node indicates the node that receives the directed traffic
+ type: string
+ x-kubernetes-validations:
+ - message: Value is immutable
+ rule: self == oldSelf
+ serviceName:
+ description: ServiceName indicates the service this status represents
+ type: string
+ x-kubernetes-validations:
+ - message: Value is immutable
+ rule: self == oldSelf
+ serviceNamespace:
+ description: ServiceNamespace indicates the namespace of the service
+ type: string
+ x-kubernetes-validations:
+ - message: Value is immutable
+ rule: self == oldSelf
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/metallb-chart/policy/controller.rego b/metallb-chart/policy/controller.rego
new file mode 100644
index 0000000..a91be16
--- /dev/null
+++ b/metallb-chart/policy/controller.rego
@@ -0,0 +1,16 @@
+package main
+
+# validate serviceAccountName
+deny[msg] {
+ input.kind == "Deployment"
+ serviceAccountName := input.spec.template.spec.serviceAccountName
+ not serviceAccountName == "release-name-metallb-controller"
+ msg = sprintf("controller serviceAccountName '%s' does not match expected value", [serviceAccountName])
+}
+
+# validate node selector includes builtin when custom ones are provided
+deny[msg] {
+ input.kind == "Deployment"
+ not input.spec.template.spec.nodeSelector["kubernetes.io/os"] == "linux"
+ msg = "controller nodeSelector does not include '\"kubernetes.io/os\": linux'"
+}
diff --git a/metallb-chart/policy/rbac.rego b/metallb-chart/policy/rbac.rego
new file mode 100644
index 0000000..8e261af
--- /dev/null
+++ b/metallb-chart/policy/rbac.rego
@@ -0,0 +1,27 @@
+package main
+
+# Validate PSP exists in ClusterRole :controller
+deny[msg] {
+ input.kind == "ClusterRole"
+ input.metadata.name == "metallb:controller"
+ input.rules[3] == {
+ "apiGroups": ["policy"],
+ "resources": ["podsecuritypolicies"],
+ "resourceNames": ["metallb-controller"],
+ "verbs": ["use"]
+ }
+ msg = "ClusterRole metallb:controller does not include PSP rule"
+}
+
+# Validate PSP exists in ClusterRole :speaker
+deny[msg] {
+ input.kind == "ClusterRole"
+ input.metadata.name == "metallb:speaker"
+ input.rules[3] == {
+ "apiGroups": ["policy"],
+ "resources": ["podsecuritypolicies"],
+ "resourceNames": ["metallb-controller"],
+ "verbs": ["use"]
+ }
+ msg = "ClusterRole metallb:speaker does not include PSP rule"
+}
diff --git a/metallb-chart/policy/speaker.rego b/metallb-chart/policy/speaker.rego
new file mode 100644
index 0000000..7e7775b
--- /dev/null
+++ b/metallb-chart/policy/speaker.rego
@@ -0,0 +1,30 @@
+package main
+
+# validate serviceAccountName
+deny[msg] {
+ input.kind == "DaemonSet"
+ serviceAccountName := input.spec.template.spec.serviceAccountName
+ not serviceAccountName == "release-name-metallb-speaker"
+ msg = sprintf("speaker serviceAccountName '%s' does not match expected value", [serviceAccountName])
+}
+
+# validate METALLB_ML_SECRET_KEY (memberlist)
+deny[msg] {
+ input.kind == "DaemonSet"
+ not input.spec.template.spec.containers[0].env[5].name == "METALLB_ML_SECRET_KEY_PATH"
+ msg = "speaker env does not contain METALLB_ML_SECRET_KEY_PATH at env[5]"
+}
+
+# validate node selector includes builtin when custom ones are provided
+deny[msg] {
+ input.kind == "DaemonSet"
+ not input.spec.template.spec.nodeSelector["kubernetes.io/os"] == "linux"
+ msg = "controller nodeSelector does not include '\"kubernetes.io/os\": linux'"
+}
+
+# validate tolerations include the builtins when custom ones are provided
+deny[msg] {
+ input.kind == "DaemonSet"
+ not input.spec.template.spec.tolerations[0] == { "key": "node-role.kubernetes.io/master", "effect": "NoSchedule", "operator": "Exists" }
+ msg = "controller tolerations does not include node-role.kubernetes.io/master:NoSchedule"
+}
diff --git a/metallb-chart/templates/NOTES.txt b/metallb-chart/templates/NOTES.txt
new file mode 100644
index 0000000..ec05bd7
--- /dev/null
+++ b/metallb-chart/templates/NOTES.txt
@@ -0,0 +1,4 @@
+MetalLB is now running in the cluster.
+
+Now you can configure it via its CRs. Please refer to the metallb official docs
+on how to use the CRs.
diff --git a/metallb-chart/templates/_helpers.tpl b/metallb-chart/templates/_helpers.tpl
new file mode 100644
index 0000000..0dc55f3
--- /dev/null
+++ b/metallb-chart/templates/_helpers.tpl
@@ -0,0 +1,113 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "metallb.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "metallb.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "metallb.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "metallb.labels" -}}
+helm.sh/chart: {{ include "metallb.chart" . }}
+{{ include "metallb.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "metallb.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "metallb.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the controller service account to use
+*/}}
+{{- define "metallb.controller.serviceAccountName" -}}
+{{- if .Values.controller.serviceAccount.create }}
+{{- default (printf "%s-controller" (include "metallb.fullname" .)) .Values.controller.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.controller.serviceAccount.name }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create the name of the speaker service account to use
+*/}}
+{{- define "metallb.speaker.serviceAccountName" -}}
+{{- if .Values.speaker.serviceAccount.create }}
+{{- default (printf "%s-speaker" (include "metallb.fullname" .)) .Values.speaker.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.speaker.serviceAccount.name }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create the name of the settings Secret to use.
+*/}}
+{{- define "metallb.secretName" -}}
+ {{ default ( printf "%s-memberlist" (include "metallb.fullname" .)) .Values.speaker.secretName | trunc 63 | trimSuffix "-" }}
+{{- end -}}
+
+{{- define "metrics.exposedportname" -}}
+{{- if .Values.prometheus.secureMetricsPort -}}
+"metricshttps"
+{{- else -}}
+"metrics"
+{{- end -}}
+{{- end -}}
+
+{{- define "metrics.exposedfrrportname" -}}
+{{- if .Values.speaker.frr.secureMetricsPort -}}
+"frrmetricshttps"
+{{- else -}}
+"frrmetrics"
+{{- end }}
+{{- end }}
+
+{{- define "metrics.exposedport" -}}
+{{- if .Values.prometheus.secureMetricsPort -}}
+{{ .Values.prometheus.secureMetricsPort }}
+{{- else -}}
+{{ .Values.prometheus.metricsPort }}
+{{- end -}}
+{{- end }}
+
+{{- define "metrics.exposedfrrport" -}}
+{{- if .Values.speaker.frr.secureMetricsPort -}}
+{{ .Values.speaker.frr.secureMetricsPort }}
+{{- else -}}
+{{ .Values.speaker.frr.metricsPort }}
+{{- end }}
+{{- end }}
diff --git a/metallb-chart/templates/controller.yaml b/metallb-chart/templates/controller.yaml
new file mode 100644
index 0000000..311a559
--- /dev/null
+++ b/metallb-chart/templates/controller.yaml
@@ -0,0 +1,194 @@
+{{- if .Values.controller.enabled }}
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ template "metallb.fullname" . }}-controller
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+ app.kubernetes.io/component: controller
+ {{- range $key, $value := .Values.controller.labels }}
+ {{ $key }}: {{ $value | quote }}
+ {{- end }}
+spec:
+ {{- if .Values.controller.strategy }}
+ strategy: {{- toYaml .Values.controller.strategy | nindent 4 }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "metallb.selectorLabels" . | nindent 6 }}
+ app.kubernetes.io/component: controller
+ template:
+ metadata:
+ {{- if or .Values.prometheus.scrapeAnnotations .Values.controller.podAnnotations }}
+ annotations:
+ {{- if .Values.prometheus.scrapeAnnotations }}
+ prometheus.io/scrape: "true"
+ prometheus.io/port: "{{ .Values.prometheus.metricsPort }}"
+ {{- end }}
+ {{- with .Values.controller.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- end }}
+ labels:
+ {{- include "metallb.selectorLabels" . | nindent 8 }}
+ app.kubernetes.io/component: controller
+ {{- range $key, $value := .Values.controller.labels }}
+ {{ $key }}: {{ $value | quote }}
+ {{- end }}
+ spec:
+ {{- with .Values.controller.runtimeClassName }}
+ runtimeClassName: {{ . | quote }}
+ {{- end }}
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ template "metallb.controller.serviceAccountName" . }}
+ terminationGracePeriodSeconds: 0
+{{- if .Values.controller.securityContext }}
+ securityContext:
+{{ toYaml .Values.controller.securityContext | indent 8 }}
+{{- end }}
+ containers:
+ - name: controller
+ image: {{ .Values.controller.image.repository }}:{{ .Values.controller.image.tag | default .Chart.AppVersion }}
+ {{- if .Values.controller.image.pullPolicy }}
+ imagePullPolicy: {{ .Values.controller.image.pullPolicy }}
+ {{- end }}
+ {{- if .Values.controller.command }}
+ command:
+ - {{ .Values.controller.command }}
+ {{- end }}
+ args:
+ - --port={{ .Values.prometheus.metricsPort }}
+ {{- with .Values.controller.logLevel }}
+ - --log-level={{ . }}
+ {{- end }}
+ {{- if .Values.loadBalancerClass }}
+ - --lb-class={{ .Values.loadBalancerClass }}
+ {{- end }}
+ {{- if .Values.controller.webhookMode }}
+ - --webhook-mode={{ .Values.controller.webhookMode }}
+ {{- end }}
+ {{- if .Values.controller.tlsMinVersion }}
+ - --tls-min-version={{ .Values.controller.tlsMinVersion }}
+ {{- end }}
+ {{- if .Values.controller.tlsCipherSuites }}
+ - --tls-cipher-suites={{ .Values.controller.tlsCipherSuites }}
+ {{- end }}
+ env:
+ {{- if and .Values.speaker.enabled .Values.speaker.memberlist.enabled }}
+ - name: METALLB_ML_SECRET_NAME
+ value: {{ include "metallb.secretName" . }}
+ - name: METALLB_DEPLOYMENT
+ value: {{ template "metallb.fullname" . }}-controller
+ {{- end }}
+ {{- if .Values.speaker.frr.enabled }}
+ - name: METALLB_BGP_TYPE
+ value: frr
+ {{- end }}
+ {{- if or .Values.frrk8s.enabled .Values.frrk8s.external }}
+ - name: METALLB_BGP_TYPE
+ value: frr-k8s
+ {{- end }}
+ ports:
+ - name: monitoring
+ containerPort: {{ .Values.prometheus.metricsPort }}
+ - containerPort: 9443
+ name: webhook-server
+ protocol: TCP
+ volumeMounts:
+ - mountPath: /tmp/k8s-webhook-server/serving-certs
+ name: cert
+ readOnly: true
+ {{- if .Values.controller.livenessProbe.enabled }}
+ livenessProbe:
+ httpGet:
+ path: /metrics
+ port: monitoring
+ initialDelaySeconds: {{ .Values.controller.livenessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.controller.livenessProbe.periodSeconds }}
+ timeoutSeconds: {{ .Values.controller.livenessProbe.timeoutSeconds }}
+ successThreshold: {{ .Values.controller.livenessProbe.successThreshold }}
+ failureThreshold: {{ .Values.controller.livenessProbe.failureThreshold }}
+ {{- end }}
+ {{- if .Values.controller.readinessProbe.enabled }}
+ readinessProbe:
+ httpGet:
+ path: /metrics
+ port: monitoring
+ initialDelaySeconds: {{ .Values.controller.readinessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.controller.readinessProbe.periodSeconds }}
+ timeoutSeconds: {{ .Values.controller.readinessProbe.timeoutSeconds }}
+ successThreshold: {{ .Values.controller.readinessProbe.successThreshold }}
+ failureThreshold: {{ .Values.controller.readinessProbe.failureThreshold }}
+ {{- end }}
+ {{- with .Values.controller.resources }}
+ resources:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ securityContext:
+ allowPrivilegeEscalation: false
+ readOnlyRootFilesystem: true
+ capabilities:
+ drop:
+ - ALL
+ {{- if .Values.prometheus.secureMetricsPort }}
+ - name: kube-rbac-proxy
+ image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag }}
+ imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }}
+ args:
+ - --logtostderr
+ - --secure-listen-address=:{{ .Values.prometheus.secureMetricsPort }}
+ - --upstream=http://127.0.0.1:{{ .Values.prometheus.metricsPort }}/
+ - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ {{- if .Values.prometheus.controllerMetricsTLSSecret }}
+ - --tls-private-key-file=/etc/metrics/tls.key
+ - --tls-cert-file=/etc/metrics/tls.crt
+ {{- end }}
+ ports:
+ - containerPort: {{ .Values.prometheus.secureMetricsPort }}
+ name: metricshttps
+ resources:
+ requests:
+ cpu: 10m
+ memory: 20Mi
+ terminationMessagePolicy: FallbackToLogsOnError
+ {{- if .Values.prometheus.controllerMetricsTLSSecret }}
+ volumeMounts:
+ - name: metrics-certs
+ mountPath: /etc/metrics
+ readOnly: true
+ {{- end }}
+ {{ end }}
+ {{- if .Values.controller.extraContainers }}
+ {{- toYaml .Values.controller.extraContainers | nindent 6 }}
+ {{- end }}
+ nodeSelector:
+ "kubernetes.io/os": linux
+ {{- with .Values.controller.nodeSelector }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.controller.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.controller.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 6 }}
+ {{- end }}
+ {{- with .Values.controller.priorityClassName }}
+ priorityClassName: {{ . | quote }}
+ {{- end }}
+ volumes:
+ - name: cert
+ secret:
+ defaultMode: 420
+ secretName: metallb-webhook-cert
+ {{- if .Values.prometheus.controllerMetricsTLSSecret }}
+ - name: metrics-certs
+ secret:
+ secretName: {{ .Values.prometheus.controllerMetricsTLSSecret }}
+ {{- end }}
+{{- end }}
diff --git a/metallb-chart/templates/deprecated_configInline.yaml b/metallb-chart/templates/deprecated_configInline.yaml
new file mode 100644
index 0000000..077c7b6
--- /dev/null
+++ b/metallb-chart/templates/deprecated_configInline.yaml
@@ -0,0 +1,3 @@
+{{- if .Values.configInline }}
+{{- fail "Starting from v0.13.0 configInline is no longer supported. Please see https://metallb.universe.tf/#backward-compatibility" }}
+{{- end }}
diff --git a/metallb-chart/templates/exclude-l2-config.yaml b/metallb-chart/templates/exclude-l2-config.yaml
new file mode 100644
index 0000000..2c85c88
--- /dev/null
+++ b/metallb-chart/templates/exclude-l2-config.yaml
@@ -0,0 +1,25 @@
+{{- if and .Values.speaker.enabled .Values.speaker.excludeInterfaces.enabled }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: metallb-excludel2
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+data:
+ excludel2.yaml: |
+ announcedInterfacesToExclude:
+ - ^docker.*
+ - ^cbr.*
+ - ^dummy.*
+ - ^virbr.*
+ - ^lxcbr.*
+ - ^veth.*
+ - ^lo$
+ - ^cali.*
+ - ^tunl.*
+ - ^flannel.*
+ - ^kube-ipvs.*
+ - ^cni.*
+ - ^nodelocaldns.*
+{{- end }}
\ No newline at end of file
diff --git a/metallb-chart/templates/podmonitor.yaml b/metallb-chart/templates/podmonitor.yaml
new file mode 100644
index 0000000..40155de
--- /dev/null
+++ b/metallb-chart/templates/podmonitor.yaml
@@ -0,0 +1,106 @@
+{{- if .Values.prometheus.podMonitor.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: PodMonitor
+metadata:
+ name: {{ template "metallb.fullname" . }}-controller
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+ app.kubernetes.io/component: controller
+ {{- if .Values.prometheus.podMonitor.additionalLabels }}
+{{ toYaml .Values.prometheus.podMonitor.additionalLabels | indent 4 }}
+ {{- end }}
+ {{- if .Values.prometheus.podMonitor.annotations }}
+ annotations:
+{{ toYaml .Values.prometheus.podMonitor.annotations | indent 4 }}
+ {{- end }}
+spec:
+ jobLabel: {{ .Values.prometheus.podMonitor.jobLabel | quote }}
+ selector:
+ matchLabels:
+ {{- include "metallb.selectorLabels" . | nindent 6 }}
+ app.kubernetes.io/component: controller
+ namespaceSelector:
+ matchNames:
+ - {{ .Release.Namespace }}
+ podMetricsEndpoints:
+ - port: monitoring
+ path: /metrics
+ {{- if .Values.prometheus.podMonitor.interval }}
+ interval: {{ .Values.prometheus.podMonitor.interval }}
+ {{- end }}
+{{- if .Values.prometheus.podMonitor.metricRelabelings }}
+ metricRelabelings:
+{{- toYaml .Values.prometheus.podMonitor.metricRelabelings | nindent 4 }}
+{{- end }}
+{{- if .Values.prometheus.podMonitor.relabelings }}
+ relabelings:
+{{- toYaml .Values.prometheus.podMonitor.relabelings | nindent 4 }}
+{{- end }}
+---
+apiVersion: monitoring.coreos.com/v1
+kind: PodMonitor
+metadata:
+ name: {{ template "metallb.fullname" . }}-speaker
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+ app.kubernetes.io/component: speaker
+ {{- if .Values.prometheus.podMonitor.additionalLabels }}
+{{ toYaml .Values.prometheus.podMonitor.additionalLabels | indent 4 }}
+ {{- end }}
+ {{- if .Values.prometheus.podMonitor.annotations }}
+ annotations:
+{{ toYaml .Values.prometheus.podMonitor.annotations | indent 4 }}
+ {{- end }}
+spec:
+ jobLabel: {{ .Values.prometheus.podMonitor.jobLabel | quote }}
+ selector:
+ matchLabels:
+ {{- include "metallb.selectorLabels" . | nindent 6 }}
+ app.kubernetes.io/component: speaker
+ namespaceSelector:
+ matchNames:
+ - {{ .Release.Namespace }}
+ podMetricsEndpoints:
+ - port: monitoring
+ path: /metrics
+ {{- if .Values.prometheus.podMonitor.interval }}
+ interval: {{ .Values.prometheus.podMonitor.interval }}
+ {{- end }}
+{{- if .Values.prometheus.podMonitor.metricRelabelings }}
+ metricRelabelings:
+{{- toYaml .Values.prometheus.podMonitor.metricRelabelings | nindent 4 }}
+{{- end }}
+{{- if .Values.prometheus.podMonitor.relabelings }}
+ relabelings:
+{{- toYaml .Values.prometheus.podMonitor.relabelings | nindent 4 }}
+{{- end }}
+---
+{{- if .Values.prometheus.rbacPrometheus }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ template "metallb.fullname" . }}-prometheus
+rules:
+ - apiGroups:
+ - ""
+ resources:
+ - pods
+ verbs:
+ - get
+ - list
+ - watch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ template "metallb.fullname" . }}-prometheus
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: {{ template "metallb.fullname" . }}-prometheus
+subjects:
+ - kind: ServiceAccount
+ name: {{ required ".Values.prometheus.serviceAccount must be defined when .Values.prometheus.podMonitor.enabled == true" .Values.prometheus.serviceAccount }}
+ namespace: {{ required ".Values.prometheus.namespace must be defined when .Values.prometheus.podMonitor.enabled == true" .Values.prometheus.namespace }}
+{{- end }}
+{{- end }}
diff --git a/metallb-chart/templates/prometheusrules.yaml b/metallb-chart/templates/prometheusrules.yaml
new file mode 100644
index 0000000..50bd49a
--- /dev/null
+++ b/metallb-chart/templates/prometheusrules.yaml
@@ -0,0 +1,84 @@
+{{- if .Values.prometheus.prometheusRule.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: PrometheusRule
+metadata:
+ name: {{ template "metallb.fullname" . }}
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+ {{- if .Values.prometheus.prometheusRule.additionalLabels }}
+{{ toYaml .Values.prometheus.prometheusRule.additionalLabels | indent 4 }}
+ {{- end }}
+ {{- if .Values.prometheus.prometheusRule.annotations }}
+ annotations:
+{{ toYaml .Values.prometheus.prometheusRule.annotations | indent 4 }}
+ {{- end }}
+spec:
+ groups:
+ - name: {{ template "metallb.fullname" . }}.rules
+ rules:
+ {{- if .Values.prometheus.prometheusRule.staleConfig.enabled }}
+ - alert: MetalLBStaleConfig
+ annotations:
+ message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod
+ }} has a stale config for > 1 minute'`}}
+ expr: metallb_k8s_client_config_stale_bool{job=~"{{ template "metallb.fullname" . }}.*"} == 1
+ for: 1m
+ {{- with .Values.prometheus.prometheusRule.staleConfig.labels }}
+ labels:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.prometheus.prometheusRule.configNotLoaded.enabled }}
+ - alert: MetalLBConfigNotLoaded
+ annotations:
+ message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod
+ }} has not loaded for > 1 minute'`}}
+ expr: metallb_k8s_client_config_loaded_bool{job=~"{{ template "metallb.fullname" . }}.*"} == 0
+ for: 1m
+ {{- with .Values.prometheus.prometheusRule.configNotLoaded.labels }}
+ labels:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.prometheus.prometheusRule.addressPoolExhausted.enabled }}
+ - alert: MetalLBAddressPoolExhausted
+ annotations:
+ message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod
+ }} has exhausted address pool {{ $labels.pool }} for > 1 minute'`}}
+ expr: metallb_allocator_addresses_in_use_total >= on(pool) metallb_allocator_addresses_total
+ for: 1m
+ {{- with .Values.prometheus.prometheusRule.addressPoolExhausted.labels }}
+ labels:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- end }}
+
+ {{- if .Values.prometheus.prometheusRule.addressPoolUsage.enabled }}
+ {{- range .Values.prometheus.prometheusRule.addressPoolUsage.thresholds }}
+ - alert: MetalLBAddressPoolUsage{{ .percent }}Percent
+ annotations:
+ message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod
+ }} has address pool {{ $labels.pool }} past `}}{{ .percent }}{{`% usage for > 1 minute'`}}
+ expr: ( metallb_allocator_addresses_in_use_total / on(pool) metallb_allocator_addresses_total ) * 100 > {{ .percent }}
+ {{- with .labels }}
+ labels:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.prometheus.prometheusRule.bgpSessionDown.enabled }}
+ - alert: MetalLBBGPSessionDown
+ annotations:
+ message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod
+ }} has BGP session {{ $labels.peer }} down for > 1 minute'`}}
+ expr: metallb_bgp_session_up{job=~"{{ template "metallb.fullname" . }}.*"} == 0
+ for: 1m
+ {{- with .Values.prometheus.prometheusRule.bgpSessionDown.labels }}
+ labels:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- end }}
+ {{- with .Values.prometheus.prometheusRule.extraAlerts }}
+ {{- toYaml . | nindent 4 }}
+ {{- end}}
+{{- end }}
diff --git a/metallb-chart/templates/rbac.yaml b/metallb-chart/templates/rbac.yaml
new file mode 100644
index 0000000..8c66b80
--- /dev/null
+++ b/metallb-chart/templates/rbac.yaml
@@ -0,0 +1,212 @@
+{{- if .Values.rbac.create -}}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ template "metallb.fullname" . }}:controller
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+rules:
+- apiGroups: [""]
+ resources: ["services", "namespaces"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: [""]
+ resources: ["nodes"]
+ verbs: ["list"]
+- apiGroups: [""]
+ resources: ["services/status"]
+ verbs: ["update"]
+- apiGroups: [""]
+ resources: ["events"]
+ verbs: ["create", "patch"]
+- apiGroups: ["admissionregistration.k8s.io"]
+ resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"]
+ resourceNames: ["metallb-webhook-configuration"]
+ verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
+- apiGroups: ["admissionregistration.k8s.io"]
+ resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"]
+ verbs: ["list", "watch"]
+- apiGroups: ["apiextensions.k8s.io"]
+ resources: ["customresourcedefinitions"]
+ resourceNames: ["bfdprofiles.metallb.io","bgpadvertisements.metallb.io",
+ "bgppeers.metallb.io","ipaddresspools.metallb.io","l2advertisements.metallb.io","communities.metallb.io"]
+ verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
+- apiGroups: ["apiextensions.k8s.io"]
+ resources: ["customresourcedefinitions"]
+ verbs: ["list", "watch"]
+{{- if .Values.prometheus.secureMetricsPort }}
+- apiGroups: ["authentication.k8s.io"]
+ resources: ["tokenreviews"]
+ verbs: ["create"]
+- apiGroups: ["authorization.k8s.io"]
+ resources: ["subjectaccessreviews"]
+ verbs: ["create"]
+{{- end }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ template "metallb.fullname" . }}:speaker
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+rules:
+- apiGroups: [""]
+ resources: ["services", "endpoints", "nodes", "namespaces"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: ["discovery.k8s.io"]
+ resources: ["endpointslices"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: [""]
+ resources: ["events"]
+ verbs: ["create", "patch"]
+- apiGroups: ["metallb.io"]
+ resources: ["servicel2statuses","servicel2statuses/status"]
+ verbs: ["*"]
+{{- if .Values.prometheus.secureMetricsPort }}
+- apiGroups: ["authentication.k8s.io"]
+ resources: ["tokenreviews"]
+ verbs: ["create"]
+- apiGroups: ["authorization.k8s.io"]
+ resources: ["subjectaccessreviews"]
+ verbs: ["create"]
+{{- end }}
+{{- if or .Values.frrk8s.enabled .Values.frrk8s.external }}
+- apiGroups: ["frrk8s.metallb.io"]
+ resources: ["frrconfigurations"]
+ verbs: ["get", "list", "watch","create","update"]
+{{- end }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ include "metallb.fullname" . }}-pod-lister
+ namespace: {{ .Release.Namespace | quote }}
+ labels: {{- include "metallb.labels" . | nindent 4 }}
+rules:
+- apiGroups: [""]
+ resources: ["pods"]
+ verbs: ["list", "get"]
+- apiGroups: [""]
+ resources: ["secrets"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: [""]
+ resources: ["configmaps"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: ["metallb.io"]
+ resources: ["bfdprofiles"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: ["metallb.io"]
+ resources: ["bgppeers"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: ["metallb.io"]
+ resources: ["l2advertisements"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: ["metallb.io"]
+ resources: ["bgpadvertisements"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: ["metallb.io"]
+ resources: ["ipaddresspools"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: ["metallb.io"]
+ resources: ["communities"]
+ verbs: ["get", "list", "watch"]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ include "metallb.fullname" . }}-controller
+ namespace: {{ .Release.Namespace | quote }}
+ labels: {{- include "metallb.labels" . | nindent 4 }}
+rules:
+{{- if .Values.speaker.memberlist.enabled }}
+- apiGroups: [""]
+ resources: ["secrets"]
+ verbs: ["create", "get", "list", "watch"]
+- apiGroups: [""]
+ resources: ["secrets"]
+ resourceNames: [{{ include "metallb.secretName" . | quote }}]
+ verbs: ["list"]
+- apiGroups: ["apps"]
+ resources: ["deployments"]
+ resourceNames: ["{{ template "metallb.fullname" . }}-controller"]
+ verbs: ["get"]
+{{- end }}
+- apiGroups: [""]
+ resources: ["secrets"]
+ verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
+- apiGroups: ["metallb.io"]
+ resources: ["ipaddresspools"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: ["metallb.io"]
+ resources: ["bgppeers"]
+ verbs: ["get", "list"]
+- apiGroups: ["metallb.io"]
+ resources: ["bgpadvertisements"]
+ verbs: ["get", "list"]
+- apiGroups: ["metallb.io"]
+ resources: ["l2advertisements"]
+ verbs: ["get", "list"]
+- apiGroups: ["metallb.io"]
+ resources: ["communities"]
+ verbs: ["get", "list","watch"]
+- apiGroups: ["metallb.io"]
+ resources: ["bfdprofiles"]
+ verbs: ["get", "list","watch"]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ template "metallb.fullname" . }}:controller
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+subjects:
+- kind: ServiceAccount
+ name: {{ template "metallb.controller.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ template "metallb.fullname" . }}:controller
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ template "metallb.fullname" . }}:speaker
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+subjects:
+- kind: ServiceAccount
+ name: {{ template "metallb.speaker.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ template "metallb.fullname" . }}:speaker
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ include "metallb.fullname" . }}-pod-lister
+ namespace: {{ .Release.Namespace | quote }}
+ labels: {{- include "metallb.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: {{ include "metallb.fullname" . }}-pod-lister
+subjects:
+- kind: ServiceAccount
+ name: {{ include "metallb.speaker.serviceAccountName" . }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ include "metallb.fullname" . }}-controller
+ namespace: {{ .Release.Namespace | quote }}
+ labels: {{- include "metallb.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: {{ include "metallb.fullname" . }}-controller
+subjects:
+- kind: ServiceAccount
+ name: {{ include "metallb.controller.serviceAccountName" . }}
+{{- end -}}
diff --git a/metallb-chart/templates/service-accounts.yaml b/metallb-chart/templates/service-accounts.yaml
new file mode 100644
index 0000000..c2157ff
--- /dev/null
+++ b/metallb-chart/templates/service-accounts.yaml
@@ -0,0 +1,30 @@
+{{- if .Values.controller.serviceAccount.create }}
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ template "metallb.controller.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+ app.kubernetes.io/component: controller
+ {{- with .Values.controller.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
+{{- if .Values.speaker.serviceAccount.create }}
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ template "metallb.speaker.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+ app.kubernetes.io/component: speaker
+ {{- with .Values.speaker.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/metallb-chart/templates/servicemonitor.yaml b/metallb-chart/templates/servicemonitor.yaml
new file mode 100644
index 0000000..0aacf85
--- /dev/null
+++ b/metallb-chart/templates/servicemonitor.yaml
@@ -0,0 +1,194 @@
+{{- if .Values.prometheus.serviceMonitor.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+ name: {{ template "metallb.fullname" . }}-speaker-monitor
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+ app.kubernetes.io/component: speaker
+ {{- if .Values.prometheus.serviceMonitor.speaker.additionalLabels }}
+{{ toYaml .Values.prometheus.serviceMonitor.speaker.additionalLabels | indent 4 }}
+ {{- end }}
+ {{- if .Values.prometheus.serviceMonitor.speaker.annotations }}
+ annotations:
+{{ toYaml .Values.prometheus.serviceMonitor.speaker.annotations | indent 4 }}
+ {{- end }}
+spec:
+ endpoints:
+ - port: {{ template "metrics.exposedportname" . }}
+ honorLabels: true
+ {{- if .Values.prometheus.serviceMonitor.metricRelabelings }}
+ metricRelabelings:
+ {{- toYaml .Values.prometheus.serviceMonitor.metricRelabelings | nindent 8 }}
+ {{- end -}}
+ {{- if .Values.prometheus.serviceMonitor.relabelings }}
+ relabelings:
+ {{- toYaml .Values.prometheus.serviceMonitor.relabelings | nindent 8 }}
+ {{- end }}
+ {{- if .Values.prometheus.serviceMonitor.interval }}
+ interval: {{ .Values.prometheus.serviceMonitor.interval }}
+ {{- end -}}
+{{ if .Values.prometheus.secureMetricsPort }}
+ bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token"
+ scheme: "https"
+{{- if .Values.prometheus.serviceMonitor.speaker.tlsConfig }}
+ tlsConfig:
+{{ toYaml .Values.prometheus.serviceMonitor.speaker.tlsConfig | indent 8 }}
+{{- end }}
+{{ end }}
+{{- if .Values.speaker.frr.enabled }}
+ - port: {{ template "metrics.exposedfrrportname" . }}
+ honorLabels: true
+{{ if .Values.speaker.frr.secureMetricsPort }}
+ {{- if .Values.prometheus.serviceMonitor.interval }}
+ interval: {{ .Values.prometheus.serviceMonitor.interval }}
+ {{- end }}
+ bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token"
+ scheme: "https"
+{{- if .Values.prometheus.serviceMonitor.speaker.tlsConfig }}
+ tlsConfig:
+{{ toYaml .Values.prometheus.serviceMonitor.speaker.tlsConfig | indent 8 }}
+{{- end }}
+{{- end }}
+{{- end }}
+ jobLabel: {{ .Values.prometheus.serviceMonitor.jobLabel | quote }}
+ namespaceSelector:
+ matchNames:
+ - {{ .Release.Namespace }}
+ selector:
+ matchLabels:
+ name: {{ template "metallb.fullname" . }}-speaker-monitor-service
+---
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ prometheus.io/scrape: "true"
+ {{- if .Values.prometheus.serviceMonitor.speaker.annotations }}
+{{ toYaml .Values.prometheus.serviceMonitor.speaker.annotations | indent 4 }}
+ {{- end }}
+ labels:
+ name: {{ template "metallb.fullname" . }}-speaker-monitor-service
+ {{- include "metallb.labels" . | nindent 4 }}
+ name: {{ template "metallb.fullname" . }}-speaker-monitor-service
+ namespace: {{ .Release.Namespace | quote }}
+spec:
+ selector:
+ {{- include "metallb.selectorLabels" . | nindent 4 }}
+ app.kubernetes.io/component: speaker
+ clusterIP: None
+ ports:
+ - name: {{ template "metrics.exposedportname" . }}
+ port: {{ template "metrics.exposedport" . }}
+ targetPort: {{ template "metrics.exposedport" . }}
+{{- if .Values.speaker.frr.enabled }}
+ - name: {{ template "metrics.exposedfrrportname" . }}
+ port: {{ template "metrics.exposedfrrport" . }}
+ targetPort: {{ template "metrics.exposedfrrport" . }}
+{{- end }}
+ sessionAffinity: None
+ type: ClusterIP
+---
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+ name: {{ template "metallb.fullname" . }}-controller-monitor
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+ app.kubernetes.io/component: speaker
+ {{- if .Values.prometheus.serviceMonitor.controller.additionalLabels }}
+{{ toYaml .Values.prometheus.serviceMonitor.controller.additionalLabels | indent 4 }}
+ {{- end }}
+ {{- if .Values.prometheus.serviceMonitor.controller.annotations }}
+ annotations:
+{{ toYaml .Values.prometheus.serviceMonitor.controller.annotations | indent 4 }}
+ {{- end }}
+spec:
+ endpoints:
+ - port: {{ template "metrics.exposedportname" . }}
+ {{- if .Values.prometheus.serviceMonitor.metricRelabelings }}
+ metricRelabelings:
+ {{- toYaml .Values.prometheus.serviceMonitor.metricRelabelings | nindent 8 }}
+ {{- end -}}
+ {{- if .Values.prometheus.serviceMonitor.relabelings }}
+ relabelings:
+ {{- toYaml .Values.prometheus.serviceMonitor.relabelings | nindent 8 }}
+ {{- end }}
+ {{- if .Values.prometheus.serviceMonitor.interval }}
+ interval: {{ .Values.prometheus.serviceMonitor.interval }}
+ {{- end }}
+ honorLabels: true
+{{- if .Values.prometheus.secureMetricsPort }}
+ bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token"
+ scheme: "https"
+{{- if .Values.prometheus.serviceMonitor.controller.tlsConfig }}
+ tlsConfig:
+{{ toYaml .Values.prometheus.serviceMonitor.controller.tlsConfig | indent 8 }}
+{{- end }}
+{{- end }}
+ jobLabel: {{ .Values.prometheus.serviceMonitor.jobLabel | quote }}
+ namespaceSelector:
+ matchNames:
+ - {{ .Release.Namespace }}
+ selector:
+ matchLabels:
+ name: {{ template "metallb.fullname" . }}-controller-monitor-service
+---
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ prometheus.io/scrape: "true"
+ {{- if .Values.prometheus.serviceMonitor.controller.annotations }}
+{{ toYaml .Values.prometheus.serviceMonitor.controller.annotations | indent 4 }}
+ {{- end }}
+ labels:
+ name: {{ template "metallb.fullname" . }}-controller-monitor-service
+ name: {{ template "metallb.fullname" . }}-controller-monitor-service
+spec:
+ selector:
+ {{- include "metallb.selectorLabels" . | nindent 4 }}
+ app.kubernetes.io/component: controller
+ clusterIP: None
+ ports:
+ - name: {{ template "metrics.exposedportname" . }}
+ port: {{ template "metrics.exposedport" . }}
+ targetPort: {{ template "metrics.exposedport" . }}
+ sessionAffinity: None
+ type: ClusterIP
+---
+{{- if .Values.prometheus.rbacPrometheus }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ template "metallb.fullname" . }}-prometheus
+ namespace: {{ .Release.Namespace | quote }}
+rules:
+ - apiGroups:
+ - ""
+ resources:
+ - pods
+ - services
+ - endpoints
+ verbs:
+ - get
+ - list
+ - watch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ template "metallb.fullname" . }}-prometheus
+ namespace: {{ .Release.Namespace | quote }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: {{ template "metallb.fullname" . }}-prometheus
+subjects:
+ - kind: ServiceAccount
+ name: {{ required ".Values.prometheus.serviceAccount must be defined when .Values.prometheus.serviceMonitor.enabled == true" .Values.prometheus.serviceAccount }}
+ namespace: {{ required ".Values.prometheus.namespace must be defined when .Values.prometheus.serviceMonitor.enabled == true" .Values.prometheus.namespace }}
+{{- end }}
+{{- end }}
diff --git a/metallb-chart/templates/speaker.yaml b/metallb-chart/templates/speaker.yaml
new file mode 100644
index 0000000..567d820
--- /dev/null
+++ b/metallb-chart/templates/speaker.yaml
@@ -0,0 +1,568 @@
+{{- if .Values.speaker.frr.enabled }}
+{{- if or .Values.frrk8s.enabled .Values.frrk8s.external }}
+{{- fail "speaker.frr.enabled and frrk8s.enabled / external are mutually exclusive!" }}
+{{- end }}
+{{- end }}
+
+{{- if and .Values.frrk8s.enabled .Values.frrk8s.external }}
+{{- fail "frrk8s.enabled frrk8s.external are mutually exclusive!" }}
+{{- end }}
+
+{{- if .Values.speaker.frr.enabled }}
+
+# FRR expects to have these files owned by frr:frr on startup.
+# Having them in a ConfigMap allows us to modify behaviors: for example enabling more daemons on startup.
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ template "metallb.fullname" . }}-frr-startup
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+ app.kubernetes.io/component: speaker
+data:
+ daemons: |
+ # This file tells the frr package which daemons to start.
+ #
+ # Sample configurations for these daemons can be found in
+ # /usr/share/doc/frr/examples/.
+ #
+ # ATTENTION:
+ #
+ # When activating a daemon for the first time, a config file, even if it is
+ # empty, has to be present *and* be owned by the user and group "frr", else
+ # the daemon will not be started by /etc/init.d/frr. The permissions should
+ # be u=rw,g=r,o=.
+ # When using "vtysh" such a config file is also needed. It should be owned by
+ # group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too.
+ #
+ # The watchfrr and zebra daemons are always started.
+ #
+ bgpd=yes
+ ospfd=no
+ ospf6d=no
+ ripd=no
+ ripngd=no
+ isisd=no
+ pimd=no
+ ldpd=no
+ nhrpd=no
+ eigrpd=no
+ babeld=no
+ sharpd=no
+ pbrd=no
+ bfdd=yes
+ fabricd=no
+ vrrpd=no
+
+ #
+ # If this option is set the /etc/init.d/frr script automatically loads
+ # the config via "vtysh -b" when the servers are started.
+ # Check /etc/pam.d/frr if you intend to use "vtysh"!
+ #
+ vtysh_enable=yes
+ zebra_options=" -A 127.0.0.1 -s 90000000"
+ bgpd_options=" -A 127.0.0.1 -p 0"
+ ospfd_options=" -A 127.0.0.1"
+ ospf6d_options=" -A ::1"
+ ripd_options=" -A 127.0.0.1"
+ ripngd_options=" -A ::1"
+ isisd_options=" -A 127.0.0.1"
+ pimd_options=" -A 127.0.0.1"
+ ldpd_options=" -A 127.0.0.1"
+ nhrpd_options=" -A 127.0.0.1"
+ eigrpd_options=" -A 127.0.0.1"
+ babeld_options=" -A 127.0.0.1"
+ sharpd_options=" -A 127.0.0.1"
+ pbrd_options=" -A 127.0.0.1"
+ staticd_options="-A 127.0.0.1"
+ bfdd_options=" -A 127.0.0.1"
+ fabricd_options="-A 127.0.0.1"
+ vrrpd_options=" -A 127.0.0.1"
+
+ # configuration profile
+ #
+ #frr_profile="traditional"
+ #frr_profile="datacenter"
+
+ #
+ # This is the maximum number of FD's that will be available.
+ # Upon startup this is read by the control files and ulimit
+ # is called. Uncomment and use a reasonable value for your
+ # setup if you are expecting a large number of peers in
+ # say BGP.
+ #MAX_FDS=1024
+
+ # The list of daemons to watch is automatically generated by the init script.
+ #watchfrr_options=""
+
+ # for debugging purposes, you can specify a "wrap" command to start instead
+ # of starting the daemon directly, e.g. to use valgrind on ospfd:
+ # ospfd_wrap="/usr/bin/valgrind"
+ # or you can use "all_wrap" for all daemons, e.g. to use perf record:
+ # all_wrap="/usr/bin/perf record --call-graph -"
+ # the normal daemon command is added to this at the end.
+ vtysh.conf: |+
+ service integrated-vtysh-config
+ frr.conf: |+
+ ! This file gets overriden the first time the speaker renders a config.
+ ! So anything configured here is only temporary.
+ frr version 8.0
+ frr defaults traditional
+ hostname Router
+ line vty
+ log file /etc/frr/frr.log informational
+{{- end }}
+---
+{{- if .Values.speaker.enabled }}
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+ name: {{ template "metallb.fullname" . }}-speaker
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+ app.kubernetes.io/component: speaker
+ {{- range $key, $value := .Values.speaker.labels }}
+ {{ $key }}: {{ $value | quote }}
+ {{- end }}
+spec:
+ {{- if .Values.speaker.updateStrategy }}
+ updateStrategy: {{- toYaml .Values.speaker.updateStrategy | nindent 4 }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "metallb.selectorLabels" . | nindent 6 }}
+ app.kubernetes.io/component: speaker
+ template:
+ metadata:
+ {{- if or .Values.prometheus.scrapeAnnotations .Values.speaker.podAnnotations }}
+ annotations:
+ {{- if .Values.prometheus.scrapeAnnotations }}
+ prometheus.io/scrape: "true"
+ {{- if not .Values.speaker.frr.enabled }}
+ prometheus.io/port: "{{ .Values.prometheus.metricsPort }}"
+ {{- end }}
+ {{- end }}
+ {{- with .Values.speaker.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- end }}
+ labels:
+ {{- include "metallb.selectorLabels" . | nindent 8 }}
+ app.kubernetes.io/component: speaker
+ {{- range $key, $value := .Values.speaker.labels }}
+ {{ $key }}: {{ $value | quote }}
+ {{- end }}
+ spec:
+ {{- if .Values.speaker.runtimeClassName }}
+ runtimeClassName: {{ .Values.speaker.runtimeClassName }}
+ {{- end }}
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ template "metallb.speaker.serviceAccountName" . }}
+ terminationGracePeriodSeconds: 0
+ hostNetwork: true
+ {{- if .Values.speaker.securityContext }}
+ securityContext:
+ {{- toYaml .Values.speaker.securityContext | nindent 8 }}
+ {{- end }}
+ volumes:
+ {{- if .Values.prometheus.speakerMetricsTLSSecret }}
+ - name: metrics-certs
+ secret:
+ secretName: {{ .Values.prometheus.speakerMetricsTLSSecret }}
+ {{- end }}
+ {{- if .Values.speaker.memberlist.enabled }}
+ - name: memberlist
+ secret:
+ secretName: {{ include "metallb.secretName" . }}
+ defaultMode: 420
+ {{- end }}
+ {{- if .Values.speaker.excludeInterfaces.enabled }}
+ - name: metallb-excludel2
+ configMap:
+ defaultMode: 256
+ name: metallb-excludel2
+ {{- end }}
+ {{- if .Values.speaker.frr.enabled }}
+ - name: frr-sockets
+ emptyDir: {}
+ - name: frr-startup
+ configMap:
+ name: {{ template "metallb.fullname" . }}-frr-startup
+ - name: frr-conf
+ emptyDir: {}
+ - name: reloader
+ emptyDir: {}
+ - name: metrics
+ emptyDir: {}
+ initContainers:
+ # Copies the initial config files with the right permissions to the shared volume.
+ - name: cp-frr-files
+ image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }}
+ securityContext:
+ runAsUser: 100
+ runAsGroup: 101
+ command: ["/bin/sh", "-c", "cp -rLf /tmp/frr/* /etc/frr/"]
+ volumeMounts:
+ - name: frr-startup
+ mountPath: /tmp/frr
+ - name: frr-conf
+ mountPath: /etc/frr
+ # Copies the reloader to the shared volume between the speaker and reloader.
+ - name: cp-reloader
+ image: {{ .Values.speaker.image.repository }}:{{ .Values.speaker.image.tag | default .Chart.AppVersion }}
+ command: ["/cp-tool","/frr-reloader.sh","/etc/frr_reloader/frr-reloader.sh"]
+ volumeMounts:
+ - name: reloader
+ mountPath: /etc/frr_reloader
+ # Copies the metrics exporter
+ - name: cp-metrics
+ image: {{ .Values.speaker.image.repository }}:{{ .Values.speaker.image.tag | default .Chart.AppVersion }}
+ command: ["/cp-tool","/frr-metrics","/etc/frr_metrics/frr-metrics"]
+ volumeMounts:
+ - name: metrics
+ mountPath: /etc/frr_metrics
+ shareProcessNamespace: true
+ {{- end }}
+ containers:
+ - name: speaker
+ image: {{ .Values.speaker.image.repository }}:{{ .Values.speaker.image.tag | default .Chart.AppVersion }}
+ {{- if .Values.speaker.image.pullPolicy }}
+ imagePullPolicy: {{ .Values.speaker.image.pullPolicy }}
+ {{- end }}
+ {{- if .Values.speaker.command }}
+ command:
+ - {{ .Values.speaker.command }}
+ {{- end }}
+ args:
+ - --port={{ .Values.prometheus.metricsPort }}
+ {{- with .Values.speaker.logLevel }}
+ - --log-level={{ . }}
+ {{- end }}
+ {{- if .Values.loadBalancerClass }}
+ - --lb-class={{ .Values.loadBalancerClass }}
+ {{- end }}
+ {{- if .Values.speaker.wanConfig }}
+ - --ml-wan-config
+ {{- end }}
+ {{- if .Values.speaker.ignoreExcludeLB}}
+ - --ignore-exclude-lb
+ {{- end }}
+ {{- if .Values.prometheus.secureMetricsPort }}
+ - --host=localhost
+ {{- end }}
+ {{- if .Values.frrk8s.external }}
+ - --frrk8s-namespace={{ required "namespace is required when frrk8s is external" .Values.frrk8s.namespace }}
+ {{- end }}
+ env:
+ - name: METALLB_NODE_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: spec.nodeName
+ - name: METALLB_HOST
+ valueFrom:
+ fieldRef:
+ fieldPath: status.hostIP
+ {{- if .Values.speaker.memberlist.enabled }}
+ {{- if .Values.speaker.memberlist.mlBindAddrOverride }}
+ - name: METALLB_ML_BIND_ADDR
+ value: "{{ .Values.speaker.memberlist.mlBindAddrOverride }}"
+ {{ else }}
+ - name: METALLB_ML_BIND_ADDR
+ valueFrom:
+ fieldRef:
+ fieldPath: status.podIP
+ {{ end }}
+ - name: METALLB_ML_LABELS
+ value: "app.kubernetes.io/name={{ include "metallb.name" . }},app.kubernetes.io/component=speaker"
+ - name: METALLB_ML_BIND_PORT
+ value: "{{ .Values.speaker.memberlist.mlBindPort }}"
+ - name: METALLB_ML_SECRET_KEY_PATH
+ value: "{{ .Values.speaker.memberlist.mlSecretKeyPath }}"
+ {{- end }}
+ {{- if .Values.speaker.frr.enabled }}
+ - name: FRR_CONFIG_FILE
+ value: /etc/frr_reloader/frr.conf
+ - name: FRR_RELOADER_PID_FILE
+ value: /etc/frr_reloader/reloader.pid
+ - name: METALLB_BGP_TYPE
+ value: frr
+ {{- end }}
+ {{- if or .Values.frrk8s.enabled .Values.frrk8s.external }}
+ - name: METALLB_BGP_TYPE
+ value: frr-k8s
+ {{- end }}
+ - name: METALLB_POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ ports:
+ - name: monitoring
+ containerPort: {{ .Values.prometheus.metricsPort }}
+ {{- if .Values.speaker.memberlist.enabled }}
+ - name: memberlist-tcp
+ containerPort: {{ .Values.speaker.memberlist.mlBindPort }}
+ protocol: TCP
+ - name: memberlist-udp
+ containerPort: {{ .Values.speaker.memberlist.mlBindPort }}
+ protocol: UDP
+ {{- end }}
+ {{- if .Values.speaker.livenessProbe.enabled }}
+ livenessProbe:
+ httpGet:
+ {{- if .Values.prometheus.secureMetricsPort }}
+ host: localhost
+ {{- end }}
+ path: /metrics
+ port: monitoring
+ initialDelaySeconds: {{ .Values.speaker.livenessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.speaker.livenessProbe.periodSeconds }}
+ timeoutSeconds: {{ .Values.speaker.livenessProbe.timeoutSeconds }}
+ successThreshold: {{ .Values.speaker.livenessProbe.successThreshold }}
+ failureThreshold: {{ .Values.speaker.livenessProbe.failureThreshold }}
+ {{- end }}
+ {{- if .Values.speaker.readinessProbe.enabled }}
+ readinessProbe:
+ httpGet:
+ {{- if .Values.prometheus.secureMetricsPort }}
+ host: localhost
+ {{- end }}
+ path: /metrics
+ port: monitoring
+ initialDelaySeconds: {{ .Values.speaker.readinessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.speaker.readinessProbe.periodSeconds }}
+ timeoutSeconds: {{ .Values.speaker.readinessProbe.timeoutSeconds }}
+ successThreshold: {{ .Values.speaker.readinessProbe.successThreshold }}
+ failureThreshold: {{ .Values.speaker.readinessProbe.failureThreshold }}
+ {{- end }}
+ {{- with .Values.speaker.resources }}
+ resources:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ securityContext:
+ allowPrivilegeEscalation: false
+ readOnlyRootFilesystem: true
+ capabilities:
+ drop:
+ - ALL
+ add:
+ - NET_RAW
+ {{- if or .Values.speaker.frr.enabled .Values.speaker.memberlist.enabled .Values.speaker.excludeInterfaces.enabled }}
+ volumeMounts:
+ {{- if .Values.speaker.memberlist.enabled }}
+ - name: memberlist
+ mountPath: {{ .Values.speaker.memberlist.mlSecretKeyPath }}
+ {{- end }}
+ {{- if .Values.speaker.frr.enabled }}
+ - name: reloader
+ mountPath: /etc/frr_reloader
+ {{- end }}
+ {{- if .Values.speaker.excludeInterfaces.enabled }}
+ - name: metallb-excludel2
+ mountPath: /etc/metallb
+ {{- end }}
+ {{- end }}
+ {{- if .Values.speaker.frr.enabled }}
+ - name: frr
+ securityContext:
+ capabilities:
+ add:
+ - NET_ADMIN
+ - NET_RAW
+ - SYS_ADMIN
+ - NET_BIND_SERVICE
+ image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }}
+ {{- if .Values.speaker.frr.image.pullPolicy }}
+ imagePullPolicy: {{ .Values.speaker.frr.image.pullPolicy }}
+ {{- end }}
+ env:
+ - name: TINI_SUBREAPER
+ value: "true"
+ volumeMounts:
+ - name: frr-sockets
+ mountPath: /var/run/frr
+ - name: frr-conf
+ mountPath: /etc/frr
+ # The command is FRR's default entrypoint & waiting for the log file to appear and tailing it.
+ # If the log file isn't created in 60 seconds the tail fails and the container is restarted.
+ # This workaround is needed to have the frr logs as part of kubectl logs -c frr < speaker_pod_name >.
+ command:
+ - /bin/sh
+ - -c
+ - |
+ /sbin/tini -- /usr/lib/frr/docker-start &
+ attempts=0
+ until [[ -f /etc/frr/frr.log || $attempts -eq 60 ]]; do
+ sleep 1
+ attempts=$(( $attempts + 1 ))
+ done
+ tail -f /etc/frr/frr.log
+ {{- with .Values.speaker.frr.resources }}
+ resources:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ {{- if .Values.speaker.livenessProbe.enabled }}
+ livenessProbe:
+ httpGet:
+ {{- if .Values.prometheus.secureMetricsPort }}
+ host: localhost
+ {{- end }}
+ path: livez
+ port: {{ .Values.speaker.frr.metricsPort }}
+ initialDelaySeconds: {{ .Values.speaker.livenessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.speaker.livenessProbe.periodSeconds }}
+ timeoutSeconds: {{ .Values.speaker.livenessProbe.timeoutSeconds }}
+ successThreshold: {{ .Values.speaker.livenessProbe.successThreshold }}
+ failureThreshold: {{ .Values.speaker.livenessProbe.failureThreshold }}
+ {{- end }}
+ {{- if .Values.speaker.startupProbe.enabled }}
+ startupProbe:
+ httpGet:
+ {{- if .Values.prometheus.secureMetricsPort }}
+ host: localhost
+ {{- end }}
+ path: /livez
+ port: {{ .Values.speaker.frr.metricsPort }}
+ failureThreshold: {{ .Values.speaker.startupProbe.failureThreshold }}
+ periodSeconds: {{ .Values.speaker.startupProbe.periodSeconds }}
+ {{- end }}
+ - name: reloader
+ image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }}
+ {{- if .Values.speaker.frr.image.pullPolicy }}
+ imagePullPolicy: {{ .Values.speaker.frr.image.pullPolicy }}
+ {{- end }}
+ command: ["/etc/frr_reloader/frr-reloader.sh"]
+ volumeMounts:
+ - name: frr-sockets
+ mountPath: /var/run/frr
+ - name: frr-conf
+ mountPath: /etc/frr
+ - name: reloader
+ mountPath: /etc/frr_reloader
+ {{- with .Values.speaker.reloader.resources }}
+ resources:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ - name: frr-metrics
+ image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }}
+ command: ["/etc/frr_metrics/frr-metrics"]
+ args:
+ - --metrics-port={{ .Values.speaker.frr.metricsPort }}
+ {{- if .Values.prometheus.secureMetricsPort }}
+ - --host=localhost
+ {{- end }}
+ env:
+ - name: VTYSH_HISTFILE
+ value: /dev/null
+ ports:
+ - containerPort: {{ .Values.speaker.frr.metricsPort }}
+ name: monitoring
+ volumeMounts:
+ - name: frr-sockets
+ mountPath: /var/run/frr
+ - name: frr-conf
+ mountPath: /etc/frr
+ - name: metrics
+ mountPath: /etc/frr_metrics
+ {{- with .Values.speaker.frrMetrics.resources }}
+ resources:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.prometheus.secureMetricsPort }}
+ - name: kube-rbac-proxy
+ image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag }}
+ imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }}
+ args:
+ - --logtostderr
+ - --secure-listen-address=:{{ .Values.prometheus.secureMetricsPort }}
+ - --upstream=http://localhost:{{ .Values.prometheus.metricsPort }}/
+ - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ {{- if .Values.prometheus.speakerMetricsTLSSecret }}
+ - --tls-private-key-file=/etc/metrics/tls.key
+ - --tls-cert-file=/etc/metrics/tls.crt
+ {{- end }}
+ ports:
+ - containerPort: {{ .Values.prometheus.secureMetricsPort }}
+ name: metricshttps
+ resources:
+ requests:
+ cpu: 10m
+ memory: 20Mi
+ terminationMessagePolicy: FallbackToLogsOnError
+ {{- if .Values.prometheus.speakerMetricsTLSSecret }}
+ volumeMounts:
+ - name: metrics-certs
+ mountPath: /etc/metrics
+ readOnly: true
+ {{- end }}
+ {{ end }}
+ {{- if .Values.speaker.frr.enabled }}
+ {{- if .Values.speaker.frr.secureMetricsPort }}
+ - name: kube-rbac-proxy-frr
+ image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag | default .Chart.AppVersion }}
+ imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }}
+ args:
+ - --logtostderr
+ - --secure-listen-address=:{{ .Values.speaker.frr.secureMetricsPort }}
+ - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ - --upstream=http://localhost:{{ .Values.speaker.frr.metricsPort }}/
+ {{- if .Values.prometheus.speakerMetricsTLSSecret }}
+ - --tls-private-key-file=/etc/metrics/tls.key
+ - --tls-cert-file=/etc/metrics/tls.crt
+ {{- end }}
+ ports:
+ - containerPort: {{ .Values.speaker.frr.secureMetricsPort }}
+ name: frrmetricshttps
+ env:
+ - name: METALLB_HOST
+ valueFrom:
+ fieldRef:
+ fieldPath: status.hostIP
+ resources:
+ requests:
+ cpu: 10m
+ memory: 20Mi
+ terminationMessagePolicy: FallbackToLogsOnError
+ {{- if .Values.prometheus.speakerMetricsTLSSecret }}
+ volumeMounts:
+ - name: metrics-certs
+ mountPath: /etc/metrics
+ readOnly: true
+ {{- end }}
+ {{ end }}
+ {{- end }}
+ {{- if .Values.speaker.extraContainers }}
+ {{- toYaml .Values.speaker.extraContainers | nindent 6 }}
+ {{- end }}
+ nodeSelector:
+ "kubernetes.io/os": linux
+ {{- with .Values.speaker.nodeSelector }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.speaker.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- if or .Values.speaker.tolerateMaster .Values.speaker.tolerations }}
+ tolerations:
+ {{- if .Values.speaker.tolerateMaster }}
+ - key: node-role.kubernetes.io/master
+ effect: NoSchedule
+ operator: Exists
+ - key: node-role.kubernetes.io/control-plane
+ effect: NoSchedule
+ operator: Exists
+ {{- end }}
+ {{- with .Values.speaker.tolerations }}
+ {{- toYaml . | nindent 6 }}
+ {{- end }}
+ {{- end }}
+ {{- with .Values.speaker.priorityClassName }}
+ priorityClassName: {{ . | quote }}
+ {{- end }}
+{{- end }}
diff --git a/metallb-chart/templates/webhooks.yaml b/metallb-chart/templates/webhooks.yaml
new file mode 100644
index 0000000..3cdac01
--- /dev/null
+++ b/metallb-chart/templates/webhooks.yaml
@@ -0,0 +1,150 @@
+apiVersion: admissionregistration.k8s.io/v1
+kind: ValidatingWebhookConfiguration
+metadata:
+ name: metallb-webhook-configuration
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+webhooks:
+- admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: metallb-webhook-service
+ namespace: {{ .Release.Namespace }}
+ path: /validate-metallb-io-v1beta2-bgppeer
+ failurePolicy: {{ .Values.crds.validationFailurePolicy }}
+ name: bgppeervalidationwebhook.metallb.io
+ rules:
+ - apiGroups:
+ - metallb.io
+ apiVersions:
+ - v1beta2
+ operations:
+ - CREATE
+ - UPDATE
+ resources:
+ - bgppeers
+ sideEffects: None
+- admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: metallb-webhook-service
+ namespace: {{ .Release.Namespace }}
+ path: /validate-metallb-io-v1beta1-ipaddresspool
+ failurePolicy: {{ .Values.crds.validationFailurePolicy }}
+ name: ipaddresspoolvalidationwebhook.metallb.io
+ rules:
+ - apiGroups:
+ - metallb.io
+ apiVersions:
+ - v1beta1
+ operations:
+ - CREATE
+ - UPDATE
+ resources:
+ - ipaddresspools
+ sideEffects: None
+- admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: metallb-webhook-service
+ namespace: {{ .Release.Namespace }}
+ path: /validate-metallb-io-v1beta1-bgpadvertisement
+ failurePolicy: {{ .Values.crds.validationFailurePolicy }}
+ name: bgpadvertisementvalidationwebhook.metallb.io
+ rules:
+ - apiGroups:
+ - metallb.io
+ apiVersions:
+ - v1beta1
+ operations:
+ - CREATE
+ - UPDATE
+ resources:
+ - bgpadvertisements
+ sideEffects: None
+- admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: metallb-webhook-service
+ namespace: {{ .Release.Namespace }}
+ path: /validate-metallb-io-v1beta1-community
+ failurePolicy: {{ .Values.crds.validationFailurePolicy }}
+ name: communityvalidationwebhook.metallb.io
+ rules:
+ - apiGroups:
+ - metallb.io
+ apiVersions:
+ - v1beta1
+ operations:
+ - CREATE
+ - UPDATE
+ resources:
+ - communities
+ sideEffects: None
+- admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: metallb-webhook-service
+ namespace: {{ .Release.Namespace }}
+ path: /validate-metallb-io-v1beta1-bfdprofile
+ failurePolicy: {{ .Values.crds.validationFailurePolicy }}
+ name: bfdprofilevalidationwebhook.metallb.io
+ rules:
+ - apiGroups:
+ - metallb.io
+ apiVersions:
+ - v1beta1
+ operations:
+ - CREATE
+ - DELETE
+ resources:
+ - bfdprofiles
+ sideEffects: None
+- admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: metallb-webhook-service
+ namespace: {{ .Release.Namespace }}
+ path: /validate-metallb-io-v1beta1-l2advertisement
+ failurePolicy: {{ .Values.crds.validationFailurePolicy }}
+ name: l2advertisementvalidationwebhook.metallb.io
+ rules:
+ - apiGroups:
+ - metallb.io
+ apiVersions:
+ - v1beta1
+ operations:
+ - CREATE
+ - UPDATE
+ resources:
+ - l2advertisements
+ sideEffects: None
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: metallb-webhook-service
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
+spec:
+ ports:
+ - port: 443
+ targetPort: 9443
+ selector:
+ {{- include "metallb.selectorLabels" . | nindent 4 }}
+ app.kubernetes.io/component: controller
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: metallb-webhook-cert
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}
diff --git a/metallb-chart/values.schema.json b/metallb-chart/values.schema.json
new file mode 100644
index 0000000..5015d56
--- /dev/null
+++ b/metallb-chart/values.schema.json
@@ -0,0 +1,448 @@
+{
+ "$schema": "https://json-schema.org/draft-07/schema#",
+ "title": "Values",
+ "type": "object",
+ "definitions": {
+ "prometheusAlert": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "labels": {
+ "type": "object",
+ "additionalProperties": { "type": "string" }
+ }
+ },
+ "required": [ "enabled" ]
+ },
+ "probe": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "failureThreshold": {
+ "type": "integer"
+ },
+ "initialDelaySeconds": {
+ "type": "integer"
+ },
+ "periodSeconds": {
+ "type": "integer"
+ },
+ "successThreshold": {
+ "type": "integer"
+ },
+ "timeoutSeconds": {
+ "type": "integer"
+ }
+ },
+ "required": [
+ "failureThreshold",
+ "initialDelaySeconds",
+ "periodSeconds",
+ "successThreshold",
+ "timeoutSeconds"
+ ]
+ },
+ "component": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "logLevel": {
+ "type": "string",
+ "enum": [ "all", "debug", "info", "warn", "error", "none" ]
+ },
+ "image": {
+ "type": "object",
+ "properties": {
+ "repository": {
+ "type": "string"
+ },
+ "tag": {
+ "anyOf": [
+ { "type": "string" },
+ { "type": "null" }
+ ]
+ },
+ "pullPolicy": {
+ "anyOf": [
+ {
+ "type": "null"
+ },
+ {
+ "type": "string",
+ "enum": [ "Always", "IfNotPresent", "Never" ]
+ }
+ ]
+ }
+ }
+ },
+ "serviceAccount": {
+ "type": "object",
+ "properties": {
+ "create": {
+ "type": "boolean"
+ },
+ "name": {
+ "type": "string"
+ },
+ "annotations": {
+ "type": "object"
+ }
+ }
+ },
+ "resources": {
+ "type": "object"
+ },
+ "nodeSelector": {
+ "type": "object"
+ },
+ "tolerations": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "priorityClassName": {
+ "type":"string"
+ },
+ "runtimeClassName": {
+ "type":"string"
+ },
+ "affinity": {
+ "type": "object"
+ },
+ "podAnnotations": {
+ "type": "object"
+ },
+ "livenessProbe": {
+ "$ref": "#/definitions/probe"
+ },
+ "readinessProbe": {
+ "$ref": "#/definitions/probe"
+ }
+ },
+ "required": [
+ "image",
+ "serviceAccount"
+ ]
+ }
+ },
+ "properties": {
+ "imagePullSecrets": {
+ "description": "Secrets used for pulling images",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ }
+ },
+ "required": [ "name" ],
+ "additionalProperties": false
+ }
+ },
+ "nameOverride": {
+ "description": "Override chart name",
+ "type": "string"
+ },
+ "fullNameOverride": {
+ "description": "Override fully qualified app name",
+ "type": "string"
+ },
+ "configInLine": {
+ "description": "MetalLB configuration",
+ "type": "object"
+ },
+ "loadBalancerClass": {
+ "type":"string"
+ },
+ "rbac": {
+ "description": "RBAC configuration",
+ "type": "object",
+ "properties": {
+ "create": {
+ "description": "Enable RBAC",
+ "type": "boolean"
+ }
+ }
+ },
+ "prometheus": {
+ "description": "Prometheus monitoring config",
+ "type": "object",
+ "properties": {
+ "scrapeAnnotations": { "type": "boolean" },
+ "metricsPort": { "type": "integer" },
+ "secureMetricsPort": { "type": "integer" },
+ "rbacPrometheus": { "type": "boolean" },
+ "serviceAccount": { "type": "string" },
+ "namespace": { "type": "string" },
+ "rbacProxy": {
+ "description": "kube-rbac-proxy configuration",
+ "type": "object",
+ "properties": {
+ "repository": { "type": "string" },
+ "tag": { "type": "string" }
+ }
+ },
+ "podMonitor": {
+ "description": "Prometheus Operator PodMonitors",
+ "type": "object",
+ "properties": {
+ "enabled": { "type": "boolean" },
+ "additionalMonitors": { "type": "object" },
+ "jobLabel": { "type": "string" },
+ "interval": {
+ "anyOf": [
+ { "type": "integer" },
+ { "type": "null" }
+ ]
+ },
+ "metricRelabelings": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "relabelings": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ }
+ }
+ },
+ "serviceMonitor": {
+ "description": "Prometheus Operator ServiceMonitors",
+ "type": "object",
+ "properties": {
+ "enabled": { "type": "boolean" },
+ "jobLabel": { "type": "string" },
+ "interval": {
+ "anyOf": [
+ { "type": "integer" },
+ { "type": "null" }
+ ]
+ },
+ "metricRelabelings": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "relabelings": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ }
+ }
+ },
+ "prometheusRule": {
+ "description": "Prometheus Operator alertmanager alerts",
+ "type": "object",
+ "properties": {
+ "enabled": { "type": "boolean" },
+ "additionalMonitors": { "type": "object" },
+ "staleConfig": { "$ref": "#/definitions/prometheusAlert" },
+ "configNotLoaded": { "$ref": "#/definitions/prometheusAlert" },
+ "addressPoolExhausted": { "$ref": "#/definitions/prometheusAlert" },
+ "addressPoolUsage": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "thresholds": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "percent": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 100
+ },
+ "labels": {
+ "type": "object",
+ "additionalProperties": { "type": "string" }
+ }
+ },
+ "required": [ "percent" ]
+ }
+ }
+ },
+ "required": [ "enabled" ]
+ },
+ "bgpSessionDown": { "$ref": "#/definitions/prometheusAlert" },
+ "extraAlerts": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ }
+ },
+ "required": [
+ "enabled",
+ "staleConfig",
+ "configNotLoaded",
+ "addressPoolExhausted",
+ "addressPoolUsage",
+ "bgpSessionDown"
+ ]
+ }
+ },
+ "required": [ "podMonitor", "prometheusRule" ]
+ },
+ "controller": {
+ "allOf": [
+ { "$ref": "#/definitions/component" },
+ { "description": "MetalLB Controller",
+ "type": "object",
+ "properties": {
+ "strategy": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ }
+ },
+ "required": [ "type" ]
+ },
+ "command" : {
+ "type": "string"
+ },
+ "webhookMode" : {
+ "type": "string"
+ },
+ "extraContainers": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ ]
+ },
+ "speaker": {
+ "allOf": [
+ { "$ref": "#/definitions/component" },
+ { "description": "MetalLB Speaker",
+ "type": "object",
+ "properties": {
+ "tolerateMaster": {
+ "type": "boolean"
+ },
+ "memberlist": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "mlBindPort": {
+ "type": "integer"
+ },
+ "mlBindAddrOverride": {
+ "type": "string"
+ },
+ "mlSecretKeyPath": {
+ "type": "string"
+ }
+ }
+ },
+ "excludeInterfaces": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ }
+ }
+ },
+ "ignoreExcludeLB": {
+ "type": "boolean"
+ },
+ "updateStrategy": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ }
+ },
+ "required": [ "type" ]
+ },
+ "runtimeClassName": {
+ "type": "string"
+ },
+ "securityContext": {
+ "type": "object"
+ },
+ "secretName": {
+ "type": "string"
+ },
+ "frr": {
+ "description": "Install FRR container in speaker deployment",
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "image": { "$ref": "#/definitions/component/properties/image" },
+ "metricsPort": { "type": "integer" },
+ "secureMetricsPort": { "type": "integer" },
+ "resources:": { "type": "object" }
+ },
+ "required": [ "enabled" ]
+ },
+ "command" : {
+ "type": "string"
+ },
+ "reloader": {
+ "type": "object",
+ "properties": {
+ "resources": { "type": "object" }
+ }
+ },
+ "frrMetrics": {
+ "type": "object",
+ "properties": {
+ "resources": { "type": "object" }
+ }
+ },
+ "extraContainers": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ }
+ },
+ "required": [ "tolerateMaster" ]
+ }
+ ]
+ },
+ "crds": {
+ "description": "CRD configuration",
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "description": "Enable CRDs",
+ "type": "boolean"
+ },
+ "validationFailurePolicy": {
+ "description": "Failure policy to use with validating webhooks",
+ "type": "string",
+ "enum": [ "Ignore", "Fail" ]
+ }
+ }
+ }
+ },
+ "required": [
+ "controller",
+ "speaker"
+ ]
+}
diff --git a/metallb-chart/values.yaml b/metallb-chart/values.yaml
new file mode 100644
index 0000000..49bd819
--- /dev/null
+++ b/metallb-chart/values.yaml
@@ -0,0 +1,380 @@
+# Default values for metallb.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+# MetalLB supports LoadBalancerClass, which allows multiple load balancer implementations to co-exist.
+# In order to set the loadbalancer class MetalLB should be listening for, the --lb-class=
+# parameter must be provided to both the speaker and the controller.
+loadBalancerClass: ""
+
+# To configure MetalLB, you must specify ONE of the following two
+# options.
+
+rbac:
+ # create specifies whether to install and use RBAC rules.
+ create: true
+
+prometheus:
+ # scrape annotations specifies whether to add Prometheus metric
+ # auto-collection annotations to pods. See
+ # https://github.com/prometheus/prometheus/blob/release-2.1/documentation/examples/prometheus-kubernetes.yml
+ # for a corresponding Prometheus configuration. Alternatively, you
+ # may want to use the Prometheus Operator
+ # (https://github.com/coreos/prometheus-operator) for more powerful
+ # monitoring configuration. If you use the Prometheus operator, this
+ # can be left at false.
+ scrapeAnnotations: false
+
+ # port both controller and speaker will listen on for metrics
+ metricsPort: 7472
+
+ # if set, enables rbac proxy on the controller and speaker to expose
+ # the metrics via tls.
+ # secureMetricsPort: 9120
+
+ # the name of the secret to be mounted in the speaker pod
+ # to expose the metrics securely. If not present, a self signed
+ # certificate to be used.
+ speakerMetricsTLSSecret: ""
+
+ # the name of the secret to be mounted in the controller pod
+ # to expose the metrics securely. If not present, a self signed
+ # certificate to be used.
+ controllerMetricsTLSSecret: ""
+
+ # prometheus doens't have the permission to scrape all namespaces so we give it permission to scrape metallb's one
+ rbacPrometheus: true
+
+ # the service account used by prometheus
+ # required when " .Values.prometheus.rbacPrometheus == true " and " .Values.prometheus.podMonitor.enabled=true or prometheus.serviceMonitor.enabled=true "
+ serviceAccount: ""
+
+ # the namespace where prometheus is deployed
+ # required when " .Values.prometheus.rbacPrometheus == true " and " .Values.prometheus.podMonitor.enabled=true or prometheus.serviceMonitor.enabled=true "
+ namespace: ""
+
+ # the image to be used for the kuberbacproxy container
+ rbacProxy:
+ repository: "%%IMG_REPO%%/%%IMG_PREFIX%%kube-rbac-proxy"
+ tag: "v0.18.0"
+ pullPolicy: IfNotPresent
+
+ # Prometheus Operator PodMonitors
+ podMonitor:
+ # enable support for Prometheus Operator
+ enabled: false
+
+ # optional additionnal labels for podMonitors
+ additionalLabels: {}
+
+ # optional annotations for podMonitors
+ annotations: {}
+
+ # Job label for scrape target
+ jobLabel: "app.kubernetes.io/name"
+
+ # Scrape interval. If not set, the Prometheus default scrape interval is used.
+ interval:
+
+ # metric relabel configs to apply to samples before ingestion.
+ metricRelabelings: []
+ # - action: keep
+ # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'
+ # sourceLabels: [__name__]
+
+ # relabel configs to apply to samples before ingestion.
+ relabelings: []
+ # - sourceLabels: [__meta_kubernetes_pod_node_name]
+ # separator: ;
+ # regex: ^(.*)$
+ # target_label: nodename
+ # replacement: $1
+ # action: replace
+
+ # Prometheus Operator ServiceMonitors. To be used as an alternative
+ # to podMonitor, supports secure metrics.
+ serviceMonitor:
+ # enable support for Prometheus Operator
+ enabled: false
+
+ speaker:
+ # optional additional labels for the speaker serviceMonitor
+ additionalLabels: {}
+ # optional additional annotations for the speaker serviceMonitor
+ annotations: {}
+ # optional tls configuration for the speaker serviceMonitor, in case
+ # secure metrics are enabled.
+ tlsConfig:
+ insecureSkipVerify: true
+
+ controller:
+ # optional additional labels for the controller serviceMonitor
+ additionalLabels: {}
+ # optional additional annotations for the controller serviceMonitor
+ annotations: {}
+ # optional tls configuration for the controller serviceMonitor, in case
+ # secure metrics are enabled.
+ tlsConfig:
+ insecureSkipVerify: true
+
+ # Job label for scrape target
+ jobLabel: "app.kubernetes.io/name"
+
+ # Scrape interval. If not set, the Prometheus default scrape interval is used.
+ interval:
+
+ # metric relabel configs to apply to samples before ingestion.
+ metricRelabelings: []
+ # - action: keep
+ # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'
+ # sourceLabels: [__name__]
+
+ # relabel configs to apply to samples before ingestion.
+ relabelings: []
+ # - sourceLabels: [__meta_kubernetes_pod_node_name]
+ # separator: ;
+ # regex: ^(.*)$
+ # target_label: nodename
+ # replacement: $1
+ # action: replace
+
+ # Prometheus Operator alertmanager alerts
+ prometheusRule:
+ # enable alertmanager alerts
+ enabled: false
+
+ # optional additionnal labels for prometheusRules
+ additionalLabels: {}
+
+ # optional annotations for prometheusRules
+ annotations: {}
+
+ # MetalLBStaleConfig
+ staleConfig:
+ enabled: true
+ labels:
+ severity: warning
+
+ # MetalLBConfigNotLoaded
+ configNotLoaded:
+ enabled: true
+ labels:
+ severity: warning
+
+ # MetalLBAddressPoolExhausted
+ addressPoolExhausted:
+ enabled: true
+ labels:
+ severity: alert
+
+ addressPoolUsage:
+ enabled: true
+ thresholds:
+ - percent: 75
+ labels:
+ severity: warning
+ - percent: 85
+ labels:
+ severity: warning
+ - percent: 95
+ labels:
+ severity: alert
+
+ # MetalLBBGPSessionDown
+ bgpSessionDown:
+ enabled: true
+ labels:
+ severity: alert
+
+ extraAlerts: []
+
+# controller contains configuration specific to the MetalLB cluster
+# controller.
+controller:
+ enabled: true
+ # -- Controller log level. Must be one of: `all`, `debug`, `info`, `warn`, `error` or `none`
+ logLevel: info
+ # command: /controller
+ # webhookMode: enabled
+ image:
+ repository: "%%IMG_REPO%%/%%IMG_PREFIX%%metallb-controller"
+ tag: "v0.14.8"
+ pullPolicy: IfNotPresent
+ ## @param controller.updateStrategy.type Metallb controller deployment strategy type.
+ ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy
+ ## e.g:
+ ## strategy:
+ ## type: RollingUpdate
+ ## rollingUpdate:
+ ## maxSurge: 25%
+ ## maxUnavailable: 25%
+ ##
+ strategy:
+ type: RollingUpdate
+ serviceAccount:
+ # Specifies whether a ServiceAccount should be created
+ create: true
+ # The name of the ServiceAccount to use. If not set and create is
+ # true, a name is generated using the fullname template
+ name: ""
+ annotations: {}
+ securityContext:
+ runAsNonRoot: true
+ # nobody
+ runAsUser: 65534
+ fsGroup: 65534
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
+ seccompProfile:
+ type: RuntimeDefault
+ resources: {}
+ # limits:
+ # cpu: 100m
+ # memory: 100Mi
+ nodeSelector: {}
+ tolerations: []
+ priorityClassName: ""
+ runtimeClassName: ""
+ affinity: {}
+ podAnnotations: {}
+ labels: {}
+ livenessProbe:
+ enabled: true
+ failureThreshold: 3
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 1
+ readinessProbe:
+ enabled: true
+ failureThreshold: 3
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 1
+ tlsMinVersion: "VersionTLS12"
+ tlsCipherSuites: ""
+
+ extraContainers: []
+
+# speaker contains configuration specific to the MetalLB speaker
+# daemonset.
+speaker:
+ enabled: true
+ # command: /speaker
+ # -- Speaker log level. Must be one of: `all`, `debug`, `info`, `warn`, `error` or `none`
+ logLevel: info
+ tolerateMaster: true
+ memberlist:
+ enabled: true
+ mlBindPort: 7946
+ mlBindAddrOverride: ""
+ mlSecretKeyPath: "/etc/ml_secret_key"
+ excludeInterfaces:
+ enabled: true
+ # ignore the exclude-from-external-loadbalancer label
+ ignoreExcludeLB: false
+
+ image:
+ repository: "%%IMG_REPO%%/%%IMG_PREFIX%%metallb-speaker"
+ tag: "v0.14.8"
+ pullPolicy: IfNotPresent
+ ## @param speaker.updateStrategy.type Speaker daemonset strategy type
+ ## ref: https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/
+ ##
+ updateStrategy:
+ ## StrategyType
+ ## Can be set to RollingUpdate or OnDelete
+ ##
+ type: RollingUpdate
+ serviceAccount:
+ # Specifies whether a ServiceAccount should be created
+ create: true
+ # The name of the ServiceAccount to use. If not set and create is
+ # true, a name is generated using the fullname template
+ name: ""
+ annotations: {}
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
+ seccompProfile:
+ type: RuntimeDefault
+ ## Defines a secret name for the controller to generate a memberlist encryption secret
+ ## By default secretName: {{ "metallb.fullname" }}-memberlist
+ ##
+ # secretName:
+ resources: {}
+ # limits:
+ # cpu: 100m
+ # memory: 100Mi
+ nodeSelector: {}
+ tolerations: []
+ priorityClassName: ""
+ affinity: {}
+ ## Selects which runtime class will be used by the pod.
+ runtimeClassName: ""
+ podAnnotations: {}
+ labels: {}
+ livenessProbe:
+ enabled: true
+ failureThreshold: 3
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 1
+ readinessProbe:
+ enabled: true
+ failureThreshold: 3
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 1
+ startupProbe:
+ enabled: true
+ failureThreshold: 30
+ periodSeconds: 5
+ # frr contains configuration specific to the MetalLB FRR container,
+ # for speaker running alongside FRR.
+ frr:
+ enabled: false
+ image:
+ repository: "%%IMG_REPO%%/%%IMG_PREFIX%%frr"
+ tag: "8.4"
+ pullPolicy: IfNotPresent
+ metricsPort: 7473
+ resources: {}
+
+ # if set, enables a rbac proxy sidecar container on the speaker to
+ # expose the frr metrics via tls.
+ # secureMetricsPort: 9121
+
+
+ reloader:
+ resources: {}
+
+ frrMetrics:
+ resources: {}
+
+ extraContainers: []
+
+crds:
+ enabled: true
+ validationFailurePolicy: Fail
+
+# frrk8s contains the configuration related to using an frrk8s instance
+# (github.com/metallb/frr-k8s) as the backend for the BGP implementation.
+# This allows configuring additional frr parameters in combination to those
+# applied by MetalLB.
+frrk8s:
+ # if set, enables frrk8s as a backend. This is mutually exclusive to frr
+ # mode.
+ enabled: false
+ external: false
+ namespace: ""
diff --git a/metallb-controller-image/Dockerfile b/metallb-controller-image/Dockerfile
new file mode 100644
index 0000000..2b48337
--- /dev/null
+++ b/metallb-controller-image/Dockerfile
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: Apache-2.0
+#!BuildTag: %%IMG_PREFIX%%metallb-controller:v%%metallb-controller_version%%
+#!BuildTag: %%IMG_PREFIX%%metallb-controller:v%%metallb-controller_version%%-%RELEASE%
+#!BuildVersion: 15.6
+ARG SLE_VERSION
+FROM registry.suse.com/bci/bci-micro:$SLE_VERSION AS micro
+
+FROM registry.suse.com/bci/bci-base:$SLE_VERSION AS base
+COPY --from=micro / /installroot/
+RUN zypper --installroot /installroot --non-interactive install --no-recommends metallb-controller; zypper -n clean; rm -rf /var/log/*
+
+FROM micro AS final
+# Define labels according to https://en.opensuse.org/Building_derived_containers
+# labelprefix=com.suse.application.metallb
+LABEL org.opencontainers.image.authors="SUSE LLC (https://www.suse.com/)"
+LABEL org.opencontainers.image.title="SLE Metallb Controller Container Image"
+LABEL org.opencontainers.image.description="metallb-controller based on the SLE Base Container Image."
+LABEL org.opencontainers.image.version="%%metallb-controller_version%%"
+LABEL org.opencontainers.image.url="https://www.suse.com/products/server/"
+LABEL org.opencontainers.image.created="%BUILDTIME%"
+LABEL org.opencontainers.image.vendor="SUSE LLC"
+LABEL org.opensuse.reference="%%IMG_REPO%%/%%IMG_PREFIX%%metallb-controller:v%%metallb-controller_version%%-%RELEASE%"
+LABEL org.openbuildservice.disturl="%DISTURL%"
+LABEL com.suse.supportlevel="l3"
+LABEL com.suse.eula="SUSE Combined EULA February 2024"
+LABEL com.suse.lifecycle-url="https://www.suse.com/lifecycle"
+LABEL com.suse.image-type="application"
+LABEL com.suse.release-stage="released"
+# endlabelprefix
+
+COPY --from=base /installroot /
+ENTRYPOINT ["/controller"]
diff --git a/metallb-controller-image/_service b/metallb-controller-image/_service
new file mode 100644
index 0000000..11af884
--- /dev/null
+++ b/metallb-controller-image/_service
@@ -0,0 +1,17 @@
+
+
+
+
+ Dockerfile
+ %%metallb-controller_version%%
+ metallb-controller
+ patch
+
+
+ Dockerfile
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+
\ No newline at end of file
diff --git a/metallb-speaker-image/Dockerfile b/metallb-speaker-image/Dockerfile
new file mode 100644
index 0000000..6a9157f
--- /dev/null
+++ b/metallb-speaker-image/Dockerfile
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: Apache-2.0
+#!BuildTag: %%IMG_PREFIX%%metallb-speaker:v%%metallb-speaker_version%%
+#!BuildTag: %%IMG_PREFIX%%metallb-speaker:v%%metallb-speaker_version%%-%RELEASE%
+#!BuildVersion: 15.6
+ARG SLE_VERSION
+FROM registry.suse.com/bci/bci-micro:$SLE_VERSION AS micro
+
+FROM registry.suse.com/bci/bci-base:$SLE_VERSION AS base
+COPY --from=micro / /installroot/
+RUN zypper --installroot /installroot --non-interactive install --no-recommends metallb-speaker; zypper -n clean; rm -rf /var/log/*
+
+FROM micro AS final
+# Define labels according to https://en.opensuse.org/Building_derived_containers
+# labelprefix=com.suse.application.metallb
+LABEL org.opencontainers.image.authors="SUSE LLC (https://www.suse.com/)"
+LABEL org.opencontainers.image.title="SLE Metallb Speaker Container Image"
+LABEL org.opencontainers.image.description="metallb-speaker based on the SLE Base Container Image."
+LABEL org.opencontainers.image.version="%%metallb-speaker_version%%"
+LABEL org.opencontainers.image.url="https://www.suse.com/products/server/"
+LABEL org.opencontainers.image.created="%BUILDTIME%"
+LABEL org.opencontainers.image.vendor="SUSE LLC"
+LABEL org.opensuse.reference="%%IMG_REPO%%/%%IMG_PREFIX%%metallb-speaker:v%%metallb-speaker_version%%-%RELEASE%"
+LABEL org.openbuildservice.disturl="%DISTURL%"
+LABEL com.suse.supportlevel="l3"
+LABEL com.suse.eula="SUSE Combined EULA February 2024"
+LABEL com.suse.lifecycle-url="https://www.suse.com/lifecycle"
+LABEL com.suse.image-type="application"
+LABEL com.suse.release-stage="released"
+# endlabelprefix
+
+COPY --from=base /installroot /
+ENTRYPOINT ["/speaker"]
diff --git a/metallb-speaker-image/_service b/metallb-speaker-image/_service
new file mode 100644
index 0000000..1ed0813
--- /dev/null
+++ b/metallb-speaker-image/_service
@@ -0,0 +1,17 @@
+
+
+
+
+ Dockerfile
+ %%metallb-speaker_version%%
+ metallb-speaker
+ patch
+
+
+ Dockerfile
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+
\ No newline at end of file
diff --git a/sriov-crd-chart/Chart.yaml b/sriov-crd-chart/Chart.yaml
new file mode 100644
index 0000000..5953b18
--- /dev/null
+++ b/sriov-crd-chart/Chart.yaml
@@ -0,0 +1,13 @@
+#!BuildTag: %%IMG_PREFIX%%sriov-crd-chart:1.3.0-%RELEASE%
+#!BuildTag: %%IMG_PREFIX%%sriov-crd-chart:1.3.0
+annotations:
+ catalog.cattle.io/experimental: "true"
+ catalog.cattle.io/hidden: "true"
+ catalog.cattle.io/namespace: cattle-sriov-system
+ catalog.cattle.io/permits-os: linux
+ catalog.cattle.io/release-name: sriov-crd
+apiVersion: v2
+description: Installs the CRDs for the SR-IOV operator
+name: sriov-crd
+type: application
+version: 1.3.0
diff --git a/sriov-crd-chart/_service b/sriov-crd-chart/_service
new file mode 100644
index 0000000..6b8f891
--- /dev/null
+++ b/sriov-crd-chart/_service
@@ -0,0 +1,8 @@
+
+
+
+ Chart.yaml
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+
+
diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_ovsnetworks.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_ovsnetworks.yaml
new file mode 100644
index 0000000..7e7d9ba
--- /dev/null
+++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_ovsnetworks.yaml
@@ -0,0 +1,105 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: ovsnetworks.sriovnetwork.openshift.io
+spec:
+ group: sriovnetwork.openshift.io
+ names:
+ kind: OVSNetwork
+ listKind: OVSNetworkList
+ plural: ovsnetworks
+ singular: ovsnetwork
+ scope: Namespaced
+ versions:
+ - name: v1
+ schema:
+ openAPIV3Schema:
+ description: OVSNetwork is the Schema for the ovsnetworks API
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: OVSNetworkSpec defines the desired state of OVSNetwork
+ properties:
+ bridge:
+ description: |-
+ name of the OVS bridge, if not set OVS will automatically select bridge
+ based on VF PCI address
+ type: string
+ capabilities:
+ description: |-
+ Capabilities to be configured for this network.
+ Capabilities supported: (mac|ips), e.g. '{"mac": true}'
+ type: string
+ interfaceType:
+ description: The type of interface on ovs.
+ type: string
+ ipam:
+ description: IPAM configuration to be used for this network.
+ type: string
+ metaPlugins:
+ description: MetaPluginsConfig configuration to be used in order to
+ chain metaplugins
+ type: string
+ mtu:
+ description: Mtu for the OVS port
+ type: integer
+ networkNamespace:
+ description: Namespace of the NetworkAttachmentDefinition custom resource
+ type: string
+ resourceName:
+ description: OVS Network device plugin endpoint resource name
+ type: string
+ trunk:
+ description: Trunk configuration for the OVS port
+ items:
+ description: TrunkConfig contains configuration for bridge trunk
+ properties:
+ id:
+ maximum: 4095
+ minimum: 0
+ type: integer
+ maxID:
+ maximum: 4095
+ minimum: 0
+ type: integer
+ minID:
+ maximum: 4095
+ minimum: 0
+ type: integer
+ type: object
+ type: array
+ vlan:
+ description: Vlan to assign for the OVS port
+ maximum: 4095
+ minimum: 0
+ type: integer
+ required:
+ - resourceName
+ type: object
+ status:
+ description: OVSNetworkStatus defines the observed state of OVSNetwork
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovibnetworks.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovibnetworks.yaml
new file mode 100644
index 0000000..8a4f88c
--- /dev/null
+++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovibnetworks.yaml
@@ -0,0 +1,78 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: sriovibnetworks.sriovnetwork.openshift.io
+spec:
+ group: sriovnetwork.openshift.io
+ names:
+ kind: SriovIBNetwork
+ listKind: SriovIBNetworkList
+ plural: sriovibnetworks
+ singular: sriovibnetwork
+ scope: Namespaced
+ versions:
+ - name: v1
+ schema:
+ openAPIV3Schema:
+ description: SriovIBNetwork is the Schema for the sriovibnetworks API
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: SriovIBNetworkSpec defines the desired state of SriovIBNetwork
+ properties:
+ capabilities:
+ description: |-
+ Capabilities to be configured for this network.
+ Capabilities supported: (infinibandGUID), e.g. '{"infinibandGUID": true}'
+ type: string
+ ipam:
+ description: IPAM configuration to be used for this network.
+ type: string
+ linkState:
+ description: VF link state (enable|disable|auto)
+ enum:
+ - auto
+ - enable
+ - disable
+ type: string
+ metaPlugins:
+ description: |-
+ MetaPluginsConfig configuration to be used in order to chain metaplugins to the sriov interface returned
+ by the operator.
+ type: string
+ networkNamespace:
+ description: Namespace of the NetworkAttachmentDefinition custom resource
+ type: string
+ resourceName:
+ description: SRIOV Network device plugin endpoint resource name
+ type: string
+ required:
+ - resourceName
+ type: object
+ status:
+ description: SriovIBNetworkStatus defines the observed state of SriovIBNetwork
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml
new file mode 100644
index 0000000..47aacdd
--- /dev/null
+++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml
@@ -0,0 +1,209 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: sriovnetworknodepolicies.sriovnetwork.openshift.io
+spec:
+ group: sriovnetwork.openshift.io
+ names:
+ kind: SriovNetworkNodePolicy
+ listKind: SriovNetworkNodePolicyList
+ plural: sriovnetworknodepolicies
+ singular: sriovnetworknodepolicy
+ scope: Namespaced
+ versions:
+ - name: v1
+ schema:
+ openAPIV3Schema:
+ description: SriovNetworkNodePolicy is the Schema for the sriovnetworknodepolicies
+ API
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: SriovNetworkNodePolicySpec defines the desired state of SriovNetworkNodePolicy
+ properties:
+ bridge:
+ description: |-
+ contains bridge configuration for matching PFs,
+ valid only for eSwitchMode==switchdev
+ properties:
+ ovs:
+ description: contains configuration for the OVS bridge,
+ properties:
+ bridge:
+ description: contains bridge level settings
+ properties:
+ datapathType:
+ description: configure datapath_type field in the Bridge
+ table in OVSDB
+ type: string
+ externalIDs:
+ additionalProperties:
+ type: string
+ description: IDs to inject to external_ids field in the
+ Bridge table in OVSDB
+ type: object
+ otherConfig:
+ additionalProperties:
+ type: string
+ description: additional options to inject to other_config
+ field in the bridge table in OVSDB
+ type: object
+ type: object
+ uplink:
+ description: contains settings for uplink (PF)
+ properties:
+ interface:
+ description: contains settings for PF interface in the
+ OVS bridge
+ properties:
+ externalIDs:
+ additionalProperties:
+ type: string
+ description: external_ids field in the Interface table
+ in OVSDB
+ type: object
+ options:
+ additionalProperties:
+ type: string
+ description: options field in the Interface table
+ in OVSDB
+ type: object
+ otherConfig:
+ additionalProperties:
+ type: string
+ description: other_config field in the Interface table
+ in OVSDB
+ type: object
+ type:
+ description: type field in the Interface table in
+ OVSDB
+ type: string
+ type: object
+ type: object
+ type: object
+ type: object
+ deviceType:
+ default: netdevice
+ description: The driver type for configured VFs. Allowed value "netdevice",
+ "vfio-pci". Defaults to netdevice.
+ enum:
+ - netdevice
+ - vfio-pci
+ type: string
+ eSwitchMode:
+ description: NIC Device Mode. Allowed value "legacy","switchdev".
+ enum:
+ - legacy
+ - switchdev
+ type: string
+ excludeTopology:
+ description: Exclude device's NUMA node when advertising this resource
+ by SRIOV network device plugin. Default to false.
+ type: boolean
+ externallyManaged:
+ description: don't create the virtual function only allocated them
+ to the device plugin. Defaults to false.
+ type: boolean
+ isRdma:
+ description: RDMA mode. Defaults to false.
+ type: boolean
+ linkType:
+ description: NIC Link Type. Allowed value "eth", "ETH", "ib", and
+ "IB".
+ enum:
+ - eth
+ - ETH
+ - ib
+ - IB
+ type: string
+ mtu:
+ description: MTU of VF
+ minimum: 1
+ type: integer
+ needVhostNet:
+ description: mount vhost-net device. Defaults to false.
+ type: boolean
+ nicSelector:
+ description: NicSelector selects the NICs to be configured
+ properties:
+ deviceID:
+ description: The device hex code of SR-IoV device. Allowed value
+ "0d58", "1572", "158b", "1013", "1015", "1017", "101b".
+ type: string
+ netFilter:
+ description: Infrastructure Networking selection filter. Allowed
+ value "openstack/NetworkID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
+ type: string
+ pfNames:
+ description: Name of SR-IoV PF.
+ items:
+ type: string
+ type: array
+ rootDevices:
+ description: PCI address of SR-IoV PF.
+ items:
+ type: string
+ type: array
+ vendor:
+ description: The vendor hex code of SR-IoV device. Allowed value
+ "8086", "15b3".
+ type: string
+ type: object
+ nodeSelector:
+ additionalProperties:
+ type: string
+ description: NodeSelector selects the nodes to be configured
+ type: object
+ numVfs:
+ description: Number of VFs for each PF
+ minimum: 0
+ type: integer
+ priority:
+ description: Priority of the policy, higher priority policies can
+ override lower ones.
+ maximum: 99
+ minimum: 0
+ type: integer
+ resourceName:
+ description: SRIOV Network device plugin endpoint resource name
+ type: string
+ vdpaType:
+ description: VDPA device type. Allowed value "virtio", "vhost"
+ enum:
+ - virtio
+ - vhost
+ type: string
+ required:
+ - nicSelector
+ - nodeSelector
+ - numVfs
+ - resourceName
+ type: object
+ status:
+ description: SriovNetworkNodePolicyStatus defines the observed state of
+ SriovNetworkNodePolicy
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodestates.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodestates.yaml
new file mode 100644
index 0000000..6ed2486
--- /dev/null
+++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodestates.yaml
@@ -0,0 +1,343 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: sriovnetworknodestates.sriovnetwork.openshift.io
+spec:
+ group: sriovnetwork.openshift.io
+ names:
+ kind: SriovNetworkNodeState
+ listKind: SriovNetworkNodeStateList
+ plural: sriovnetworknodestates
+ singular: sriovnetworknodestate
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .status.syncStatus
+ name: Sync Status
+ type: string
+ - jsonPath: .metadata.annotations.sriovnetwork\.openshift\.io/desired-state
+ name: Desired Sync State
+ type: string
+ - jsonPath: .metadata.annotations.sriovnetwork\.openshift\.io/current-state
+ name: Current Sync State
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1
+ schema:
+ openAPIV3Schema:
+ description: SriovNetworkNodeState is the Schema for the sriovnetworknodestates
+ API
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: SriovNetworkNodeStateSpec defines the desired state of SriovNetworkNodeState
+ properties:
+ bridges:
+ description: Bridges contains list of bridges
+ properties:
+ ovs:
+ items:
+ description: OVSConfigExt contains configuration for the concrete
+ OVS bridge
+ properties:
+ bridge:
+ description: bridge-level configuration for the bridge
+ properties:
+ datapathType:
+ description: configure datapath_type field in the Bridge
+ table in OVSDB
+ type: string
+ externalIDs:
+ additionalProperties:
+ type: string
+ description: IDs to inject to external_ids field in
+ the Bridge table in OVSDB
+ type: object
+ otherConfig:
+ additionalProperties:
+ type: string
+ description: additional options to inject to other_config
+ field in the bridge table in OVSDB
+ type: object
+ type: object
+ name:
+ description: name of the bridge
+ type: string
+ uplinks:
+ description: |-
+ uplink-level bridge configuration for each uplink(PF).
+ currently must contain only one element
+ items:
+ description: OVSUplinkConfigExt contains configuration
+ for the concrete OVS uplink(PF)
+ properties:
+ interface:
+ description: configuration from the Interface OVS
+ table for the PF
+ properties:
+ externalIDs:
+ additionalProperties:
+ type: string
+ description: external_ids field in the Interface
+ table in OVSDB
+ type: object
+ options:
+ additionalProperties:
+ type: string
+ description: options field in the Interface table
+ in OVSDB
+ type: object
+ otherConfig:
+ additionalProperties:
+ type: string
+ description: other_config field in the Interface
+ table in OVSDB
+ type: object
+ type:
+ description: type field in the Interface table
+ in OVSDB
+ type: string
+ type: object
+ name:
+ description: name of the PF interface
+ type: string
+ pciAddress:
+ description: pci address of the PF
+ type: string
+ required:
+ - pciAddress
+ type: object
+ type: array
+ required:
+ - name
+ type: object
+ type: array
+ type: object
+ interfaces:
+ items:
+ properties:
+ eSwitchMode:
+ type: string
+ externallyManaged:
+ type: boolean
+ linkType:
+ type: string
+ mtu:
+ type: integer
+ name:
+ type: string
+ numVfs:
+ type: integer
+ pciAddress:
+ type: string
+ vfGroups:
+ items:
+ properties:
+ deviceType:
+ type: string
+ isRdma:
+ type: boolean
+ mtu:
+ type: integer
+ policyName:
+ type: string
+ resourceName:
+ type: string
+ vdpaType:
+ type: string
+ vfRange:
+ type: string
+ type: object
+ type: array
+ required:
+ - pciAddress
+ type: object
+ type: array
+ type: object
+ status:
+ description: SriovNetworkNodeStateStatus defines the observed state of
+ SriovNetworkNodeState
+ properties:
+ bridges:
+ description: Bridges contains list of bridges
+ properties:
+ ovs:
+ items:
+ description: OVSConfigExt contains configuration for the concrete
+ OVS bridge
+ properties:
+ bridge:
+ description: bridge-level configuration for the bridge
+ properties:
+ datapathType:
+ description: configure datapath_type field in the Bridge
+ table in OVSDB
+ type: string
+ externalIDs:
+ additionalProperties:
+ type: string
+ description: IDs to inject to external_ids field in
+ the Bridge table in OVSDB
+ type: object
+ otherConfig:
+ additionalProperties:
+ type: string
+ description: additional options to inject to other_config
+ field in the bridge table in OVSDB
+ type: object
+ type: object
+ name:
+ description: name of the bridge
+ type: string
+ uplinks:
+ description: |-
+ uplink-level bridge configuration for each uplink(PF).
+ currently must contain only one element
+ items:
+ description: OVSUplinkConfigExt contains configuration
+ for the concrete OVS uplink(PF)
+ properties:
+ interface:
+ description: configuration from the Interface OVS
+ table for the PF
+ properties:
+ externalIDs:
+ additionalProperties:
+ type: string
+ description: external_ids field in the Interface
+ table in OVSDB
+ type: object
+ options:
+ additionalProperties:
+ type: string
+ description: options field in the Interface table
+ in OVSDB
+ type: object
+ otherConfig:
+ additionalProperties:
+ type: string
+ description: other_config field in the Interface
+ table in OVSDB
+ type: object
+ type:
+ description: type field in the Interface table
+ in OVSDB
+ type: string
+ type: object
+ name:
+ description: name of the PF interface
+ type: string
+ pciAddress:
+ description: pci address of the PF
+ type: string
+ required:
+ - pciAddress
+ type: object
+ type: array
+ required:
+ - name
+ type: object
+ type: array
+ type: object
+ interfaces:
+ items:
+ properties:
+ Vfs:
+ items:
+ properties:
+ Vlan:
+ type: integer
+ assigned:
+ type: string
+ deviceID:
+ type: string
+ driver:
+ type: string
+ guid:
+ type: string
+ mac:
+ type: string
+ mtu:
+ type: integer
+ name:
+ type: string
+ pciAddress:
+ type: string
+ representorName:
+ type: string
+ vdpaType:
+ type: string
+ vendor:
+ type: string
+ vfID:
+ type: integer
+ required:
+ - pciAddress
+ - vfID
+ type: object
+ type: array
+ deviceID:
+ type: string
+ driver:
+ type: string
+ eSwitchMode:
+ type: string
+ externallyManaged:
+ type: boolean
+ linkAdminState:
+ type: string
+ linkSpeed:
+ type: string
+ linkType:
+ type: string
+ mac:
+ type: string
+ mtu:
+ type: integer
+ name:
+ type: string
+ netFilter:
+ type: string
+ numVfs:
+ type: integer
+ pciAddress:
+ type: string
+ totalvfs:
+ type: integer
+ vendor:
+ type: string
+ required:
+ - pciAddress
+ type: object
+ type: array
+ lastSyncError:
+ type: string
+ syncStatus:
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml
new file mode 100644
index 0000000..502e0eb
--- /dev/null
+++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml
@@ -0,0 +1,123 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: sriovnetworkpoolconfigs.sriovnetwork.openshift.io
+spec:
+ group: sriovnetwork.openshift.io
+ names:
+ kind: SriovNetworkPoolConfig
+ listKind: SriovNetworkPoolConfigList
+ plural: sriovnetworkpoolconfigs
+ singular: sriovnetworkpoolconfig
+ scope: Namespaced
+ versions:
+ - name: v1
+ schema:
+ openAPIV3Schema:
+ description: SriovNetworkPoolConfig is the Schema for the sriovnetworkpoolconfigs
+ API
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: SriovNetworkPoolConfigSpec defines the desired state of SriovNetworkPoolConfig
+ properties:
+ maxUnavailable:
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ maxUnavailable defines either an integer number or percentage
+ of nodes in the pool that can go Unavailable during an update.
+
+
+ A value larger than 1 will mean multiple nodes going unavailable during
+ the update, which may affect your workload stress on the remaining nodes.
+ Drain will respect Pod Disruption Budgets (PDBs) such as etcd quorum guards,
+ even if maxUnavailable is greater than one.
+ x-kubernetes-int-or-string: true
+ nodeSelector:
+ description: nodeSelector specifies a label selector for Nodes
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label selector requirements.
+ The requirements are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the selector applies
+ to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ ovsHardwareOffloadConfig:
+ description: OvsHardwareOffloadConfig describes the OVS HWOL configuration
+ for selected Nodes
+ properties:
+ name:
+ description: |-
+ Name is mandatory and must be unique.
+ On Kubernetes:
+ Name is the name of OvsHardwareOffloadConfig
+ On OpenShift:
+ Name is the name of MachineConfigPool to be enabled with OVS hardware offload
+ type: string
+ type: object
+ type: object
+ status:
+ description: SriovNetworkPoolConfigStatus defines the observed state of
+ SriovNetworkPoolConfig
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworks.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworks.yaml
new file mode 100644
index 0000000..cd807f9
--- /dev/null
+++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworks.yaml
@@ -0,0 +1,136 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: sriovnetworks.sriovnetwork.openshift.io
+spec:
+ group: sriovnetwork.openshift.io
+ names:
+ kind: SriovNetwork
+ listKind: SriovNetworkList
+ plural: sriovnetworks
+ singular: sriovnetwork
+ scope: Namespaced
+ versions:
+ - name: v1
+ schema:
+ openAPIV3Schema:
+ description: SriovNetwork is the Schema for the sriovnetworks API
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: SriovNetworkSpec defines the desired state of SriovNetwork
+ properties:
+ capabilities:
+ description: |-
+ Capabilities to be configured for this network.
+ Capabilities supported: (mac|ips), e.g. '{"mac": true}'
+ type: string
+ ipam:
+ description: IPAM configuration to be used for this network.
+ type: string
+ linkState:
+ description: VF link state (enable|disable|auto)
+ enum:
+ - auto
+ - enable
+ - disable
+ type: string
+ logFile:
+ description: |-
+ LogFile sets the log file of the SRIOV CNI plugin logs. If unset (default), this will log to stderr and thus
+ to multus and container runtime logs.
+ type: string
+ logLevel:
+ default: info
+ description: |-
+ LogLevel sets the log level of the SRIOV CNI plugin - either of panic, error, warning, info, debug. Defaults
+ to info if left blank.
+ enum:
+ - panic
+ - error
+ - warning
+ - info
+ - debug
+ - ""
+ type: string
+ maxTxRate:
+ description: Maximum tx rate, in Mbps, for the VF. Defaults to 0 (no
+ rate limiting)
+ minimum: 0
+ type: integer
+ metaPlugins:
+ description: |-
+ MetaPluginsConfig configuration to be used in order to chain metaplugins to the sriov interface returned
+ by the operator.
+ type: string
+ minTxRate:
+ description: Minimum tx rate, in Mbps, for the VF. Defaults to 0 (no
+ rate limiting). min_tx_rate should be <= max_tx_rate.
+ minimum: 0
+ type: integer
+ networkNamespace:
+ description: Namespace of the NetworkAttachmentDefinition custom resource
+ type: string
+ resourceName:
+ description: SRIOV Network device plugin endpoint resource name
+ type: string
+ spoofChk:
+ description: VF spoof check, (on|off)
+ enum:
+ - "on"
+ - "off"
+ type: string
+ trust:
+ description: VF trust mode (on|off)
+ enum:
+ - "on"
+ - "off"
+ type: string
+ vlan:
+ description: VLAN ID to assign for the VF. Defaults to 0.
+ maximum: 4096
+ minimum: 0
+ type: integer
+ vlanProto:
+ description: VLAN proto to assign for the VF. Defaults to 802.1q.
+ enum:
+ - 802.1q
+ - 802.1Q
+ - 802.1ad
+ - 802.1AD
+ type: string
+ vlanQoS:
+ description: VLAN QoS ID to assign for the VF. Defaults to 0.
+ maximum: 7
+ minimum: 0
+ type: integer
+ required:
+ - resourceName
+ type: object
+ status:
+ description: SriovNetworkStatus defines the observed state of SriovNetwork
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml
new file mode 100644
index 0000000..49d5429
--- /dev/null
+++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml
@@ -0,0 +1,114 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: sriovoperatorconfigs.sriovnetwork.openshift.io
+spec:
+ group: sriovnetwork.openshift.io
+ names:
+ kind: SriovOperatorConfig
+ listKind: SriovOperatorConfigList
+ plural: sriovoperatorconfigs
+ singular: sriovoperatorconfig
+ scope: Namespaced
+ versions:
+ - name: v1
+ schema:
+ openAPIV3Schema:
+ description: SriovOperatorConfig is the Schema for the sriovoperatorconfigs
+ API
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: SriovOperatorConfigSpec defines the desired state of SriovOperatorConfig
+ properties:
+ configDaemonNodeSelector:
+ additionalProperties:
+ type: string
+ description: NodeSelector selects the nodes to be configured
+ type: object
+ configurationMode:
+ description: |-
+ Flag to enable the sriov-network-config-daemon to use a systemd service to configure SR-IOV devices on boot
+ Default mode: daemon
+ enum:
+ - daemon
+ - systemd
+ type: string
+ disableDrain:
+ description: Flag to disable nodes drain during debugging
+ type: boolean
+ disablePlugins:
+ description: DisablePlugins is a list of sriov-network-config-daemon
+ plugins to disable
+ items:
+ description: PluginNameValue defines the plugin name
+ enum:
+ - mellanox
+ type: string
+ type: array
+ enableInjector:
+ description: Flag to control whether the network resource injector
+ webhook shall be deployed
+ type: boolean
+ enableOperatorWebhook:
+ description: Flag to control whether the operator admission controller
+ webhook shall be deployed
+ type: boolean
+ enableOvsOffload:
+ description: Flag to enable OVS hardware offload. Set to 'true' to
+ provision switchdev-configuration.service and enable OpenvSwitch
+ hw-offload on nodes.
+ type: boolean
+ featureGates:
+ additionalProperties:
+ type: boolean
+ description: FeatureGates to enable experimental features
+ type: object
+ logLevel:
+ description: Flag to control the log verbose level of the operator.
+ Set to '0' to show only the basic logs. And set to '2' to show all
+ the available logs.
+ maximum: 2
+ minimum: 0
+ type: integer
+ useCDI:
+ description: Flag to enable Container Device Interface mode for SR-IOV
+ Network Device Plugin
+ type: boolean
+ type: object
+ status:
+ description: SriovOperatorConfigStatus defines the observed state of SriovOperatorConfig
+ properties:
+ injector:
+ description: Show the runtime status of the network resource injector
+ webhook
+ type: string
+ operatorWebhook:
+ description: Show the runtime status of the operator admission controller
+ webhook
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/sriov-network-operator-chart/Chart.yaml b/sriov-network-operator-chart/Chart.yaml
new file mode 100644
index 0000000..538f7e3
--- /dev/null
+++ b/sriov-network-operator-chart/Chart.yaml
@@ -0,0 +1,28 @@
+#!BuildTag: %%IMG_PREFIX%%sriov-network-operator-chart:1.3.0-%RELEASE%
+#!BuildTag: %%IMG_PREFIX%%sriov-network-operator-chart:1.3.0
+annotations:
+ catalog.cattle.io/auto-install: sriov-crd=match
+ catalog.cattle.io/experimental: "true"
+ catalog.cattle.io/namespace: cattle-sriov-system
+ catalog.cattle.io/os: linux
+ catalog.cattle.io/permits-os: linux
+ catalog.cattle.io/upstream-version: 1.3.0
+apiVersion: v2
+appVersion: v1.3.0
+dependencies:
+- condition: sriov-nfd.enabled
+ name: sriov-nfd
+ repository: file://./charts/sriov-nfd
+ version: 0.15.6
+description: SR-IOV network operator configures and manages SR-IOV networks in the
+ kubernetes cluster
+home: https://github.com/k8snetworkplumbingwg/sriov-network-operator
+icon: https://charts.rancher.io/assets/logos/sr-iov.svg
+keywords:
+- sriov
+kubeVersion: '>= 1.16.0-0'
+name: sriov-network-operator
+sources:
+- https://github.com/k8snetworkplumbingwg/sriov-network-operator
+type: application
+version: 1.3.0
diff --git a/sriov-network-operator-chart/README.md b/sriov-network-operator-chart/README.md
new file mode 100644
index 0000000..86b0519
--- /dev/null
+++ b/sriov-network-operator-chart/README.md
@@ -0,0 +1,130 @@
+# SR-IOV Network Operator Helm Chart
+
+SR-IOV Network Operator Helm Chart provides an easy way to install, configure and manage
+the lifecycle of SR-IOV network operator.
+
+## SR-IOV Network Operator
+SR-IOV Network Operator leverages [Kubernetes CRDs](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/)
+and [Operator SDK](https://github.com/operator-framework/operator-sdk) to configure and manage SR-IOV networks in a Kubernetes cluster.
+
+SR-IOV Network Operator features:
+- Initialize the supported SR-IOV NIC types on selected nodes.
+- Provision/upgrade SR-IOV device plugin executable on selected node.
+- Provision/upgrade SR-IOV CNI plugin executable on selected nodes.
+- Manage configuration of SR-IOV device plugin on host.
+- Generate net-att-def CRs for SR-IOV CNI plugin
+- Supports operation in a virtualized Kubernetes deployment
+ - Discovers VFs attached to the Virtual Machine (VM)
+ - Does not require attached of associated PFs
+ - VFs can be associated to SriovNetworks by selecting the appropriate PciAddress as the RootDevice in the SriovNetworkNodePolicy
+
+## QuickStart
+
+### Prerequisites
+
+- Kubernetes v1.17+
+- Helm v3
+
+### Install Helm
+
+Helm provides an install script to copy helm binary to your system:
+```
+$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
+$ chmod 500 get_helm.sh
+$ ./get_helm.sh
+```
+
+For additional information and methods for installing Helm, refer to the official [helm website](https://helm.sh/)
+
+### Deploy SR-IOV Network Operator
+
+```
+# Install Operator
+$ helm install -n sriov-network-operator --create-namespace --wait sriov-network-operator ./
+
+# View deployed resources
+$ kubectl -n sriov-network-operator get pods
+```
+
+In the case that [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) is enabled, the sriov network operator namespace will require a security level of 'privileged'
+```
+$ kubectl label ns sriov-network-operator pod-security.kubernetes.io/enforce=privileged
+```
+
+## Chart parameters
+
+In order to tailor the deployment of the network operator to your cluster needs
+We have introduced the following Chart parameters.
+
+| Name | Type | Default | description |
+| ---- |------|---------|-------------|
+| `imagePullSecrets` | list | `[]` | An optional list of references to secrets to use for pulling any of the SR-IOV Network Operator image |
+| `supportedExtraNICs` | list | `[]` | An optional list of whitelisted NICs |
+
+### Operator parameters
+
+| Name | Type | Default | description |
+| ---- | ---- | ------- | ----------- |
+| `operator.tolerations` | list | `[{"key":"node-role.kubernetes.io/master","operator":"Exists","effect":"NoSchedule"},{"key":"node-role.kubernetes.io/control-plane","operator":"Exists","effect":"NoSchedule"}]` | Operator's tolerations |
+| `operator.nodeSelector` | object | {} | Operator's node selector |
+| `operator.affinity` | object | `{"nodeAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":1,"preference":{"matchExpressions":[{"key":"node-role.kubernetes.io/master","operator":"In","values":[""]}]}},{"weight":1,"preference":{"matchExpressions":[{"key":"node-role.kubernetes.io/control-plane","operator":"In","values":[""]}]}}]}}` | Operator's afffinity configuration |
+| `operator.nameOverride` | string | `` | Operator's resource name override |
+| `operator.fullnameOverride` | string | `` | Operator's resource full name override |
+| `operator.resourcePrefix` | string | `openshift.io` | Device plugin resource prefix |
+| `operator.cniBinPath` | string | `/opt/cni/bin` | Path for CNI binary |
+| `operator.clustertype` | string | `kubernetes` | Cluster environment type |
+
+#### Admission Controllers parameters
+
+The admission controllers can be enabled by switching on a single parameter `operator.admissionControllers.enabled`. By
+default, the user needs to pre-create Kubernetes Secrets that match the names provided in
+`operator.admissionControllers.certificates.secretNames`. The secrets should have 3 fields populated with the relevant
+content:
+* `ca.crt` (value needs to be base64 encoded twice)
+* `tls.crt`
+* `tls.key`
+
+Aside from the aforementioned mode, the chart supports 3 more modes for certificate consumption by the admission
+controllers, which can be found in the table below. In a nutshell, the modes that are supported are:
+* Consume pre-created Certificates managed by cert-manager
+* Generate self signed Certificates managed by cert-manager
+* Specify the content of the certificates as Helm values
+
+| Name | Type | Default | description |
+| ---- | ---- | ------- | ----------- |
+| `operator.admissionControllers.enabled` | bool | false | Flag that switches on the admission controllers |
+| `operator.admissionControllers.certificates.secretNames.operator` | string | `operator-webhook-cert` | Secret that stores the certificate for the Operator's admission controller |
+| `operator.admissionControllers.certificates.secretNames.injector` | string | `network-resources-injector-cert` | Secret that stores the certificate for the Network Resources Injector's admission controller |
+| `operator.admissionControllers.certificates.certManager.enabled` | bool | false | Flag that switches on consumption of certificates managed by cert-manager |
+| `operator.admissionControllers.certificates.certManager.generateSelfSigned` | bool | false | Flag that switches on generation of self signed certificates managed by cert-manager. The secrets in which the certificates are stored will have the names provided in `operator.admissionControllers.certificates.secretNames` |
+| `operator.admissionControllers.certificates.custom.enabled` | bool | false | Flag that switches on consumption of user provided certificates that are part of `operator.admissionControllers.certificates.custom.operator` and `operator.admissionControllers.certificates.custom.injector` objects |
+| `operator.admissionControllers.certificates.custom.operator.caCrt` | string | `` | The CA certificate to be used by the Operator's admission controller |
+| `operator.admissionControllers.certificates.custom.operator.tlsCrt` | string | `` | The public part of the certificate to be used by the Operator's admission controller |
+| `operator.admissionControllers.certificates.custom.operator.tlsKey` | string | `` | The private part of the certificate to be used by the Operator's admission controller |
+| `operator.admissionControllers.certificates.custom.injector.caCrt` | string | `` | The CA certificate to be used by the Network Resources Injector's admission controller |
+| `operator.admissionControllers.certificates.custom.injector.tlsCrt` | string | `` | The public part of the certificate to be used by the Network Resources Injector's admission controller |
+| `operator.admissionControllers.certificates.custom.injector.tlsKey` | string | `` | The private part of the certificate to be used by the Network Resources Injector's admission controller |
+
+### SR-IOV Operator Configuration Parameters
+
+This section contains general parameters that apply to both the operator and daemon componets of SR-IOV Network Operator.
+
+| Name | Type | Default | description |
+| ---- | ---- | ------- | ----------- |
+| `sriovOperatorConfig.deploy` | bool | `false` | deploy SriovOperatorConfig custom resource |
+| `sriovOperatorConfig.configDaemonNodeSelector` | map[string]string | `{}` | node slectors for sriov-network-config-daemon |
+| `sriovOperatorConfig.logLevel` | int | `2` | log level for both operator and sriov-network-config-daemon |
+| `sriovOperatorConfig.disableDrain` | bool | `false` | disable node draining when configuring SR-IOV, set to true in case of a single node cluster or any other justifiable reason |
+| `sriovOperatorConfig.configurationMode` | string | `daemon` | sriov-network-config-daemon configuration mode. either `daemon` or `systemd` |
+
+### Images parameters
+
+| Name | description |
+| ---- | ----------- |
+| `images.operator` | Operator controller image |
+| `images.sriovConfigDaemon` | Daemon node agent image |
+| `images.sriovCni` | SR-IOV CNI image |
+| `images.ibSriovCni` | InfiniBand SR-IOV CNI image |
+| `images.sriovDevicePlugin` | SR-IOV device plugin image |
+| `images.resourcesInjector` | Resources Injector image |
+| `images.webhook` | Operator Webhook image |
diff --git a/sriov-network-operator-chart/_service b/sriov-network-operator-chart/_service
new file mode 100644
index 0000000..6b8f891
--- /dev/null
+++ b/sriov-network-operator-chart/_service
@@ -0,0 +1,8 @@
+
+
+
+ Chart.yaml
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+
+
diff --git a/sriov-network-operator-chart/app-README.md b/sriov-network-operator-chart/app-README.md
new file mode 100644
index 0000000..7dcf664
--- /dev/null
+++ b/sriov-network-operator-chart/app-README.md
@@ -0,0 +1,13 @@
+# Rancher SR-IOV Network Operator
+
+This chart is based on the upstream [k8snetworkplumbingwg/sriov-network-operator](https://github.com/k8snetworkplumbingwg/sriov-network-operator) project. The chart deploys the SR-IOV Operator and its CRDs, which are designed to help the user provision and configure the SR-IOV CNI in a cluster that uses [Multus CNI](https://github.com/k8snetworkplumbingwg/multus-cni), to provide high performing extra network interfaces to pods. This chart is expected to be deployed on an RKE2 cluster and only meant for advanced use cases where multiple CNI plugins and high performing network interfaces on pods are required. Users who do not need these features are not advised to install this chart.
+
+The chart installs the following components:
+
+ - SR-IOV Operator - An operator that helps provision and configure the SR-IOV CNI plugin and SR-IOV Device plugin
+ - SR-IOV Network Config Daemon - A Daemon deployed by the Operator that discovers SR-IOV NICs on each node
+
+Note that SR-IOV requires NICs that support SR-IOV and the activation of specific configuration options in the operating system. Nodes that fulfill these requirements should be labeled with: `feature.node.kubernetes.io/network-sriov.capable=true`.
+
+The SR-IOV Network Config Daemon will be deployed on such capable nodes. For more information on how to use this feature, refer to our RKE2 networking docs.
+
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/.helmignore b/sriov-network-operator-chart/charts/sriov-nfd/.helmignore
new file mode 100644
index 0000000..1b9a9cc
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/Chart.yaml b/sriov-network-operator-chart/charts/sriov-nfd/Chart.yaml
new file mode 100644
index 0000000..5415b0d
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/Chart.yaml
@@ -0,0 +1,14 @@
+apiVersion: v2
+appVersion: v0.15.6
+description: Detects hardware features available on each node in a Kubernetes cluster,
+ and advertises those features using node labels
+home: https://github.com/kubernetes-sigs/node-feature-discovery
+keywords:
+- feature-discovery
+- feature-detection
+- node-labels
+name: sriov-nfd
+sources:
+- https://github.com/kubernetes-sigs/node-feature-discovery
+type: application
+version: 0.15.6
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/README.md b/sriov-network-operator-chart/charts/sriov-nfd/README.md
new file mode 100644
index 0000000..9aa6c75
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/README.md
@@ -0,0 +1,10 @@
+# Node Feature Discovery
+
+Node Feature Discovery (NFD) is a Kubernetes add-on for detecting hardware
+features and system configuration. Detected features are advertised as node
+labels. NFD provides flexible configuration and extension points for a wide
+range of vendor and application specific node labeling needs.
+
+See
+[NFD documentation](https://kubernetes-sigs.github.io/node-feature-discovery/v0.15/deployment/helm.html)
+for deployment instructions.
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/crds/nfd-api-crds.yaml b/sriov-network-operator-chart/charts/sriov-nfd/crds/nfd-api-crds.yaml
new file mode 100644
index 0000000..0339f35
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/crds/nfd-api-crds.yaml
@@ -0,0 +1,426 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.12.1
+ name: nodefeatures.nfd.k8s-sigs.io
+spec:
+ group: nfd.k8s-sigs.io
+ names:
+ kind: NodeFeature
+ listKind: NodeFeatureList
+ plural: nodefeatures
+ singular: nodefeature
+ scope: Namespaced
+ versions:
+ - name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: NodeFeature resource holds the features discovered for one node
+ in the cluster.
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: NodeFeatureSpec describes a NodeFeature object.
+ properties:
+ features:
+ description: Features is the full "raw" features data that has been
+ discovered.
+ properties:
+ attributes:
+ additionalProperties:
+ description: AttributeFeatureSet is a set of features having
+ string value.
+ properties:
+ elements:
+ additionalProperties:
+ type: string
+ type: object
+ required:
+ - elements
+ type: object
+ description: Attributes contains all the attribute-type features
+ of the node.
+ type: object
+ flags:
+ additionalProperties:
+ description: FlagFeatureSet is a set of simple features only
+ containing names without values.
+ properties:
+ elements:
+ additionalProperties:
+ description: Nil is a dummy empty struct for protobuf
+ compatibility
+ type: object
+ type: object
+ required:
+ - elements
+ type: object
+ description: Flags contains all the flag-type features of the
+ node.
+ type: object
+ instances:
+ additionalProperties:
+ description: InstanceFeatureSet is a set of features each of
+ which is an instance having multiple attributes.
+ properties:
+ elements:
+ items:
+ description: InstanceFeature represents one instance of
+ a complex features, e.g. a device.
+ properties:
+ attributes:
+ additionalProperties:
+ type: string
+ type: object
+ required:
+ - attributes
+ type: object
+ type: array
+ required:
+ - elements
+ type: object
+ description: Instances contains all the instance-type features
+ of the node.
+ type: object
+ type: object
+ labels:
+ additionalProperties:
+ type: string
+ description: Labels is the set of node labels that are requested to
+ be created.
+ type: object
+ type: object
+ required:
+ - spec
+ type: object
+ served: true
+ storage: true
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.12.1
+ name: nodefeaturerules.nfd.k8s-sigs.io
+spec:
+ group: nfd.k8s-sigs.io
+ names:
+ kind: NodeFeatureRule
+ listKind: NodeFeatureRuleList
+ plural: nodefeaturerules
+ shortNames:
+ - nfr
+ singular: nodefeaturerule
+ scope: Cluster
+ versions:
+ - name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: NodeFeatureRule resource specifies a configuration for feature-based
+ customization of node objects, such as node labeling.
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: NodeFeatureRuleSpec describes a NodeFeatureRule.
+ properties:
+ rules:
+ description: Rules is a list of node customization rules.
+ items:
+ description: Rule defines a rule for node customization such as
+ labeling.
+ properties:
+ annotations:
+ additionalProperties:
+ type: string
+ description: Annotations to create if the rule matches.
+ type: object
+ extendedResources:
+ additionalProperties:
+ type: string
+ description: ExtendedResources to create if the rule matches.
+ type: object
+ labels:
+ additionalProperties:
+ type: string
+ description: Labels to create if the rule matches.
+ type: object
+ labelsTemplate:
+ description: LabelsTemplate specifies a template to expand for
+ dynamically generating multiple labels. Data (after template
+ expansion) must be keys with an optional value ([=])
+ separated by newlines.
+ type: string
+ matchAny:
+ description: MatchAny specifies a list of matchers one of which
+ must match.
+ items:
+ description: MatchAnyElem specifies one sub-matcher of MatchAny.
+ properties:
+ matchFeatures:
+ description: MatchFeatures specifies a set of matcher
+ terms all of which must match.
+ items:
+ description: FeatureMatcherTerm defines requirements
+ against one feature set. All requirements (specified
+ as MatchExpressions) are evaluated against each element
+ in the feature set.
+ properties:
+ feature:
+ description: Feature is the name of the feature
+ set to match against.
+ type: string
+ matchExpressions:
+ additionalProperties:
+ description: MatchExpression specifies an expression
+ to evaluate against a set of input values. It
+ contains an operator that is applied when matching
+ the input and an array of values that the operator
+ evaluates the input against.
+ properties:
+ op:
+ description: Op is the operator to be applied.
+ enum:
+ - In
+ - NotIn
+ - InRegexp
+ - Exists
+ - DoesNotExist
+ - Gt
+ - Lt
+ - GtLt
+ - IsTrue
+ - IsFalse
+ type: string
+ value:
+ description: Value is the list of values that
+ the operand evaluates the input against.
+ Value should be empty if the operator is
+ Exists, DoesNotExist, IsTrue or IsFalse.
+ Value should contain exactly one element
+ if the operator is Gt or Lt and exactly
+ two elements if the operator is GtLt. In
+ other cases Value should contain at least
+ one element.
+ items:
+ type: string
+ type: array
+ required:
+ - op
+ type: object
+ description: MatchExpressions is the set of per-element
+ expressions evaluated. These match against the
+ value of the specified elements.
+ type: object
+ matchName:
+ description: MatchName in an expression that is
+ matched against the name of each element in the
+ feature set.
+ properties:
+ op:
+ description: Op is the operator to be applied.
+ enum:
+ - In
+ - NotIn
+ - InRegexp
+ - Exists
+ - DoesNotExist
+ - Gt
+ - Lt
+ - GtLt
+ - IsTrue
+ - IsFalse
+ type: string
+ value:
+ description: Value is the list of values that
+ the operand evaluates the input against. Value
+ should be empty if the operator is Exists,
+ DoesNotExist, IsTrue or IsFalse. Value should
+ contain exactly one element if the operator
+ is Gt or Lt and exactly two elements if the
+ operator is GtLt. In other cases Value should
+ contain at least one element.
+ items:
+ type: string
+ type: array
+ required:
+ - op
+ type: object
+ required:
+ - feature
+ type: object
+ type: array
+ required:
+ - matchFeatures
+ type: object
+ type: array
+ matchFeatures:
+ description: MatchFeatures specifies a set of matcher terms
+ all of which must match.
+ items:
+ description: FeatureMatcherTerm defines requirements against
+ one feature set. All requirements (specified as MatchExpressions)
+ are evaluated against each element in the feature set.
+ properties:
+ feature:
+ description: Feature is the name of the feature set to
+ match against.
+ type: string
+ matchExpressions:
+ additionalProperties:
+ description: MatchExpression specifies an expression
+ to evaluate against a set of input values. It contains
+ an operator that is applied when matching the input
+ and an array of values that the operator evaluates
+ the input against.
+ properties:
+ op:
+ description: Op is the operator to be applied.
+ enum:
+ - In
+ - NotIn
+ - InRegexp
+ - Exists
+ - DoesNotExist
+ - Gt
+ - Lt
+ - GtLt
+ - IsTrue
+ - IsFalse
+ type: string
+ value:
+ description: Value is the list of values that the
+ operand evaluates the input against. Value should
+ be empty if the operator is Exists, DoesNotExist,
+ IsTrue or IsFalse. Value should contain exactly
+ one element if the operator is Gt or Lt and exactly
+ two elements if the operator is GtLt. In other
+ cases Value should contain at least one element.
+ items:
+ type: string
+ type: array
+ required:
+ - op
+ type: object
+ description: MatchExpressions is the set of per-element
+ expressions evaluated. These match against the value
+ of the specified elements.
+ type: object
+ matchName:
+ description: MatchName in an expression that is matched
+ against the name of each element in the feature set.
+ properties:
+ op:
+ description: Op is the operator to be applied.
+ enum:
+ - In
+ - NotIn
+ - InRegexp
+ - Exists
+ - DoesNotExist
+ - Gt
+ - Lt
+ - GtLt
+ - IsTrue
+ - IsFalse
+ type: string
+ value:
+ description: Value is the list of values that the
+ operand evaluates the input against. Value should
+ be empty if the operator is Exists, DoesNotExist,
+ IsTrue or IsFalse. Value should contain exactly
+ one element if the operator is Gt or Lt and exactly
+ two elements if the operator is GtLt. In other cases
+ Value should contain at least one element.
+ items:
+ type: string
+ type: array
+ required:
+ - op
+ type: object
+ required:
+ - feature
+ type: object
+ type: array
+ name:
+ description: Name of the rule.
+ type: string
+ taints:
+ description: Taints to create if the rule matches.
+ items:
+ description: The node this Taint is attached to has the "effect"
+ on any pod that does not tolerate the Taint.
+ properties:
+ effect:
+ description: Required. The effect of the taint on pods
+ that do not tolerate the taint. Valid effects are NoSchedule,
+ PreferNoSchedule and NoExecute.
+ type: string
+ key:
+ description: Required. The taint key to be applied to
+ a node.
+ type: string
+ timeAdded:
+ description: TimeAdded represents the time at which the
+ taint was added. It is only written for NoExecute taints.
+ format: date-time
+ type: string
+ value:
+ description: The taint value corresponding to the taint
+ key.
+ type: string
+ required:
+ - effect
+ - key
+ type: object
+ type: array
+ vars:
+ additionalProperties:
+ type: string
+ description: Vars is the variables to store if the rule matches.
+ Variables do not directly inflict any changes in the node
+ object. However, they can be referenced from other rules enabling
+ more complex rule hierarchies, without exposing intermediary
+ output values as labels.
+ type: object
+ varsTemplate:
+ description: VarsTemplate specifies a template to expand for
+ dynamically generating multiple variables. Data (after template
+ expansion) must be keys with an optional value ([=])
+ separated by newlines.
+ type: string
+ required:
+ - name
+ type: object
+ type: array
+ required:
+ - rules
+ type: object
+ required:
+ - spec
+ type: object
+ served: true
+ storage: true
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/_helpers.tpl b/sriov-network-operator-chart/charts/sriov-nfd/templates/_helpers.tpl
new file mode 100644
index 0000000..f8b1e30
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/_helpers.tpl
@@ -0,0 +1,107 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "node-feature-discovery.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "node-feature-discovery.fullname" -}}
+{{- if .Values.fullnameOverride -}}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- $name := default .Chart.Name .Values.nameOverride -}}
+{{- if contains $name .Release.Name -}}
+{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Allow the release namespace to be overridden for multi-namespace deployments in combined charts
+*/}}
+{{- define "node-feature-discovery.namespace" -}}
+ {{- if .Values.namespaceOverride -}}
+ {{- .Values.namespaceOverride -}}
+ {{- else -}}
+ {{- .Release.Namespace -}}
+ {{- end -}}
+{{- end -}}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "node-feature-discovery.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Common labels
+*/}}
+{{- define "node-feature-discovery.labels" -}}
+helm.sh/chart: {{ include "node-feature-discovery.chart" . }}
+{{ include "node-feature-discovery.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end -}}
+
+{{/*
+Selector labels
+*/}}
+{{- define "node-feature-discovery.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "node-feature-discovery.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end -}}
+
+{{/*
+Create the name of the service account which the nfd master will use
+*/}}
+{{- define "node-feature-discovery.master.serviceAccountName" -}}
+{{- if .Values.master.serviceAccount.create -}}
+ {{ default (include "node-feature-discovery.fullname" .) .Values.master.serviceAccount.name }}
+{{- else -}}
+ {{ default "default" .Values.master.serviceAccount.name }}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Create the name of the service account which the nfd worker will use
+*/}}
+{{- define "node-feature-discovery.worker.serviceAccountName" -}}
+{{- if .Values.worker.serviceAccount.create -}}
+ {{ default (printf "%s-worker" (include "node-feature-discovery.fullname" .)) .Values.worker.serviceAccount.name }}
+{{- else -}}
+ {{ default "default" .Values.worker.serviceAccount.name }}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Create the name of the service account which topologyUpdater will use
+*/}}
+{{- define "node-feature-discovery.topologyUpdater.serviceAccountName" -}}
+{{- if .Values.topologyUpdater.serviceAccount.create -}}
+ {{ default (printf "%s-topology-updater" (include "node-feature-discovery.fullname" .)) .Values.topologyUpdater.serviceAccount.name }}
+{{- else -}}
+ {{ default "default" .Values.topologyUpdater.serviceAccount.name }}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Create the name of the service account which nfd-gc will use
+*/}}
+{{- define "node-feature-discovery.gc.serviceAccountName" -}}
+{{- if .Values.gc.serviceAccount.create -}}
+ {{ default (printf "%s-gc" (include "node-feature-discovery.fullname" .)) .Values.gc.serviceAccount.name }}
+{{- else -}}
+ {{ default "default" .Values.gc.serviceAccount.name }}
+{{- end -}}
+{{- end -}}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-certs.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-certs.yaml
new file mode 100644
index 0000000..43a647a
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-certs.yaml
@@ -0,0 +1,68 @@
+{{- if .Values.tls.certManager }}
+{{- if .Values.master.enable }}
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: nfd-master-cert
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+spec:
+ secretName: nfd-master-cert
+ subject:
+ organizations:
+ - node-feature-discovery
+ commonName: nfd-master
+ dnsNames:
+ # must match the service name
+ - {{ include "node-feature-discovery.fullname" . }}-master
+ # first one is configured for use by the worker; below are for completeness
+ - {{ include "node-feature-discovery.fullname" . }}-master.{{ include "node-feature-discovery.namespace" . }}.svc
+ - {{ include "node-feature-discovery.fullname" . }}-master.{{ include "node-feature-discovery.namespace" . }}.svc.cluster.local
+ issuerRef:
+ name: nfd-ca-issuer
+ kind: Issuer
+ group: cert-manager.io
+{{- end }}
+---
+{{- if .Values.worker.enable }}
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: nfd-worker-cert
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+spec:
+ secretName: nfd-worker-cert
+ subject:
+ organizations:
+ - node-feature-discovery
+ commonName: nfd-worker
+ dnsNames:
+ - {{ include "node-feature-discovery.fullname" . }}-worker.{{ include "node-feature-discovery.namespace" . }}.svc.cluster.local
+ issuerRef:
+ name: nfd-ca-issuer
+ kind: Issuer
+ group: cert-manager.io
+{{- end }}
+
+{{- if .Values.topologyUpdater.enable }}
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: nfd-topology-updater-cert
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+spec:
+ secretName: nfd-topology-updater-cert
+ subject:
+ organizations:
+ - node-feature-discovery
+ commonName: nfd-topology-updater
+ dnsNames:
+ - {{ include "node-feature-discovery.fullname" . }}-topology-updater.{{ include "node-feature-discovery.namespace" . }}.svc.cluster.local
+ issuerRef:
+ name: nfd-ca-issuer
+ kind: Issuer
+ group: cert-manager.io
+{{- end }}
+
+{{- end }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-issuer.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-issuer.yaml
new file mode 100644
index 0000000..742ebe1
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-issuer.yaml
@@ -0,0 +1,42 @@
+{{- if .Values.tls.certManager }}
+# See https://cert-manager.io/docs/configuration/selfsigned/#bootstrapping-ca-issuers
+# - Create a self signed issuer
+# - Use this to create a CA cert
+# - Use this to now create a CA issuer
+---
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: nfd-ca-bootstrap
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+spec:
+ selfSigned: {}
+
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: nfd-ca-cert
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+spec:
+ isCA: true
+ secretName: nfd-ca-cert
+ subject:
+ organizations:
+ - node-feature-discovery
+ commonName: nfd-ca-cert
+ issuerRef:
+ name: nfd-ca-bootstrap
+ kind: Issuer
+ group: cert-manager.io
+
+---
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: nfd-ca-issuer
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+spec:
+ ca:
+ secretName: nfd-ca-cert
+{{- end }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrole.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrole.yaml
new file mode 100644
index 0000000..8853613
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrole.yaml
@@ -0,0 +1,119 @@
+{{- if and .Values.master.enable .Values.master.rbac.create }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - nodes
+ - nodes/status
+ verbs:
+ - get
+ - patch
+ - update
+ - list
+- apiGroups:
+ - nfd.k8s-sigs.io
+ resources:
+ - nodefeatures
+ - nodefeaturerules
+ verbs:
+ - get
+ - list
+ - watch
+- apiGroups:
+ - coordination.k8s.io
+ resources:
+ - leases
+ verbs:
+ - create
+- apiGroups:
+ - coordination.k8s.io
+ resources:
+ - leases
+ resourceNames:
+ - "nfd-master.nfd.kubernetes.io"
+ verbs:
+ - get
+ - update
+{{- end }}
+
+{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.rbac.create }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}-topology-updater
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - nodes
+ verbs:
+ - get
+ - list
+- apiGroups:
+ - ""
+ resources:
+ - nodes/proxy
+ verbs:
+ - get
+- apiGroups:
+ - ""
+ resources:
+ - pods
+ verbs:
+ - get
+- apiGroups:
+ - topology.node.k8s.io
+ resources:
+ - noderesourcetopologies
+ verbs:
+ - create
+ - get
+ - update
+{{- end }}
+
+{{- if and .Values.gc.enable .Values.gc.rbac.create (or .Values.enableNodeFeatureApi .Values.topologyUpdater.enable) }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}-gc
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - nodes
+ verbs:
+ - list
+ - watch
+- apiGroups:
+ - ""
+ resources:
+ - nodes/proxy
+ verbs:
+ - get
+- apiGroups:
+ - topology.node.k8s.io
+ resources:
+ - noderesourcetopologies
+ verbs:
+ - delete
+ - list
+- apiGroups:
+ - nfd.k8s-sigs.io
+ resources:
+ - nodefeatures
+ verbs:
+ - delete
+ - list
+{{- end }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrolebinding.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrolebinding.yaml
new file mode 100644
index 0000000..1d49ec5
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrolebinding.yaml
@@ -0,0 +1,52 @@
+{{- if and .Values.master.enable .Values.master.rbac.create }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ include "node-feature-discovery.fullname" . }}
+subjects:
+- kind: ServiceAccount
+ name: {{ include "node-feature-discovery.master.serviceAccountName" . }}
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+{{- end }}
+
+{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.rbac.create }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}-topology-updater
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ include "node-feature-discovery.fullname" . }}-topology-updater
+subjects:
+- kind: ServiceAccount
+ name: {{ include "node-feature-discovery.topologyUpdater.serviceAccountName" . }}
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+{{- end }}
+
+{{- if and .Values.gc.enable .Values.gc.rbac.create (or .Values.enableNodeFeatureApi .Values.topologyUpdater.enable) }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}-gc
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ include "node-feature-discovery.fullname" . }}-gc
+subjects:
+- kind: ServiceAccount
+ name: {{ include "node-feature-discovery.gc.serviceAccountName" . }}
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+{{- end }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/master.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/master.yaml
new file mode 100644
index 0000000..19b543a
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/master.yaml
@@ -0,0 +1,145 @@
+{{- if .Values.master.enable }}
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}-master
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+ role: master
+ {{- with .Values.master.deploymentAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ replicas: {{ .Values.master.replicaCount }}
+ selector:
+ matchLabels:
+ {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }}
+ role: master
+ template:
+ metadata:
+ labels:
+ {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }}
+ role: master
+ {{- with .Values.master.annotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "node-feature-discovery.master.serviceAccountName" . }}
+ enableServiceLinks: false
+ securityContext:
+ {{- toYaml .Values.master.podSecurityContext | nindent 8 }}
+ containers:
+ - name: master
+ securityContext:
+ {{- toYaml .Values.master.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ livenessProbe:
+ grpc:
+ port: 8080
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ readinessProbe:
+ grpc:
+ port: 8080
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ failureThreshold: 10
+ ports:
+ - containerPort: {{ .Values.master.port | default "8080" }}
+ name: grpc
+ - containerPort: {{ .Values.master.metricsPort | default "8081" }}
+ name: metrics
+ env:
+ - name: NODE_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: spec.nodeName
+ command:
+ - "nfd-master"
+ resources:
+ {{- toYaml .Values.master.resources | nindent 12 }}
+ args:
+ {{- if .Values.master.instance | empty | not }}
+ - "-instance={{ .Values.master.instance }}"
+ {{- end }}
+ {{- if not .Values.enableNodeFeatureApi }}
+ - "-port={{ .Values.master.port | default "8080" }}"
+ - "-enable-nodefeature-api=false"
+ {{- else if gt (int .Values.master.replicaCount) 1 }}
+ - "-enable-leader-election"
+ {{- end }}
+ {{- if .Values.master.extraLabelNs | empty | not }}
+ - "-extra-label-ns={{- join "," .Values.master.extraLabelNs }}"
+ {{- end }}
+ {{- if .Values.master.denyLabelNs | empty | not }}
+ - "-deny-label-ns={{- join "," .Values.master.denyLabelNs }}"
+ {{- end }}
+ {{- if .Values.master.resourceLabels | empty | not }}
+ - "-resource-labels={{- join "," .Values.master.resourceLabels }}"
+ {{- end }}
+ {{- if .Values.master.enableTaints }}
+ - "-enable-taints"
+ {{- end }}
+ {{- if .Values.master.crdController | kindIs "invalid" | not }}
+ - "-crd-controller={{ .Values.master.crdController }}"
+ {{- else }}
+ ## By default, disable crd controller for other than the default instances
+ - "-crd-controller={{ .Values.master.instance | empty }}"
+ {{- end }}
+ {{- if .Values.master.featureRulesController | kindIs "invalid" | not }}
+ - "-featurerules-controller={{ .Values.master.featureRulesController }}"
+ {{- end }}
+ {{- if .Values.master.resyncPeriod }}
+ - "-resync-period={{ .Values.master.resyncPeriod }}"
+ {{- end }}
+ {{- if .Values.master.nfdApiParallelism | empty | not }}
+ - "-nfd-api-parallelism={{ .Values.master.nfdApiParallelism }}"
+ {{- end }}
+ {{- if .Values.tls.enable }}
+ - "-ca-file=/etc/kubernetes/node-feature-discovery/certs/ca.crt"
+ - "-key-file=/etc/kubernetes/node-feature-discovery/certs/tls.key"
+ - "-cert-file=/etc/kubernetes/node-feature-discovery/certs/tls.crt"
+ {{- end }}
+ - "-metrics={{ .Values.master.metricsPort | default "8081" }}"
+ volumeMounts:
+ {{- if .Values.tls.enable }}
+ - name: nfd-master-cert
+ mountPath: "/etc/kubernetes/node-feature-discovery/certs"
+ readOnly: true
+ {{- end }}
+ - name: nfd-master-conf
+ mountPath: "/etc/kubernetes/node-feature-discovery"
+ readOnly: true
+ volumes:
+ {{- if .Values.tls.enable }}
+ - name: nfd-master-cert
+ secret:
+ secretName: nfd-master-cert
+ {{- end }}
+ - name: nfd-master-conf
+ configMap:
+ name: {{ include "node-feature-discovery.fullname" . }}-master-conf
+ items:
+ - key: nfd-master.conf
+ path: nfd-master.conf
+ {{- with .Values.master.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.master.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.master.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+{{- end }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-gc.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-gc.yaml
new file mode 100644
index 0000000..641202b
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-gc.yaml
@@ -0,0 +1,77 @@
+{{- if and .Values.gc.enable (or .Values.enableNodeFeatureApi .Values.topologyUpdater.enable) -}}
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}-gc
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+ role: gc
+ {{- with .Values.gc.deploymentAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ replicas: {{ .Values.gc.replicaCount | default 1 }}
+ selector:
+ matchLabels:
+ {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }}
+ role: gc
+ template:
+ metadata:
+ labels:
+ {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }}
+ role: gc
+ {{- with .Values.gc.annotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ spec:
+ serviceAccountName: {{ include "node-feature-discovery.gc.serviceAccountName" . }}
+ dnsPolicy: ClusterFirstWithHostNet
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ securityContext:
+ {{- toYaml .Values.gc.podSecurityContext | nindent 8 }}
+ containers:
+ - name: gc
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: "{{ .Values.image.pullPolicy }}"
+ env:
+ - name: NODE_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: spec.nodeName
+ command:
+ - "nfd-gc"
+ args:
+ {{- if .Values.gc.interval | empty | not }}
+ - "-gc-interval={{ .Values.gc.interval }}"
+ {{- end }}
+ resources:
+ {{- toYaml .Values.gc.resources | nindent 12 }}
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop: [ "ALL" ]
+ readOnlyRootFilesystem: true
+ runAsNonRoot: true
+ ports:
+ - name: metrics
+ containerPort: {{ .Values.gc.metricsPort | default "8081"}}
+
+ {{- with .Values.gc.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.gc.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.gc.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+{{- end }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-master-conf.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-master-conf.yaml
new file mode 100644
index 0000000..be92601
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-master-conf.yaml
@@ -0,0 +1,12 @@
+{{- if .Values.master.enable }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}-master-conf
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+data:
+ nfd-master.conf: |-
+ {{- .Values.master.config | toYaml | nindent 4 }}
+{{- end }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-topologyupdater-conf.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-topologyupdater-conf.yaml
new file mode 100644
index 0000000..1680d69
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-topologyupdater-conf.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}-topology-updater-conf
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+data:
+ nfd-topology-updater.conf: |-
+ {{- .Values.topologyUpdater.config | toYaml | nindent 4 }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-worker-conf.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-worker-conf.yaml
new file mode 100644
index 0000000..3e1148d
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-worker-conf.yaml
@@ -0,0 +1,12 @@
+{{- if .Values.worker.enable }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}-worker-conf
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+data:
+ nfd-worker.conf: |-
+ {{- .Values.worker.config | toYaml | nindent 4 }}
+{{- end }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/prometheus.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/prometheus.yaml
new file mode 100644
index 0000000..cbc8f85
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/prometheus.yaml
@@ -0,0 +1,26 @@
+{{- if .Values.prometheus.enable }}
+# Prometheus Monitor Service (Metrics)
+apiVersion: monitoring.coreos.com/v1
+kind: PodMonitor
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}
+ labels:
+ {{- include "node-feature-discovery.selectorLabels" . | nindent 4 }}
+ {{- with .Values.prometheus.labels }}
+ {{ toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ podMetricsEndpoints:
+ - honorLabels: true
+ interval: 10s
+ path: /metrics
+ port: metrics
+ scheme: http
+ namespaceSelector:
+ matchNames:
+ - {{ include "node-feature-discovery.namespace" . }}
+ selector:
+ matchExpressions:
+ - {key: app.kubernetes.io/instance, operator: In, values: ["{{ .Release.Name }}"]}
+ - {key: app.kubernetes.io/name, operator: In, values: ["{{ include "node-feature-discovery.name" . }}"]}
+{{- end }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/role.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/role.yaml
new file mode 100644
index 0000000..06ca73e
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/role.yaml
@@ -0,0 +1,24 @@
+{{- if and .Values.worker.enable .Values.worker.rbac.create }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}-worker
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+rules:
+- apiGroups:
+ - nfd.k8s-sigs.io
+ resources:
+ - nodefeatures
+ verbs:
+ - create
+ - get
+ - update
+- apiGroups:
+ - ""
+ resources:
+ - pods
+ verbs:
+ - get
+{{- end }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/rolebinding.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/rolebinding.yaml
new file mode 100644
index 0000000..46ac7f7
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/rolebinding.yaml
@@ -0,0 +1,18 @@
+{{- if and .Values.worker.enable .Values.worker.rbac.create }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}-worker
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: {{ include "node-feature-discovery.fullname" . }}-worker
+subjects:
+- kind: ServiceAccount
+ name: {{ include "node-feature-discovery.worker.serviceAccountName" . }}
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+{{- end }}
+
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/service.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/service.yaml
new file mode 100644
index 0000000..a82c22d
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/service.yaml
@@ -0,0 +1,20 @@
+{{- if and (not .Values.enableNodeFeatureApi) .Values.master.enable }}
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}-master
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+ role: master
+spec:
+ type: {{ .Values.master.service.type }}
+ ports:
+ - port: {{ .Values.master.service.port | default "8080" }}
+ targetPort: grpc
+ protocol: TCP
+ name: grpc
+ selector:
+ {{- include "node-feature-discovery.selectorLabels" . | nindent 4 }}
+ role: master
+{{- end}}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/serviceaccount.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/serviceaccount.yaml
new file mode 100644
index 0000000..52706f7
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/serviceaccount.yaml
@@ -0,0 +1,58 @@
+{{- if and .Values.master.enable .Values.master.serviceAccount.create }}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "node-feature-discovery.master.serviceAccountName" . }}
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+ {{- with .Values.master.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
+
+{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.serviceAccount.create }}
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "node-feature-discovery.topologyUpdater.serviceAccountName" . }}
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+ {{- with .Values.topologyUpdater.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
+
+{{- if and .Values.gc.enable .Values.gc.serviceAccount.create (or .Values.enableNodeFeatureApi .Values.topologyUpdater.enable) }}
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "node-feature-discovery.gc.serviceAccountName" . }}
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+ {{- with .Values.gc.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
+
+{{- if and .Values.worker.enable .Values.worker.serviceAccount.create }}
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "node-feature-discovery.worker.serviceAccountName" . }}
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+ {{- with .Values.worker.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater-crds.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater-crds.yaml
new file mode 100644
index 0000000..94b7b35
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater-crds.yaml
@@ -0,0 +1,278 @@
+{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.createCRDs -}}
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ api-approved.kubernetes.io: https://github.com/kubernetes/enhancements/pull/1870
+ controller-gen.kubebuilder.io/version: v0.11.2
+ creationTimestamp: null
+ name: noderesourcetopologies.topology.node.k8s.io
+spec:
+ group: topology.node.k8s.io
+ names:
+ kind: NodeResourceTopology
+ listKind: NodeResourceTopologyList
+ plural: noderesourcetopologies
+ shortNames:
+ - node-res-topo
+ singular: noderesourcetopology
+ scope: Cluster
+ versions:
+ - name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: NodeResourceTopology describes node resources and their topology.
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ topologyPolicies:
+ items:
+ type: string
+ type: array
+ zones:
+ description: ZoneList contains an array of Zone objects.
+ items:
+ description: Zone represents a resource topology zone, e.g. socket,
+ node, die or core.
+ properties:
+ attributes:
+ description: AttributeList contains an array of AttributeInfo objects.
+ items:
+ description: AttributeInfo contains one attribute of a Zone.
+ properties:
+ name:
+ type: string
+ value:
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ type: array
+ costs:
+ description: CostList contains an array of CostInfo objects.
+ items:
+ description: CostInfo describes the cost (or distance) between
+ two Zones.
+ properties:
+ name:
+ type: string
+ value:
+ format: int64
+ type: integer
+ required:
+ - name
+ - value
+ type: object
+ type: array
+ name:
+ type: string
+ parent:
+ type: string
+ resources:
+ description: ResourceInfoList contains an array of ResourceInfo
+ objects.
+ items:
+ description: ResourceInfo contains information about one resource
+ type.
+ properties:
+ allocatable:
+ anyOf:
+ - type: integer
+ - type: string
+ description: Allocatable quantity of the resource, corresponding
+ to allocatable in node status, i.e. total amount of this
+ resource available to be used by pods.
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ available:
+ anyOf:
+ - type: integer
+ - type: string
+ description: Available is the amount of this resource currently
+ available for new (to be scheduled) pods, i.e. Allocatable
+ minus the resources reserved by currently running pods.
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ capacity:
+ anyOf:
+ - type: integer
+ - type: string
+ description: Capacity of the resource, corresponding to capacity
+ in node status, i.e. total amount of this resource that
+ the node has.
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ name:
+ description: Name of the resource.
+ type: string
+ required:
+ - allocatable
+ - available
+ - capacity
+ - name
+ type: object
+ type: array
+ type:
+ type: string
+ required:
+ - name
+ - type
+ type: object
+ type: array
+ required:
+ - topologyPolicies
+ - zones
+ type: object
+ served: true
+ storage: false
+ - name: v1alpha2
+ schema:
+ openAPIV3Schema:
+ description: NodeResourceTopology describes node resources and their topology.
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ attributes:
+ description: AttributeList contains an array of AttributeInfo objects.
+ items:
+ description: AttributeInfo contains one attribute of a Zone.
+ properties:
+ name:
+ type: string
+ value:
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ type: array
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ topologyPolicies:
+ description: 'DEPRECATED (to be removed in v1beta1): use top level attributes
+ if needed'
+ items:
+ type: string
+ type: array
+ zones:
+ description: ZoneList contains an array of Zone objects.
+ items:
+ description: Zone represents a resource topology zone, e.g. socket,
+ node, die or core.
+ properties:
+ attributes:
+ description: AttributeList contains an array of AttributeInfo objects.
+ items:
+ description: AttributeInfo contains one attribute of a Zone.
+ properties:
+ name:
+ type: string
+ value:
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ type: array
+ costs:
+ description: CostList contains an array of CostInfo objects.
+ items:
+ description: CostInfo describes the cost (or distance) between
+ two Zones.
+ properties:
+ name:
+ type: string
+ value:
+ format: int64
+ type: integer
+ required:
+ - name
+ - value
+ type: object
+ type: array
+ name:
+ type: string
+ parent:
+ type: string
+ resources:
+ description: ResourceInfoList contains an array of ResourceInfo
+ objects.
+ items:
+ description: ResourceInfo contains information about one resource
+ type.
+ properties:
+ allocatable:
+ anyOf:
+ - type: integer
+ - type: string
+ description: Allocatable quantity of the resource, corresponding
+ to allocatable in node status, i.e. total amount of this
+ resource available to be used by pods.
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ available:
+ anyOf:
+ - type: integer
+ - type: string
+ description: Available is the amount of this resource currently
+ available for new (to be scheduled) pods, i.e. Allocatable
+ minus the resources reserved by currently running pods.
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ capacity:
+ anyOf:
+ - type: integer
+ - type: string
+ description: Capacity of the resource, corresponding to capacity
+ in node status, i.e. total amount of this resource that
+ the node has.
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ name:
+ description: Name of the resource.
+ type: string
+ required:
+ - allocatable
+ - available
+ - capacity
+ - name
+ type: object
+ type: array
+ type:
+ type: string
+ required:
+ - name
+ - type
+ type: object
+ type: array
+ required:
+ - zones
+ type: object
+ served: true
+ storage: true
+status:
+ acceptedNames:
+ kind: ""
+ plural: ""
+ conditions: []
+ storedVersions: []
+{{- end }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater.yaml
new file mode 100644
index 0000000..28ed58b
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater.yaml
@@ -0,0 +1,156 @@
+{{- if .Values.topologyUpdater.enable -}}
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}-topology-updater
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+ role: topology-updater
+ {{- with .Values.topologyUpdater.daemonsetAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ selector:
+ matchLabels:
+ {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }}
+ role: topology-updater
+ template:
+ metadata:
+ labels:
+ {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }}
+ role: topology-updater
+ {{- with .Values.topologyUpdater.annotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ spec:
+ serviceAccountName: {{ include "node-feature-discovery.topologyUpdater.serviceAccountName" . }}
+ dnsPolicy: ClusterFirstWithHostNet
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ securityContext:
+ {{- toYaml .Values.topologyUpdater.podSecurityContext | nindent 8 }}
+ containers:
+ - name: topology-updater
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: "{{ .Values.image.pullPolicy }}"
+ env:
+ - name: NODE_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: spec.nodeName
+ - name: NODE_ADDRESS
+ valueFrom:
+ fieldRef:
+ fieldPath: status.hostIP
+ command:
+ - "nfd-topology-updater"
+ args:
+ - "-podresources-socket=/host-var/lib/kubelet-podresources/kubelet.sock"
+ {{- if .Values.topologyUpdater.updateInterval | empty | not }}
+ - "-sleep-interval={{ .Values.topologyUpdater.updateInterval }}"
+ {{- else }}
+ - "-sleep-interval=3s"
+ {{- end }}
+ {{- if .Values.topologyUpdater.watchNamespace | empty | not }}
+ - "-watch-namespace={{ .Values.topologyUpdater.watchNamespace }}"
+ {{- else }}
+ - "-watch-namespace=*"
+ {{- end }}
+ {{- if .Values.tls.enable }}
+ - "-ca-file=/etc/kubernetes/node-feature-discovery/certs/ca.crt"
+ - "-key-file=/etc/kubernetes/node-feature-discovery/certs/tls.key"
+ - "-cert-file=/etc/kubernetes/node-feature-discovery/certs/tls.crt"
+ {{- end }}
+ {{- if .Values.topologyUpdater.podSetFingerprint }}
+ - "-pods-fingerprint"
+ {{- end }}
+ {{- if .Values.topologyUpdater.kubeletConfigPath | empty | not }}
+ - "-kubelet-config-uri=file:///host-var/kubelet-config"
+ {{- end }}
+ {{- if .Values.topologyUpdater.kubeletStateDir | empty }}
+ # Disable kubelet state tracking by giving an empty path
+ - "-kubelet-state-dir="
+ {{- end }}
+ - -metrics={{ .Values.topologyUpdater.metricsPort | default "8081"}}
+ ports:
+ - name: metrics
+ containerPort: {{ .Values.topologyUpdater.metricsPort | default "8081"}}
+ volumeMounts:
+ {{- if .Values.topologyUpdater.kubeletConfigPath | empty | not }}
+ - name: kubelet-config
+ mountPath: /host-var/kubelet-config
+ {{- end }}
+ - name: kubelet-podresources-sock
+ mountPath: /host-var/lib/kubelet-podresources/kubelet.sock
+ - name: host-sys
+ mountPath: /host-sys
+ {{- if .Values.topologyUpdater.kubeletStateDir | empty | not }}
+ - name: kubelet-state-files
+ mountPath: /host-var/lib/kubelet
+ readOnly: true
+ {{- end }}
+ {{- if .Values.tls.enable }}
+ - name: nfd-topology-updater-cert
+ mountPath: "/etc/kubernetes/node-feature-discovery/certs"
+ readOnly: true
+ {{- end }}
+ - name: nfd-topology-updater-conf
+ mountPath: "/etc/kubernetes/node-feature-discovery"
+ readOnly: true
+
+ resources:
+ {{- toYaml .Values.topologyUpdater.resources | nindent 12 }}
+ securityContext:
+ {{- toYaml .Values.topologyUpdater.securityContext | nindent 12 }}
+ volumes:
+ - name: host-sys
+ hostPath:
+ path: "/sys"
+ {{- if .Values.topologyUpdater.kubeletConfigPath | empty | not }}
+ - name: kubelet-config
+ hostPath:
+ path: {{ .Values.topologyUpdater.kubeletConfigPath }}
+ {{- end }}
+ - name: kubelet-podresources-sock
+ hostPath:
+ {{- if .Values.topologyUpdater.kubeletPodResourcesSockPath | empty | not }}
+ path: {{ .Values.topologyUpdater.kubeletPodResourcesSockPath }}
+ {{- else }}
+ path: /var/lib/kubelet/pod-resources/kubelet.sock
+ {{- end }}
+ {{- if .Values.topologyUpdater.kubeletStateDir | empty | not }}
+ - name: kubelet-state-files
+ hostPath:
+ path: {{ .Values.topologyUpdater.kubeletStateDir }}
+ {{- end }}
+ - name: nfd-topology-updater-conf
+ configMap:
+ name: {{ include "node-feature-discovery.fullname" . }}-topology-updater-conf
+ items:
+ - key: nfd-topology-updater.conf
+ path: nfd-topology-updater.conf
+ {{- if .Values.tls.enable }}
+ - name: nfd-topology-updater-cert
+ secret:
+ secretName: nfd-topology-updater-cert
+ {{- end }}
+
+
+ {{- with .Values.topologyUpdater.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.topologyUpdater.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.topologyUpdater.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+{{- end }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/worker.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/worker.yaml
new file mode 100644
index 0000000..124e1a0
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/worker.yaml
@@ -0,0 +1,162 @@
+{{- if .Values.worker.enable }}
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+ name: {{ include "node-feature-discovery.fullname" . }}-worker
+ namespace: {{ include "node-feature-discovery.namespace" . }}
+ labels:
+ {{- include "node-feature-discovery.labels" . | nindent 4 }}
+ role: worker
+ {{- with .Values.worker.daemonsetAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ selector:
+ matchLabels:
+ {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }}
+ role: worker
+ template:
+ metadata:
+ labels:
+ {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }}
+ role: worker
+ {{- with .Values.worker.annotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ spec:
+ dnsPolicy: ClusterFirstWithHostNet
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "node-feature-discovery.worker.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.worker.podSecurityContext | nindent 8 }}
+ containers:
+ - name: worker
+ securityContext:
+ {{- toYaml .Values.worker.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ env:
+ - name: NODE_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: spec.nodeName
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: POD_UID
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.uid
+ resources:
+ {{- toYaml .Values.worker.resources | nindent 12 }}
+ command:
+ - "nfd-worker"
+ args:
+ {{- if not .Values.enableNodeFeatureApi }}
+ - "-server={{ include "node-feature-discovery.fullname" . }}-master:{{ .Values.master.service.port }}"
+ - "-enable-nodefeature-api=false"
+ {{- end }}
+{{- if .Values.tls.enable }}
+ - "-ca-file=/etc/kubernetes/node-feature-discovery/certs/ca.crt"
+ - "-key-file=/etc/kubernetes/node-feature-discovery/certs/tls.key"
+ - "-cert-file=/etc/kubernetes/node-feature-discovery/certs/tls.crt"
+{{- end }}
+ - "-metrics={{ .Values.worker.metricsPort | default "8081"}}"
+ ports:
+ - name: metrics
+ containerPort: {{ .Values.worker.metricsPort | default "8081"}}
+ volumeMounts:
+ - name: host-boot
+ mountPath: "/host-boot"
+ readOnly: true
+ - name: host-os-release
+ mountPath: "/host-etc/os-release"
+ readOnly: true
+ - name: host-sys
+ mountPath: "/host-sys"
+ readOnly: true
+ - name: host-usr-lib
+ mountPath: "/host-usr/lib"
+ readOnly: true
+ - name: host-lib
+ mountPath: "/host-lib"
+ readOnly: true
+ {{- if .Values.worker.mountUsrSrc }}
+ - name: host-usr-src
+ mountPath: "/host-usr/src"
+ readOnly: true
+ {{- end }}
+ - name: source-d
+ mountPath: "/etc/kubernetes/node-feature-discovery/source.d/"
+ readOnly: true
+ - name: features-d
+ mountPath: "/etc/kubernetes/node-feature-discovery/features.d/"
+ readOnly: true
+ - name: nfd-worker-conf
+ mountPath: "/etc/kubernetes/node-feature-discovery"
+ readOnly: true
+{{- if .Values.tls.enable }}
+ - name: nfd-worker-cert
+ mountPath: "/etc/kubernetes/node-feature-discovery/certs"
+ readOnly: true
+{{- end }}
+ volumes:
+ - name: host-boot
+ hostPath:
+ path: "/boot"
+ - name: host-os-release
+ hostPath:
+ path: "/etc/os-release"
+ - name: host-sys
+ hostPath:
+ path: "/sys"
+ - name: host-usr-lib
+ hostPath:
+ path: "/usr/lib"
+ - name: host-lib
+ hostPath:
+ path: "/lib"
+ {{- if .Values.worker.mountUsrSrc }}
+ - name: host-usr-src
+ hostPath:
+ path: "/usr/src"
+ {{- end }}
+ - name: source-d
+ hostPath:
+ path: "/etc/kubernetes/node-feature-discovery/source.d/"
+ - name: features-d
+ hostPath:
+ path: "/etc/kubernetes/node-feature-discovery/features.d/"
+ - name: nfd-worker-conf
+ configMap:
+ name: {{ include "node-feature-discovery.fullname" . }}-worker-conf
+ items:
+ - key: nfd-worker.conf
+ path: nfd-worker.conf
+{{- if .Values.tls.enable }}
+ - name: nfd-worker-cert
+ secret:
+ secretName: nfd-worker-cert
+{{- end }}
+ {{- with .Values.worker.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.worker.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.worker.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.worker.priorityClassName }}
+ priorityClassName: {{ . | quote }}
+ {{- end }}
+{{- end }}
diff --git a/sriov-network-operator-chart/charts/sriov-nfd/values.yaml b/sriov-network-operator-chart/charts/sriov-nfd/values.yaml
new file mode 100644
index 0000000..9d9aa94
--- /dev/null
+++ b/sriov-network-operator-chart/charts/sriov-nfd/values.yaml
@@ -0,0 +1,534 @@
+image:
+ repository: rancher/hardened-node-feature-discovery
+ # This should be set to 'IfNotPresent' for released version
+ pullPolicy: IfNotPresent
+ # tag, if defined will use the given image tag, else Chart.AppVersion will be used
+ tag: v0.15.6-build20240822
+imagePullSecrets: []
+
+nameOverride: ""
+fullnameOverride: ""
+namespaceOverride: ""
+
+enableNodeFeatureApi: true
+
+master:
+ enable: true
+ config: ###
+ # noPublish: false
+ # autoDefaultNs: true
+ # extraLabelNs: ["added.ns.io","added.kubernets.io"]
+ # denyLabelNs: ["denied.ns.io","denied.kubernetes.io"]
+ # resourceLabels: ["vendor-1.com/feature-1","vendor-2.io/feature-2"]
+ # enableTaints: false
+ # labelWhiteList: "foo"
+ # resyncPeriod: "2h"
+ # klog:
+ # addDirHeader: false
+ # alsologtostderr: false
+ # logBacktraceAt:
+ # logtostderr: true
+ # skipHeaders: false
+ # stderrthreshold: 2
+ # v: 0
+ # vmodule:
+ ## NOTE: the following options are not dynamically run-time configurable
+ ## and require a nfd-master restart to take effect after being changed
+ # logDir:
+ # logFile:
+ # logFileMaxSize: 1800
+ # skipLogHeaders: false
+ # leaderElection:
+ # leaseDuration: 15s
+ # # this value has to be lower than leaseDuration and greater than retryPeriod*1.2
+ # renewDeadline: 10s
+ # # this value has to be greater than 0
+ # retryPeriod: 2s
+ # nfdApiParallelism: 10
+ ###
+ # The TCP port that nfd-master listens for incoming requests. Default: 8080
+ # Deprecated this parameter is related to the deprecated gRPC API and will
+ # be removed with it in a future release
+ port: 8080
+ metricsPort: 8081
+ instance:
+ featureApi:
+ resyncPeriod:
+ denyLabelNs: []
+ extraLabelNs: []
+ resourceLabels: []
+ enableTaints: false
+ crdController: null
+ featureRulesController: null
+ nfdApiParallelism: null
+ deploymentAnnotations: {}
+ replicaCount: 1
+
+ podSecurityContext: {}
+ # fsGroup: 2000
+
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop: [ "ALL" ]
+ readOnlyRootFilesystem: true
+ runAsNonRoot: true
+ # runAsUser: 1000
+
+ serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name:
+
+ rbac:
+ create: true
+
+ service:
+ type: ClusterIP
+ port: 8080
+
+ resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+ nodeSelector: {}
+
+ tolerations:
+ - key: "node-role.kubernetes.io/master"
+ operator: "Equal"
+ value: ""
+ effect: "NoSchedule"
+ - key: "node-role.kubernetes.io/control-plane"
+ operator: "Equal"
+ value: ""
+ effect: "NoSchedule"
+
+ annotations: {}
+
+ affinity:
+ nodeAffinity:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ - weight: 1
+ preference:
+ matchExpressions:
+ - key: "node-role.kubernetes.io/master"
+ operator: In
+ values: [""]
+ - weight: 1
+ preference:
+ matchExpressions:
+ - key: "node-role.kubernetes.io/control-plane"
+ operator: In
+ values: [""]
+
+worker:
+ enable: true
+ config: ###
+ #core:
+ # labelWhiteList:
+ # noPublish: false
+ # sleepInterval: 60s
+ # featureSources: [all]
+ # labelSources: [all]
+ # klog:
+ # addDirHeader: false
+ # alsologtostderr: false
+ # logBacktraceAt:
+ # logtostderr: true
+ # skipHeaders: false
+ # stderrthreshold: 2
+ # v: 0
+ # vmodule:
+ ## NOTE: the following options are not dynamically run-time configurable
+ ## and require a nfd-worker restart to take effect after being changed
+ # logDir:
+ # logFile:
+ # logFileMaxSize: 1800
+ # skipLogHeaders: false
+ #sources:
+ # cpu:
+ # cpuid:
+ ## NOTE: whitelist has priority over blacklist
+ # attributeBlacklist:
+ # - "BMI1"
+ # - "BMI2"
+ # - "CLMUL"
+ # - "CMOV"
+ # - "CX16"
+ # - "ERMS"
+ # - "F16C"
+ # - "HTT"
+ # - "LZCNT"
+ # - "MMX"
+ # - "MMXEXT"
+ # - "NX"
+ # - "POPCNT"
+ # - "RDRAND"
+ # - "RDSEED"
+ # - "RDTSCP"
+ # - "SGX"
+ # - "SSE"
+ # - "SSE2"
+ # - "SSE3"
+ # - "SSE4"
+ # - "SSE42"
+ # - "SSSE3"
+ # - "TDX_GUEST"
+ # attributeWhitelist:
+ # kernel:
+ # kconfigFile: "/path/to/kconfig"
+ # configOpts:
+ # - "NO_HZ"
+ # - "X86"
+ # - "DMI"
+ # pci:
+ # deviceClassWhitelist:
+ # - "0200"
+ # - "03"
+ # - "12"
+ # deviceLabelFields:
+ # - "class"
+ # - "vendor"
+ # - "device"
+ # - "subsystem_vendor"
+ # - "subsystem_device"
+ # usb:
+ # deviceClassWhitelist:
+ # - "0e"
+ # - "ef"
+ # - "fe"
+ # - "ff"
+ # deviceLabelFields:
+ # - "class"
+ # - "vendor"
+ # - "device"
+ # local:
+ # hooksEnabled: false
+ # custom:
+ # # The following feature demonstrates the capabilities of the matchFeatures
+ # - name: "my custom rule"
+ # labels:
+ # "vendor.io/my-ng-feature": "true"
+ # # matchFeatures implements a logical AND over all matcher terms in the
+ # # list (i.e. all of the terms, or per-feature matchers, must match)
+ # matchFeatures:
+ # - feature: cpu.cpuid
+ # matchExpressions:
+ # AVX512F: {op: Exists}
+ # - feature: cpu.cstate
+ # matchExpressions:
+ # enabled: {op: IsTrue}
+ # - feature: cpu.pstate
+ # matchExpressions:
+ # no_turbo: {op: IsFalse}
+ # scaling_governor: {op: In, value: ["performance"]}
+ # - feature: cpu.rdt
+ # matchExpressions:
+ # RDTL3CA: {op: Exists}
+ # - feature: cpu.sst
+ # matchExpressions:
+ # bf.enabled: {op: IsTrue}
+ # - feature: cpu.topology
+ # matchExpressions:
+ # hardware_multithreading: {op: IsFalse}
+ #
+ # - feature: kernel.config
+ # matchExpressions:
+ # X86: {op: Exists}
+ # LSM: {op: InRegexp, value: ["apparmor"]}
+ # - feature: kernel.loadedmodule
+ # matchExpressions:
+ # e1000e: {op: Exists}
+ # - feature: kernel.selinux
+ # matchExpressions:
+ # enabled: {op: IsFalse}
+ # - feature: kernel.version
+ # matchExpressions:
+ # major: {op: In, value: ["5"]}
+ # minor: {op: Gt, value: ["10"]}
+ #
+ # - feature: storage.block
+ # matchExpressions:
+ # rotational: {op: In, value: ["0"]}
+ # dax: {op: In, value: ["0"]}
+ #
+ # - feature: network.device
+ # matchExpressions:
+ # operstate: {op: In, value: ["up"]}
+ # speed: {op: Gt, value: ["100"]}
+ #
+ # - feature: memory.numa
+ # matchExpressions:
+ # node_count: {op: Gt, value: ["2"]}
+ # - feature: memory.nv
+ # matchExpressions:
+ # devtype: {op: In, value: ["nd_dax"]}
+ # mode: {op: In, value: ["memory"]}
+ #
+ # - feature: system.osrelease
+ # matchExpressions:
+ # ID: {op: In, value: ["fedora", "centos"]}
+ # - feature: system.name
+ # matchExpressions:
+ # nodename: {op: InRegexp, value: ["^worker-X"]}
+ #
+ # - feature: local.label
+ # matchExpressions:
+ # custom-feature-knob: {op: Gt, value: ["100"]}
+ #
+ # # The following feature demonstrates the capabilities of the matchAny
+ # - name: "my matchAny rule"
+ # labels:
+ # "vendor.io/my-ng-feature-2": "my-value"
+ # # matchAny implements a logical IF over all elements (sub-matchers) in
+ # # the list (i.e. at least one feature matcher must match)
+ # matchAny:
+ # - matchFeatures:
+ # - feature: kernel.loadedmodule
+ # matchExpressions:
+ # driver-module-X: {op: Exists}
+ # - feature: pci.device
+ # matchExpressions:
+ # vendor: {op: In, value: ["8086"]}
+ # class: {op: In, value: ["0200"]}
+ # - matchFeatures:
+ # - feature: kernel.loadedmodule
+ # matchExpressions:
+ # driver-module-Y: {op: Exists}
+ # - feature: usb.device
+ # matchExpressions:
+ # vendor: {op: In, value: ["8086"]}
+ # class: {op: In, value: ["02"]}
+ #
+ # - name: "avx wildcard rule"
+ # labels:
+ # "my-avx-feature": "true"
+ # matchFeatures:
+ # - feature: cpu.cpuid
+ # matchName: {op: InRegexp, value: ["^AVX512"]}
+ #
+ # # The following features demonstreate label templating capabilities
+ # - name: "my template rule"
+ # labelsTemplate: |
+ # {{ range .system.osrelease }}vendor.io/my-system-feature.{{ .Name }}={{ .Value }}
+ # {{ end }}
+ # matchFeatures:
+ # - feature: system.osrelease
+ # matchExpressions:
+ # ID: {op: InRegexp, value: ["^open.*"]}
+ # VERSION_ID.major: {op: In, value: ["13", "15"]}
+ #
+ # - name: "my template rule 2"
+ # labelsTemplate: |
+ # {{ range .pci.device }}vendor.io/my-pci-device.{{ .class }}-{{ .device }}=with-cpuid
+ # {{ end }}
+ # matchFeatures:
+ # - feature: pci.device
+ # matchExpressions:
+ # class: {op: InRegexp, value: ["^06"]}
+ # vendor: ["8086"]
+ # - feature: cpu.cpuid
+ # matchExpressions:
+ # AVX: {op: Exists}
+ #
+ # # The following examples demonstrate vars field and back-referencing
+ # # previous labels and vars
+ # - name: "my dummy kernel rule"
+ # labels:
+ # "vendor.io/my.kernel.feature": "true"
+ # matchFeatures:
+ # - feature: kernel.version
+ # matchExpressions:
+ # major: {op: Gt, value: ["2"]}
+ #
+ # - name: "my dummy rule with no labels"
+ # vars:
+ # "my.dummy.var": "1"
+ # matchFeatures:
+ # - feature: cpu.cpuid
+ # matchExpressions: {}
+ #
+ # - name: "my rule using backrefs"
+ # labels:
+ # "vendor.io/my.backref.feature": "true"
+ # matchFeatures:
+ # - feature: rule.matched
+ # matchExpressions:
+ # vendor.io/my.kernel.feature: {op: IsTrue}
+ # my.dummy.var: {op: Gt, value: ["0"]}
+ #
+ # - name: "kconfig template rule"
+ # labelsTemplate: |
+ # {{ range .kernel.config }}kconfig-{{ .Name }}={{ .Value }}
+ # {{ end }}
+ # matchFeatures:
+ # - feature: kernel.config
+ # matchName: {op: In, value: ["SWAP", "X86", "ARM"]}
+###
+
+ metricsPort: 8081
+ daemonsetAnnotations: {}
+ podSecurityContext: {}
+ # fsGroup: 2000
+
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop: [ "ALL" ]
+ readOnlyRootFilesystem: true
+ runAsNonRoot: true
+ # runAsUser: 1000
+
+ serviceAccount:
+ # Specifies whether a service account should be created.
+ # We create this by default to make it easier for downstream users to apply PodSecurityPolicies.
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name:
+
+ rbac:
+ create: true
+
+ # Allow users to mount the hostPath /usr/src, useful for RHCOS on s390x
+ # Does not work on systems without /usr/src AND a read-only /usr, such as Talos
+ mountUsrSrc: false
+
+ resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+ nodeSelector: {}
+
+ tolerations: []
+
+ annotations: {}
+
+ affinity: {}
+
+ priorityClassName: ""
+
+topologyUpdater:
+ config: ###
+ ## key = node name, value = list of resources to be excluded.
+ ## use * to exclude from all nodes.
+ ## an example for how the exclude list should looks like
+ #excludeList:
+ # node1: [cpu]
+ # node2: [memory, example/deviceA]
+ # *: [hugepages-2Mi]
+###
+
+ enable: false
+ createCRDs: false
+
+ serviceAccount:
+ create: true
+ annotations: {}
+ name:
+ rbac:
+ create: true
+
+ metricsPort: 8081
+ kubeletConfigPath:
+ kubeletPodResourcesSockPath:
+ updateInterval: 60s
+ watchNamespace: "*"
+ kubeletStateDir: /var/lib/kubelet
+
+ podSecurityContext: {}
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop: [ "ALL" ]
+ readOnlyRootFilesystem: true
+ runAsUser: 0
+
+ resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+ nodeSelector: {}
+ tolerations: []
+ annotations: {}
+ daemonsetAnnotations: {}
+ affinity: {}
+ podSetFingerprint: true
+
+gc:
+ enable: true
+ replicaCount: 1
+
+ serviceAccount:
+ create: true
+ annotations: {}
+ name:
+ rbac:
+ create: true
+
+ interval: 1h
+
+ podSecurityContext: {}
+
+ resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+ metricsPort: 8081
+
+ nodeSelector: {}
+ tolerations: []
+ annotations: {}
+ deploymentAnnotations: {}
+ affinity: {}
+
+# Optionally use encryption for worker <--> master comms
+# TODO: verify hostname is not yet supported
+#
+# If you do not enable certManager (and have it installed) you will
+# need to manually, or otherwise, provision the TLS certs as secrets
+tls:
+ enable: false
+ certManager: false
+
+prometheus:
+ enable: false
+ labels: {}
diff --git a/sriov-network-operator-chart/templates/NOTES.txt b/sriov-network-operator-chart/templates/NOTES.txt
new file mode 100644
index 0000000..e246ccd
--- /dev/null
+++ b/sriov-network-operator-chart/templates/NOTES.txt
@@ -0,0 +1,17 @@
+Get Network Operator deployed resources by running the following commands:
+
+$ kubectl -n {{ .Release.Namespace }} get pods
+
+For additional instructions on how to use SR-IOV network operator,
+refer to: https://github.com/k8snetworkplumbingwg/sriov-network-operator
+
+{{- if .Values.operator.enableAdmissionController }}
+{{- if not .Values.cert_manager }}
+Thank you for installing {{ .Chart.Name }}.
+
+WARNING! Self signed certificates have been generated for webhooks.
+These certificates have a one-year validity and will not be rotated
+automatically. This should not be a production cluster. Please deploy
+and use cert-manager for production clusters.
+{{- end }}
+{{- end }}
diff --git a/sriov-network-operator-chart/templates/_helpers.tpl b/sriov-network-operator-chart/templates/_helpers.tpl
new file mode 100644
index 0000000..3a3a9b8
--- /dev/null
+++ b/sriov-network-operator-chart/templates/_helpers.tpl
@@ -0,0 +1,85 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "sriov-network-operator.name" -}}
+{{- default "sriov-network-operator" .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "sriov-network-operator.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default "sriov-network-operator" .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "sriov-network-operator.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "sriov-network-operator.labels" -}}
+helm.sh/chart: {{ include "sriov-network-operator.chart" . }}
+{{ include "sriov-network-operator.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "sriov-network-operator.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "sriov-network-operator.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "sriov-network-operator.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "sriov-network-operator.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
+
+{{- define "system_default_registry" -}}
+{{- if .Values.global.cattle.systemDefaultRegistry -}}
+{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}}
+{{- else -}}
+{{- "" -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Windows cluster will add default taint for linux nodes,
+add below linux tolerations to workloads could be scheduled to those linux nodes
+*/}}
+{{- define "linux-node-tolerations" -}}
+- key: "cattle.io/os"
+ value: "linux"
+ effect: "NoSchedule"
+ operator: "Equal"
+{{- end -}}
+
+{{- define "linux-node-selector" -}}
+kubernetes.io/os: linux
+{{- end -}}
diff --git a/sriov-network-operator-chart/templates/_webhook-certs.tpl b/sriov-network-operator-chart/templates/_webhook-certs.tpl
new file mode 100644
index 0000000..046a174
--- /dev/null
+++ b/sriov-network-operator-chart/templates/_webhook-certs.tpl
@@ -0,0 +1,31 @@
+{{/*
+Generate TLS certificates for webhooks.
+Note: these 2 lines, that are repeated several times below, are a trick to
+ensure the CA certs are generated only once:
+ $ca := .ca | default (genCA "sriov-network-operator.k8s.cni.cncf.io" 365)
+ $_ := set . "ca" $ca
+Please, don't try to "simplify" them as without this trick, every generated
+certificate would be signed by a different CA.
+*/}}
+{{- define "sriov_operator_ca_cert" }}
+{{- $ca := .ca | default (genCA "sriov-network-operator.k8s.cni.cncf.io" 365) -}}
+{{- $_ := set . "ca" $ca -}}
+{{- printf "%s" $ca.Cert | b64enc -}}
+{{- end }}
+{{- define "sriov_operator_cert" }}
+{{- $ca := .ca | default (genCA "sriov-network-operator.k8s.cni.cncf.io" 365) -}}
+{{- $_ := set . "ca" $ca -}}
+{{- $cn := printf "operator-webhook-service.%s.svc" .Release.Namespace -}}
+{{- $cert := genSignedCert $cn nil (list $cn) 365 $ca -}}
+tls.crt: {{ $cert.Cert | b64enc }}
+tls.key: {{ $cert.Key | b64enc }}
+{{- end }}
+{{- define "sriov_resource_injector_cert" }}
+{{- $ca := .ca | default (genCA "sriov-network-operator.k8s.cni.cncf.io" 365) -}}
+{{- $_ := set . "ca" $ca -}}
+{{- $cn := printf "network-resources-injector-service.%s.svc" .Release.Namespace -}}
+{{- $cert := genSignedCert $cn nil (list $cn) 365 $ca -}}
+tls.crt: {{ $cert.Cert | b64enc }}
+tls.key: {{ $cert.Key | b64enc }}
+{{- end }}
+
diff --git a/sriov-network-operator-chart/templates/certificate.yaml b/sriov-network-operator-chart/templates/certificate.yaml
new file mode 100644
index 0000000..1c6a38c
--- /dev/null
+++ b/sriov-network-operator-chart/templates/certificate.yaml
@@ -0,0 +1,71 @@
+{{- if .Values.operator.admissionControllers.enabled }}
+{{- if and (.Values.operator.admissionControllers.certificates.certManager.enabled) (.Values.operator.admissionControllers.certificates.certManager.generateSelfSigned) }}
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: {{ .Values.operator.admissionControllers.certificates.secretNames.operator }}
+ namespace: {{ .Release.Namespace }}
+spec:
+ dnsNames:
+ - operator-webhook-service.{{ .Release.Namespace }}.svc
+ - operator-webhook-service.{{ .Release.Namespace }}.svc.cluster.local
+ issuerRef:
+ kind: Issuer
+ name: operator-webhook-selfsigned-issuer
+ secretName: {{ .Values.operator.admissionControllers.certificates.secretNames.operator }}
+---
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: operator-webhook-selfsigned-issuer
+ namespace: {{ .Release.Namespace }}
+spec:
+ selfSigned: {}
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: {{ .Values.operator.admissionControllers.certificates.secretNames.injector }}
+ namespace: {{ .Release.Namespace }}
+spec:
+ dnsNames:
+ - network-resources-injector-service.{{ .Release.Namespace }}.svc
+ - network-resources-injector-service.{{ .Release.Namespace }}.svc.cluster.local
+ issuerRef:
+ kind: Issuer
+ name: network-resources-injector-selfsigned-issuer
+ secretName: {{ .Values.operator.admissionControllers.certificates.secretNames.injector }}
+---
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: network-resources-injector-selfsigned-issuer
+ namespace: {{ .Release.Namespace }}
+spec:
+ selfSigned: {}
+{{- else if and (not .Values.operator.admissionControllers.certificates.certManager.enabled) (.Values.operator.admissionControllers.certificates.custom.enabled) }}
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Values.operator.admissionControllers.certificates.secretNames.operator }}
+ namespace: {{ .Release.Namespace }}
+type: Opaque
+data:
+ ca.crt: {{ .Values.operator.admissionControllers.certificates.custom.operator.caCrt | b64enc | b64enc | quote }}
+ tls.crt: {{ .Values.operator.admissionControllers.certificates.custom.operator.tlsCrt | b64enc | quote }}
+ tls.key: {{ .Values.operator.admissionControllers.certificates.custom.operator.tlsKey | b64enc | quote }}
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Values.operator.admissionControllers.certificates.secretNames.injector }}
+ namespace: {{ .Release.Namespace }}
+type: Opaque
+data:
+ ca.crt: {{ .Values.operator.admissionControllers.certificates.custom.injector.caCrt | b64enc | b64enc | quote }}
+ tls.crt: {{ .Values.operator.admissionControllers.certificates.custom.injector.tlsCrt | b64enc | quote }}
+ tls.key: {{ .Values.operator.admissionControllers.certificates.custom.injector.tlsKey | b64enc | quote }}
+{{- end }}
+{{- end }}
diff --git a/sriov-network-operator-chart/templates/certmanagercerts.yaml b/sriov-network-operator-chart/templates/certmanagercerts.yaml
new file mode 100644
index 0000000..6103da6
--- /dev/null
+++ b/sriov-network-operator-chart/templates/certmanagercerts.yaml
@@ -0,0 +1,41 @@
+{{- if and (.Values.operator.enableAdmissionController) (.Values.cert_manager) -}}
+{{- if not (.Capabilities.APIVersions.Has "cert-manager.io/v1") -}}
+{{- required "cert-manager is required but not found" "" -}}
+{{- end -}}
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: sriov-network-operator-selfsigned-issuer
+ namespace: {{ .Release.Namespace }}
+spec:
+ selfSigned: {}
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: operator-webhook-service
+ namespace: {{ .Release.Namespace }}
+spec:
+ secretName: operator-webhook-service
+ dnsNames:
+ - operator-webhook-service.{{ .Release.Namespace }}.svc
+ issuerRef:
+ name: sriov-network-operator-selfsigned-issuer
+ privateKey:
+ rotationPolicy: Always
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: network-resources-injector-service
+ namespace: {{ .Release.Namespace }}
+spec:
+ secretName: network-resources-injector-secret
+ dnsNames:
+ - network-resources-injector-service.{{ .Release.Namespace }}.svc
+ issuerRef:
+ name: sriov-network-operator-selfsigned-issuer
+ privateKey:
+ rotationPolicy: Always
+{{- end -}}
+
diff --git a/sriov-network-operator-chart/templates/clusterrole.yaml b/sriov-network-operator-chart/templates/clusterrole.yaml
new file mode 100644
index 0000000..f282fa3
--- /dev/null
+++ b/sriov-network-operator-chart/templates/clusterrole.yaml
@@ -0,0 +1,111 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ include "sriov-network-operator.fullname" . }}
+ labels:
+ {{- include "sriov-network-operator.labels" . | nindent 4 }}
+rules:
+ - apiGroups: [""]
+ resources: ["nodes"]
+ verbs: ["get", "list", "watch", "patch", "update"]
+ - apiGroups: [""]
+ resources: ["pods"]
+ verbs: ["*"]
+ - apiGroups: [""]
+ resources: ["pods/eviction"]
+ verbs: ["create"]
+ - apiGroups: ["apps"]
+ resources: ["daemonsets"]
+ verbs: ["get"]
+ - apiGroups: [""]
+ resources: ["namespaces", "serviceaccounts"]
+ verbs: ["*"]
+ - apiGroups: ["k8s.cni.cncf.io"]
+ resources: ["network-attachment-definitions"]
+ verbs: ["*"]
+ - apiGroups: ["rbac.authorization.k8s.io"]
+ resources: [clusterroles, clusterrolebindings]
+ verbs: ["*"]
+ - apiGroups: ["admissionregistration.k8s.io"]
+ resources: ["mutatingwebhookconfigurations", "validatingwebhookconfigurations"]
+ verbs: ["*"]
+ - apiGroups: ["sriovnetwork.openshift.io"]
+ resources: ["*"]
+ verbs: ["*"]
+ - apiGroups: ["machineconfiguration.openshift.io"]
+ resources: ["*"]
+ verbs: ["*"]
+ - apiGroups: ["config.openshift.io"]
+ resources: ["infrastructures"]
+ verbs: ["get", "list", "watch"]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: sriov-network-config-daemon
+ labels:
+ {{- include "sriov-network-operator.labels" . | nindent 4 }}
+rules:
+ - apiGroups: [""]
+ resources: ["nodes"]
+ verbs: ["get", "list", "watch", "patch", "update"]
+ - apiGroups: [""]
+ resources: ["pods"]
+ verbs: ["*"]
+ - apiGroups: ["apps"]
+ resources: ["daemonsets"]
+ verbs: ["get"]
+ - apiGroups: [ "config.openshift.io" ]
+ resources: [ "infrastructures" ]
+ verbs: [ "get", "list", "watch" ]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: sriov-admin
+ {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }}
+ rbac.authorization.k8s.io/aggregate-to-admin: "true"
+ {{- end }}
+rules:
+- apiGroups:
+ - sriovnetwork.openshift.io
+ resources:
+ - '*'
+ verbs:
+ - "get"
+ - "watch"
+ - "list"
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: sriov-edit
+ {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }}
+ rbac.authorization.k8s.io/aggregate-to-edit: "true"
+ {{- end }}
+rules:
+- apiGroups:
+ - sriovnetwork.openshift.io
+ resources:
+ - '*'
+ verbs:
+ - "get"
+ - "watch"
+ - "list"
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: sriov-view
+ {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }}
+ rbac.authorization.k8s.io/aggregate-to-view: "true"
+ {{- end }}
+rules:
+- apiGroups:
+ - sriovnetwork.openshift.io
+ resources:
+ - '*'
+ verbs:
+ - "get"
+ - "watch"
+ - "list"
diff --git a/sriov-network-operator-chart/templates/clusterrolebinding.yaml b/sriov-network-operator-chart/templates/clusterrolebinding.yaml
new file mode 100644
index 0000000..56788db
--- /dev/null
+++ b/sriov-network-operator-chart/templates/clusterrolebinding.yaml
@@ -0,0 +1,29 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ include "sriov-network-operator.fullname" . }}
+ labels:
+ {{- include "sriov-network-operator.labels" . | nindent 4 }}
+roleRef:
+ kind: ClusterRole
+ name: {{ include "sriov-network-operator.fullname" . }}
+ apiGroup: rbac.authorization.k8s.io
+subjects:
+ - kind: ServiceAccount
+ namespace: {{ .Release.Namespace }}
+ name: {{ include "sriov-network-operator.fullname" . }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: sriov-network-config-daemon
+ labels:
+ {{- include "sriov-network-operator.labels" . | nindent 4 }}
+roleRef:
+ kind: ClusterRole
+ name: sriov-network-config-daemon
+ apiGroup: rbac.authorization.k8s.io
+subjects:
+ - kind: ServiceAccount
+ namespace: {{ .Release.Namespace }}
+ name: sriov-network-config-daemon
diff --git a/sriov-network-operator-chart/templates/configmap.yaml b/sriov-network-operator-chart/templates/configmap.yaml
new file mode 100644
index 0000000..d9e6a29
--- /dev/null
+++ b/sriov-network-operator-chart/templates/configmap.yaml
@@ -0,0 +1,47 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: supported-nic-ids
+data:
+ Intel_i40e_XXV710: "8086 158a 154c"
+ Intel_i40e_25G_SFP28: "8086 158b 154c"
+ Intel_i40e_10G_X710_SFP: "8086 1572 154c"
+ Intel_ixgbe_10G_X550: "8086 1563 1565"
+ Intel_ixgbe_82576: "8086 10c9 10ca"
+ Intel_i40e_X710_X557_AT_10G: "8086 1589 154c"
+ Intel_i40e_10G_X710_BACKPLANE: "8086 1581 154c"
+ Intel_i40e_10G_X710_BASE_T: "8086 15ff 154c"
+ Intel_i40e_XXV710_N3000: "8086 0d58 154c"
+ Intel_i40e_40G_XL710_QSFP: "8086 1583 154c"
+ Intel_i40e_X550T: "8086 1563 1565"
+ Intel_i40e_X722: "8086 37d2 37cd"
+ Intel_i40e_X722_SFP: "8086 37d0 37cd"
+ Intel_i40e_X722_SFPP: "8086 37d3 37cd"
+ Intel_ice_Columbiaville_E810-CQDA2_2CQDA2: "8086 1592 1889"
+ Intel_ice_Columbiaville_E810-XXVDA4: "8086 1593 1889"
+ Intel_ice_Columbiaville_E810-XXVDA2: "8086 159b 1889"
+ Intel_ice_Columbiaville_E810: "8086 1591 1889"
+ Intel_ice_Columbiapark_E823C: "8086 188a 1889"
+ Nvidia_mlx5_ConnectX-4: "15b3 1013 1014"
+ Nvidia_mlx5_ConnectX-4LX: "15b3 1015 1016"
+ Nvidia_mlx5_ConnectX-5: "15b3 1017 1018"
+ Nvidia_mlx5_ConnectX-5_Ex: "15b3 1019 101a"
+ Nvidia_mlx5_ConnectX-6: "15b3 101b 101c"
+ Nvidia_mlx5_ConnectX-6_Dx: "15b3 101d 101e"
+ Nvidia_mlx5_ConnectX-6_Lx: "15b3 101f 101e"
+ Nvidia_mlx5_ConnectX-7: "15b3 1021 101e"
+ Nvidia_mlx5_MT42822_BlueField-2_integrated_ConnectX-6_Dx: "15b3 a2d6 101e"
+ Nvidia_mlx5_MT43244_BlueField-3_integrated_ConnectX-7_Dx: "15b3 a2dc 101e"
+ Broadcom_bnxt_BCM57414_2x25G: "14e4 16d7 16dc"
+ Broadcom_bnxt_BCM75508_2x100G: "14e4 1750 1806"
+ Qlogic_qede_QL45000_50G: "1077 1654 1664"
+ Red_Hat_Virtio_network_device: "1af4 1000 1000"
+ Red_Hat_Virtio_1_0_network_device: "1af4 1041 1041"
+ Marvell_OCTEON_TX2_CN96XX: "177d b200 b203"
+ Marvell_OCTEON_TX2_CN98XX: "177d b100 b103"
+ Marvell_OCTEON_Fusion_CNF95XX: "177d b600 b603"
+ Marvell_OCTEON10_CN10XXX: "177d b900 b903"
+ Marvell_OCTEON_Fusion_CNF105XX: "177d ba00 ba03"
+ {{- range .Values.supportedExtraNICs }}
+ {{ . }}
+ {{- end }}
diff --git a/sriov-network-operator-chart/templates/operator.yaml b/sriov-network-operator-chart/templates/operator.yaml
new file mode 100644
index 0000000..6768e37
--- /dev/null
+++ b/sriov-network-operator-chart/templates/operator.yaml
@@ -0,0 +1,116 @@
+{{- if not (.Capabilities.APIVersions.Has "k8s.cni.cncf.io/v1/NetworkAttachmentDefinition") -}}
+{{- required "rke2-multus is required but not found" "" -}}
+{{- end -}}
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "sriov-network-operator.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "sriov-network-operator.labels" . | nindent 4 }}
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ name: sriov-network-operator
+ strategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxUnavailable: 33%
+ template:
+ metadata:
+ labels:
+ name: sriov-network-operator
+ spec:
+ {{- with .Values.operator.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.operator.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8}}
+ {{- end }}
+ {{- with .Values.operator.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "sriov-network-operator.fullname" . }}
+ priorityClassName: "system-node-critical"
+ {{- if .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- range .Values.imagePullSecrets }}
+ - name: {{ . }}
+ {{- end }}
+ {{- end }}
+ containers:
+ - name: {{ include "sriov-network-operator.fullname" . }}
+ image: {{ include "system_default_registry" . }}{{ .Values.images.operator.repository }}:{{ .Values.images.operator.tag }}
+ command:
+ - sriov-network-operator
+ resources:
+ requests:
+ cpu: 100m
+ memory: 100Mi
+ env:
+ - name: WATCH_NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ - name: SRIOV_CNI_IMAGE
+ value: {{ include "system_default_registry" . }}{{ .Values.images.sriovCni.repository }}:{{ .Values.images.sriovCni.tag }}
+ - name: SRIOV_INFINIBAND_CNI_IMAGE
+ value: {{ include "system_default_registry" . }}{{ .Values.images.ibSriovCni.repository }}:{{ .Values.images.ibSriovCni.tag }}
+ - name: SRIOV_DEVICE_PLUGIN_IMAGE
+ value: {{ include "system_default_registry" . }}{{ .Values.images.sriovDevicePlugin.repository }}:{{ .Values.images.sriovDevicePlugin.tag }}
+ - name: NETWORK_RESOURCES_INJECTOR_IMAGE
+ value: {{ include "system_default_registry" . }}{{ .Values.images.resourcesInjector.repository }}:{{ .Values.images.resourcesInjector.tag }}
+ - name: OPERATOR_NAME
+ value: sriov-network-operator
+ - name: SRIOV_NETWORK_CONFIG_DAEMON_IMAGE
+ value: {{ include "system_default_registry" . }}{{ .Values.images.sriovConfigDaemon.repository }}:{{ .Values.images.sriovConfigDaemon.tag }}
+ - name: SRIOV_NETWORK_WEBHOOK_IMAGE
+ value: {{ include "system_default_registry" . }}{{ .Values.images.webhook.repository }}:{{ .Values.images.webhook.tag }}
+ - name: RESOURCE_PREFIX
+ value: {{ .Values.operator.resourcePrefix }}
+ - name: IMAGE_PULL_SECRETS
+ value: {{ join "," .Values.imagePullSecrets }}
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: NODE_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: spec.nodeName
+ - name: RELEASE_VERSION
+ value: {{ .Release.AppVersion }}
+ - name: SRIOV_CNI_BIN_PATH
+ value: {{ .Values.operator.cniBinPath }}
+ - name: CLUSTER_TYPE
+ value: {{ .Values.operator.clusterType }}
+ {{- if .Values.operator.admissionControllers.enabled }}
+ - name: ADMISSION_CONTROLLERS_CERTIFICATES_OPERATOR_SECRET_NAME
+ value: {{ .Values.operator.admissionControllers.certificates.secretNames.operator }}
+ - name: ADMISSION_CONTROLLERS_CERTIFICATES_INJECTOR_SECRET_NAME
+ value: {{ .Values.operator.admissionControllers.certificates.secretNames.injector }}
+ {{- if .Values.operator.admissionControllers.certificates.certManager.enabled }}
+ - name: ADMISSION_CONTROLLERS_CERTIFICATES_CERT_MANAGER_ENABLED
+ value: {{ .Values.operator.admissionControllers.certificates.certManager.enabled | quote }}
+ {{- else }}
+ - name: ADMISSION_CONTROLLERS_CERTIFICATES_OPERATOR_CA_CRT
+ valueFrom:
+ secretKeyRef:
+ name: {{ .Values.operator.admissionControllers.certificates.secretNames.operator }}
+ key: ca.crt
+ - name: ADMISSION_CONTROLLERS_CERTIFICATES_INJECTOR_CA_CRT
+ valueFrom:
+ secretKeyRef:
+ name: {{ .Values.operator.admissionControllers.certificates.secretNames.injector }}
+ key: ca.crt
+ {{- end }}
+ {{- end }}
diff --git a/sriov-network-operator-chart/templates/role.yaml b/sriov-network-operator-chart/templates/role.yaml
new file mode 100644
index 0000000..15c043d
--- /dev/null
+++ b/sriov-network-operator-chart/templates/role.yaml
@@ -0,0 +1,138 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ creationTimestamp: null
+ name: {{ include "sriov-network-operator.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "sriov-network-operator.labels" . | nindent 4 }}
+rules:
+ - apiGroups:
+ - ""
+ resources:
+ - pods
+ - services
+ - endpoints
+ - persistentvolumeclaims
+ - events
+ - configmaps
+ - secrets
+ verbs:
+ - '*'
+ - apiGroups:
+ - apps
+ resources:
+ - deployments
+ - daemonsets
+ - replicasets
+ - statefulsets
+ verbs:
+ - '*'
+ - apiGroups:
+ - monitoring.coreos.com
+ resources:
+ - servicemonitors
+ verbs:
+ - get
+ - create
+ - apiGroups:
+ - apps
+ resourceNames:
+ - sriov-network-operator
+ resources:
+ - deployments/finalizers
+ verbs:
+ - update
+ - apiGroups:
+ - rbac.authorization.k8s.io
+ resources:
+ - serviceaccounts
+ - roles
+ - rolebindings
+ verbs:
+ - '*'
+ - apiGroups:
+ - config.openshift.io
+ resources:
+ - infrastructures
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - 'coordination.k8s.io'
+ resources:
+ - 'leases'
+ verbs:
+ - '*'
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: sriov-network-config-daemon
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "sriov-network-operator.labels" . | nindent 4 }}
+rules:
+ - apiGroups:
+ - ""
+ resources:
+ - pods
+ verbs:
+ - '*'
+ - apiGroups:
+ - apps
+ resources:
+ - daemonsets
+ verbs:
+ - '*'
+ - apiGroups:
+ - sriovnetwork.openshift.io
+ resources:
+ - '*'
+ - sriovnetworknodestates
+ verbs:
+ - '*'
+ - apiGroups:
+ - security.openshift.io
+ resourceNames:
+ - privileged
+ resources:
+ - securitycontextconstraints
+ verbs:
+ - use
+ - apiGroups:
+ - ""
+ resources:
+ - configmaps
+ verbs:
+ - get
+ - update
+ - apiGroups:
+ - 'coordination.k8s.io'
+ resources:
+ - 'leases'
+ verbs:
+ - '*'
+ - apiGroups:
+ - ""
+ resources:
+ - events
+ verbs:
+ - create
+ - patch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: operator-webhook-sa
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "sriov-network-operator.labels" . | nindent 4 }}
+rules:
+ - apiGroups:
+ - ""
+ resources:
+ - configmaps
+ verbs:
+ - get
diff --git a/sriov-network-operator-chart/templates/rolebinding.yaml b/sriov-network-operator-chart/templates/rolebinding.yaml
new file mode 100644
index 0000000..85df9fe
--- /dev/null
+++ b/sriov-network-operator-chart/templates/rolebinding.yaml
@@ -0,0 +1,44 @@
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+ name: {{ include "sriov-network-operator.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "sriov-network-operator.labels" . | nindent 4 }}
+subjects:
+ - kind: ServiceAccount
+ name: {{ include "sriov-network-operator.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+roleRef:
+ kind: Role
+ name: {{ include "sriov-network-operator.fullname" . }}
+ apiGroup: rbac.authorization.k8s.io
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+ name: sriov-network-config-daemon
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "sriov-network-operator.labels" . | nindent 4 }}
+subjects:
+ - kind: ServiceAccount
+ name: sriov-network-config-daemon
+ namespace: {{ .Release.Namespace }}
+roleRef:
+ kind: Role
+ name: sriov-network-config-daemon
+ apiGroup: rbac.authorization.k8s.io
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+ name: operator-webhook-sa
+ namespace: {{ .Release.Namespace }}
+subjects:
+- kind: ServiceAccount
+ name: operator-webhook-sa
+roleRef:
+ kind: Role
+ name: operator-webhook-sa
+ apiGroup: rbac.authorization.k8s.io
diff --git a/sriov-network-operator-chart/templates/secrets.yaml b/sriov-network-operator-chart/templates/secrets.yaml
new file mode 100644
index 0000000..07d7a45
--- /dev/null
+++ b/sriov-network-operator-chart/templates/secrets.yaml
@@ -0,0 +1,20 @@
+{{- if not .Values.cert_manager -}}
+{{- if .Values.operator.enableAdmissionController }}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: operator-webhook-service
+ namespace: {{ .Release.Namespace }}
+data: {{ include "sriov_operator_cert" . | nindent 2 }}
+{{- end }}
+---
+{{- if .Values.operator.enableAdmissionController }}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: network-resources-injector-secret
+ namespace: {{ .Release.Namespace }}
+data: {{ include "sriov_resource_injector_cert" . | nindent 2 }}
+{{- end }}
+{{- end }}
+
diff --git a/sriov-network-operator-chart/templates/serviceaccount.yaml b/sriov-network-operator-chart/templates/serviceaccount.yaml
new file mode 100644
index 0000000..98b7553
--- /dev/null
+++ b/sriov-network-operator-chart/templates/serviceaccount.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "sriov-network-operator.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "sriov-network-operator.labels" . | nindent 4 }}
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: sriov-network-config-daemon
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "sriov-network-operator.labels" . | nindent 4 }}
diff --git a/sriov-network-operator-chart/templates/sriovoperatorconfig.yaml b/sriov-network-operator-chart/templates/sriovoperatorconfig.yaml
new file mode 100644
index 0000000..c65aa2d
--- /dev/null
+++ b/sriov-network-operator-chart/templates/sriovoperatorconfig.yaml
@@ -0,0 +1,17 @@
+{{ if .Values.sriovOperatorConfig.deploy }}
+apiVersion: sriovnetwork.openshift.io/v1
+kind: SriovOperatorConfig
+metadata:
+ name: default
+ namespace: {{ .Release.Namespace }}
+spec:
+ enableInjector: {{ .Values.operator.admissionControllers.enabled }}
+ enableOperatorWebhook: {{ .Values.operator.admissionControllers.enabled }}
+ {{- with .Values.sriovOperatorConfig.configDaemonNodeSelector }}
+ configDaemonNodeSelector:
+ {{- range $k, $v := .}}{{printf "%s: \"%s\"" $k $v | nindent 4 }}{{ end }}
+ {{- end }}
+ logLevel: {{ .Values.sriovOperatorConfig.logLevel }}
+ disableDrain: {{ .Values.sriovOperatorConfig.disableDrain }}
+ configurationMode: {{ .Values.sriovOperatorConfig.configurationMode }}
+{{ end }}
\ No newline at end of file
diff --git a/sriov-network-operator-chart/templates/validate-install-crd.yaml b/sriov-network-operator-chart/templates/validate-install-crd.yaml
new file mode 100644
index 0000000..dca7fa3
--- /dev/null
+++ b/sriov-network-operator-chart/templates/validate-install-crd.yaml
@@ -0,0 +1,20 @@
+#{{- if gt (len (lookup "rbac.authorization.k8s.io/v1" "ClusterRole" "" "")) 0 -}}
+# {{- $found := dict -}}
+# {{- set $found "sriovnetwork.openshift.io/v1/OVSNetwork" false -}}
+# {{- set $found "sriovnetwork.openshift.io/v1/SriovIBNetwork" false -}}
+# {{- set $found "sriovnetwork.openshift.io/v1/SriovNetworkNodePolicy" false -}}
+# {{- set $found "sriovnetwork.openshift.io/v1/SriovNetworkNodeState" false -}}
+# {{- set $found "sriovnetwork.openshift.io/v1/SriovNetworkPoolConfig" false -}}
+# {{- set $found "sriovnetwork.openshift.io/v1/SriovNetwork" false -}}
+# {{- set $found "sriovnetwork.openshift.io/v1/SriovOperatorConfig" false -}}
+# {{- range .Capabilities.APIVersions -}}
+# {{- if hasKey $found (toString .) -}}
+# {{- set $found (toString .) true -}}
+# {{- end -}}
+# {{- end -}}
+# {{- range $_, $exists := $found -}}
+# {{- if (eq $exists false) -}}
+# {{- required "Required CRDs are missing. Please install the corresponding CRD chart before installing this chart." "" -}}
+# {{- end -}}
+# {{- end -}}
+#{{- end -}}
\ No newline at end of file
diff --git a/sriov-network-operator-chart/values.yaml b/sriov-network-operator-chart/values.yaml
new file mode 100644
index 0000000..9d6c741
--- /dev/null
+++ b/sriov-network-operator-chart/values.yaml
@@ -0,0 +1,124 @@
+operator:
+ tolerations:
+ - key: "node-role.kubernetes.io/master"
+ operator: "Exists"
+ effect: "NoSchedule"
+ - key: "node-role.kubernetes.io/control-plane"
+ operator: "Exists"
+ effect: "NoSchedule"
+ - effect: NoExecute
+ key: node-role.kubernetes.io/etcd
+ operator: Exists
+ nodeSelector: {}
+ affinity:
+ nodeAffinity:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ - weight: 1
+ preference:
+ matchExpressions:
+ - key: "node-role.kubernetes.io/master"
+ operator: In
+ values: [""]
+ - weight: 1
+ preference:
+ matchExpressions:
+ - key: "node-role.kubernetes.io/control-plane"
+ operator: In
+ values: [""]
+ nameOverride: ""
+ fullnameOverride: ""
+ resourcePrefix: "rancher.io"
+ cniBinPath: "/opt/cni/bin"
+ clusterType: "kubernetes"
+ admissionControllers:
+ enabled: false
+ certificates:
+ secretNames:
+ operator: "operator-webhook-cert"
+ injector: "network-resources-injector-cert"
+ certManager:
+ # When enabled, makes use of certificates managed by cert-manager.
+ enabled: false
+ # When enabled, certificates are generated via cert-manager and then name will match the name of the secrets
+ # defined above
+ generateSelfSigned: false
+ # If not specified, no secret is created and secrets with the names defined above are expected to exist in the
+ # cluster. In that case, the ca.crt must be base64 encoded twice since it ends up being an env variable.
+ custom:
+ enabled: false
+ # operator:
+ # caCrt: |
+ # -----BEGIN CERTIFICATE-----
+ # MIIMIICLDCCAdKgAwIBAgIBADAKBggqhkjOPQQDAjB9MQswCQYDVQQGEwJCRTEPMA0G
+ # ...
+ # -----END CERTIFICATE-----
+ # tlsCrt: |
+ # -----BEGIN CERTIFICATE-----
+ # MIIMIICLDCCAdKgAwIBAgIBADAKBggqhkjOPQQDAjB9MQswCQYDVQQGEwJCRTEPMA0G
+ # ...
+ # -----END CERTIFICATE-----
+ # tlsKey: |
+ # -----BEGIN EC PRIVATE KEY-----
+ # MHcl4wOuDwKQa+upc8GftXE2C//4mKANBC6It01gUaTIpo=
+ # ...
+ # -----END EC PRIVATE KEY-----
+ # injector:
+ # caCrt: |
+ # -----BEGIN CERTIFICATE-----
+ # MIIMIICLDCCAdKgAwIBAgIBADAKBggqhkjOPQQDAjB9MQswCQYDVQQGEwJCRTEPMA0G
+ # ...
+ # -----END CERTIFICATE-----
+ # tlsCrt: |
+ # -----BEGIN CERTIFICATE-----
+ # MIIMIICLDCCAdKgAwIBAgIBADAKBggqhkjOPQQDAjB9MQswCQYDVQQGEwJCRTEPMA0G
+ # ...
+ # -----END CERTIFICATE-----
+ # tlsKey: |
+ # -----BEGIN EC PRIVATE KEY-----
+ # MHcl4wOuDwKQa+upc8GftXE2C//4mKANBC6It01gUaTIpo=
+ # ...
+ # -----END EC PRIVATE KEY-----
+sriovOperatorConfig:
+ # deploy sriovOperatorConfig CR with the below values
+ deploy: true
+ # node slectors for sriov-network-config-daemon
+ configDaemonNodeSelector: {feature.node.kubernetes.io/network-sriov.capable: 'true'}
+ # log level for both operator and sriov-network-config-daemon
+ logLevel: 2
+ # disable node draining when configuring SR-IOV, set to true in case of a single node
+ # cluster or any other justifiable reason
+ disableDrain: false
+ # sriov-network-config-daemon configuration mode. either "daemon" or "systemd"
+ configurationMode: daemon
+# Example for supportedExtraNICs values ['MyNIC: "8086 1521 1520"']
+supportedExtraNICs: []
+# Image URIs for sriov-network-operator components
+images:
+ operator:
+ repository: rancher/hardened-sriov-network-operator
+ tag: v1.3.0-build20240816
+ sriovConfigDaemon:
+ repository: rancher/hardened-sriov-network-config-daemon
+ tag: v1.3.0-build20240816
+ sriovCni:
+ repository: rancher/hardened-sriov-cni
+ tag: v2.8.1-build20240820
+ ibSriovCni:
+ repository: rancher/hardened-ib-sriov-cni
+ tag: v1.1.1-build20240816
+ sriovDevicePlugin:
+ repository: rancher/hardened-sriov-network-device-plugin
+ tag: v3.7.0-build20240816
+ resourcesInjector:
+ repository: rancher/hardened-sriov-network-resources-injector
+ tag: v1.6.0-build20240816
+ webhook:
+ repository: rancher/hardened-sriov-network-webhook
+ tag: v1.3.0-build20240816
+imagePullSecrets: []
+global:
+ cattle:
+ systemDefaultRegistry: ""
+ rbac:
+ userRoles:
+ aggregateToDefaultRoles: false
diff --git a/upgrade-controller-chart/Chart.yaml b/upgrade-controller-chart/Chart.yaml
new file mode 100644
index 0000000..380b36e
--- /dev/null
+++ b/upgrade-controller-chart/Chart.yaml
@@ -0,0 +1,13 @@
+#!BuildTag: %%IMG_PREFIX%%upgrade-controller-chart:0.1.0
+#!BuildTag: %%IMG_PREFIX%%upgrade-controller-chart:0.1.0-%RELEASE%
+apiVersion: v2
+appVersion: 0.1.0
+dependencies:
+- condition: crds.enabled
+ name: lifecycle-crds
+ repository: file://./charts/lifecycle-crds
+ version: 0.1.0
+description: A Helm chart for Upgrade Controller
+name: upgrade-controller
+type: application
+version: 0.1.0
diff --git a/upgrade-controller-chart/_service b/upgrade-controller-chart/_service
new file mode 100644
index 0000000..3cd1d17
--- /dev/null
+++ b/upgrade-controller-chart/_service
@@ -0,0 +1,16 @@
+
+
+
+ values.yaml
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+
+ Chart.yaml
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+
+
+
diff --git a/upgrade-controller-chart/charts/lifecycle-crds/Chart.yaml b/upgrade-controller-chart/charts/lifecycle-crds/Chart.yaml
new file mode 100644
index 0000000..2ac8dc1
--- /dev/null
+++ b/upgrade-controller-chart/charts/lifecycle-crds/Chart.yaml
@@ -0,0 +1,6 @@
+apiVersion: v2
+appVersion: 0.1.0
+description: A Helm chart containing SUSE Lifecycle CRDs
+name: lifecycle-crds
+type: application
+version: 0.1.0
diff --git a/upgrade-controller-chart/charts/lifecycle-crds/templates/release-manifest-crd.yaml b/upgrade-controller-chart/charts/lifecycle-crds/templates/release-manifest-crd.yaml
new file mode 100644
index 0000000..5927e10
--- /dev/null
+++ b/upgrade-controller-chart/charts/lifecycle-crds/templates/release-manifest-crd.yaml
@@ -0,0 +1,135 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ name: releasemanifests.lifecycle.suse.com
+spec:
+ group: lifecycle.suse.com
+ names:
+ kind: ReleaseManifest
+ listKind: ReleaseManifestList
+ plural: releasemanifests
+ singular: releasemanifest
+ scope: Namespaced
+ versions:
+ - name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: ReleaseManifest is the Schema for the releasemanifests API
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: ReleaseManifestSpec defines the desired state of ReleaseManifest
+ properties:
+ components:
+ properties:
+ kubernetes:
+ properties:
+ k3s:
+ properties:
+ version:
+ type: string
+ required:
+ - version
+ type: object
+ rke2:
+ properties:
+ version:
+ type: string
+ required:
+ - version
+ type: object
+ required:
+ - k3s
+ - rke2
+ type: object
+ operatingSystem:
+ properties:
+ cpeScheme:
+ type: string
+ prettyName:
+ type: string
+ supportedArchs:
+ items:
+ enum:
+ - x86_64
+ - aarch64
+ type: string
+ minItems: 1
+ type: array
+ version:
+ type: string
+ zypperID:
+ type: string
+ required:
+ - cpeScheme
+ - prettyName
+ - supportedArchs
+ - version
+ - zypperID
+ type: object
+ workloads:
+ properties:
+ helm:
+ items:
+ properties:
+ addonCharts:
+ x-kubernetes-preserve-unknown-fields: true
+ chart:
+ type: string
+ dependencyCharts:
+ x-kubernetes-preserve-unknown-fields: true
+ prettyName:
+ type: string
+ releaseName:
+ type: string
+ repository:
+ type: string
+ values:
+ x-kubernetes-preserve-unknown-fields: true
+ version:
+ type: string
+ required:
+ - chart
+ - prettyName
+ - releaseName
+ - version
+ type: object
+ type: array
+ required:
+ - helm
+ type: object
+ required:
+ - kubernetes
+ - operatingSystem
+ - workloads
+ type: object
+ releaseVersion:
+ type: string
+ required:
+ - releaseVersion
+ type: object
+ status:
+ description: ReleaseManifestStatus defines the observed state of ReleaseManifest
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/upgrade-controller-chart/charts/lifecycle-crds/templates/upgrade-plan-crd.yaml b/upgrade-controller-chart/charts/lifecycle-crds/templates/upgrade-plan-crd.yaml
new file mode 100644
index 0000000..a115df3
--- /dev/null
+++ b/upgrade-controller-chart/charts/lifecycle-crds/templates/upgrade-plan-crd.yaml
@@ -0,0 +1,180 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ name: upgradeplans.lifecycle.suse.com
+ annotations:
+ cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "upgrade-controller.certificate" . }}
+spec:
+ conversion:
+ strategy: Webhook
+ webhook:
+ clientConfig:
+ service:
+ namespace: {{ .Release.Namespace }}
+ name: {{ include "upgrade-controller.webhookServiceName" $ }}
+ path: /convert
+ conversionReviewVersions:
+ - v1
+ group: lifecycle.suse.com
+ names:
+ kind: UpgradePlan
+ listKind: UpgradePlanList
+ plural: upgradeplans
+ singular: upgradeplan
+ scope: Namespaced
+ versions:
+ - name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: UpgradePlan is the Schema for the upgradeplans API
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: UpgradePlanSpec defines the desired state of UpgradePlan
+ properties:
+ disableDrain:
+ description: DisableDrain specifies whether control-plane and worker
+ nodes drain should be disabled.
+ properties:
+ controlPlane:
+ type: boolean
+ worker:
+ type: boolean
+ type: object
+ helm:
+ description: |-
+ Helm specifies additional values for components installed via Helm.
+ It is only advised to use this field for values that are critical for upgrades.
+ Standard chart value updates should be performed after
+ the respective charts have been upgraded to the next version.
+ items:
+ properties:
+ chart:
+ type: string
+ values:
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - chart
+ - values
+ type: object
+ type: array
+ releaseVersion:
+ description: |-
+ ReleaseVersion specifies the target version for platform upgrade.
+ The version format is X.Y.Z, for example "3.0.2".
+ type: string
+ required:
+ - releaseVersion
+ type: object
+ status:
+ description: UpgradePlanStatus defines the observed state of UpgradePlan
+ properties:
+ conditions:
+ items:
+ description: "Condition contains details for one aspect of the current
+ state of this API Resource.\n---\nThis struct is intended for
+ direct use as an array at the field path .status.conditions. For
+ example,\n\n\n\ttype FooStatus struct{\n\t // Represents the
+ observations of a foo's current state.\n\t // Known .status.conditions.type
+ are: \"Available\", \"Progressing\", and \"Degraded\"\n\t //
+ +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t
+ \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\"
+ patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
+ \ // other fields\n\t}"
+ properties:
+ lastTransitionTime:
+ description: |-
+ lastTransitionTime is the last time the condition transitioned from one status to another.
+ This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: |-
+ message is a human readable message indicating details about the transition.
+ This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: |-
+ observedGeneration represents the .metadata.generation that the condition was set based upon.
+ For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
+ with respect to the current state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: |-
+ reason contains a programmatic identifier indicating the reason for the condition's last transition.
+ Producers of specific condition types may define expected values and meanings for this field,
+ and whether the values are considered a guaranteed API.
+ The value should be a CamelCase string.
+ This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: |-
+ type of condition in CamelCase or in foo.example.com/CamelCase.
+ ---
+ Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
+ useful (see .node.status.conditions), the ability to deconflict is important.
+ The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ type: array
+ x-kubernetes-list-map-keys:
+ - type
+ x-kubernetes-list-type: map
+ lastSuccessfulReleaseVersion:
+ description: LastSuccessfulReleaseVersion is the last release version
+ that this UpgradePlan has successfully upgraded to.
+ type: string
+ observedGeneration:
+ description: ObservedGeneration is the currently tracked generation
+ of the UpgradePlan. Meant for internal use only.
+ format: int64
+ type: integer
+ sucNameSuffix:
+ description: |-
+ SUCNameSuffix is the suffix added to all resources created for SUC. Meant for internal use only.
+ Changes for each new ObservedGeneration.
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/upgrade-controller-chart/templates/NOTES.txt b/upgrade-controller-chart/templates/NOTES.txt
new file mode 100644
index 0000000..473a0f4
diff --git a/upgrade-controller-chart/templates/_helpers.tpl b/upgrade-controller-chart/templates/_helpers.tpl
new file mode 100644
index 0000000..892acbd
--- /dev/null
+++ b/upgrade-controller-chart/templates/_helpers.tpl
@@ -0,0 +1,83 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "upgrade-controller.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "upgrade-controller.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "upgrade-controller.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "upgrade-controller.labels" -}}
+helm.sh/chart: {{ include "upgrade-controller.chart" . }}
+{{ include "upgrade-controller.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "upgrade-controller.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "upgrade-controller.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "upgrade-controller.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "upgrade-controller.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
+
+{{/*
+Webhook service name
+*/}}
+{{- define "upgrade-controller.webhookServiceName" -}}
+{{ .Release.Name }}-webhook
+{{- end }}
+
+{{/*
+Certificate issuer name
+*/}}
+{{- define "upgrade-controller.certificateIssuer" -}}
+{{ .Release.Name }}-self-signed-issuer
+{{- end }}
+
+{{/*
+Certificate name
+*/}}
+{{- define "upgrade-controller.certificate" -}}
+{{ .Release.Name }}-serving-cert
+{{- end }}
diff --git a/upgrade-controller-chart/templates/certificate.yaml b/upgrade-controller-chart/templates/certificate.yaml
new file mode 100644
index 0000000..6805cdd
--- /dev/null
+++ b/upgrade-controller-chart/templates/certificate.yaml
@@ -0,0 +1,28 @@
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ labels:
+ {{- include "upgrade-controller.labels" . | nindent 4 }}
+ name: {{ include "upgrade-controller.certificateIssuer" . }}
+ namespace: {{ .Release.Namespace }}
+spec:
+ selfSigned: {}
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ labels:
+ {{- include "upgrade-controller.labels" . | nindent 4 }}
+ app.kubernetes.io/component: certificate
+ name: {{ include "upgrade-controller.certificate" . }}
+ namespace: {{ .Release.Namespace }}
+spec:
+ dnsNames:
+ - {{ include "upgrade-controller.webhookServiceName" . }}.{{ .Release.Namespace }}.svc
+ - {{ include "upgrade-controller.webhookServiceName" . }}.{{ .Release.Namespace }}.svc.cluster.local
+ issuerRef:
+ kind: Issuer
+ name: {{ include "upgrade-controller.certificateIssuer" . }}
+ {{- with first .Values.volumes }}
+ secretName: {{ .secret.secretName }}
+ {{- end }}
diff --git a/upgrade-controller-chart/templates/clusterrole.yaml b/upgrade-controller-chart/templates/clusterrole.yaml
new file mode 100644
index 0000000..8e9c6e7
--- /dev/null
+++ b/upgrade-controller-chart/templates/clusterrole.yaml
@@ -0,0 +1,114 @@
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ include "upgrade-controller.fullname" . }}
+ labels:
+ {{- include "upgrade-controller.labels" . | nindent 4 }}
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - nodes
+ verbs:
+ - list
+ - watch
+- apiGroups:
+ - ""
+ resources:
+ - secrets
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - watch
+- apiGroups:
+ - apiextensions.k8s.io
+ resources:
+ - customresourcedefinitions
+ verbs:
+ - get
+- apiGroups:
+ - batch
+ resources:
+ - jobs
+ verbs:
+ - create
+ - get
+ - list
+ - watch
+- apiGroups:
+ - batch
+ resources:
+ - jobs/status
+ verbs:
+ - get
+- apiGroups:
+ - ""
+ resources:
+ - events
+ verbs:
+ - create
+ - patch
+- apiGroups:
+ - helm.cattle.io
+ resources:
+ - helmcharts
+ verbs:
+ - create
+ - get
+ - list
+ - update
+ - watch
+- apiGroups:
+ - helm.cattle.io
+ resources:
+ - helmcharts/status
+ verbs:
+ - get
+- apiGroups:
+ - lifecycle.suse.com
+ resources:
+ - releasemanifests
+ verbs:
+ - create
+ - get
+ - list
+ - watch
+- apiGroups:
+ - lifecycle.suse.com
+ resources:
+ - upgradeplans
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - lifecycle.suse.com
+ resources:
+ - upgradeplans/finalizers
+ verbs:
+ - update
+- apiGroups:
+ - lifecycle.suse.com
+ resources:
+ - upgradeplans/status
+ verbs:
+ - get
+ - patch
+ - update
+- apiGroups:
+ - upgrade.cattle.io
+ resources:
+ - plans
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - watch
diff --git a/upgrade-controller-chart/templates/clusterrole_binding.yaml b/upgrade-controller-chart/templates/clusterrole_binding.yaml
new file mode 100644
index 0000000..5ef4e17
--- /dev/null
+++ b/upgrade-controller-chart/templates/clusterrole_binding.yaml
@@ -0,0 +1,14 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ include "upgrade-controller.fullname" . }}
+ labels:
+ {{- include "upgrade-controller.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ include "upgrade-controller.fullname" . }}
+subjects:
+- kind: ServiceAccount
+ name: {{ include "upgrade-controller.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace }}
diff --git a/upgrade-controller-chart/templates/deployment.yaml b/upgrade-controller-chart/templates/deployment.yaml
new file mode 100644
index 0000000..4488189
--- /dev/null
+++ b/upgrade-controller-chart/templates/deployment.yaml
@@ -0,0 +1,85 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "upgrade-controller.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "upgrade-controller.labels" . | nindent 4 }}
+spec:
+ replicas: {{ .Values.replicaCount }}
+ selector:
+ matchLabels:
+ {{- include "upgrade-controller.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ {{- with .Values.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "upgrade-controller.labels" . | nindent 8 }}
+ {{- with .Values.podLabels }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "upgrade-controller.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ containers:
+ - name: {{ .Chart.Name }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ args:
+ - --leader-elect
+ - --health-probe-bind-address=:8081
+ env:
+ - name: WATCH_NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ - name: RELEASE_MANIFEST_IMAGE
+ value: {{ .Values.env.releaseManifest.image }}
+ - name: KUBECTL_IMAGE
+ value: {{ .Values.env.kubectl.image }}
+ - name: KUBECTL_VERSION
+ value: {{ .Values.env.kubectl.version }}
+ - name: SERVICE_ACCOUNT_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: spec.serviceAccountName
+ ports:
+ - name: {{ .Values.webhookService.name }}
+ containerPort: {{ .Values.webhookService.targetPort }}
+ protocol: TCP
+ livenessProbe:
+ {{- toYaml .Values.livenessProbe | nindent 12 }}
+ readinessProbe:
+ {{- toYaml .Values.readinessProbe | nindent 12 }}
+ resources:
+ {{- toYaml .Values.resources | nindent 12 }}
+ {{- with .Values.volumeMounts }}
+ volumeMounts:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ {{- with .Values.volumes }}
+ volumes:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
diff --git a/upgrade-controller-chart/templates/leader_election_role.yaml b/upgrade-controller-chart/templates/leader_election_role.yaml
new file mode 100644
index 0000000..acebc4f
--- /dev/null
+++ b/upgrade-controller-chart/templates/leader_election_role.yaml
@@ -0,0 +1,40 @@
+# permissions to do leader election.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ include "upgrade-controller.fullname" . }}-leader-election
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "upgrade-controller.labels" . | nindent 4 }}
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - configmaps
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - patch
+ - delete
+- apiGroups:
+ - coordination.k8s.io
+ resources:
+ - leases
+ verbs:
+ - get
+ - list
+ - watch
+ - create
+ - update
+ - patch
+ - delete
+- apiGroups:
+ - ""
+ resources:
+ - events
+ verbs:
+ - create
+ - patch
diff --git a/upgrade-controller-chart/templates/leader_election_role_binding.yaml b/upgrade-controller-chart/templates/leader_election_role_binding.yaml
new file mode 100644
index 0000000..1a0e7d2
--- /dev/null
+++ b/upgrade-controller-chart/templates/leader_election_role_binding.yaml
@@ -0,0 +1,15 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ include "upgrade-controller.fullname" . }}-leader-election
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "upgrade-controller.labels" . | nindent 4 }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: {{ include "upgrade-controller.fullname" . }}-leader-election
+subjects:
+- kind: ServiceAccount
+ name: {{ include "upgrade-controller.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace }}
diff --git a/upgrade-controller-chart/templates/serviceaccount.yaml b/upgrade-controller-chart/templates/serviceaccount.yaml
new file mode 100644
index 0000000..f860a12
--- /dev/null
+++ b/upgrade-controller-chart/templates/serviceaccount.yaml
@@ -0,0 +1,14 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "upgrade-controller.serviceAccountName" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "upgrade-controller.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
+{{- end }}
diff --git a/upgrade-controller-chart/templates/validating_webhook_configuration.yaml b/upgrade-controller-chart/templates/validating_webhook_configuration.yaml
new file mode 100644
index 0000000..43ad580
--- /dev/null
+++ b/upgrade-controller-chart/templates/validating_webhook_configuration.yaml
@@ -0,0 +1,29 @@
+apiVersion: admissionregistration.k8s.io/v1
+kind: ValidatingWebhookConfiguration
+metadata:
+ name: {{ include "upgrade-controller.fullname" . }}-validating-webhook-configuration
+ labels:
+ {{- include "upgrade-controller.labels" . | nindent 4 }}
+ annotations:
+ cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "upgrade-controller.certificate" . }}
+webhooks:
+ - admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: {{ include "upgrade-controller.webhookServiceName" . }}
+ namespace: {{ .Release.Namespace }}
+ path: /validate-lifecycle-suse-com-v1alpha1-upgradeplan
+ failurePolicy: Fail
+ name: upgrade-plan-policy.suse.com
+ rules:
+ - apiGroups:
+ - lifecycle.suse.com
+ apiVersions:
+ - v1alpha1
+ operations:
+ - CREATE
+ - UPDATE
+ resources:
+ - upgradeplans
+ sideEffects: None
diff --git a/upgrade-controller-chart/templates/webhook_service.yaml b/upgrade-controller-chart/templates/webhook_service.yaml
new file mode 100644
index 0000000..f8b48fe
--- /dev/null
+++ b/upgrade-controller-chart/templates/webhook_service.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "upgrade-controller.webhookServiceName" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "upgrade-controller.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.webhookService.type }}
+ ports:
+ - port: {{ .Values.webhookService.port }}
+ targetPort: {{ .Values.webhookService.targetPort }}
+ protocol: TCP
+ selector:
+ {{- include "upgrade-controller.selectorLabels" . | nindent 4 }}
diff --git a/upgrade-controller-chart/values.yaml b/upgrade-controller-chart/values.yaml
new file mode 100644
index 0000000..91ec22e
--- /dev/null
+++ b/upgrade-controller-chart/values.yaml
@@ -0,0 +1,91 @@
+# Default values for upgrade-controller.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+replicaCount: 1
+
+image:
+ repository: %%IMG_REPO%%/%%IMG_PREFIX%%upgrade-controller
+ pullPolicy: IfNotPresent
+ # Overrides the image tag whose default is the chart appVersion.
+ tag: ""
+
+env:
+ releaseManifest:
+ image: %%IMG_REPO%%/%%IMG_PREFIX%%release-manifest
+ kubectl:
+ image: %%IMG_REPO%%/%%IMG_PREFIX%%kubectl
+ version: 1.30.3
+
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+
+serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Automatically mount a ServiceAccount's API credentials?
+ automount: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: ""
+
+podAnnotations: {}
+podLabels: {}
+
+podSecurityContext:
+ runAsNonRoot: true
+ seccompProfile:
+ type: RuntimeDefault
+
+securityContext:
+ capabilities:
+ drop:
+ - ALL
+ allowPrivilegeEscalation: false
+
+webhookService:
+ name: webhook-server
+ type: ClusterIP
+ port: 443
+ targetPort: 9443
+
+resources: {}
+
+livenessProbe:
+ httpGet:
+ path: /healthz
+ port: 8081
+ initialDelaySeconds: 15
+ periodSeconds: 20
+readinessProbe:
+ httpGet:
+ path: /readyz
+ port: 8081
+ initialDelaySeconds: 5
+ periodSeconds: 10
+
+# Always keep the cert volume first in case others are appended
+# or adjust the certificate resources lookup.
+volumes:
+ - name: cert
+ secret:
+ secretName: webhook-server-cert
+ defaultMode: 420
+ optional: false
+
+volumeMounts:
+ - name: cert
+ mountPath: "/tmp/k8s-webhook-server/serving-certs"
+ readOnly: true
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
+
+crds:
+ enabled: true
diff --git a/upgrade-controller-image/Dockerfile b/upgrade-controller-image/Dockerfile
new file mode 100644
index 0000000..92d0f99
--- /dev/null
+++ b/upgrade-controller-image/Dockerfile
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: Apache-2.0
+#!BuildTag: %%IMG_PREFIX%%upgrade-controller:0.1.0
+#!BuildTag: %%IMG_PREFIX%%upgrade-controller:0.1.0-%RELEASE%
+#!BuildVersion: 15.6
+ARG SLE_VERSION
+FROM registry.suse.com/bci/bci-micro:$SLE_VERSION AS micro
+
+FROM registry.suse.com/bci/bci-base:$SLE_VERSION AS base
+COPY --from=micro / /installroot/
+RUN zypper --installroot /installroot --non-interactive install --no-recommends upgrade-controller; zypper -n clean; rm -rf /var/log/*
+
+FROM micro AS final
+
+# Define labels according to https://en.opensuse.org/Building_derived_containers
+# labelprefix=com.suse.application.upgrade-controller
+LABEL org.opencontainers.image.authors="SUSE LLC (https://www.suse.com/)"
+LABEL org.opencontainers.image.title="SLE Edge Upgrade Controller Container Image"
+LABEL org.opencontainers.image.description="Edge Update Controller Image based on the SLE Base Container Image."
+LABEL org.opencontainers.image.version="0.1.0"
+LABEL org.opencontainers.image.url="https://www.suse.com/solutions/edge-computing/"
+LABEL org.opencontainers.image.created="%BUILDTIME%"
+LABEL org.opencontainers.image.vendor="SUSE LLC"
+LABEL org.opensuse.reference="%%IMG_REPO%%/%%IMG_PREFIX%%upgrade-controller:0.1.0-%RELEASE%"
+LABEL org.openbuildservice.disturl="%DISTURL%"
+LABEL com.suse.supportlevel="techpreview"
+LABEL com.suse.eula="SUSE Combined EULA February 2024"
+LABEL com.suse.lifecycle-url="https://www.suse.com/lifecycle"
+LABEL com.suse.image-type="application"
+LABEL com.suse.release-stage="released"
+# endlabelprefix
+
+COPY --from=base /installroot /
+RUN mv /usr/bin/upgrade-controller /manager
+# Use uid of nonroot user (65532) because kubernetes expects numeric user when applying pod security policies
+USER 65532
+
+ENTRYPOINT [ "/manager" ]
+
diff --git a/upgrade-controller-image/_service b/upgrade-controller-image/_service
new file mode 100644
index 0000000..0041dd1
--- /dev/null
+++ b/upgrade-controller-image/_service
@@ -0,0 +1,10 @@
+
+
+
+ Dockerfile
+ IMG_PREFIX=$(rpm --macros=/root/.rpmmacros -E %img_prefix)
+ IMG_PREFIX
+ IMG_REPO=$(rpm --macros=/root/.rpmmacros -E %img_repo)
+ IMG_REPO
+
+