From eb44d33b15c924ba9e46cd24d78a21bd7763688b Mon Sep 17 00:00:00 2001 From: Nicolas Dreno Date: Tue, 7 Jul 2026 17:17:28 +0200 Subject: [PATCH 1/2] [metal3] ironic: let dnsmasq use its NET_BIND_SERVICE file-cap (#256) The ironic-dnsmasq container runs non-root (runAsUser 10475) but must bind privileged ports (DHCP 67, TFTP 69). The ironic image already grants the needed file-caps: setcap cap_net_bind_service,cap_net_raw,cap_net_admin+eip /usr/sbin/dnsmasq but file-caps are inert while no_new_privs is on, so dnsmasq still fails to bind. Two fixes, both in the ironic subchart: 1. values.yaml: dnsmasqSecurityContext now sets allowPrivilegeEscalation: true (so the file-caps take effect) and adds NET_BIND_SERVICE to the bounding set (required for the +e file-cap to apply). Container stays non-root. 2. deployment.yaml: flip the `merge` argument order for the dnsmasq securityContext. `merge` favours the first dict, so the shared securityContext was overriding the per-container dnsmasqSecurityContext (allowPrivilegeEscalation:false always won). dnsmasqSecurityContext must take precedence. Bumps ironic 0.13.1 -> 0.13.2 and metal3 0.15.1 -> 0.15.2. NOTE: this is inert until the downstream ironic image carries the upstream setcap (already present in metal3-io/ironic-image's configure-nonroot.sh). Refs: suse-edge/charts#256 Signed-off-by: Nicolas Dreno --- packages/ironic/charts/Chart.yaml | 2 +- packages/ironic/charts/templates/deployment.yaml | 5 ++++- packages/ironic/charts/values.yaml | 9 +++++++++ packages/metal3/charts/Chart.yaml | 4 ++-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/ironic/charts/Chart.yaml b/packages/ironic/charts/Chart.yaml index 0d35b32f..ca7622a7 100644 --- a/packages/ironic/charts/Chart.yaml +++ b/packages/ironic/charts/Chart.yaml @@ -3,4 +3,4 @@ appVersion: 35.0.0 description: A Helm chart for Ironic, used by Metal3 name: ironic type: application -version: 0.13.1 +version: 0.13.2 diff --git a/packages/ironic/charts/templates/deployment.yaml b/packages/ironic/charts/templates/deployment.yaml index 071fd667..f5a7d47d 100644 --- a/packages/ironic/charts/templates/deployment.yaml +++ b/packages/ironic/charts/templates/deployment.yaml @@ -152,7 +152,10 @@ spec: image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }} imagePullPolicy: {{ .Values.images.ironic.pullPolicy }} securityContext: - {{- merge .Values.securityContext .Values.dnsmasqSecurityContext | toYaml | nindent 10 }} + # dnsmasqSecurityContext takes precedence: `merge` favours the first + # dict, so per-container overrides (e.g. allowPrivilegeEscalation) must + # win over the shared securityContext. See issue #256. + {{- merge .Values.dnsmasqSecurityContext .Values.securityContext | toYaml | nindent 10 }} command: - /bin/rundnsmasq envFrom: diff --git a/packages/ironic/charts/values.yaml b/packages/ironic/charts/values.yaml index 13182984..8c78a93b 100644 --- a/packages/ironic/charts/values.yaml +++ b/packages/ironic/charts/values.yaml @@ -109,10 +109,19 @@ securityContext: runAsNonRoot: true dnsmasqSecurityContext: + # dnsmasq binds privileged ports (DHCP 67, TFTP 69). The container stays + # non-root (runAsUser 10475 from podSecurityContext); the ironic image grants + # the needed file-caps via + # setcap cap_net_bind_service,cap_net_raw,cap_net_admin+eip /usr/sbin/dnsmasq + # but file-caps only take effect when no_new_privs is off, hence + # allowPrivilegeEscalation must be true here. NET_BIND_SERVICE must also be in + # the bounding set (added below) for the +e file-cap to apply. See issue #256. + allowPrivilegeEscalation: true capabilities: add: - NET_ADMIN - NET_RAW + - NET_BIND_SERVICE service: type: LoadBalancer diff --git a/packages/metal3/charts/Chart.yaml b/packages/metal3/charts/Chart.yaml index 730011ed..cb4aaf36 100644 --- a/packages/metal3/charts/Chart.yaml +++ b/packages/metal3/charts/Chart.yaml @@ -8,7 +8,7 @@ dependencies: - alias: metal3-ironic name: ironic repository: file://./charts/ironic - version: 0.13.1 + version: 0.13.2 - alias: metal3-mariadb condition: global.enable_mariadb name: mariadb @@ -23,4 +23,4 @@ description: A Helm chart that installs all of the dependencies needed for Metal icon: https://github.com/cncf/artwork/raw/master/projects/metal3/icon/color/metal3-icon-color.svg name: metal3 type: application -version: 0.15.1 +version: 0.15.2 From 126d74fbc8cef70e177a5b721d47dd44edccb5eb Mon Sep 17 00:00:00 2001 From: Nicolas Dreno Date: Tue, 7 Jul 2026 17:20:45 +0200 Subject: [PATCH 2/2] make charts && make html Signed-off-by: Nicolas Dreno --- assets/metal3/metal3-0.15.2.tgz | Bin 0 -> 37696 bytes charts/metal3/0.15.2/.helmignore | 23 + charts/metal3/0.15.2/Chart.yaml | 26 + charts/metal3/0.15.2/README.md | 100 ++ charts/metal3/0.15.2/app-readme.md | 1 + .../charts/baremetal-operator/.helmignore | 23 + .../charts/baremetal-operator/Chart.yaml | 6 + .../crds/customresource-baremetalhosts.yaml | 1359 +++++++++++++++++ .../customresource-bmceventsubscriptions.yaml | 91 ++ .../crds/customresource-dataimages.yaml | 81 + .../crds/customresource-firmwareschemas.yaml | 96 ++ .../crds/customresource-hardwaredata.yaml | 239 +++ ...customresource-hostfirmwarecomponents.yaml | 174 +++ .../customresource-hostfirmwaresettings.yaml | 158 ++ .../customresource-hostupdatepolicies.yaml | 62 + .../customresource-preprovisioningimages.yaml | 180 +++ .../baremetal-operator/templates/NOTES.txt | 16 + .../baremetal-operator/templates/_helpers.tpl | 79 + .../templates/certificate.yaml | 14 + .../templates/clusterrole-manager.yaml | 206 +++ .../templates/clusterrolebinding-manager.yaml | 14 + .../templates/configmap-ironic.yaml | 31 + .../templates/deployment.yaml | 112 ++ .../baremetal-operator/templates/issuer.yaml | 8 + .../templates/metrics_auth_role.yaml | 19 + .../templates/metrics_auth_role_binding.yaml | 14 + .../templates/metrics_reader_role.yaml | 11 + .../templates/metrics_service.yaml | 15 + .../baremetal-operator/templates/role.yaml | 45 + .../templates/rolebinding.yaml | 13 + .../templates/service-webhook.yaml | 14 + .../templates/serviceaccount.yaml | 12 + .../validatingwebhookconfiguration.yaml | 51 + .../charts/baremetal-operator/values.yaml | 91 ++ .../metal3/0.15.2/charts/ironic/.helmignore | 23 + charts/metal3/0.15.2/charts/ironic/Chart.yaml | 6 + charts/metal3/0.15.2/charts/ironic/README.md | 24 + .../charts/ironic/templates/_helpers.tpl | 137 ++ .../charts/ironic/templates/certificates.yaml | 40 + .../charts/ironic/templates/configmap.yaml | 62 + .../charts/ironic/templates/deployment.yaml | 311 ++++ .../charts/ironic/templates/issuers.yaml | 16 + .../0.15.2/charts/ironic/templates/pvc.yaml | 26 + .../charts/ironic/templates/secret-tls.yaml | 16 + .../ironic/templates/secrets-basic-auth.yaml | 33 + .../charts/ironic/templates/service.yaml | 40 + .../ironic/templates/serviceaccount.yaml | 12 + .../metal3/0.15.2/charts/ironic/values.yaml | 186 +++ .../metal3/0.15.2/charts/mariadb/.helmignore | 24 + .../metal3/0.15.2/charts/mariadb/Chart.yaml | 6 + .../charts/mariadb/templates/_helpers.tpl | 64 + .../mariadb/templates/configmap-mariadb.yaml | 13 + .../charts/mariadb/templates/configmap.yaml | 11 + .../charts/mariadb/templates/deployment.yaml | 122 ++ .../0.15.2/charts/mariadb/templates/pvc.yaml | 24 + .../charts/mariadb/templates/secret.yaml | 21 + .../mariadb/templates/service-account.yaml | 13 + .../charts/mariadb/templates/service.yaml | 15 + .../metal3/0.15.2/charts/mariadb/values.yaml | 68 + charts/metal3/0.15.2/charts/media/.helmignore | 23 + charts/metal3/0.15.2/charts/media/Chart.yaml | 6 + .../0.15.2/charts/media/templates/NOTES.txt | 22 + .../charts/media/templates/_helpers.tpl | 63 + .../charts/media/templates/deployment.yaml | 62 + .../0.15.2/charts/media/templates/hpa.yaml | 28 + .../charts/media/templates/ingress.yaml | 61 + .../media/templates/persistentvolume.yaml | 18 + .../templates/persistentvolumeclaim.yaml | 14 + .../charts/media/templates/service.yaml | 16 + .../media/templates/serviceaccount.yaml | 12 + .../charts/media/templates/storageclass.yaml | 9 + charts/metal3/0.15.2/charts/media/values.yaml | 122 ++ charts/metal3/0.15.2/templates/NOTES.txt | 3 + charts/metal3/0.15.2/templates/_helpers.tpl | 77 + charts/metal3/0.15.2/values.yaml | 122 ++ index.html | 4 +- index.yaml | 30 + 77 files changed, 5387 insertions(+), 2 deletions(-) create mode 100644 assets/metal3/metal3-0.15.2.tgz create mode 100644 charts/metal3/0.15.2/.helmignore create mode 100644 charts/metal3/0.15.2/Chart.yaml create mode 100644 charts/metal3/0.15.2/README.md create mode 100644 charts/metal3/0.15.2/app-readme.md create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/.helmignore create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/Chart.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-baremetalhosts.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-bmceventsubscriptions.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-dataimages.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-firmwareschemas.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hardwaredata.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hostfirmwarecomponents.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hostfirmwaresettings.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hostupdatepolicies.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-preprovisioningimages.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/NOTES.txt create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/_helpers.tpl create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/certificate.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/clusterrole-manager.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/clusterrolebinding-manager.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/configmap-ironic.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/deployment.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/issuer.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_auth_role.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_auth_role_binding.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_reader_role.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_service.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/role.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/rolebinding.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/service-webhook.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/serviceaccount.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/templates/validatingwebhookconfiguration.yaml create mode 100644 charts/metal3/0.15.2/charts/baremetal-operator/values.yaml create mode 100644 charts/metal3/0.15.2/charts/ironic/.helmignore create mode 100644 charts/metal3/0.15.2/charts/ironic/Chart.yaml create mode 100644 charts/metal3/0.15.2/charts/ironic/README.md create mode 100644 charts/metal3/0.15.2/charts/ironic/templates/_helpers.tpl create mode 100644 charts/metal3/0.15.2/charts/ironic/templates/certificates.yaml create mode 100644 charts/metal3/0.15.2/charts/ironic/templates/configmap.yaml create mode 100644 charts/metal3/0.15.2/charts/ironic/templates/deployment.yaml create mode 100644 charts/metal3/0.15.2/charts/ironic/templates/issuers.yaml create mode 100644 charts/metal3/0.15.2/charts/ironic/templates/pvc.yaml create mode 100644 charts/metal3/0.15.2/charts/ironic/templates/secret-tls.yaml create mode 100644 charts/metal3/0.15.2/charts/ironic/templates/secrets-basic-auth.yaml create mode 100644 charts/metal3/0.15.2/charts/ironic/templates/service.yaml create mode 100644 charts/metal3/0.15.2/charts/ironic/templates/serviceaccount.yaml create mode 100644 charts/metal3/0.15.2/charts/ironic/values.yaml create mode 100644 charts/metal3/0.15.2/charts/mariadb/.helmignore create mode 100644 charts/metal3/0.15.2/charts/mariadb/Chart.yaml create mode 100644 charts/metal3/0.15.2/charts/mariadb/templates/_helpers.tpl create mode 100644 charts/metal3/0.15.2/charts/mariadb/templates/configmap-mariadb.yaml create mode 100644 charts/metal3/0.15.2/charts/mariadb/templates/configmap.yaml create mode 100644 charts/metal3/0.15.2/charts/mariadb/templates/deployment.yaml create mode 100644 charts/metal3/0.15.2/charts/mariadb/templates/pvc.yaml create mode 100644 charts/metal3/0.15.2/charts/mariadb/templates/secret.yaml create mode 100644 charts/metal3/0.15.2/charts/mariadb/templates/service-account.yaml create mode 100644 charts/metal3/0.15.2/charts/mariadb/templates/service.yaml create mode 100644 charts/metal3/0.15.2/charts/mariadb/values.yaml create mode 100644 charts/metal3/0.15.2/charts/media/.helmignore create mode 100644 charts/metal3/0.15.2/charts/media/Chart.yaml create mode 100644 charts/metal3/0.15.2/charts/media/templates/NOTES.txt create mode 100644 charts/metal3/0.15.2/charts/media/templates/_helpers.tpl create mode 100644 charts/metal3/0.15.2/charts/media/templates/deployment.yaml create mode 100644 charts/metal3/0.15.2/charts/media/templates/hpa.yaml create mode 100644 charts/metal3/0.15.2/charts/media/templates/ingress.yaml create mode 100644 charts/metal3/0.15.2/charts/media/templates/persistentvolume.yaml create mode 100644 charts/metal3/0.15.2/charts/media/templates/persistentvolumeclaim.yaml create mode 100644 charts/metal3/0.15.2/charts/media/templates/service.yaml create mode 100644 charts/metal3/0.15.2/charts/media/templates/serviceaccount.yaml create mode 100644 charts/metal3/0.15.2/charts/media/templates/storageclass.yaml create mode 100644 charts/metal3/0.15.2/charts/media/values.yaml create mode 100644 charts/metal3/0.15.2/templates/NOTES.txt create mode 100644 charts/metal3/0.15.2/templates/_helpers.tpl create mode 100644 charts/metal3/0.15.2/values.yaml diff --git a/assets/metal3/metal3-0.15.2.tgz b/assets/metal3/metal3-0.15.2.tgz new file mode 100644 index 0000000000000000000000000000000000000000..c42126c4e16bdea5ba9e43e197b2d9f82e0c4ed0 GIT binary patch literal 37696 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 + +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/charts/metal3/0.15.2/app-readme.md b/charts/metal3/0.15.2/app-readme.md new file mode 100644 index 00000000..ffa1c862 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/baremetal-operator/.helmignore b/charts/metal3/0.15.2/charts/baremetal-operator/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/baremetal-operator/Chart.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/Chart.yaml new file mode 100644 index 00000000..26a1c097 --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 0.12.3 +description: A Helm chart for baremetal-operator, used by Metal3 +name: baremetal-operator +type: application +version: 0.12.3 diff --git a/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-baremetalhosts.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-baremetalhosts.yaml new file mode 100644 index 00000000..511fddda --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-baremetalhosts.yaml @@ -0,0 +1,1359 @@ +--- +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.16.5 + 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: 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 skipped + during provisioning and deprovisioning. + enum: + - metadata + - disabled + type: string + bmc: + description: |- + How do we connect to the BMC (Baseboard Management Controller) on + the host? + properties: + address: + description: |- + Address holds the URL for accessing the controller on the network. + The scheme part designates the driver to use with the host. + 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: |- + The MAC address of the NIC used for provisioning the host. In case + of network boot, this is the MAC address of the PXE booting + interface. The MAC address of the BMC must never be used here! + 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. Legacy boot should only be used for hardware that + does not support UEFI correctly. Set to UEFISecureBoot to turn + secure boot on automatically after provisioning. + 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". The common use case is a link to a Machine + resource when the host is used by Cluster API. + 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. + 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. This is an advanced feature that allows + using a custom deploy step provided by a site-specific deployment + ramdisk. Most users will want to use "image" instead. Setting this + field triggers provisioning. + 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 + disablePowerOff: + description: |- + When set to true, power off of the node will be disabled, + instead, a reboot will be used in place of power on/off + type: boolean + externallyProvisioned: + description: |- + ExternallyProvisioned means something else has provisioned the + image running on the host, and the operator should only manage + the power status. This field is used for integration with already + provisioned hosts and when pivoting hosts between clusters. + + This field can be set to true either: + 1. During initial host creation (e.g., for pre-provisioned hosts) + 2. After inspection completes when the host reaches Available state + + When used in environments with Cluster API Provider Metal3 (CAPM3), + ensure hosts are labeled appropriately so CAPM3's host selector can + distinguish them from CAPM3-managed hosts. If unsure, leave this + field as false. + type: boolean + firmware: + description: |- + Firmware (BIOS) configuration for bare metal server. If set, the + requested settings will be applied before the host is provisioned. + + Deprecated: no longer supported by any driver. An alternative is to + use HostFirmwareSettings resources that allow changing arbitrary + values and support the generic Redfish-based drivers. + properties: + simultaneousMultithreadingEnabled: + description: Allows a single physical processor core to appear + as several logical processors. + 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. + enum: + - true + - false + type: boolean + virtualizationEnabled: + description: Supports the virtualization of platform hardware. + 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. Populating + the image will cause the host to start provisioning. + properties: + checksum: + description: |- + Checksum is the checksum for the image. Required for all formats + except for "live-iso" and OCI images (oci://). + 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: |- + Format contains the format of the image (raw, qcow2, ...). + When set to "live-iso", an ISO 9660 image referenced by the url will + be live-booted and not deployed to disk. + 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 + inspectionMode: + description: |- + Specifies the mode for host inspection. + "disabled" - no inspection will be performed + "agent" - normal agent-based inspection will run + enum: + - disabled + - agent + type: string + metaData: + description: |- + MetaData holds the reference to the Secret containing host metadata + which is passed to the Config Drive. By default, metadata will be + generated for the host, so most users do not need to set this field. + 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 which is passed to the Config Drive and interpreted + by the first boot software such as cloud-init. + 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 host be powered on? If the host is currently in a stable + state (e.g. provisioned), its power state will be forced to match + this value. + type: boolean + preprovisioningNetworkDataName: + description: |- + PreprovisioningNetworkDataName is the name of the Secret in the + local namespace containing network configuration 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. If set, the RAID settings + will be applied before the host is provisioned. If not, the current + settings will not be modified. Only one of the sub-fields + hardwareRAIDVolumes and softwareRAIDVolumes can be set at the same + time. + 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 (drivers may support only some of them). + 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, the 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 (if set to true) or solid-state + (if set to false) storage. By default, any disks can be picked. + type: boolean + sizeGibibytes: + description: |- + Size 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 host 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 and 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 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. The default is currently to use /dev/sda as + the root device. + 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. + 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 + which is passed to the Config Drive and interpreted by the + first-boot software such as cloud-init. The format of user data is + specific to the first-boot software. + 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: + conditions: + description: Conditions defines current service state of the BareMetalHost. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + 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. + 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 + maxItems: 32 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + 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 + - servicing 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. + This field will be removed in the next API version in favour of the + separate HardwareData resource. + properties: + cpu: + description: Details of the CPU(s) in the system. + 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: System firmware information. + 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: + description: Name of the host at the inspection time. + type: string + nics: + description: List of network interfaces for the host. + 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 + lldp: + description: LLDP data for this interface + properties: + portID: + description: The switch port ID from LLDP + type: string + switchID: + description: The switch chassis ID from LLDP + type: string + switchSystemName: + description: The switch system name from LLDP + type: string + type: object + 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 + pciAddress: + description: The NIC PCI address + 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: + description: The host's amount of memory in Mebibytes. + type: integer + storage: + description: List of storage (disk, SSD, etc.) available to the + host. + 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: System vendor information. + 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. + Hardware profiles are deprecated and should not be relied on. + 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 + - servicing + type: string + poweredOn: + description: |- + The currently detected power state of the host. This field may get + briefly out of sync with the actual state of the hardware while + provisioning processes are running. + type: boolean + provisioning: + description: Information tracked by the provisioner. + properties: + ID: + description: |- + The hosts's ID from the underlying provisioning tool (e.g. the + Ironic node UUID). + type: string + bootMode: + description: BootMode indicates the boot mode used to provision + the host. + 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 firmware settings that have been applied. + properties: + simultaneousMultithreadingEnabled: + description: Allows a single physical processor core to appear + as several logical processors. + 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. + enum: + - true + - false + type: boolean + virtualizationEnabled: + description: Supports the virtualization of platform hardware. + 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. Required for all formats + except for "live-iso" and OCI images (oci://). + 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: |- + Format contains the format of the image (raw, qcow2, ...). + When set to "live-iso", an ISO 9660 image referenced by the url will + be live-booted and not deployed to disk. + 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 configuration that has been applied. + 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 (drivers may support only some of them). + 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, the 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 (if set to true) or solid-state + (if set to false) storage. By default, any disks can be picked. + type: boolean + sizeGibibytes: + description: |- + Size 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 host 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 and 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 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 root device hints used to provision the host. + 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 indicator 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 + - operationalStatus + - poweredOn + - provisioning + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-bmceventsubscriptions.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-bmceventsubscriptions.yaml new file mode 100644 index 00000000..d5341f49 --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-bmceventsubscriptions.yaml @@ -0,0 +1,91 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + 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/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-dataimages.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-dataimages.yaml new file mode 100644 index 00000000..fa4176b3 --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-dataimages.yaml @@ -0,0 +1,81 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + 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/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-firmwareschemas.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-firmwareschemas.yaml new file mode 100644 index 00000000..2eae7b6e --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-firmwareschemas.yaml @@ -0,0 +1,96 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + 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/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hardwaredata.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hardwaredata.yaml new file mode 100644 index 00000000..0d1029ef --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hardwaredata.yaml @@ -0,0 +1,239 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + 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: Details of the CPU(s) in the system. + 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: System firmware information. + 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: + description: Name of the host at the inspection time. + type: string + nics: + description: List of network interfaces for the host. + 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 + lldp: + description: LLDP data for this interface + properties: + portID: + description: The switch port ID from LLDP + type: string + switchID: + description: The switch chassis ID from LLDP + type: string + switchSystemName: + description: The switch system name from LLDP + type: string + type: object + 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 + pciAddress: + description: The NIC PCI address + 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: + description: The host's amount of memory in Mebibytes. + type: integer + storage: + description: List of storage (disk, SSD, etc.) available to the + host. + 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: System vendor information. + 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/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hostfirmwarecomponents.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hostfirmwarecomponents.yaml new file mode 100644 index 00000000..a465189e --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hostfirmwarecomponents.yaml @@ -0,0 +1,174 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + labels: + clusterctl.cluster.x-k8s.io: "" + 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. + 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. + 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/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hostfirmwaresettings.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hostfirmwaresettings.yaml new file mode 100644 index 00000000..8bdb8f51 --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hostfirmwaresettings.yaml @@ -0,0 +1,158 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + 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. + 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. + 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/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hostupdatepolicies.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hostupdatepolicies.yaml new file mode 100644 index 00000000..611b8f3b --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-hostupdatepolicies.yaml @@ -0,0 +1,62 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + labels: + clusterctl.cluster.x-k8s.io: "" + name: hostupdatepolicies.metal3.io +spec: + group: metal3.io + names: + kind: HostUpdatePolicy + listKind: HostUpdatePolicyList + plural: hostupdatepolicies + singular: hostupdatepolicy + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: HostUpdatePolicy is the Schema for the hostupdatepolicy 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: HostUpdatePolicySpec defines the desired state of HostUpdatePolicy. + properties: + firmwareSettings: + description: Defines policy for changing firmware settings + enum: + - onPreparing + - onReboot + type: string + firmwareUpdates: + description: Defines policy for updating firmware + enum: + - onPreparing + - onReboot + type: string + type: object + status: + description: HostUpdatePolicyStatus defines the observed state of HostUpdatePolicy. + type: object + type: object + served: true + storage: true diff --git a/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-preprovisioningimages.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-preprovisioningimages.yaml new file mode 100644 index 00000000..3841cd32 --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/crds/customresource-preprovisioningimages.yaml @@ -0,0 +1,180 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + 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. + 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. + 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/charts/metal3/0.15.2/charts/baremetal-operator/templates/NOTES.txt b/charts/metal3/0.15.2/charts/baremetal-operator/templates/NOTES.txt new file mode 100644 index 00000000..47f9ee7e --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/baremetal-operator/templates/_helpers.tpl b/charts/metal3/0.15.2/charts/baremetal-operator/templates/_helpers.tpl new file mode 100644 index 00000000..e5057e3a --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/templates/_helpers.tpl @@ -0,0 +1,79 @@ +{{/* +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 }} + +{{/* +Create the URL to use for connecting to the Ironic servers (e.g. API, cache) +*/}} +{{- define "baremetal-operator.ironicHttpHost" -}} +{{- $hostIP := include "metal3.hostIP" . -}} +{{- with .Values.global }} +{{- if .provisioningHostname }} +{{- .provisioningHostname }} +{{- else if regexMatch ".*:.*" $hostIP}} +{{- print "[" $hostIP "]" }} +{{- else }} +{{- $hostIP }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/metal3/0.15.2/charts/baremetal-operator/templates/certificate.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/certificate.yaml new file mode 100644 index 00000000..2d424b75 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/baremetal-operator/templates/clusterrole-manager.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/clusterrole-manager.yaml new file mode 100644 index 00000000..ec4351ad --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/templates/clusterrole-manager.yaml @@ -0,0 +1,206 @@ +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 +- apiGroups: + - metal3.io + resources: + - hostupdatepolicies + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - hostupdatepolicies/status + verbs: + - get + - patch + - update diff --git a/charts/metal3/0.15.2/charts/baremetal-operator/templates/clusterrolebinding-manager.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/clusterrolebinding-manager.yaml new file mode 100644 index 00000000..b02f6ba6 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/baremetal-operator/templates/configmap-ironic.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/configmap-ironic.yaml new file mode 100644 index 00000000..d850d2c8 --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/templates/configmap-ironic.yaml @@ -0,0 +1,31 @@ + {{- $enableTLS := .Values.global.enable_tls }} + {{- $enableVMediaTLS := .Values.global.enable_vmedia_tls }} + {{- $protocol := ternary "https" "http" $enableTLS }} + {{- $ironicHost := include "baremetal-operator.ironicHttpHost" . | required "Missing host information for BMO to connect to Ironic" }} + {{- $ironicApiHost := print $ironicHost ":6385" }} + {{- $ironicBootHost := print $ironicHost ":6180" }} + {{- $ironicCacheHost := print $ironicHost ":6180" }} + +apiVersion: v1 +data: + IRONIC_ENDPOINT: "{{ $protocol }}://{{ $ironicApiHost }}/v1/" + # Switch VMedia to HTTP if enable_vmedia_tls is false + {{- if and $enableTLS $enableVMediaTLS }} + {{- $ironicBootHost = print $ironicHost ":" .Values.global.vmediaTLSPort }} + {{- $ironicCacheHost = print $ironicHost ":" .Values.global.vmediaTLSPort }} + {{- $protocol = "https" }} + RESTART_CONTAINER_CERTIFICATE_UPDATED: "true" + {{- else }} + {{- $protocol = "http" }} + RESTART_CONTAINER_CERTIFICATE_UPDATED: "false" + {{- end }} + CACHEURL: "{{ $protocol }}://{{ $ironicCacheHost }}/images" + {{- if .Values.baremetaloperator.externalHttpIPv6 }} + {{- $port := ternary .Values.global.vmediaTLSPort .Values.baremetaloperator.httpPort $enableVMediaTLS }} + IRONIC_EXTERNAL_URL_V6: "{{ $protocol }}://[{{ .Values.baremetaloperator.externalHttpIPv6 }}]:{{ $port }}" + {{- end }} +kind: ConfigMap +metadata: + name: baremetal-operator-ironic + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} diff --git a/charts/metal3/0.15.2/charts/baremetal-operator/templates/deployment.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/deployment.yaml new file mode 100644 index 00000000..7cc103cf --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/templates/deployment.yaml @@ -0,0 +1,112 @@ +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: + annotations: + checksum/config-env: {{ include (print $.Template.BasePath "/configmap-ironic.yaml") . | sha256sum }} + labels: + {{- include "baremetal-operator.selectorLabels" . | nindent 8 }} + control-plane: controller-manager + webhook: metal3-io-v1alpha1-baremetalhost + spec: + containers: + - args: + - --enable-leader-election + - --tls-min-version=TLS13 + 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 + - containerPort: 8443 + protocol: TCP + name: https + 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 + {{- end }} + {{- if .Values.global.enable_tls }} + - name: cacert + mountPath: "/opt/metal3/certs/ca" + readOnly: true + {{- end }} + 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 + {{- 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/charts/metal3/0.15.2/charts/baremetal-operator/templates/issuer.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/issuer.yaml new file mode 100644 index 00000000..9b12180f --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_auth_role.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_auth_role.yaml new file mode 100644 index 00000000..ffa9756a --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_auth_role.yaml @@ -0,0 +1,19 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "baremetal-operator.fullname" . }}-metrics-auth-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/charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_auth_role_binding.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_auth_role_binding.yaml new file mode 100644 index 00000000..dce821ec --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_auth_role_binding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "baremetal-operator.fullname" . }}-metrics-auth-rolebinding + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "baremetal-operator.fullname" . }}-metrics-auth-role +subjects: +- kind: ServiceAccount + name: {{ include "baremetal-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_reader_role.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_reader_role.yaml new file mode 100644 index 00000000..c93d5b9e --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_reader_role.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/charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_service.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_service.yaml new file mode 100644 index 00000000..b1c39a78 --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/templates/metrics_service.yaml @@ -0,0 +1,15 @@ +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: + ipFamilyPolicy: PreferDualStack + ports: + - name: https + port: 8443 + targetPort: https + selector: + control-plane: controller-manager diff --git a/charts/metal3/0.15.2/charts/baremetal-operator/templates/role.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/role.yaml new file mode 100644 index 00000000..313066a4 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/baremetal-operator/templates/rolebinding.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/rolebinding.yaml new file mode 100644 index 00000000..4492103e --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/baremetal-operator/templates/service-webhook.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/service-webhook.yaml new file mode 100644 index 00000000..25868cfc --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/templates/service-webhook.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + name: {{ include "baremetal-operator.fullname" . }}-webhook-service +spec: + ipFamilyPolicy: PreferDualStack + ports: + - port: 443 + targetPort: 9443 + selector: + control-plane: controller-manager + webhook: metal3-io-v1alpha1-baremetalhost diff --git a/charts/metal3/0.15.2/charts/baremetal-operator/templates/serviceaccount.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/serviceaccount.yaml new file mode 100644 index 00000000..4eab8805 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/baremetal-operator/templates/validatingwebhookconfiguration.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/templates/validatingwebhookconfiguration.yaml new file mode 100644 index 00000000..55746b9e --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/baremetal-operator/values.yaml b/charts/metal3/0.15.2/charts/baremetal-operator/values.yaml new file mode 100644 index 00000000..4fba6c6c --- /dev/null +++ b/charts/metal3/0.15.2/charts/baremetal-operator/values.yaml @@ -0,0 +1,91 @@ +# 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/containers/images/baremetal-operator + pullPolicy: IfNotPresent + tag: "0.12.3.0" + +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" + + # IPv6 used for accessing the Ironic HTTP server for BMCs with an IPv6 only address. + # It should not be used in conjunction with 'provisioningHostname' unless BMCs do not + # support hostnames. + externalHttpIPv6: "" diff --git a/charts/metal3/0.15.2/charts/ironic/.helmignore b/charts/metal3/0.15.2/charts/ironic/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/ironic/Chart.yaml b/charts/metal3/0.15.2/charts/ironic/Chart.yaml new file mode 100644 index 00000000..ca7622a7 --- /dev/null +++ b/charts/metal3/0.15.2/charts/ironic/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 35.0.0 +description: A Helm chart for Ironic, used by Metal3 +name: ironic +type: application +version: 0.13.2 diff --git a/charts/metal3/0.15.2/charts/ironic/README.md b/charts/metal3/0.15.2/charts/ironic/README.md new file mode 100644 index 00000000..860ebcab --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/ironic/templates/_helpers.tpl b/charts/metal3/0.15.2/charts/ironic/templates/_helpers.tpl new file mode 100644 index 00000000..1dd83c52 --- /dev/null +++ b/charts/metal3/0.15.2/charts/ironic/templates/_helpers.tpl @@ -0,0 +1,137 @@ +{{/* +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 +{{- if .Values.global.enable_vmedia_tls }} +- name: cert-ironic-vmedia-ca + mountPath: "/certs/ca/vmedia" + readOnly: true +{{- end }} +{{- if .Values.global.trustedCAs }} +- name: trusted-ca + mountPath: "/certs/ca/trusted" + readOnly: true +{{- end }} +{{- end }} + +{{/* +Get the formatted "External" hostname or IP based URL +*/}} +{{- define "ironic.externalHttpUrl" }} +{{- $host := ternary (include "metal3.hostIP" .) .Values.global.externalHttpHost (empty .Values.global.externalHttpHost) }} +{{- if regexMatch ".*:.*" $host }} +{{- $host = print "[" $host "]" }} +{{- end }} +{{- $protocol := "http" }} +{{- $port := "6180" }} +{{- if .Values.global.enable_vmedia_tls }} +{{- $protocol = "https" }} +{{- $port = .Values.global.vmediaTLSPort | default "6185" }} +{{- end }} +{{- print $protocol "://" $host ":" $port }} +{{- end }} + +{{/* +Get the command to use for Liveness and Readiness probes +*/}} +{{- define "ironic.probeCommand" }} +{{- $host := "127.0.0.1" }} +{{- if eq .Values.listenOnAll false }} +{{- $host = coalesce .Values.global.provisioningIP .Values.global.ironicIP .Values.global.provisioningHostname }} +{{- if regexMatch ".*:.*" $host }} +{{- $host = print "[" $host "]" }} +{{- end }} +{{- end }} +{{- print "curl -sSfk https://" $host ":6385" }} +{{- end }} + +{{/* +Create the subjectAltNames section to be set on the Certificate +*/}} +{{- define "ironic.subjectAltNames" -}} +{{- with .Values.global }} +{{- if .provisioningHostname }} +dnsNames: +- {{ .provisioningHostname }} +{{- end -}} +{{- if or .ironicIP .provisioningIP }} +ipAddresses: + - {{ coalesce .provisioningIP .ironicIP }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/metal3/0.15.2/charts/ironic/templates/certificates.yaml b/charts/metal3/0.15.2/charts/ironic/templates/certificates.yaml new file mode 100644 index 00000000..af69a907 --- /dev/null +++ b/charts/metal3/0.15.2/charts/ironic/templates/certificates.yaml @@ -0,0 +1,40 @@ +{{- if .Values.global.enable_tls -}} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: ironic-cacert +spec: + commonName: ironic-ca + isCA: true + {{- include "ironic.subjectAltNames" . | indent 2 }} + issuerRef: + kind: Issuer + name: selfsigned-issuer + secretName: ironic-cacert +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: ironic-cert +spec: + commonName: ironic-cert + {{- include "ironic.subjectAltNames" . | indent 2 }} + issuerRef: + kind: Issuer + name: ca-issuer + secretName: ironic-cert +{{- if .Values.global.enable_vmedia_tls }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: ironic-vmedia-cert +spec: + commonName: ironic-vmedia-cert + {{- include "ironic.subjectAltNames" . | indent 2 }} + issuerRef: + kind: Issuer + name: ca-issuer + secretName: ironic-vmedia-cert +{{- end }} +{{- end }} diff --git a/charts/metal3/0.15.2/charts/ironic/templates/configmap.yaml b/charts/metal3/0.15.2/charts/ironic/templates/configmap.yaml new file mode 100644 index 00000000..ee6acc2c --- /dev/null +++ b/charts/metal3/0.15.2/charts/ironic/templates/configmap.yaml @@ -0,0 +1,62 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: ironic + labels: + {{- include "ironic.labels" . | nindent 4 }} +data: + {{- if ( .Values.global.enable_dnsmasq ) }} + 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 }}" + IRONIC_EXTERNAL_HTTP_URL: {{ include "ironic.externalHttpUrl" . }} + ENABLE_PXE_BOOT: "{{ .Values.global.enable_pxe_boot }}" + {{- if .Values.global.provisioningInterface }} + PROVISIONING_INTERFACE: {{ .Values.global.provisioningInterface }} + {{- end }} + {{- if .Values.global.provisioningIP }} + PROVISIONING_IP: {{ include "metal3.hostIP" . }} + {{- else if .Values.global.ironicIP }} + IRONIC_IP: {{ include "metal3.hostIP" . }} + {{- else if .Values.global.provisioningHostname }} + IRONIC_URL_HOSTNAME: {{ .Values.global.provisioningHostname }} + {{- end }} + IRONIC_FAST_TRACK: "true" + LISTEN_ALL_INTERFACES: "{{ .Values.listenOnAll }}" + {{- if ( .Values.global.enable_tls ) }} + RESTART_CONTAINER_CERTIFICATE_UPDATED: "true" + IRONIC_KERNEL_PARAMS: {{ .Values.global.ironicKernelParams }} tls.enabled=true + IRONIC_IPA_INSECURE: "0" + IRONIC_REVERSE_PROXY_SETUP: "true" + {{- if .Values.global.trustedCAs }} + WEBSERVER_CACERT_FILE: /certs/ca/trusted/ca-bundle.pem + {{- else }} + WEBSERVER_CACERT_FILE: /var/lib/ca-certificates/ca-bundle.pem + {{- end }} + {{- 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 }} + IRONIC_IPA_INSECURE: "1" + IRONIC_REVERSE_PROXY_SETUP: "false" + {{- end }} + {{- if ( .Values.global.enable_basicAuth ) }} + AUTH_STRATEGY: "http_basic" + {{- end }} + {{- if .Values.global.enable_mariadb }} + MARIADB_HOST: {{ .Values.global.databaseServiceName }}.{{ .Release.Namespace }}.svc.cluster.local + IRONIC_USE_MARIADB: "true" + {{- else }} + IRONIC_USE_MARIADB: "false" + {{- end }} + {{- with .Values.ironicExtraEnv -}} + {{ toYaml . | nindent 2 }} + {{- end -}} \ No newline at end of file diff --git a/charts/metal3/0.15.2/charts/ironic/templates/deployment.yaml b/charts/metal3/0.15.2/charts/ironic/templates/deployment.yaml new file mode 100644 index 00000000..f5a7d47d --- /dev/null +++ b/charts/metal3/0.15.2/charts/ironic/templates/deployment.yaml @@ -0,0 +1,311 @@ +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: + annotations: + checksum/config-env: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- with .Values.podAnnotations }} + {{- 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 + livenessProbe: + exec: + command: ["sh", "-c", "{{ include "ironic.probeCommand" . }}"] + 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: ["sh", "-c", "{{ include "ironic.probeCommand" . }}"] + 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 + {{- if .Values.global.enable_vmedia_tls }} + - name: cert-ironic-vmedia + mountPath: "/certs/vmedia" + readOnly: true + {{- end }} + {{- 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 + env: + {{- if .Values.global.enable_basicAuth }} + - name: IRONIC_HTPASSWD + valueFrom: + secretKeyRef: + name: ironic-basic-auth + key: htpasswd + {{- end }} + {{- if .Values.global.enable_mariadb }} + - name: MARIADB_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: ironic-mariadb + {{- end }} + livenessProbe: + exec: + command: ["/bin/ironic-liveness"] + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 10 + successThreshold: 1 + failureThreshold: 10 + ports: + - containerPort: 6385 + name: api + protocol: TCP + readinessProbe: + exec: + command: ["/bin/ironic-readiness"] + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 10 + successThreshold: 1 + failureThreshold: 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 + {{- end }} + {{- if .Values.global.enable_tls }} + {{- include "ironic.CAVolumeMounts" . | nindent 10 }} + - name: cert-ironic + mountPath: "/certs/ironic" + readOnly: true + {{- end }} + {{- if .Values.global.enable_dnsmasq }} + - name: ironic-dnsmasq + image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }} + imagePullPolicy: {{ .Values.images.ironic.pullPolicy }} + securityContext: + # dnsmasqSecurityContext takes precedence: `merge` favours the first + # dict, so per-container overrides (e.g. allowPrivilegeEscalation) must + # win over the shared securityContext. See issue #256. + {{- merge .Values.dnsmasqSecurityContext .Values.securityContext | toYaml | nindent 10 }} + command: + - /bin/rundnsmasq + envFrom: + - configMapRef: + name: ironic + 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 + env: + {{- if .Values.ipa.useHauler }} + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: REGISTRY_INSECURE + value: "true" + {{- end }} + {{- if .Values.ipa.httpProxy }} + - name: HTTP_PROXY + value: {{ .Values.ipa.httpProxy | quote }} + - name: http_proxy + value: {{ .Values.ipa.httpProxy | quote }} + {{- end }} + {{- if .Values.ipa.httpsProxy }} + - name: HTTPS_PROXY + value: {{ .Values.ipa.httpsProxy | quote }} + - name: https_proxy + value: {{ .Values.ipa.httpsProxy | quote }} + {{- end }} + {{- if .Values.ipa.noProxy }} + - name: NO_PROXY + value: {{ .Values.ipa.noProxy | quote }} + - name: no_proxy + value: {{ .Values.ipa.noProxy | quote }} + {{- end }} + {{- if .Values.ipa.tlsInsecure }} + - name: TLS_INSECURE + value: {{ .Values.ipa.tlsInsecure | quote }} + {{- end }} + {{- if .Values.ipa.trustedCA }} + - name: CA_BUNDLE + value: "/certs/ca/ipa/ca-bundle.pem" + {{- end }} + - name: IPA_BASEURI + {{- if .Values.ipa.baseUri }} + value: {{ .Values.ipa.baseUri }} + {{- else if .Values.images.ipa }} + {{- $image := .Values.images.ipa }} + {{- $url := urlParse ( print "oci://" $image.repository ) }} + {{- if .Values.ipa.useHauler }} + {{- $url := set $url "host" "$(HOST_IP):6545" }} + {{- end }} + value: {{ urlJoin $url }}:{{ .Values.images.ipa.tag }} + {{- end }} + volumeMounts: + {{- include "ironic.sharedVolumeMount" . | nindent 10 }} + {{- if .Values.ipa.trustedCA }} + - name: ipa-trusted-ca + mountPath: /certs/ca/ipa + readOnly: true + {{- end }} + volumes: + - name: ironic-data-volume + {{- if .Values.persistence.ironic.size }} + persistentVolumeClaim: + claimName: ironic-shared-volume + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.global.enable_basicAuth }} + - name: ironic-basic-auth + secret: + secretName: ironic-basic-auth + {{- end }} + {{- if .Values.global.trustedCAs }} + - name: trusted-ca + configMap: + name: {{ .Values.global.trustedCAs }} + {{- end }} + {{- if .Values.ipa.trustedCA }} + - name: ipa-trusted-ca + configMap: + name: {{ .Values.ipa.trustedCA }} + {{- end }} + {{- if .Values.global.enable_tls }} + - name: cert-ironic-ca + secret: + secretName: ironic-cacert + - name: cert-ironic + secret: + secretName: ironic-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 }} + {{- 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/charts/metal3/0.15.2/charts/ironic/templates/issuers.yaml b/charts/metal3/0.15.2/charts/ironic/templates/issuers.yaml new file mode 100644 index 00000000..f97de264 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/ironic/templates/pvc.yaml b/charts/metal3/0.15.2/charts/ironic/templates/pvc.yaml new file mode 100644 index 00000000..c757dd3f --- /dev/null +++ b/charts/metal3/0.15.2/charts/ironic/templates/pvc.yaml @@ -0,0 +1,26 @@ +{{- if .Values.persistence.ironic.size }} +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 +{{- end }} diff --git a/charts/metal3/0.15.2/charts/ironic/templates/secret-tls.yaml b/charts/metal3/0.15.2/charts/ironic/templates/secret-tls.yaml new file mode 100644 index 00000000..1f1611dd --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/ironic/templates/secrets-basic-auth.yaml b/charts/metal3/0.15.2/charts/ironic/templates/secrets-basic-auth.yaml new file mode 100644 index 00000000..0ef47d37 --- /dev/null +++ b/charts/metal3/0.15.2/charts/ironic/templates/secrets-basic-auth.yaml @@ -0,0 +1,33 @@ +{{- 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 }} + +{{- end }} diff --git a/charts/metal3/0.15.2/charts/ironic/templates/service.yaml b/charts/metal3/0.15.2/charts/ironic/templates/service.yaml new file mode 100644 index 00000000..aaeb2615 --- /dev/null +++ b/charts/metal3/0.15.2/charts/ironic/templates/service.yaml @@ -0,0 +1,40 @@ +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 }} + ipFamilyPolicy: PreferDualStack + 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/charts/metal3/0.15.2/charts/ironic/templates/serviceaccount.yaml b/charts/metal3/0.15.2/charts/ironic/templates/serviceaccount.yaml new file mode 100644 index 00000000..25fcc8d5 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/ironic/values.yaml b/charts/metal3/0.15.2/charts/ironic/values.yaml new file mode 100644 index 00000000..8c78a93b --- /dev/null +++ b/charts/metal3/0.15.2/charts/ironic/values.yaml @@ -0,0 +1,186 @@ +# 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: "" + + # Fully Qualified Domain Name used by Ironic for both binding (to the + # associated IPv4 and/or IPv6 addresses) and exposing the API, dnsmask and + # media, also used by BMO. Note, this is the only way to enable a fully + # working dual-stack configuration. + provisioningHostname: "" + + # 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 + +listenOnAll: true + +images: + ironic: + repository: registry.opensuse.org/isv/suse/edge/containers/images/ironic + pullPolicy: IfNotPresent + tag: 35.0.0.1 + ironicIPADownloader: + repository: registry.opensuse.org/isv/suse/edge/containers/images/ironic-ipa-downloader + pullPolicy: IfNotPresent + tag: 3.1.2 + ipa: + repository: registry.opensuse.org/isv/suse/edge/containers/images/ironic-python-agent + tag: 3.0.9 + +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: {} + +ipa: + useHauler: false + httpProxy: "" + httpsProxy: "" + noProxy: "" + tlsInsecure: false + trustedCA: "" + +podSecurityContext: + runAsUser: 10475 + fsGroup: 10475 + +securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + runAsNonRoot: true + +dnsmasqSecurityContext: + # dnsmasq binds privileged ports (DHCP 67, TFTP 69). The container stays + # non-root (runAsUser 10475 from podSecurityContext); the ironic image grants + # the needed file-caps via + # setcap cap_net_bind_service,cap_net_raw,cap_net_admin+eip /usr/sbin/dnsmasq + # but file-caps only take effect when no_new_privs is off, hence + # allowPrivilegeEscalation must be true here. NET_BIND_SERVICE must also be in + # the bounding set (added below) for the +e file-cap to apply. See issue #256. + allowPrivilegeEscalation: true + capabilities: + add: + - NET_ADMIN + - NET_RAW + - NET_BIND_SERVICE + +service: + type: LoadBalancer + annotations: {} + externalIPs: [] + ports: + - name: httpd + port: 6180 + protocol: TCP + targetPort: 6180 + - name: httpd-tls + port: 6185 + protocol: TCP + targetPort: 6185 + - 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: "" + +ironicExtraEnv: {} + +tlscerts: + cacert: "" + key: "" + crt: "" + +persistence: + ironic: + # storageClass for the ironic shared volume + # Ensure the storageClass is defined + storageClass: "" + # size of the ironic shared volume e.g "1Gi" + # When unset persistent storage is disabled and emptyDir is enabled + size: "" + # 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/charts/metal3/0.15.2/charts/mariadb/.helmignore b/charts/metal3/0.15.2/charts/mariadb/.helmignore new file mode 100644 index 00000000..898df488 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/mariadb/Chart.yaml b/charts/metal3/0.15.2/charts/mariadb/Chart.yaml new file mode 100644 index 00000000..9feaf258 --- /dev/null +++ b/charts/metal3/0.15.2/charts/mariadb/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: "11.8" +description: A Helm chart for MariaDB, used by Metal3 +name: mariadb +type: application +version: 0.6.3 diff --git a/charts/metal3/0.15.2/charts/mariadb/templates/_helpers.tpl b/charts/metal3/0.15.2/charts/mariadb/templates/_helpers.tpl new file mode 100644 index 00000000..bd963d0e --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/mariadb/templates/configmap-mariadb.yaml b/charts/metal3/0.15.2/charts/mariadb/templates/configmap-mariadb.yaml new file mode 100644 index 00000000..8decd409 --- /dev/null +++ b/charts/metal3/0.15.2/charts/mariadb/templates/configmap-mariadb.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: mariadb-config + labels: + {{- include "mariadb.labels" . | nindent 4 }} +data: + ironic.conf: | + [mariadb] + max_connections 64 + max_heap_table_size 1M + innodb_buffer_pool_size 5M + innodb_log_buffer_size 512K \ No newline at end of file diff --git a/charts/metal3/0.15.2/charts/mariadb/templates/configmap.yaml b/charts/metal3/0.15.2/charts/mariadb/templates/configmap.yaml new file mode 100644 index 00000000..da642adc --- /dev/null +++ b/charts/metal3/0.15.2/charts/mariadb/templates/configmap.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: mariadb-cm + labels: + {{- include "mariadb.labels" . | nindent 4 }} +data: + MARIADB_USER: ironic + MARIADB_RANDOM_ROOT_PASSWORD: "yes" + MARIADB_DATABASE: ironic + MARIADB_AUTO_UPGRADE: "yes" \ No newline at end of file diff --git a/charts/metal3/0.15.2/charts/mariadb/templates/deployment.yaml b/charts/metal3/0.15.2/charts/mariadb/templates/deployment.yaml new file mode 100644 index 00000000..fa0fd52c --- /dev/null +++ b/charts/metal3/0.15.2/charts/mariadb/templates/deployment.yaml @@ -0,0 +1,122 @@ +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 10 }} + {{- $volumes := toYaml .Values.volumes | trim | nindent 8 }} + serviceAccountName: {{ include "mariadb.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + initContainers: + # This would run during entrypoint if run as root + - name: set-volume-owners + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + runAsUser: 0 + allowPrivilegeEscalation: true + capabilities: + drop: + - ALL + add: + - CHOWN + - FOWNER + - DAC_OVERRIDE + seccompProfile: + type: RuntimeDefault + volumeMounts: + - name: mariadb-conf + mountPath: /etc/mysql/conf.d + - name: mariadb-run + mountPath: /run/mysql + {{- $volmounts }} + command: ['bash', '-c', 'source /usr/local/bin/docker-entrypoint.sh && docker_create_db_directories'] + env: + - name: DATADIR + value: /var/lib/mysql + - name: SOCKET + value: /run/mysql/mysql.sock + containers: + - name: mariadb + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + envFrom: + - configMapRef: + name: mariadb-cm + env: + - name: MARIADB_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: ironic-mariadb + lifecycle: + preStop: + exec: + command: + - sh + - -c + - mysqladmin shutdown -uironic -p$(printenv MARIADB_PASSWORD) + livenessProbe: + exec: + command: + - healthcheck.sh + - --connect + - --innodb_initialized + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + ports: + - containerPort: 3306 + name: mariadb + protocol: TCP + readinessProbe: + exec: + command: + - healthcheck.sh + - --connect + - --innodb_initialized + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + volumeMounts: + - name: mariadb-conf + mountPath: /etc/mysql/conf.d + - name: mariadb-run + mountPath: /run/mysql + {{- $volmounts }} + {{- with .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: mariadb-conf + configMap: + name: mariadb-config + - name: mariadb-run + emptyDir: + sizeLimit: 20Mi + {{- $volumes }} diff --git a/charts/metal3/0.15.2/charts/mariadb/templates/pvc.yaml b/charts/metal3/0.15.2/charts/mariadb/templates/pvc.yaml new file mode 100644 index 00000000..573e1525 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/mariadb/templates/secret.yaml b/charts/metal3/0.15.2/charts/mariadb/templates/secret.yaml new file mode 100644 index 00000000..3cde9e58 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/mariadb/templates/service-account.yaml b/charts/metal3/0.15.2/charts/mariadb/templates/service-account.yaml new file mode 100644 index 00000000..16794876 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/mariadb/templates/service.yaml b/charts/metal3/0.15.2/charts/mariadb/templates/service.yaml new file mode 100644 index 00000000..471702b9 --- /dev/null +++ b/charts/metal3/0.15.2/charts/mariadb/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.global.databaseServiceName }} + labels: + {{- include "mariadb.labels" . | nindent 4 }} +spec: + ipFamilyPolicy: PreferDualStack + type: {{ .Values.service.type }} + selector: + {{- include "mariadb.selectorLabels" . | nindent 4 }} + ports: + {{- with .Values.service.ports }} + {{- toYaml . | nindent 2 }} + {{- end }} diff --git a/charts/metal3/0.15.2/charts/mariadb/values.yaml b/charts/metal3/0.15.2/charts/mariadb/values.yaml new file mode 100644 index 00000000..a1796e8f --- /dev/null +++ b/charts/metal3/0.15.2/charts/mariadb/values.yaml @@ -0,0 +1,68 @@ +global: + databaseServiceName: "metal3-mariadb" + nodeSelector: {} + +replicaCount: 1 + +service: + type: ClusterIP + ports: + - protocol: TCP + port: 3306 + targetPort: 3306 + +image: + repository: registry.suse.com/suse/mariadb + pullPolicy: IfNotPresent + tag: 11.8 + +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: 60 + fsGroup: 60 + +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 + subPath: data + +volumes: + - name: mariadb-data-volume + persistentVolumeClaim: + claimName: mariadb-volume-claim diff --git a/charts/metal3/0.15.2/charts/media/.helmignore b/charts/metal3/0.15.2/charts/media/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/media/Chart.yaml b/charts/metal3/0.15.2/charts/media/Chart.yaml new file mode 100644 index 00000000..fb4d3d7e --- /dev/null +++ b/charts/metal3/0.15.2/charts/media/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 1.21.0 +description: A Helm chart for Media, used by Metal3 +name: media +type: application +version: 0.7.1 diff --git a/charts/metal3/0.15.2/charts/media/templates/NOTES.txt b/charts/metal3/0.15.2/charts/media/templates/NOTES.txt new file mode 100644 index 00000000..6823b8ca --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/media/templates/_helpers.tpl b/charts/metal3/0.15.2/charts/media/templates/_helpers.tpl new file mode 100644 index 00000000..ae2a31da --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/media/templates/deployment.yaml b/charts/metal3/0.15.2/charts/media/templates/deployment.yaml new file mode 100644 index 00000000..6605cbc3 --- /dev/null +++ b/charts/metal3/0.15.2/charts/media/templates/deployment.yaml @@ -0,0 +1,62 @@ +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 }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + 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/charts/metal3/0.15.2/charts/media/templates/hpa.yaml b/charts/metal3/0.15.2/charts/media/templates/hpa.yaml new file mode 100644 index 00000000..296a627b --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/media/templates/ingress.yaml b/charts/metal3/0.15.2/charts/media/templates/ingress.yaml new file mode 100644 index 00000000..bc816995 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/media/templates/persistentvolume.yaml b/charts/metal3/0.15.2/charts/media/templates/persistentvolume.yaml new file mode 100644 index 00000000..97e08f3f --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/media/templates/persistentvolumeclaim.yaml b/charts/metal3/0.15.2/charts/media/templates/persistentvolumeclaim.yaml new file mode 100644 index 00000000..d2c7e5d3 --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/media/templates/service.yaml b/charts/metal3/0.15.2/charts/media/templates/service.yaml new file mode 100644 index 00000000..f8f524b5 --- /dev/null +++ b/charts/metal3/0.15.2/charts/media/templates/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "media.fullname" . }} + labels: + {{- include "media.labels" . | nindent 4 }} +spec: + ipFamilyPolicy: PreferDualStack + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "media.selectorLabels" . | nindent 4 }} diff --git a/charts/metal3/0.15.2/charts/media/templates/serviceaccount.yaml b/charts/metal3/0.15.2/charts/media/templates/serviceaccount.yaml new file mode 100644 index 00000000..513a44ab --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/media/templates/storageclass.yaml b/charts/metal3/0.15.2/charts/media/templates/storageclass.yaml new file mode 100644 index 00000000..001cdd9b --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/charts/media/values.yaml b/charts/metal3/0.15.2/charts/media/values.yaml new file mode 100644 index 00000000..843cbbd2 --- /dev/null +++ b/charts/metal3/0.15.2/charts/media/values.yaml @@ -0,0 +1,122 @@ +# 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.suse.com/suse/nginx + pullPolicy: IfNotPresent + tag: 1.21 + +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: 499 + fsGroup: 486 + +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 + - name: run + emptyDir: + sizeLimit: 10Mi + +# volume mounts +volumeMounts: + - mountPath: /srv/www/htdocs + name: assets + - mountPath: /run + name: run + +# media volume settings +mediaVolume: + storageClassName: local + accessModes: + - ReadOnlyMany + hostPath: /opt/media + storage: 5Gi diff --git a/charts/metal3/0.15.2/templates/NOTES.txt b/charts/metal3/0.15.2/templates/NOTES.txt new file mode 100644 index 00000000..ecac059d --- /dev/null +++ b/charts/metal3/0.15.2/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/charts/metal3/0.15.2/templates/_helpers.tpl b/charts/metal3/0.15.2/templates/_helpers.tpl new file mode 100644 index 00000000..c1725ceb --- /dev/null +++ b/charts/metal3/0.15.2/templates/_helpers.tpl @@ -0,0 +1,77 @@ +{{/* +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 }} + +{{/* +Produce the correct IP or hostname for Ironic provisioning +*/}} +{{- define "metal3.hostIP" -}} +{{- with .Values.global }} +{{- if and .provisioningHostname (or .provisioningIP .ironicIP) }} +{{ fail "Please provide either provisioningHostname or provisioningIP or ironicIP" }} +{{- end }} +{{- if and .provisioningIP .ironicIP }} +{{ fail "Please provide either ironicIP or provisioningIP" }} +{{- end }} +{{- coalesce .provisioningIP .ironicIP }} +{{- end }} +{{- end }} diff --git a/charts/metal3/0.15.2/values.yaml b/charts/metal3/0.15.2/values.yaml new file mode 100644 index 00000000..769bc869 --- /dev/null +++ b/charts/metal3/0.15.2/values.yaml @@ -0,0 +1,122 @@ +# 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 mariadb (default is sqlite) + enable_mariadb: false + + # 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: "" + + # CA bundle to be trusted by Ironic and its python agent, should be the + # name of a deployed ConfigMap in the same namespace. If left empty the + # default public CA bundle will be used. + # The ConfigMap should be like this: + # data: + # ca-bundle.pem: + trustedCAs: "" + + # 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: "" + + # Fully Qualified Domain Name used by Ironic for both binding (to the + # associated IPv4 and/or IPv6 addresses) and exposing the API, dnsmask and + # media, also used by BMO. Note, this is the only way to enable a fully + # working dual-stack configuration. + provisioningHostname: "" + + # Hostname or IP for accessing the Ironic API server from a non-provisioning network + externalHttpHost: "" + + # 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 + +# +# 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: "" + ipa: + httpProxy: "" + httpsProxy: "" + noProxy: "" + tlsInsecure: false + trustedCA: "" + +# +# Database Service +# + +# Override any settings for the metal3 mariadb service here +metal3-mariadb: + # storageClass for the mysql datastore + persistence: + storageClass: "" diff --git a/index.html b/index.html index 754d9d42..63de9241 100755 --- a/index.html +++ b/index.html @@ -267,14 +267,14 @@

Charts

- +

metal3 - (0.15.1@0.15.1) + (0.15.2@0.15.1) github link diff --git a/index.yaml b/index.yaml index ad186358..c5635ff5 100755 --- a/index.yaml +++ b/index.yaml @@ -665,6 +665,36 @@ entries: - assets/kubevirt-dashboard-extension/kubevirt-dashboard-extension-0.1.0.tgz version: 0.1.0 metal3: + - apiVersion: v2 + appVersion: 0.15.1 + created: "2026-07-07T17:17:40.161712+02:00" + dependencies: + - alias: metal3-baremetal-operator + name: baremetal-operator + repository: file://./charts/baremetal-operator + version: 0.12.3 + - alias: metal3-ironic + name: ironic + repository: file://./charts/ironic + version: 0.13.2 + - alias: metal3-mariadb + condition: global.enable_mariadb + name: mariadb + repository: file://./charts/mariadb + version: 0.6.3 + - alias: metal3-media + condition: global.enable_metal3_media_server + name: media + repository: file://./charts/media + version: 0.7.1 + description: A Helm chart that installs all of the dependencies needed for Metal3 + digest: e7e30ea37727ec3566c410fe39d0c08d21604dc3d5014ffce520fbb2f585bb06 + icon: https://github.com/cncf/artwork/raw/master/projects/metal3/icon/color/metal3-icon-color.svg + name: metal3 + type: application + urls: + - assets/metal3/metal3-0.15.2.tgz + version: 0.15.2 - apiVersion: v2 appVersion: 0.15.1 created: "2026-06-11T16:43:57.694584783+02:00"