From 21086b77bb3a012ac0888e2810f0c7baf1f8493999571eb4011bbda0206657aa Mon Sep 17 00:00:00 2001 From: Denislav Prodanov Date: Tue, 22 Oct 2024 10:51:51 +0300 Subject: [PATCH] unpack obscpio files --- cdi-chart/{crds.obscpio => crds/cdi.yaml} | Bin 356864 -> 356467 bytes cdi-chart/templates.obscpio | Bin 26624 -> 0 bytes cdi-chart/templates/NOTES.txt | 2 + cdi-chart/templates/_helpers.tpl | 62 + cdi-chart/templates/_hooks.tpl | 47 + cdi-chart/templates/cdi-operator.yaml | 671 +++++++++ cdi-chart/templates/cdi-uninstall-hooks.yaml | 69 + cdi-chart/templates/cdi.yaml | 21 + cdi-chart/templates/crd-uninstall-hooks.yaml | 55 + cdi-chart/templates/crd-upgrade-hooks.yaml | 80 ++ cdi-chart/templates/namespace-hooks.yaml | 56 + metal3-chart/charts.obscpio | Bin 189440 -> 0 bytes .../charts/baremetal-operator/.helmignore | 23 + .../charts/baremetal-operator/Chart.yaml | 6 + .../crds/customresource-baremetalhosts.yaml | 1148 ++++++++++++++++ .../customresource-bmceventsubscriptions.yaml | 85 ++ .../crds/customresource-dataimages.yaml | 75 + .../crds/customresource-firmwareschemas.yaml | 90 ++ .../crds/customresource-hardwaredata.yaml | 211 +++ ...customresource-hostfirmwarecomponents.yaml | 178 +++ .../customresource-hostfirmwaresettings.yaml | 164 +++ .../customresource-preprovisioningimages.yaml | 183 +++ .../baremetal-operator/templates/NOTES.txt | 16 + .../baremetal-operator/templates/_helpers.tpl | 63 + .../templates/certificate.yaml | 14 + .../templates/clusterrole-manager.yaml | 186 +++ .../templates/clusterrole-metrics-reader.yaml | 11 + .../templates/clusterrole-proxy.yaml | 19 + .../templates/clusterrolebinding-manager.yaml | 14 + .../templates/clusterrolebinding-proxy.yaml | 14 + .../templates/configmap-ironic.yaml | 30 + .../templates/configmap.yaml | 19 + .../templates/deployment.yaml | 131 ++ .../baremetal-operator/templates/issuer.yaml | 8 + .../baremetal-operator/templates/role.yaml | 45 + .../templates/rolebinding.yaml | 13 + .../templates/service-controller-manager.yaml | 14 + .../templates/service-webhook.yaml | 13 + .../templates/serviceaccount.yaml | 12 + .../templates/tests/test-connection.yaml | 15 + .../validatingwebhookconfiguration.yaml | 51 + .../charts/baremetal-operator/values.yaml | 90 ++ metal3-chart/charts/ironic/.helmignore | 23 + metal3-chart/charts/ironic/Chart.yaml | 6 + metal3-chart/charts/ironic/README.md | 24 + .../charts/ironic/templates/NOTES.txt | 16 + .../charts/ironic/templates/_helpers.tpl | 88 ++ .../charts/ironic/templates/certificates.yaml | 56 + .../templates/configmap-ipa-downloader.yaml | 12 + .../charts/ironic/templates/configmap.yaml | 86 ++ .../charts/ironic/templates/deployment.yaml | 367 +++++ .../charts/ironic/templates/issuers.yaml | 16 + metal3-chart/charts/ironic/templates/pvc.yaml | 24 + .../charts/ironic/templates/secret-tls.yaml | 16 + .../ironic/templates/secrets-basic-auth.yaml | 62 + .../charts/ironic/templates/service.yaml | 39 + .../ironic/templates/serviceaccount.yaml | 12 + metal3-chart/charts/ironic/values.yaml | 153 +++ metal3-chart/charts/mariadb/.helmignore | 24 + metal3-chart/charts/mariadb/Chart.yaml | 6 + .../charts/mariadb/templates/_helpers.tpl | 64 + .../charts/mariadb/templates/configmap.yaml | 8 + .../charts/mariadb/templates/deployment.yaml | 85 ++ .../charts/mariadb/templates/pvc.yaml | 24 + .../charts/mariadb/templates/secret.yaml | 21 + .../mariadb/templates/service-account.yaml | 13 + .../charts/mariadb/templates/service.yaml | 14 + metal3-chart/charts/mariadb/values.yaml | 67 + metal3-chart/charts/media/.helmignore | 23 + metal3-chart/charts/media/Chart.yaml | 6 + metal3-chart/charts/media/templates/NOTES.txt | 22 + .../charts/media/templates/_helpers.tpl | 63 + .../charts/media/templates/deployment.yaml | 66 + metal3-chart/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 | 15 + .../media/templates/serviceaccount.yaml | 12 + .../charts/media/templates/storageclass.yaml | 9 + .../templates/tests/test-connection.yaml | 15 + metal3-chart/charts/media/values.yaml | 117 ++ metal3-chart/templates/NOTES.txt | 3 + .../_helpers.tpl} | Bin 2560 -> 1772 bytes metallb-chart/charts.obscpio | Bin 141824 -> 0 bytes metallb-chart/charts/frr-k8s/Chart.yaml | 11 + metallb-chart/charts/frr-k8s/README.md | 96 ++ .../frrk8s.metallb.io_frrconfigurations.yaml | 462 +++++++ .../crds/frrk8s.metallb.io_frrnodestates.yaml | 65 + .../charts/frr-k8s/templates/NOTES.txt | 4 + .../charts/frr-k8s/templates/_helpers.tpl | 63 + .../charts/frr-k8s/templates/controller.yaml | 431 ++++++ .../charts/frr-k8s/templates/rbac.yaml | 73 + .../frr-k8s/templates/service-accounts.yaml | 16 + .../frr-k8s/templates/service-monitor.yaml | 128 ++ .../charts/frr-k8s/templates/webhooks.yaml | 163 +++ .../charts/frr-k8s/values.schema.json | 387 ++++++ metallb-chart/charts/frr-k8s/values.yaml | 176 +++ metallb-chart/charts/metallb-crds/.helmignore | 23 + metallb-chart/charts/metallb-crds/Chart.yaml | 10 + metallb-chart/charts/metallb-crds/README.md | 11 + .../charts/metallb-crds/templates/crds.yaml | 1205 +++++++++++++++++ metallb-chart/policy.obscpio | Bin 3072 -> 0 bytes metallb-chart/policy/controller.rego | 16 + metallb-chart/policy/rbac.rego | 27 + metallb-chart/policy/speaker.rego | 30 + metallb-chart/templates.obscpio | Bin 60928 -> 0 bytes metallb-chart/templates/NOTES.txt | 4 + metallb-chart/templates/_helpers.tpl | 113 ++ metallb-chart/templates/controller.yaml | 194 +++ .../templates/deprecated_configInline.yaml | 3 + .../templates/exclude-l2-config.yaml | 25 + metallb-chart/templates/podmonitor.yaml | 106 ++ metallb-chart/templates/prometheusrules.yaml | 84 ++ metallb-chart/templates/rbac.yaml | 212 +++ metallb-chart/templates/service-accounts.yaml | 30 + metallb-chart/templates/servicemonitor.yaml | 194 +++ metallb-chart/templates/speaker.yaml | 568 ++++++++ metallb-chart/templates/webhooks.yaml | 150 ++ sriov-crd-chart/templates.obscpio | Bin 47104 -> 0 bytes ...sriovnetwork.openshift.io_ovsnetworks.yaml | 105 ++ ...vnetwork.openshift.io_sriovibnetworks.yaml | 78 ++ ...openshift.io_sriovnetworknodepolicies.yaml | 209 +++ ...k.openshift.io_sriovnetworknodestates.yaml | 343 +++++ ....openshift.io_sriovnetworkpoolconfigs.yaml | 123 ++ ...iovnetwork.openshift.io_sriovnetworks.yaml | 136 ++ ...ork.openshift.io_sriovoperatorconfigs.yaml | 114 ++ sriov-network-operator-chart/charts.obscpio | Bin 90112 -> 0 bytes .../charts/sriov-nfd/.helmignore | 23 + .../charts/sriov-nfd/Chart.yaml | 14 + .../charts/sriov-nfd/README.md | 10 + .../charts/sriov-nfd/crds/nfd-api-crds.yaml | 426 ++++++ .../charts/sriov-nfd/templates/_helpers.tpl | 107 ++ .../templates/cert-manager-certs.yaml | 68 + .../templates/cert-manager-issuer.yaml | 42 + .../sriov-nfd/templates/clusterrole.yaml | 119 ++ .../templates/clusterrolebinding.yaml | 52 + .../charts/sriov-nfd/templates/master.yaml | 145 ++ .../charts/sriov-nfd/templates/nfd-gc.yaml | 77 ++ .../sriov-nfd/templates/nfd-master-conf.yaml | 12 + .../templates/nfd-topologyupdater-conf.yaml | 10 + .../sriov-nfd/templates/nfd-worker-conf.yaml | 12 + .../sriov-nfd/templates/prometheus.yaml | 26 + .../charts/sriov-nfd/templates/role.yaml | 24 + .../sriov-nfd/templates/rolebinding.yaml | 18 + .../charts/sriov-nfd/templates/service.yaml | 20 + .../sriov-nfd/templates/serviceaccount.yaml | 58 + .../templates/topologyupdater-crds.yaml | 278 ++++ .../sriov-nfd/templates/topologyupdater.yaml | 156 +++ .../charts/sriov-nfd/templates/worker.yaml | 162 +++ .../charts/sriov-nfd/values.yaml | 534 ++++++++ .../templates.obscpio | Bin 28160 -> 0 bytes .../templates/NOTES.txt | 17 + .../templates/_helpers.tpl | 85 ++ .../templates/_webhook-certs.tpl | 31 + .../templates/certificate.yaml | 71 + .../templates/certmanagercerts.yaml | 41 + .../templates/clusterrole.yaml | 111 ++ .../templates/clusterrolebinding.yaml | 29 + .../templates/configmap.yaml | 47 + .../templates/operator.yaml | 116 ++ .../templates/role.yaml | 138 ++ .../templates/rolebinding.yaml | 44 + .../templates/secrets.yaml | 20 + .../templates/serviceaccount.yaml | 15 + .../templates/sriovoperatorconfig.yaml | 17 + .../templates/validate-install-crd.yaml | 20 + .../charts/lifecycle-crds/Chart.yaml | 6 + .../templates/release-manifest-crd.yaml | 135 ++ .../templates/upgrade-plan-crd.yaml} | Bin 15360 -> 8833 bytes upgrade-controller-chart/templates.obscpio | Bin 12800 -> 0 bytes upgrade-controller-chart/templates/NOTES.txt | 0 .../templates/_helpers.tpl | 83 ++ .../templates/certificate.yaml | 28 + .../templates/clusterrole.yaml | 114 ++ .../templates/clusterrole_binding.yaml | 14 + .../templates/deployment.yaml | 85 ++ .../templates/leader_election_role.yaml | 40 + .../leader_election_role_binding.yaml | 15 + .../templates/serviceaccount.yaml | 14 + .../validating_webhook_configuration.yaml | 29 + .../templates/webhook_service.yaml | 15 + 182 files changed, 15763 insertions(+) rename cdi-chart/{crds.obscpio => crds/cdi.yaml} (99%) delete mode 100644 cdi-chart/templates.obscpio create mode 100644 cdi-chart/templates/NOTES.txt create mode 100644 cdi-chart/templates/_helpers.tpl create mode 100644 cdi-chart/templates/_hooks.tpl create mode 100644 cdi-chart/templates/cdi-operator.yaml create mode 100644 cdi-chart/templates/cdi-uninstall-hooks.yaml create mode 100644 cdi-chart/templates/cdi.yaml create mode 100644 cdi-chart/templates/crd-uninstall-hooks.yaml create mode 100644 cdi-chart/templates/crd-upgrade-hooks.yaml create mode 100644 cdi-chart/templates/namespace-hooks.yaml delete mode 100644 metal3-chart/charts.obscpio create mode 100644 metal3-chart/charts/baremetal-operator/.helmignore create mode 100644 metal3-chart/charts/baremetal-operator/Chart.yaml create mode 100644 metal3-chart/charts/baremetal-operator/crds/customresource-baremetalhosts.yaml create mode 100644 metal3-chart/charts/baremetal-operator/crds/customresource-bmceventsubscriptions.yaml create mode 100644 metal3-chart/charts/baremetal-operator/crds/customresource-dataimages.yaml create mode 100644 metal3-chart/charts/baremetal-operator/crds/customresource-firmwareschemas.yaml create mode 100644 metal3-chart/charts/baremetal-operator/crds/customresource-hardwaredata.yaml create mode 100644 metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwarecomponents.yaml create mode 100644 metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwaresettings.yaml create mode 100644 metal3-chart/charts/baremetal-operator/crds/customresource-preprovisioningimages.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/NOTES.txt create mode 100644 metal3-chart/charts/baremetal-operator/templates/_helpers.tpl create mode 100644 metal3-chart/charts/baremetal-operator/templates/certificate.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/clusterrole-manager.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/clusterrole-metrics-reader.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/clusterrole-proxy.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-manager.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-proxy.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/configmap-ironic.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/configmap.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/deployment.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/issuer.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/role.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/rolebinding.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/service-controller-manager.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/service-webhook.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/serviceaccount.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/tests/test-connection.yaml create mode 100644 metal3-chart/charts/baremetal-operator/templates/validatingwebhookconfiguration.yaml create mode 100644 metal3-chart/charts/baremetal-operator/values.yaml create mode 100644 metal3-chart/charts/ironic/.helmignore create mode 100644 metal3-chart/charts/ironic/Chart.yaml create mode 100644 metal3-chart/charts/ironic/README.md create mode 100644 metal3-chart/charts/ironic/templates/NOTES.txt create mode 100644 metal3-chart/charts/ironic/templates/_helpers.tpl create mode 100644 metal3-chart/charts/ironic/templates/certificates.yaml create mode 100644 metal3-chart/charts/ironic/templates/configmap-ipa-downloader.yaml create mode 100644 metal3-chart/charts/ironic/templates/configmap.yaml create mode 100644 metal3-chart/charts/ironic/templates/deployment.yaml create mode 100644 metal3-chart/charts/ironic/templates/issuers.yaml create mode 100644 metal3-chart/charts/ironic/templates/pvc.yaml create mode 100644 metal3-chart/charts/ironic/templates/secret-tls.yaml create mode 100644 metal3-chart/charts/ironic/templates/secrets-basic-auth.yaml create mode 100644 metal3-chart/charts/ironic/templates/service.yaml create mode 100644 metal3-chart/charts/ironic/templates/serviceaccount.yaml create mode 100644 metal3-chart/charts/ironic/values.yaml create mode 100644 metal3-chart/charts/mariadb/.helmignore create mode 100644 metal3-chart/charts/mariadb/Chart.yaml create mode 100644 metal3-chart/charts/mariadb/templates/_helpers.tpl create mode 100644 metal3-chart/charts/mariadb/templates/configmap.yaml create mode 100644 metal3-chart/charts/mariadb/templates/deployment.yaml create mode 100644 metal3-chart/charts/mariadb/templates/pvc.yaml create mode 100644 metal3-chart/charts/mariadb/templates/secret.yaml create mode 100644 metal3-chart/charts/mariadb/templates/service-account.yaml create mode 100644 metal3-chart/charts/mariadb/templates/service.yaml create mode 100644 metal3-chart/charts/mariadb/values.yaml create mode 100644 metal3-chart/charts/media/.helmignore create mode 100644 metal3-chart/charts/media/Chart.yaml create mode 100644 metal3-chart/charts/media/templates/NOTES.txt create mode 100644 metal3-chart/charts/media/templates/_helpers.tpl create mode 100644 metal3-chart/charts/media/templates/deployment.yaml create mode 100644 metal3-chart/charts/media/templates/hpa.yaml create mode 100644 metal3-chart/charts/media/templates/ingress.yaml create mode 100644 metal3-chart/charts/media/templates/persistentvolume.yaml create mode 100644 metal3-chart/charts/media/templates/persistentvolumeclaim.yaml create mode 100644 metal3-chart/charts/media/templates/service.yaml create mode 100644 metal3-chart/charts/media/templates/serviceaccount.yaml create mode 100644 metal3-chart/charts/media/templates/storageclass.yaml create mode 100644 metal3-chart/charts/media/templates/tests/test-connection.yaml create mode 100644 metal3-chart/charts/media/values.yaml create mode 100644 metal3-chart/templates/NOTES.txt rename metal3-chart/{templates.obscpio => templates/_helpers.tpl} (69%) delete mode 100644 metallb-chart/charts.obscpio create mode 100644 metallb-chart/charts/frr-k8s/Chart.yaml create mode 100644 metallb-chart/charts/frr-k8s/README.md create mode 100644 metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrconfigurations.yaml create mode 100644 metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrnodestates.yaml create mode 100644 metallb-chart/charts/frr-k8s/templates/NOTES.txt create mode 100644 metallb-chart/charts/frr-k8s/templates/_helpers.tpl create mode 100644 metallb-chart/charts/frr-k8s/templates/controller.yaml create mode 100644 metallb-chart/charts/frr-k8s/templates/rbac.yaml create mode 100644 metallb-chart/charts/frr-k8s/templates/service-accounts.yaml create mode 100644 metallb-chart/charts/frr-k8s/templates/service-monitor.yaml create mode 100644 metallb-chart/charts/frr-k8s/templates/webhooks.yaml create mode 100644 metallb-chart/charts/frr-k8s/values.schema.json create mode 100644 metallb-chart/charts/frr-k8s/values.yaml create mode 100644 metallb-chart/charts/metallb-crds/.helmignore create mode 100644 metallb-chart/charts/metallb-crds/Chart.yaml create mode 100644 metallb-chart/charts/metallb-crds/README.md create mode 100644 metallb-chart/charts/metallb-crds/templates/crds.yaml delete mode 100644 metallb-chart/policy.obscpio create mode 100644 metallb-chart/policy/controller.rego create mode 100644 metallb-chart/policy/rbac.rego create mode 100644 metallb-chart/policy/speaker.rego delete mode 100644 metallb-chart/templates.obscpio create mode 100644 metallb-chart/templates/NOTES.txt create mode 100644 metallb-chart/templates/_helpers.tpl create mode 100644 metallb-chart/templates/controller.yaml create mode 100644 metallb-chart/templates/deprecated_configInline.yaml create mode 100644 metallb-chart/templates/exclude-l2-config.yaml create mode 100644 metallb-chart/templates/podmonitor.yaml create mode 100644 metallb-chart/templates/prometheusrules.yaml create mode 100644 metallb-chart/templates/rbac.yaml create mode 100644 metallb-chart/templates/service-accounts.yaml create mode 100644 metallb-chart/templates/servicemonitor.yaml create mode 100644 metallb-chart/templates/speaker.yaml create mode 100644 metallb-chart/templates/webhooks.yaml delete mode 100644 sriov-crd-chart/templates.obscpio create mode 100644 sriov-crd-chart/templates/sriovnetwork.openshift.io_ovsnetworks.yaml create mode 100644 sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovibnetworks.yaml create mode 100644 sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml create mode 100644 sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodestates.yaml create mode 100644 sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml create mode 100644 sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworks.yaml create mode 100644 sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml delete mode 100644 sriov-network-operator-chart/charts.obscpio create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/.helmignore create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/Chart.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/README.md create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/crds/nfd-api-crds.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/_helpers.tpl create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-certs.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-issuer.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrole.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrolebinding.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/master.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-gc.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-master-conf.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-topologyupdater-conf.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-worker-conf.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/prometheus.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/role.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/rolebinding.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/service.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/serviceaccount.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater-crds.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/templates/worker.yaml create mode 100644 sriov-network-operator-chart/charts/sriov-nfd/values.yaml delete mode 100644 sriov-network-operator-chart/templates.obscpio create mode 100644 sriov-network-operator-chart/templates/NOTES.txt create mode 100644 sriov-network-operator-chart/templates/_helpers.tpl create mode 100644 sriov-network-operator-chart/templates/_webhook-certs.tpl create mode 100644 sriov-network-operator-chart/templates/certificate.yaml create mode 100644 sriov-network-operator-chart/templates/certmanagercerts.yaml create mode 100644 sriov-network-operator-chart/templates/clusterrole.yaml create mode 100644 sriov-network-operator-chart/templates/clusterrolebinding.yaml create mode 100644 sriov-network-operator-chart/templates/configmap.yaml create mode 100644 sriov-network-operator-chart/templates/operator.yaml create mode 100644 sriov-network-operator-chart/templates/role.yaml create mode 100644 sriov-network-operator-chart/templates/rolebinding.yaml create mode 100644 sriov-network-operator-chart/templates/secrets.yaml create mode 100644 sriov-network-operator-chart/templates/serviceaccount.yaml create mode 100644 sriov-network-operator-chart/templates/sriovoperatorconfig.yaml create mode 100644 sriov-network-operator-chart/templates/validate-install-crd.yaml create mode 100644 upgrade-controller-chart/charts/lifecycle-crds/Chart.yaml create mode 100644 upgrade-controller-chart/charts/lifecycle-crds/templates/release-manifest-crd.yaml rename upgrade-controller-chart/{charts.obscpio => charts/lifecycle-crds/templates/upgrade-plan-crd.yaml} (57%) delete mode 100644 upgrade-controller-chart/templates.obscpio create mode 100644 upgrade-controller-chart/templates/NOTES.txt create mode 100644 upgrade-controller-chart/templates/_helpers.tpl create mode 100644 upgrade-controller-chart/templates/certificate.yaml create mode 100644 upgrade-controller-chart/templates/clusterrole.yaml create mode 100644 upgrade-controller-chart/templates/clusterrole_binding.yaml create mode 100644 upgrade-controller-chart/templates/deployment.yaml create mode 100644 upgrade-controller-chart/templates/leader_election_role.yaml create mode 100644 upgrade-controller-chart/templates/leader_election_role_binding.yaml create mode 100644 upgrade-controller-chart/templates/serviceaccount.yaml create mode 100644 upgrade-controller-chart/templates/validating_webhook_configuration.yaml create mode 100644 upgrade-controller-chart/templates/webhook_service.yaml diff --git a/cdi-chart/crds.obscpio b/cdi-chart/crds/cdi.yaml similarity index 99% rename from cdi-chart/crds.obscpio rename to cdi-chart/crds/cdi.yaml index 934dbbbe293092174fb46c35378f87526154d3e78ee13025221b7272264ab260..8621e0f2176d59edb2a13b07fdb9d519fd672ab92ae40a6874a9cc271fc4eeae 100644 GIT binary patch delta 25 gcmZp8BKrA(Xk$%l4P$E!Q)>-#YYofR8rI?h0G5Xeh5!Hn delta 429 zcmezTK(yhBXuW|s5E>d7nVFcIB_|sIfrVkB35Yf@Ofv)128IwmP{hnE#lkYx0>n23 zYBYw(1NB2d3Y12tQegtgMJdJl$tjt7m5I4I42cDqjm)jgjIGQ}t;|3M%T{LAf`WPm osGDG#@Y686@vFj=O@ax91UY*8xCSXIDl&jUJ%k!CQW%TP0GRVVd;kCd diff --git a/cdi-chart/templates.obscpio b/cdi-chart/templates.obscpio deleted file mode 100644 index f1fb05f1303c34d3034362b2d373771e14003a3db6707f41aa1c8f59b7631450..0000000000000000000000000000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26624 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 diff --git a/cdi-chart/templates/NOTES.txt b/cdi-chart/templates/NOTES.txt new file mode 100644 index 0000000..f6a43a4 --- /dev/null +++ b/cdi-chart/templates/NOTES.txt @@ -0,0 +1,2 @@ +Verify that all CDI components are installed correctly: + kubectl get all -n {{ .Release.Namespace }} diff --git a/cdi-chart/templates/_helpers.tpl b/cdi-chart/templates/_helpers.tpl new file mode 100644 index 0000000..5f2e091 --- /dev/null +++ b/cdi-chart/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "cdi.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "cdi.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "cdi.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "cdi.labels" -}} +helm.sh/chart: {{ include "cdi.chart" . }} +{{ include "cdi.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "cdi.selectorLabels" -}} +app.kubernetes.io/name: {{ include "cdi.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "cdi.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "cdi.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/cdi-chart/templates/_hooks.tpl b/cdi-chart/templates/_hooks.tpl new file mode 100644 index 0000000..d857801 --- /dev/null +++ b/cdi-chart/templates/_hooks.tpl @@ -0,0 +1,47 @@ +{{/* Hook annotations */}} +{{- define "cdi.hook.annotations" -}} + annotations: + "helm.sh/hook": {{ .hookType }} + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + "helm.sh/hook-weight": {{ .hookWeight | quote }} +{{- end -}} + +{{/* Namespace modifying hook annotations */}} +{{- define "cdi.namespaceHook.annotations" -}} +{{ template "cdi.hook.annotations" merge (dict "hookType" "pre-install") . }} +{{- end -}} + +{{/* CRD upgrading hook annotations */}} +{{- define "cdi.crdUpgradeHook.annotations" -}} +{{ template "cdi.hook.annotations" merge (dict "hookType" "pre-upgrade") . }} +{{- end -}} + +{{/* Custom resource uninstalling hook annotations */}} +{{- define "cdi.crUninstallHook.annotations" -}} +{{ template "cdi.hook.annotations" merge (dict "hookType" "pre-delete") . }} +{{- end -}} + +{{/* CRD uninstalling hook annotations */}} +{{- define "cdi.crdUninstallHook.annotations" -}} +{{ template "cdi.hook.annotations" merge (dict "hookType" "post-delete") . }} +{{- end -}} + +{{/* Namespace modifying hook name */}} +{{- define "cdi.namespaceHook.name" -}} +{{ include "cdi.fullname" . }}-namespace-modify +{{- end }} + +{{/* CRD upgrading hook name */}} +{{- define "cdi.crdUpgradeHook.name" -}} +{{ include "cdi.fullname" . }}-crd-upgrade +{{- end }} + +{{/* Custom resource uninstalling hook name */}} +{{- define "cdi.crUninstallHook.name" -}} +{{ include "cdi.fullname" . }}-uninstall +{{- end }} + +{{/* CRD uninstalling hook name */}} +{{- define "cdi.crdUninstallHook.name" -}} +{{ include "cdi.fullname" . }}-crd-uninstall +{{- end }} diff --git a/cdi-chart/templates/cdi-operator.yaml b/cdi-chart/templates/cdi-operator.yaml new file mode 100644 index 0000000..f6ab6fe --- /dev/null +++ b/cdi-chart/templates/cdi-operator.yaml @@ -0,0 +1,671 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + operator.cdi.kubevirt.io: "" + name: cdi-operator-cluster +rules: + - apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterrolebindings + - clusterroles + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + verbs: + - get + - list + - watch + - update + - create + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + - customresourcedefinitions/status + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - cdi.kubevirt.io + - upload.cdi.kubevirt.io + resources: + - '*' + verbs: + - '*' + - apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + - mutatingwebhookconfigurations + verbs: + - create + - list + - watch + - apiGroups: + - admissionregistration.k8s.io + resourceNames: + - cdi-api-dataimportcron-validate + - cdi-api-populator-validate + - cdi-api-datavolume-validate + - cdi-api-validate + - objecttransfer-api-validate + resources: + - validatingwebhookconfigurations + verbs: + - get + - update + - delete + - apiGroups: + - admissionregistration.k8s.io + resourceNames: + - cdi-api-datavolume-mutate + - cdi-api-pvc-mutate + resources: + - mutatingwebhookconfigurations + verbs: + - get + - update + - delete + - apiGroups: + - apiregistration.k8s.io + resources: + - apiservices + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + verbs: + - get + - list + - watch + - apiGroups: + - cdi.kubevirt.io + resources: + - datavolumes + verbs: + - list + - get + - apiGroups: + - cdi.kubevirt.io + resources: + - datasources + verbs: + - get + - apiGroups: + - cdi.kubevirt.io + resources: + - volumeclonesources + verbs: + - get + - list + - watch + - apiGroups: + - cdi.kubevirt.io + resources: + - storageprofiles + verbs: + - get + - list + - watch + - apiGroups: + - cdi.kubevirt.io + resources: + - cdis + verbs: + - get + - list + - watch + - apiGroups: + - cdi.kubevirt.io + resources: + - cdiconfigs + verbs: + - get + - list + - watch + - apiGroups: + - cdi.kubevirt.io + resources: + - cdis/finalizers + verbs: + - update + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get + - list + - watch + - create + - update + - delete + - deletecollection + - patch + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch + - update + - apiGroups: + - "" + resources: + - persistentvolumeclaims/finalizers + - pods/finalizers + verbs: + - update + - apiGroups: + - "" + resources: + - pods + - services + verbs: + - get + - list + - watch + - create + - delete + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - create + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + - csidrivers + verbs: + - get + - list + - watch + - apiGroups: + - config.openshift.io + resources: + - proxies + - infrastructures + verbs: + - get + - list + - watch + - apiGroups: + - config.openshift.io + resources: + - clusterversions + verbs: + - get + - apiGroups: + - cdi.kubevirt.io + resources: + - '*' + verbs: + - '*' + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + - volumesnapshotclasses + - volumesnapshotcontents + verbs: + - get + - list + - watch + - create + - delete + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + verbs: + - update + - deletecollection + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list + - watch + - apiGroups: + - scheduling.k8s.io + resources: + - priorityclasses + verbs: + - get + - list + - watch + - apiGroups: + - image.openshift.io + resources: + - imagestreams + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - secrets + verbs: + - create + - apiGroups: + - kubevirt.io + resources: + - virtualmachines/finalizers + verbs: + - update + - apiGroups: + - forklift.cdi.kubevirt.io + resources: + - ovirtvolumepopulators + - openstackvolumepopulators + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get + - apiGroups: + - cdi.kubevirt.io + resources: + - dataimportcrons + verbs: + - get + - list + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + operator.cdi.kubevirt.io: "" + name: cdi-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cdi-operator-cluster +subjects: + - kind: ServiceAccount + name: cdi-operator + namespace: {{ .Release.Namespace }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + operator.cdi.kubevirt.io: "" + name: cdi-operator + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app: containerized-data-importer + app.kubernetes.io/component: storage + app.kubernetes.io/managed-by: cdi-operator + cdi.kubevirt.io: "" + name: cdi-operator + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: + - rbac.authorization.k8s.io + resources: + - rolebindings + - roles + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - "" + resources: + - serviceaccounts + - configmaps + - events + - secrets + - services + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - apps + resources: + - deployments + - deployments/finalizers + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - route.openshift.io + resources: + - routes + - routes/custom-host + verbs: + - get + - list + - watch + - create + - update + - apiGroups: + - config.openshift.io + resources: + - proxies + verbs: + - get + - list + - watch + - apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + - prometheusrules + verbs: + - get + - list + - watch + - create + - delete + - update + - patch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - create + - update + - apiGroups: + - "" + resources: + - secrets + - configmaps + verbs: + - get + - list + - watch + - create + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch + - apiGroups: + - batch + resources: + - cronjobs + verbs: + - get + - list + - watch + - create + - update + - deletecollection + - apiGroups: + - batch + resources: + - jobs + verbs: + - create + - deletecollection + - list + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - create + - update + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - route.openshift.io + resources: + - routes + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - apiGroups: + - "" + resources: + - services + - endpoints + - pods + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app: containerized-data-importer + app.kubernetes.io/component: storage + app.kubernetes.io/managed-by: cdi-operator + cdi.kubevirt.io: "" + name: cdi-operator + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: cdi-operator +subjects: + - kind: ServiceAccount + name: cdi-operator + namespace: {{ .Release.Namespace }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + cdi.kubevirt.io: cdi-operator + name: cdi-operator + operator.cdi.kubevirt.io: "" + prometheus.cdi.kubevirt.io: "true" + name: cdi-operator + namespace: {{ .Release.Namespace }} +spec: + replicas: 1 + selector: + matchLabels: + name: cdi-operator + operator.cdi.kubevirt.io: "" + strategy: {} + template: + metadata: + labels: + cdi.kubevirt.io: cdi-operator + name: cdi-operator + operator.cdi.kubevirt.io: "" + prometheus.cdi.kubevirt.io: "true" + spec: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchExpressions: + - key: cdi.kubevirt.io + operator: In + values: + - cdi-operator + topologyKey: kubernetes.io/hostname + weight: 1 + containers: + - env: + - name: DEPLOY_CLUSTER_RESOURCES + value: "true" + - name: OPERATOR_VERSION + value: {{ .Values.deployment.version }} + - name: CONTROLLER_IMAGE + value: {{ .Values.deployment.controllerImage }}:{{ .Values.deployment.version }} + - name: IMPORTER_IMAGE + value: {{ .Values.deployment.importerImage }}:{{ .Values.deployment.version }} + - name: CLONER_IMAGE + value: {{ .Values.deployment.clonerImage }}:{{ .Values.deployment.version }} + - name: OVIRT_POPULATOR_IMAGE + value: {{ .Values.deployment.importerImage }}:{{ .Values.deployment.version }} + - name: APISERVER_IMAGE + value: {{ .Values.deployment.apiserverImage }}:{{ .Values.deployment.version }} + - name: UPLOAD_SERVER_IMAGE + value: {{ .Values.deployment.uploadserverImage }}:{{ .Values.deployment.version }} + - name: UPLOAD_PROXY_IMAGE + value: {{ .Values.deployment.uploadproxyImage }}:{{ .Values.deployment.version }} + - name: VERBOSITY + value: "1" + - name: PULL_POLICY + value: {{ .Values.deployment.pullPolicy }} + - name: MONITORING_NAMESPACE + image: {{ .Values.deployment.operatorImage }}:{{ .Values.deployment.version }} + imagePullPolicy: {{ .Values.deployment.pullPolicy }} + name: cdi-operator + ports: + - containerPort: 8080 + name: metrics + protocol: TCP + resources: + requests: + cpu: 100m + memory: 150Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + nodeSelector: + kubernetes.io/os: linux + securityContext: + runAsNonRoot: true + serviceAccountName: cdi-operator + tolerations: + - key: CriticalAddonsOnly + operator: Exists diff --git a/cdi-chart/templates/cdi-uninstall-hooks.yaml b/cdi-chart/templates/cdi-uninstall-hooks.yaml new file mode 100644 index 0000000..d737539 --- /dev/null +++ b/cdi-chart/templates/cdi-uninstall-hooks.yaml @@ -0,0 +1,69 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crUninstallHook.name" . }} + {{ template "cdi.crUninstallHook.annotations" (dict "hookWeight" 1) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cdi.crUninstallHook.name" . }} + {{ template "cdi.crUninstallHook.annotations" (dict "hookWeight" 1) }} +rules: + - apiGroups: [ "cdi.kubevirt.io" ] + resources: [ "cdis" ] + resourceNames: + - "cdi" + verbs: [ "delete" ] + - apiGroups: [ "apps" ] + resources: [ "deployments" ] + verbs: [ "get", "list" ] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cdi.crUninstallHook.name" . }} + {{ template "cdi.crUninstallHook.annotations" (dict "hookWeight" 2) }} +subjects: + - kind: ServiceAccount + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crUninstallHook.name" . }} +roleRef: + kind: ClusterRole + name: {{ template "cdi.crUninstallHook.name" . }} + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: batch/v1 +kind: Job +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crUninstallHook.name" . }} + {{ template "cdi.crUninstallHook.annotations" (dict "hookWeight" 3) }} +spec: + template: + metadata: + name: {{ template "cdi.crUninstallHook.name" . }} + spec: + serviceAccountName: {{ template "cdi.crUninstallHook.name" . }} + restartPolicy: {{ .Values.hookRestartPolicy }} + containers: + - name: {{ template "cdi.crUninstallHook.name" . }} + image: {{ .Values.hookImage }} + securityContext: + {{- toYaml .Values.hookSecurityContext | nindent 12 }} + args: + - delete + - cdi + - cdi + - name: {{ template "cdi.crUninstallHook.name" . }}-cleanup + image: {{ .Values.hookImage }} + securityContext: + {{- toYaml .Values.hookSecurityContext | nindent 12 }} + args: + - wait + - --for=delete + - deployments/cdi-apiserver + - deployments/cdi-deployment + - deployments/cdi-uploadproxy + - --timeout=60s diff --git a/cdi-chart/templates/cdi.yaml b/cdi-chart/templates/cdi.yaml new file mode 100644 index 0000000..b3e476d --- /dev/null +++ b/cdi-chart/templates/cdi.yaml @@ -0,0 +1,21 @@ +apiVersion: cdi.kubevirt.io/v1beta1 +kind: CDI +metadata: + name: cdi +spec: + {{- with .Values.cdi.config }} + config: + {{- toYaml . | nindent 4 }} + {{- end }} + imagePullPolicy: {{ .Values.cdi.imagePullPolicy }} + {{- with .Values.cdi.infra }} + infra: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.cdi.uninstallStrategy }} + uninstallStrategy: {{ .Values.cdi.uninstallStrategy }} + {{- end }} + {{- with .Values.cdi.workload }} + workload: + {{- toYaml . | nindent 4 }} + {{- end }} diff --git a/cdi-chart/templates/crd-uninstall-hooks.yaml b/cdi-chart/templates/crd-uninstall-hooks.yaml new file mode 100644 index 0000000..19bdaf2 --- /dev/null +++ b/cdi-chart/templates/crd-uninstall-hooks.yaml @@ -0,0 +1,55 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crdUninstallHook.name" . }} + {{ template "cdi.crdUninstallHook.annotations" (dict "hookWeight" 1) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cdi.crdUninstallHook.name" . }} + {{ template "cdi.crdUninstallHook.annotations" (dict "hookWeight" 1) }} +rules: + - apiGroups: [ "apiextensions.k8s.io" ] + resources: [ "customresourcedefinitions" ] + resourceNames: + - "cdis.cdi.kubevirt.io" + verbs: [ "delete" ] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cdi.crdUninstallHook.name" . }} + {{ template "cdi.crdUninstallHook.annotations" (dict "hookWeight" 2) }} +subjects: + - kind: ServiceAccount + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crdUninstallHook.name" . }} +roleRef: + kind: ClusterRole + name: {{ template "cdi.crdUninstallHook.name" . }} + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: batch/v1 +kind: Job +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crdUninstallHook.name" . }} + {{ template "cdi.crdUninstallHook.annotations" (dict "hookWeight" 3) }} +spec: + template: + metadata: + name: {{ template "cdi.crdUninstallHook.name" . }} + spec: + serviceAccountName: {{ template "cdi.crdUninstallHook.name" . }} + restartPolicy: {{ .Values.hookRestartPolicy }} + containers: + - name: {{ template "cdi.crdUninstallHook.name" . }} + image: {{ .Values.hookImage }} + args: + - delete + - customresourcedefinitions + - cdis.cdi.kubevirt.io + securityContext: + {{- toYaml .Values.hookSecurityContext | nindent 12 }} diff --git a/cdi-chart/templates/crd-upgrade-hooks.yaml b/cdi-chart/templates/crd-upgrade-hooks.yaml new file mode 100644 index 0000000..f650adc --- /dev/null +++ b/cdi-chart/templates/crd-upgrade-hooks.yaml @@ -0,0 +1,80 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Release.Namespace }} + name: cdi-crd-manifest + {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 1) }} +data: + crd: |- + {{ $.Files.Get "crds/cdi.yaml" | nindent 4 }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crdUpgradeHook.name" . }} + {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 2) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cdi.crdUpgradeHook.name" . }} + {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 2) }} +rules: + - apiGroups: [ "" ] + resources: [ "configmaps" ] + resourceNames: + - "cdi-crd-manifest" + verbs: [ "get" ] + - apiGroups: [ "apiextensions.k8s.io" ] + resources: [ "customresourcedefinitions" ] + resourceNames: + - "cdis.cdi.kubevirt.io" + verbs: [ "get", "patch" ] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cdi.crdUpgradeHook.name" . }} + {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 3) }} +subjects: + - kind: ServiceAccount + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crdUpgradeHook.name" . }} +roleRef: + kind: ClusterRole + name: {{ template "cdi.crdUpgradeHook.name" . }} + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: batch/v1 +kind: Job +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crdUpgradeHook.name" . }} + {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 4) }} +spec: + template: + metadata: + name: {{ template "cdi.crdUpgradeHook.name" . }} + spec: + serviceAccountName: {{ template "cdi.crdUpgradeHook.name" . }} + restartPolicy: {{ .Values.hookRestartPolicy }} + containers: + - name: {{ template "cdi.crdUpgradeHook.name" . }} + image: {{ .Values.hookImage }} + args: + - apply + - -f + - /etc/manifests/crd.yaml + securityContext: + {{- toYaml .Values.hookSecurityContext | nindent 12 }} + volumeMounts: + - name: crd-volume + mountPath: /etc/manifests + volumes: + - name: crd-volume + configMap: + name: cdi-crd-manifest + items: + - key: crd + path: crd.yaml diff --git a/cdi-chart/templates/namespace-hooks.yaml b/cdi-chart/templates/namespace-hooks.yaml new file mode 100644 index 0000000..30d16a4 --- /dev/null +++ b/cdi-chart/templates/namespace-hooks.yaml @@ -0,0 +1,56 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.namespaceHook.name" . }} + {{ template "cdi.namespaceHook.annotations" (dict "hookWeight" 1) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cdi.namespaceHook.name" . }} + {{ template "cdi.namespaceHook.annotations" (dict "hookWeight" 1) }} +rules: + - apiGroups: [ "" ] + resources: [ "namespaces" ] + resourceNames: + - {{ .Release.Namespace | quote }} + verbs: [ "get", "patch" ] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cdi.namespaceHook.name" . }} + {{ template "cdi.namespaceHook.annotations" (dict "hookWeight" 2) }} +subjects: + - kind: ServiceAccount + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.namespaceHook.name" . }} +roleRef: + kind: ClusterRole + name: {{ template "cdi.namespaceHook.name" . }} + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: batch/v1 +kind: Job +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.namespaceHook.name" . }} + {{ template "cdi.namespaceHook.annotations" (dict "hookWeight" 3) }} +spec: + template: + metadata: + name: {{ template "cdi.namespaceHook.name" . }} + spec: + serviceAccountName: {{ template "cdi.namespaceHook.name" . }} + restartPolicy: {{ .Values.hookRestartPolicy }} + containers: + - name: {{ template "cdi.namespaceHook.name" . }} + securityContext: + {{- toYaml .Values.hookSecurityContext | nindent 12 }} + image: {{ .Values.hookImage }} + args: + - label + - namespace + - {{ .Release.Namespace }} + - cdi.kubevirt.io= diff --git a/metal3-chart/charts.obscpio b/metal3-chart/charts.obscpio deleted file mode 100644 index c3b1f6c9ef7d814628bd678502988a1b9d3df4afd6c3e3159ea1c080d6efc21e..0000000000000000000000000000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 189440 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

VK^b~Y%!{woY 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 TXIp!J_`@GSlAnJ*F$VrWaeM*~ diff --git a/metal3-chart/charts/baremetal-operator/.helmignore b/metal3-chart/charts/baremetal-operator/.helmignore new file mode 100644 index 0000000..1b9a9cc --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/metal3-chart/charts/baremetal-operator/Chart.yaml b/metal3-chart/charts/baremetal-operator/Chart.yaml new file mode 100644 index 0000000..1900441 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 0.6.1 +description: A Helm chart for baremetal-operator, used by Metal3 +name: baremetal-operator +type: application +version: 0.5.0 diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-baremetalhosts.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-baremetalhosts.yaml new file mode 100644 index 0000000..6406700 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-baremetalhosts.yaml @@ -0,0 +1,1148 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: baremetal-operator-system/baremetal-operator-serving-cert + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + clusterctl.cluster.x-k8s.io: "" + name: baremetalhosts.metal3.io +spec: + group: metal3.io + names: + kind: BareMetalHost + listKind: BareMetalHostList + plural: baremetalhosts + shortNames: + - bmh + - bmhost + singular: baremetalhost + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Operational status + jsonPath: .status.operationalStatus + name: Status + priority: 1 + type: string + - description: Provisioning status + jsonPath: .status.provisioning.state + name: State + type: string + - description: Consumer using this host + jsonPath: .spec.consumerRef.name + name: Consumer + type: string + - description: Address of management controller + jsonPath: .spec.bmc.address + name: BMC + priority: 1 + type: string + - description: The type of hardware detected + jsonPath: .status.hardwareProfile + name: Hardware_Profile + priority: 1 + type: string + - description: Whether the host is online or not + jsonPath: .spec.online + name: Online + type: string + - description: Type of the most recent error + jsonPath: .status.errorType + name: Error + type: string + - description: Time duration since creation of BaremetalHost + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: BareMetalHost is the Schema for the baremetalhosts API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: BareMetalHostSpec defines the desired state of BareMetalHost. + properties: + architecture: + description: CPU architecture of the host, e.g. "x86_64" or "aarch64". + If unset, eventually populated by inspection. + type: string + automatedCleaningMode: + default: metadata + description: When set to disabled, automated cleaning will be avoided + during provisioning and deprovisioning. + enum: + - metadata + - disabled + type: string + bmc: + description: How do we connect to the BMC? + properties: + address: + description: Address holds the URL for accessing the controller + on the network. + type: string + credentialsName: + description: The name of the secret containing the BMC credentials + (requires keys "username" and "password"). + type: string + disableCertificateVerification: + description: DisableCertificateVerification disables verification + of server certificates when using HTTPS to connect to the BMC. + This is required when the server certificate is self-signed, + but is insecure because it allows a man-in-the-middle to intercept + the connection. + type: boolean + required: + - address + - credentialsName + type: object + bootMACAddress: + description: Which MAC address will PXE boot? This is optional for + some types, but required for libvirt VMs driven by vbmc. + pattern: '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}' + type: string + bootMode: + description: Select the method of initializing the hardware during + boot. Defaults to UEFI. + enum: + - UEFI + - UEFISecureBoot + - legacy + type: string + consumerRef: + description: ConsumerRef can be used to store information about something + that is using a host. When it is not empty, the host is considered + "in use". + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + type: object + x-kubernetes-map-type: atomic + customDeploy: + description: A custom deploy procedure. + properties: + method: + description: Custom deploy method name. This name is specific + to the deploy ramdisk used. If you don't have a custom deploy + ramdisk, you shouldn't use CustomDeploy. + type: string + required: + - method + type: object + description: + description: Description is a human-entered text used to help identify + the host + type: string + externallyProvisioned: + description: ExternallyProvisioned means something else is managing + the image running on the host and the operator should only manage + the power status and hardware inventory inspection. If the Image + field is filled in, this field is ignored. + type: boolean + firmware: + description: BIOS configuration for bare metal server + properties: + simultaneousMultithreadingEnabled: + description: 'Allows a single physical processor core to appear + as several logical processors. This supports following options: + true, false.' + enum: + - true + - false + type: boolean + sriovEnabled: + description: 'SR-IOV support enables a hypervisor to create virtual + instances of a PCI-express device, potentially increasing performance. + This supports following options: true, false.' + enum: + - true + - false + type: boolean + virtualizationEnabled: + description: 'Supports the virtualization of platform hardware. + This supports following options: true, false.' + enum: + - true + - false + type: boolean + type: object + hardwareProfile: + description: What is the name of the hardware profile for this host? + Hardware profiles are deprecated and should not be used. Use the + separate fields Architecture and RootDeviceHints instead. Set to + "empty" to prepare for the future version of the API without hardware + profiles. + type: string + image: + description: Image holds the details of the image to be provisioned. + properties: + checksum: + description: Checksum is the checksum for the image. + type: string + checksumType: + description: ChecksumType is the checksum algorithm for the image, + e.g md5, sha256 or sha512. The special value "auto" can be used + to detect the algorithm from the checksum. If missing, MD5 is + used. If in doubt, use "auto". + enum: + - md5 + - sha256 + - sha512 + - auto + type: string + format: + description: DiskFormat contains the format of the image (raw, + qcow2, ...). Needs to be set to raw for raw images streaming. + Note live-iso means an iso referenced by the url will be live-booted + and not deployed to disk, and in this case the checksum options + are not required and if specified will be ignored. + enum: + - raw + - qcow2 + - vdi + - vmdk + - live-iso + type: string + url: + description: URL is a location of an image to deploy. + type: string + required: + - url + type: object + metaData: + description: MetaData holds the reference to the Secret containing + host metadata (e.g. meta_data.json) which is passed to the Config + Drive. + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + networkData: + description: NetworkData holds the reference to the Secret containing + network configuration (e.g content of network_data.json) which is + passed to the Config Drive. + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + online: + description: Should the server be online? + type: boolean + preprovisioningNetworkDataName: + description: PreprovisioningNetworkDataName is the name of the Secret + in the local namespace containing network configuration (e.g content + of network_data.json) which is passed to the preprovisioning image, + and to the Config Drive if not overridden by specifying NetworkData. + type: string + raid: + description: RAID configuration for bare metal server + properties: + hardwareRAIDVolumes: + description: The list of logical disks for hardware RAID, if rootDeviceHints + isn't used, first volume is root volume. You can set the value + of this field to `[]` to clear all the hardware RAID configurations. + items: + description: HardwareRAIDVolume defines the desired configuration + of volume in hardware RAID. + properties: + controller: + description: The name of the RAID controller to use + type: string + level: + description: 'RAID level for the logical disk. The following + levels are supported: 0;1;2;5;6;1+0;5+0;6+0.' + enum: + - "0" + - "1" + - "2" + - "5" + - "6" + - 1+0 + - 5+0 + - 6+0 + type: string + name: + description: Name of the volume. Should be unique within + the Node. If not specified, volume name will be auto-generated. + maxLength: 64 + type: string + numberOfPhysicalDisks: + description: Integer, number of physical disks to use for + the logical disk. Defaults to minimum number of disks + required for the particular RAID level. + minimum: 1 + type: integer + physicalDisks: + description: Optional list of physical disk names to be + used for the Hardware RAID volumes. The disk names are + interpreted by the Hardware RAID controller, and the format + is hardware specific. + items: + type: string + type: array + rotational: + description: Select disks with only rotational or solid-state + storage + type: boolean + sizeGibibytes: + description: Size (Integer) of the logical disk to be created + in GiB. If unspecified or set be 0, the maximum capacity + of disk will be used for logical disk. + minimum: 0 + type: integer + required: + - level + type: object + nullable: true + type: array + softwareRAIDVolumes: + description: The list of logical disks for software RAID, if rootDeviceHints + isn't used, first volume is root volume. If HardwareRAIDVolumes + is set this item will be invalid. The number of created Software + RAID devices must be 1 or 2. If there is only one Software RAID + device, it has to be a RAID-1. If there are two, the first one + has to be a RAID-1, while the RAID level for the second one + can be 0, 1, or 1+0. As the first RAID device will be the deployment + device, enforcing a RAID-1 reduces the risk of ending up with + a non-booting node in case of a disk failure. Software RAID + will always be deleted. + items: + description: SoftwareRAIDVolume defines the desired configuration + of volume in software RAID. + properties: + level: + description: 'RAID level for the logical disk. The following + levels are supported: 0;1;1+0.' + enum: + - "0" + - "1" + - 1+0 + type: string + physicalDisks: + description: A list of device hints, the number of items + should be greater than or equal to 2. + items: + description: RootDeviceHints holds the hints for specifying + the storage location for the root filesystem for the + image. + properties: + deviceName: + description: A Linux device name like "/dev/vda", + or a by-path link to it like "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0". + The hint must match the actual value exactly. + type: string + hctl: + description: A SCSI bus address like 0:0:0:0. The + hint must match the actual value exactly. + type: string + minSizeGigabytes: + description: The minimum size of the device in Gigabytes. + minimum: 0 + type: integer + model: + description: A vendor-specific device identifier. + The hint can be a substring of the actual value. + type: string + rotational: + description: True if the device should use spinning + media, false otherwise. + type: boolean + serialNumber: + description: Device serial number. The hint must match + the actual value exactly. + type: string + vendor: + description: The name of the vendor or manufacturer + of the device. The hint can be a substring of the + actual value. + type: string + wwn: + description: Unique storage identifier. The hint must + match the actual value exactly. + type: string + wwnVendorExtension: + description: Unique vendor storage identifier. The + hint must match the actual value exactly. + type: string + wwnWithExtension: + description: Unique storage identifier with the vendor + extension appended. The hint must match the actual + value exactly. + type: string + type: object + minItems: 2 + type: array + sizeGibibytes: + description: Size (Integer) of the logical disk to be created + in GiB. If unspecified or set be 0, the maximum capacity + of disk will be used for logical disk. + minimum: 0 + type: integer + required: + - level + type: object + maxItems: 2 + nullable: true + type: array + type: object + rootDeviceHints: + description: Provide guidance about how to choose the device for the + image being provisioned. + properties: + deviceName: + description: A Linux device name like "/dev/vda", or a by-path + link to it like "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0". + The hint must match the actual value exactly. + type: string + hctl: + description: A SCSI bus address like 0:0:0:0. The hint must match + the actual value exactly. + type: string + minSizeGigabytes: + description: The minimum size of the device in Gigabytes. + minimum: 0 + type: integer + model: + description: A vendor-specific device identifier. The hint can + be a substring of the actual value. + type: string + rotational: + description: True if the device should use spinning media, false + otherwise. + type: boolean + serialNumber: + description: Device serial number. The hint must match the actual + value exactly. + type: string + vendor: + description: The name of the vendor or manufacturer of the device. + The hint can be a substring of the actual value. + type: string + wwn: + description: Unique storage identifier. The hint must match the + actual value exactly. + type: string + wwnVendorExtension: + description: Unique vendor storage identifier. The hint must match + the actual value exactly. + type: string + wwnWithExtension: + description: Unique storage identifier with the vendor extension + appended. The hint must match the actual value exactly. + type: string + type: object + taints: + description: Taints is the full, authoritative list of taints to apply + to the corresponding Machine. This list will overwrite any modifications + made to the Machine on an ongoing basis. + items: + description: The node this Taint is attached to has the "effect" + on any pod that does not tolerate the Taint. + properties: + effect: + description: Required. The effect of the taint on pods that + do not tolerate the taint. Valid effects are NoSchedule, PreferNoSchedule + and NoExecute. + type: string + key: + description: Required. The taint key to be applied to a node. + type: string + timeAdded: + description: TimeAdded represents the time at which the taint + was added. It is only written for NoExecute taints. + format: date-time + type: string + value: + description: The taint value corresponding to the taint key. + type: string + required: + - effect + - key + type: object + type: array + userData: + description: UserData holds the reference to the Secret containing + the user data to be passed to the host before it boots. + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - online + type: object + status: + description: BareMetalHostStatus defines the observed state of BareMetalHost. + properties: + errorCount: + default: 0 + description: ErrorCount records how many times the host has encoutered + an error since the last successful operation + type: integer + errorMessage: + description: the last error message reported by the provisioning subsystem + type: string + errorType: + description: ErrorType indicates the type of failure encountered when + the OperationalStatus is OperationalStatusError + enum: + - provisioned registration error + - registration error + - inspection error + - preparation error + - provisioning error + - power management error + type: string + goodCredentials: + description: the last credentials we were able to validate as working + properties: + credentials: + description: SecretReference represents a Secret Reference. It + has enough information to retrieve secret in any namespace + properties: + name: + description: name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: namespace defines the space within which the + secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + credentialsVersion: + type: string + type: object + hardware: + description: The hardware discovered to exist on the host. + properties: + cpu: + description: CPU describes one processor on the host. + properties: + arch: + type: string + clockMegahertz: + description: ClockSpeed is a clock speed in MHz + format: double + type: number + count: + type: integer + flags: + items: + type: string + type: array + model: + type: string + type: object + firmware: + description: Firmware describes the firmware on the host. + properties: + bios: + description: The BIOS for this firmware + properties: + date: + description: The release/build date for this BIOS + type: string + vendor: + description: The vendor name for this BIOS + type: string + version: + description: The version of the BIOS + type: string + type: object + type: object + hostname: + type: string + nics: + items: + description: NIC describes one network interface on the host. + properties: + ip: + description: The IP address of the interface. This will + be an IPv4 or IPv6 address if one is present. If both + IPv4 and IPv6 addresses are present in a dual-stack environment, + two nics will be output, one with each IP. + type: string + mac: + description: The device MAC address + pattern: '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}' + type: string + model: + description: The vendor and product IDs of the NIC, e.g. + "0x8086 0x1572" + type: string + name: + description: The name of the network interface, e.g. "en0" + type: string + pxe: + description: Whether the NIC is PXE Bootable + type: boolean + speedGbps: + description: The speed of the device in Gigabits per second + type: integer + vlanId: + description: The untagged VLAN ID + format: int32 + maximum: 4094 + minimum: 0 + type: integer + vlans: + description: The VLANs available + items: + description: VLAN represents the name and ID of a VLAN. + properties: + id: + description: VLANID is a 12-bit 802.1Q VLAN identifier + format: int32 + maximum: 4094 + minimum: 0 + type: integer + name: + type: string + type: object + type: array + type: object + type: array + ramMebibytes: + type: integer + storage: + items: + description: Storage describes one storage device (disk, SSD, + etc.) on the host. + properties: + alternateNames: + description: A list of alternate Linux device names of the + disk, e.g. "/dev/sda". Note that this list is not exhaustive, + and names may not be stable across reboots. + items: + type: string + type: array + hctl: + description: The SCSI location of the device + type: string + model: + description: Hardware model + type: string + name: + description: A Linux device name of the disk, e.g. "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0". + This will be a name that is stable across reboots if one + is available. + type: string + rotational: + description: Whether this disk represents rotational storage. + This field is not recommended for usage, please prefer + using 'Type' field instead, this field will be deprecated + eventually. + type: boolean + serialNumber: + description: The serial number of the device + type: string + sizeBytes: + description: The size of the disk in Bytes + format: int64 + type: integer + type: + description: 'Device type, one of: HDD, SSD, NVME.' + enum: + - HDD + - SSD + - NVME + type: string + vendor: + description: The name of the vendor of the device + type: string + wwn: + description: The WWN of the device + type: string + wwnVendorExtension: + description: The WWN Vendor extension of the device + type: string + wwnWithExtension: + description: The WWN with the extension + type: string + type: object + type: array + systemVendor: + description: HardwareSystemVendor stores details about the whole + hardware system. + properties: + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + type: object + type: object + hardwareProfile: + description: The name of the profile matching the hardware details. + type: string + lastUpdated: + description: LastUpdated identifies when this status was last observed. + format: date-time + type: string + operationHistory: + description: OperationHistory holds information about operations performed + on this host. + properties: + deprovision: + description: OperationMetric contains metadata about an operation + (inspection, provisioning, etc.) used for tracking metrics. + properties: + end: + format: date-time + nullable: true + type: string + start: + format: date-time + nullable: true + type: string + type: object + inspect: + description: OperationMetric contains metadata about an operation + (inspection, provisioning, etc.) used for tracking metrics. + properties: + end: + format: date-time + nullable: true + type: string + start: + format: date-time + nullable: true + type: string + type: object + provision: + description: OperationMetric contains metadata about an operation + (inspection, provisioning, etc.) used for tracking metrics. + properties: + end: + format: date-time + nullable: true + type: string + start: + format: date-time + nullable: true + type: string + type: object + register: + description: OperationMetric contains metadata about an operation + (inspection, provisioning, etc.) used for tracking metrics. + properties: + end: + format: date-time + nullable: true + type: string + start: + format: date-time + nullable: true + type: string + type: object + type: object + operationalStatus: + description: OperationalStatus holds the status of the host + enum: + - "" + - OK + - discovered + - error + - delayed + - detached + type: string + poweredOn: + description: indicator for whether or not the host is powered on + type: boolean + provisioning: + description: Information tracked by the provisioner. + properties: + ID: + description: The machine's UUID from the underlying provisioning + tool + type: string + bootMode: + description: BootMode indicates the boot mode used to provision + the node + enum: + - UEFI + - UEFISecureBoot + - legacy + type: string + customDeploy: + description: Custom deploy procedure applied to the host. + properties: + method: + description: Custom deploy method name. This name is specific + to the deploy ramdisk used. If you don't have a custom deploy + ramdisk, you shouldn't use CustomDeploy. + type: string + required: + - method + type: object + firmware: + description: The Bios set by the user + properties: + simultaneousMultithreadingEnabled: + description: 'Allows a single physical processor core to appear + as several logical processors. This supports following options: + true, false.' + enum: + - true + - false + type: boolean + sriovEnabled: + description: 'SR-IOV support enables a hypervisor to create + virtual instances of a PCI-express device, potentially increasing + performance. This supports following options: true, false.' + enum: + - true + - false + type: boolean + virtualizationEnabled: + description: 'Supports the virtualization of platform hardware. + This supports following options: true, false.' + enum: + - true + - false + type: boolean + type: object + image: + description: Image holds the details of the last image successfully + provisioned to the host. + properties: + checksum: + description: Checksum is the checksum for the image. + type: string + checksumType: + description: ChecksumType is the checksum algorithm for the + image, e.g md5, sha256 or sha512. The special value "auto" + can be used to detect the algorithm from the checksum. If + missing, MD5 is used. If in doubt, use "auto". + enum: + - md5 + - sha256 + - sha512 + - auto + type: string + format: + description: DiskFormat contains the format of the image (raw, + qcow2, ...). Needs to be set to raw for raw images streaming. + Note live-iso means an iso referenced by the url will be + live-booted and not deployed to disk, and in this case the + checksum options are not required and if specified will + be ignored. + enum: + - raw + - qcow2 + - vdi + - vmdk + - live-iso + type: string + url: + description: URL is a location of an image to deploy. + type: string + required: + - url + type: object + raid: + description: The Raid set by the user + properties: + hardwareRAIDVolumes: + description: The list of logical disks for hardware RAID, + if rootDeviceHints isn't used, first volume is root volume. + You can set the value of this field to `[]` to clear all + the hardware RAID configurations. + items: + description: HardwareRAIDVolume defines the desired configuration + of volume in hardware RAID. + properties: + controller: + description: The name of the RAID controller to use + type: string + level: + description: 'RAID level for the logical disk. The following + levels are supported: 0;1;2;5;6;1+0;5+0;6+0.' + enum: + - "0" + - "1" + - "2" + - "5" + - "6" + - 1+0 + - 5+0 + - 6+0 + type: string + name: + description: Name of the volume. Should be unique within + the Node. If not specified, volume name will be auto-generated. + maxLength: 64 + type: string + numberOfPhysicalDisks: + description: Integer, number of physical disks to use + for the logical disk. Defaults to minimum number of + disks required for the particular RAID level. + minimum: 1 + type: integer + physicalDisks: + description: Optional list of physical disk names to + be used for the Hardware RAID volumes. The disk names + are interpreted by the Hardware RAID controller, and + the format is hardware specific. + items: + type: string + type: array + rotational: + description: Select disks with only rotational or solid-state + storage + type: boolean + sizeGibibytes: + description: Size (Integer) of the logical disk to be + created in GiB. If unspecified or set be 0, the maximum + capacity of disk will be used for logical disk. + minimum: 0 + type: integer + required: + - level + type: object + nullable: true + type: array + softwareRAIDVolumes: + description: The list of logical disks for software RAID, + if rootDeviceHints isn't used, first volume is root volume. + If HardwareRAIDVolumes is set this item will be invalid. + The number of created Software RAID devices must be 1 or + 2. If there is only one Software RAID device, it has to + be a RAID-1. If there are two, the first one has to be a + RAID-1, while the RAID level for the second one can be 0, + 1, or 1+0. As the first RAID device will be the deployment + device, enforcing a RAID-1 reduces the risk of ending up + with a non-booting node in case of a disk failure. Software + RAID will always be deleted. + items: + description: SoftwareRAIDVolume defines the desired configuration + of volume in software RAID. + properties: + level: + description: 'RAID level for the logical disk. The following + levels are supported: 0;1;1+0.' + enum: + - "0" + - "1" + - 1+0 + type: string + physicalDisks: + description: A list of device hints, the number of items + should be greater than or equal to 2. + items: + description: RootDeviceHints holds the hints for specifying + the storage location for the root filesystem for + the image. + properties: + deviceName: + description: A Linux device name like "/dev/vda", + or a by-path link to it like "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0". + The hint must match the actual value exactly. + type: string + hctl: + description: A SCSI bus address like 0:0:0:0. + The hint must match the actual value exactly. + type: string + minSizeGigabytes: + description: The minimum size of the device in + Gigabytes. + minimum: 0 + type: integer + model: + description: A vendor-specific device identifier. + The hint can be a substring of the actual value. + type: string + rotational: + description: True if the device should use spinning + media, false otherwise. + type: boolean + serialNumber: + description: Device serial number. The hint must + match the actual value exactly. + type: string + vendor: + description: The name of the vendor or manufacturer + of the device. The hint can be a substring of + the actual value. + type: string + wwn: + description: Unique storage identifier. The hint + must match the actual value exactly. + type: string + wwnVendorExtension: + description: Unique vendor storage identifier. + The hint must match the actual value exactly. + type: string + wwnWithExtension: + description: Unique storage identifier with the + vendor extension appended. The hint must match + the actual value exactly. + type: string + type: object + minItems: 2 + type: array + sizeGibibytes: + description: Size (Integer) of the logical disk to be + created in GiB. If unspecified or set be 0, the maximum + capacity of disk will be used for logical disk. + minimum: 0 + type: integer + required: + - level + type: object + maxItems: 2 + nullable: true + type: array + type: object + rootDeviceHints: + description: The RootDevicehints set by the user + properties: + deviceName: + description: A Linux device name like "/dev/vda", or a by-path + link to it like "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0". + The hint must match the actual value exactly. + type: string + hctl: + description: A SCSI bus address like 0:0:0:0. The hint must + match the actual value exactly. + type: string + minSizeGigabytes: + description: The minimum size of the device in Gigabytes. + minimum: 0 + type: integer + model: + description: A vendor-specific device identifier. The hint + can be a substring of the actual value. + type: string + rotational: + description: True if the device should use spinning media, + false otherwise. + type: boolean + serialNumber: + description: Device serial number. The hint must match the + actual value exactly. + type: string + vendor: + description: The name of the vendor or manufacturer of the + device. The hint can be a substring of the actual value. + type: string + wwn: + description: Unique storage identifier. The hint must match + the actual value exactly. + type: string + wwnVendorExtension: + description: Unique vendor storage identifier. The hint must + match the actual value exactly. + type: string + wwnWithExtension: + description: Unique storage identifier with the vendor extension + appended. The hint must match the actual value exactly. + type: string + type: object + state: + description: An indiciator for what the provisioner is doing with + the host. + type: string + required: + - ID + - state + type: object + triedCredentials: + description: the last credentials we sent to the provisioning backend + properties: + credentials: + description: SecretReference represents a Secret Reference. It + has enough information to retrieve secret in any namespace + properties: + name: + description: name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: namespace defines the space within which the + secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + credentialsVersion: + type: string + type: object + required: + - errorCount + - errorMessage + - hardwareProfile + - operationalStatus + - poweredOn + - provisioning + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-bmceventsubscriptions.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-bmceventsubscriptions.yaml new file mode 100644 index 0000000..c0dc2bf --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-bmceventsubscriptions.yaml @@ -0,0 +1,85 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + clusterctl.cluster.x-k8s.io: "" + name: bmceventsubscriptions.metal3.io +spec: + group: metal3.io + names: + kind: BMCEventSubscription + listKind: BMCEventSubscriptionList + plural: bmceventsubscriptions + shortNames: + - bes + - bmcevent + singular: bmceventsubscription + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: The most recent error message + jsonPath: .status.error + name: Error + type: string + - description: Time duration since creation of BMCEventSubscription + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: BMCEventSubscription is the Schema for the fast eventing API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + context: + description: Arbitrary user-provided context for the event + type: string + destination: + description: A webhook URL to send events to + type: string + hostName: + description: A reference to a BareMetalHost + type: string + httpHeadersRef: + description: A secret containing HTTP headers which should be passed + along to the Destination when making a request + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + type: object + status: + properties: + error: + type: string + subscriptionID: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-dataimages.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-dataimages.yaml new file mode 100644 index 0000000..c1bb7b0 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-dataimages.yaml @@ -0,0 +1,75 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: dataimages.metal3.io +spec: + group: metal3.io + names: + kind: DataImage + listKind: DataImageList + plural: dataimages + singular: dataimage + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: DataImage is the Schema for the dataimages API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: DataImageSpec defines the desired state of DataImage. + properties: + url: + description: Url is the address of the dataImage that we want to attach + to a BareMetalHost + type: string + required: + - url + type: object + status: + description: DataImageStatus defines the observed state of DataImage. + properties: + attachedImage: + description: Currently attached DataImage + properties: + url: + type: string + required: + - url + type: object + error: + description: Error count and message when attaching/detaching + properties: + count: + type: integer + message: + type: string + required: + - count + - message + type: object + lastReconciled: + description: Time of last reconciliation + format: date-time + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-firmwareschemas.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-firmwareschemas.yaml new file mode 100644 index 0000000..3b3c4fe --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-firmwareschemas.yaml @@ -0,0 +1,90 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + clusterctl.cluster.x-k8s.io: "" + name: firmwareschemas.metal3.io +spec: + group: metal3.io + names: + kind: FirmwareSchema + listKind: FirmwareSchemaList + plural: firmwareschemas + singular: firmwareschema + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: FirmwareSchema is the Schema for the firmwareschemas API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: FirmwareSchemaSpec defines the desired state of FirmwareSchema. + properties: + hardwareModel: + description: The hardware model associated with this schema + type: string + hardwareVendor: + description: The hardware vendor associated with this schema + type: string + schema: + additionalProperties: + description: Additional data describing the firmware setting. + properties: + allowable_values: + description: The allowable value for an Enumeration type setting. + items: + type: string + type: array + attribute_type: + description: The type of setting. + enum: + - Enumeration + - String + - Integer + - Boolean + - Password + type: string + lower_bound: + description: The lowest value for an Integer type setting. + type: integer + max_length: + description: Maximum length for a String type setting. + type: integer + min_length: + description: Minimum length for a String type setting. + type: integer + read_only: + description: Whether or not this setting is read only. + type: boolean + unique: + description: Whether or not this setting's value is unique to + this node, e.g. a serial number. + type: boolean + upper_bound: + description: The highest value for an Integer type setting. + type: integer + type: object + description: Map of firmware name to schema + type: object + required: + - schema + type: object + type: object + served: true + storage: true diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-hardwaredata.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-hardwaredata.yaml new file mode 100644 index 0000000..7a39068 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-hardwaredata.yaml @@ -0,0 +1,211 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + clusterctl.cluster.x-k8s.io: "" + name: hardwaredata.metal3.io +spec: + group: metal3.io + names: + kind: HardwareData + listKind: HardwareDataList + plural: hardwaredata + shortNames: + - hd + singular: hardwaredata + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Time duration since creation of HardwareData + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: HardwareData is the Schema for the hardwaredata API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: HardwareDataSpec defines the desired state of HardwareData. + properties: + hardware: + description: The hardware discovered on the host during its inspection. + properties: + cpu: + description: CPU describes one processor on the host. + properties: + arch: + type: string + clockMegahertz: + description: ClockSpeed is a clock speed in MHz + format: double + type: number + count: + type: integer + flags: + items: + type: string + type: array + model: + type: string + type: object + firmware: + description: Firmware describes the firmware on the host. + properties: + bios: + description: The BIOS for this firmware + properties: + date: + description: The release/build date for this BIOS + type: string + vendor: + description: The vendor name for this BIOS + type: string + version: + description: The version of the BIOS + type: string + type: object + type: object + hostname: + type: string + nics: + items: + description: NIC describes one network interface on the host. + properties: + ip: + description: The IP address of the interface. This will + be an IPv4 or IPv6 address if one is present. If both + IPv4 and IPv6 addresses are present in a dual-stack environment, + two nics will be output, one with each IP. + type: string + mac: + description: The device MAC address + pattern: '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}' + type: string + model: + description: The vendor and product IDs of the NIC, e.g. + "0x8086 0x1572" + type: string + name: + description: The name of the network interface, e.g. "en0" + type: string + pxe: + description: Whether the NIC is PXE Bootable + type: boolean + speedGbps: + description: The speed of the device in Gigabits per second + type: integer + vlanId: + description: The untagged VLAN ID + format: int32 + maximum: 4094 + minimum: 0 + type: integer + vlans: + description: The VLANs available + items: + description: VLAN represents the name and ID of a VLAN. + properties: + id: + description: VLANID is a 12-bit 802.1Q VLAN identifier + format: int32 + maximum: 4094 + minimum: 0 + type: integer + name: + type: string + type: object + type: array + type: object + type: array + ramMebibytes: + type: integer + storage: + items: + description: Storage describes one storage device (disk, SSD, + etc.) on the host. + properties: + alternateNames: + description: A list of alternate Linux device names of the + disk, e.g. "/dev/sda". Note that this list is not exhaustive, + and names may not be stable across reboots. + items: + type: string + type: array + hctl: + description: The SCSI location of the device + type: string + model: + description: Hardware model + type: string + name: + description: A Linux device name of the disk, e.g. "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0". + This will be a name that is stable across reboots if one + is available. + type: string + rotational: + description: Whether this disk represents rotational storage. + This field is not recommended for usage, please prefer + using 'Type' field instead, this field will be deprecated + eventually. + type: boolean + serialNumber: + description: The serial number of the device + type: string + sizeBytes: + description: The size of the disk in Bytes + format: int64 + type: integer + type: + description: 'Device type, one of: HDD, SSD, NVME.' + enum: + - HDD + - SSD + - NVME + type: string + vendor: + description: The name of the vendor of the device + type: string + wwn: + description: The WWN of the device + type: string + wwnVendorExtension: + description: The WWN Vendor extension of the device + type: string + wwnWithExtension: + description: The WWN with the extension + type: string + type: object + type: array + systemVendor: + description: HardwareSystemVendor stores details about the whole + hardware system. + properties: + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + type: object + type: object + type: object + type: object + served: true + storage: true + subresources: {} diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwarecomponents.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwarecomponents.yaml new file mode 100644 index 0000000..2962d52 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwarecomponents.yaml @@ -0,0 +1,178 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: hostfirmwarecomponents.metal3.io +spec: + group: metal3.io + names: + kind: HostFirmwareComponents + listKind: HostFirmwareComponentsList + plural: hostfirmwarecomponents + singular: hostfirmwarecomponents + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: HostFirmwareComponents is the Schema for the hostfirmwarecomponents + API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: HostFirmwareComponentsSpec defines the desired state of HostFirmwareComponents. + properties: + updates: + items: + description: FirmwareUpdate defines a firmware update specification. + properties: + component: + type: string + url: + type: string + required: + - component + - url + type: object + type: array + required: + - updates + type: object + status: + description: HostFirmwareComponentsStatus defines the observed state of + HostFirmwareComponents. + properties: + components: + description: Components is the list of all available firmware components + and their information. + items: + description: FirmwareComponentStatus defines the status of a firmware + component. + properties: + component: + type: string + currentVersion: + type: string + initialVersion: + type: string + lastVersionFlashed: + type: string + updatedAt: + format: date-time + type: string + required: + - component + - initialVersion + type: object + type: array + conditions: + description: Track whether updates stored in the spec are valid based + on the schema + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + lastUpdated: + description: Time that the status was last updated + format: date-time + type: string + updates: + description: Updates is the list of all firmware components that should + be updated they are specified via name and url fields. + items: + description: FirmwareUpdate defines a firmware update specification. + properties: + component: + type: string + url: + type: string + required: + - component + - url + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwaresettings.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwaresettings.yaml new file mode 100644 index 0000000..62679cf --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwaresettings.yaml @@ -0,0 +1,164 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + clusterctl.cluster.x-k8s.io: "" + name: hostfirmwaresettings.metal3.io +spec: + group: metal3.io + names: + kind: HostFirmwareSettings + listKind: HostFirmwareSettingsList + plural: hostfirmwaresettings + shortNames: + - hfs + singular: hostfirmwaresettings + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: HostFirmwareSettings is the Schema for the hostfirmwaresettings + API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: HostFirmwareSettingsSpec defines the desired state of HostFirmwareSettings. + properties: + settings: + additionalProperties: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + description: Settings are the desired firmware settings stored as + name/value pairs. + type: object + required: + - settings + type: object + status: + description: HostFirmwareSettingsStatus defines the observed state of + HostFirmwareSettings. + properties: + conditions: + description: Track whether settings stored in the spec are valid based + on the schema + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + lastUpdated: + description: Time that the status was last updated + format: date-time + type: string + schema: + description: FirmwareSchema is a reference to the Schema used to describe + each FirmwareSetting. By default, this will be a Schema in the same + Namespace as the settings but it can be overwritten in the Spec + properties: + name: + description: '`name` is the reference to the schema.' + type: string + namespace: + description: '`namespace` is the namespace of the where the schema + is stored.' + type: string + required: + - name + - namespace + type: object + settings: + additionalProperties: + type: string + description: Settings are the firmware settings stored as name/value + pairs + type: object + required: + - settings + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-preprovisioningimages.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-preprovisioningimages.yaml new file mode 100644 index 0000000..f743a89 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-preprovisioningimages.yaml @@ -0,0 +1,183 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + clusterctl.cluster.x-k8s.io: "" + name: preprovisioningimages.metal3.io +spec: + group: metal3.io + names: + kind: PreprovisioningImage + listKind: PreprovisioningImageList + plural: preprovisioningimages + shortNames: + - ppimg + singular: preprovisioningimage + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Whether the image is ready + jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - description: The reason for the image readiness status + jsonPath: .status.conditions[?(@.type=='Ready')].reason + name: Reason + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: PreprovisioningImage is the Schema for the preprovisioningimages + API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: PreprovisioningImageSpec defines the desired state of PreprovisioningImage. + properties: + acceptFormats: + description: acceptFormats is a list of acceptable image formats. + items: + description: ImageFormat enumerates the allowed image formats + enum: + - iso + - initrd + type: string + type: array + architecture: + description: architecture is the processor architecture for which + to build the image. + type: string + networkDataName: + description: networkDataName is the name of a Secret in the local + namespace that contains network data to build in to the image. + type: string + type: object + status: + description: PreprovisioningImageStatus defines the observed state of + PreprovisioningImage. + properties: + architecture: + description: architecture is the processor architecture for which + the image is built + type: string + conditions: + description: conditions describe the state of the built image + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + extraKernelParams: + description: extraKernelParams is a string with extra parameters to + pass to the kernel when booting the image over network. Only makes + sense for initrd images. + type: string + format: + description: 'format is the type of image that is available at the + download url: either iso or initrd.' + enum: + - iso + - initrd + type: string + imageUrl: + description: imageUrl is the URL from which the built image can be + downloaded. + type: string + kernelUrl: + description: kernelUrl is the URL from which the kernel of the image + can be downloaded. Only makes sense for initrd images. + type: string + networkData: + description: networkData is a reference to the version of the Secret + containing the network data used to build the image. + properties: + name: + type: string + version: + type: string + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metal3-chart/charts/baremetal-operator/templates/NOTES.txt b/metal3-chart/charts/baremetal-operator/templates/NOTES.txt new file mode 100644 index 0000000..a46dc2b --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/NOTES.txt @@ -0,0 +1,16 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "baremetal-operator.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "baremetal-operator.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "baremetal-operator.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "baremetal-operator.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/metal3-chart/charts/baremetal-operator/templates/_helpers.tpl b/metal3-chart/charts/baremetal-operator/templates/_helpers.tpl new file mode 100644 index 0000000..08dc581 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "baremetal-operator.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "baremetal-operator.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "baremetal-operator.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "baremetal-operator.labels" -}} +helm.sh/chart: {{ include "baremetal-operator.chart" . }} +{{ include "baremetal-operator.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "baremetal-operator.selectorLabels" -}} +app.kubernetes.io/component: baremetal-operator +app.kubernetes.io/name: {{ include "baremetal-operator.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "baremetal-operator.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "baremetal-operator.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/metal3-chart/charts/baremetal-operator/templates/certificate.yaml b/metal3-chart/charts/baremetal-operator/templates/certificate.yaml new file mode 100644 index 0000000..ad0fd88 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/certificate.yaml @@ -0,0 +1,14 @@ +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "baremetal-operator.fullname" . }}-serving-cert + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +spec: + dnsNames: + - baremetal-operator-webhook-service.{{ .Release.Namespace }}.svc + - baremetal-operator-webhook-service.{{ .Release.Namespace }}.svc.cluster.local + issuerRef: + kind: Issuer + name: {{ include "baremetal-operator.fullname" . }}-selfsigned-issuer + secretName: bmo-webhook-server-cert diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrole-manager.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrole-manager.yaml new file mode 100644 index 0000000..e55cb06 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/clusterrole-manager.yaml @@ -0,0 +1,186 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: {{ include "baremetal-operator.fullname" . }}-manager-role + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - events + verbs: + - create + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - update + - watch +- apiGroups: + - metal3.io + resources: + - baremetalhosts + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - baremetalhosts/status + verbs: + - get + - patch + - update +- apiGroups: + - metal3.io + resources: + - bmceventsubscriptions + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - bmceventsubscriptions/status + verbs: + - get + - patch + - update +- apiGroups: + - metal3.io + resources: + - firmwareschemas + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - firmwareschemas/status + verbs: + - get + - patch + - update +- apiGroups: + - metal3.io + resources: + - hardware/finalizers + verbs: + - update +- apiGroups: + - metal3.io + resources: + - hardwaredata + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - hostfirmwaresettings + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - hostfirmwaresettings/status + verbs: + - get + - patch + - update +- apiGroups: + - metal3.io + resources: + - preprovisioningimages + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - preprovisioningimages/status + verbs: + - get + - patch + - update +- apiGroups: + - metal3.io + resources: + - dataimages + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - dataimages/status + verbs: + - get + - patch + - update +- apiGroups: + - metal3.io + resources: + - hostfirmwarecomponents + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - hostfirmwarecomponents/status + verbs: + - get + - patch + - update diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrole-metrics-reader.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrole-metrics-reader.yaml new file mode 100644 index 0000000..cad7903 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/clusterrole-metrics-reader.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "baremetal-operator.fullname" . }}-metrics-reader + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +rules: +- nonResourceURLs: + - /metrics + verbs: + - get diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrole-proxy.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrole-proxy.yaml new file mode 100644 index 0000000..db6d71d --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/clusterrole-proxy.yaml @@ -0,0 +1,19 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "baremetal-operator.fullname" . }}-proxy-role + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-manager.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-manager.yaml new file mode 100644 index 0000000..bfce20a --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-manager.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "baremetal-operator.fullname" . }}-manager-rolebinding + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "baremetal-operator.fullname" . }}-manager-role +subjects: +- kind: ServiceAccount + name: {{ include "baremetal-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-proxy.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-proxy.yaml new file mode 100644 index 0000000..5207b62 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-proxy.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "baremetal-operator.fullname" . }}-proxy-rolebinding + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "baremetal-operator.fullname" . }}-proxy-role +subjects: +- kind: ServiceAccount + name: {{ include "baremetal-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/metal3-chart/charts/baremetal-operator/templates/configmap-ironic.yaml b/metal3-chart/charts/baremetal-operator/templates/configmap-ironic.yaml new file mode 100644 index 0000000..20d3b8c --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/configmap-ironic.yaml @@ -0,0 +1,30 @@ + {{- $enableTLS := .Values.global.enable_tls }} + {{- $enableVMediaTLS := .Values.global.enable_vmedia_tls }} + {{- $protocol := ternary "https" "http" $enableTLS }} + {{- $ironicIP := .Values.global.ironicIP | default "" }} + {{- $ironicApiHost := print $ironicIP ":6385" }} + {{- $ironicInspectorHost := print $ironicIP ":5050" }} + {{- $ironicBootHost := print $ironicIP ":6180" }} + {{- $ironicCacheHost := print $ironicIP ":6180" }} + +apiVersion: v1 +data: + IRONIC_ENDPOINT: "{{ $protocol }}://{{ $ironicApiHost }}/v1/" + IRONIC_INSPECTOR_ENDPOINT: "{{ $protocol }}://{{ $ironicInspectorHost }}/v1/" + RESTART_CONTAINER_CERTIFICATE_UPDATED: "false" + # Switch VMedia to HTTP if enable_vmedia_tls is false + {{- if and $enableTLS $enableVMediaTLS }} + {{- $ironicBootHost = print $ironicIP ":" .Values.global.vmediaTLSPort }} + {{- $ironicCacheHost = print $ironicIP ":" .Values.global.vmediaTLSPort }} + {{- $protocol = "https" }} + {{- else }} + {{- $protocol = "http" }} + {{- end }} + CACHEURL: "{{ $protocol }}://{{ $ironicCacheHost }}/images" + DEPLOY_KERNEL_URL: "{{ $protocol }}://{{ $ironicBootHost }}/images/ironic-python-agent.kernel" + DEPLOY_RAMDISK_URL: "{{ $protocol }}://{{ $ironicBootHost }}/images/ironic-python-agent.initramfs" +kind: ConfigMap +metadata: + name: baremetal-operator-ironic + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} diff --git a/metal3-chart/charts/baremetal-operator/templates/configmap.yaml b/metal3-chart/charts/baremetal-operator/templates/configmap.yaml new file mode 100644 index 0000000..b22579a --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/configmap.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +data: + controller_manager_config.yaml: | + apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 + kind: ControllerManagerConfig + health: + healthProbeBindAddress: :9440 + metrics: + bindAddress: 127.0.0.1:8085 + webhook: + port: 9443 + leaderElection: + leaderElect: true + resourceName: a9498140.metal3.io +kind: ConfigMap +metadata: + name: baremetal-operator-manager-config + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} diff --git a/metal3-chart/charts/baremetal-operator/templates/deployment.yaml b/metal3-chart/charts/baremetal-operator/templates/deployment.yaml new file mode 100644 index 0000000..877c714 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/deployment.yaml @@ -0,0 +1,131 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + control-plane: controller-manager + webhook: metal3-io-v1alpha1-baremetalhost + name: {{ include "baremetal-operator.fullname" . }}-controller-manager +spec: + minReadySeconds: 10 + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "baremetal-operator.selectorLabels" . | nindent 6 }} + control-plane: controller-manager + template: + metadata: + labels: + {{- include "baremetal-operator.selectorLabels" . | nindent 8 }} + control-plane: controller-manager + webhook: metal3-io-v1alpha1-baremetalhost + spec: + containers: + - args: + - --metrics-addr=127.0.0.1:8085 + - --enable-leader-election + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + envFrom: + - configMapRef: + name: {{ include "baremetal-operator.fullname" . }}-ironic + image: "{{ .Values.images.baremetalOperator.repository }}:{{ .Values.images.baremetalOperator.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.images.baremetalOperator.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + livenessProbe: + failureThreshold: 10 + httpGet: + path: /healthz + port: 9440 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 2 + name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + readinessProbe: + failureThreshold: 10 + httpGet: + path: /readyz + port: 9440 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 2 + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + {{- if .Values.global.enable_basicAuth }} + - name: ironic-basic-auth + mountPath: "/opt/metal3/auth/ironic/username" + subPath: username + readOnly: true + - name: ironic-basic-auth + mountPath: "/opt/metal3/auth/ironic/password" + subPath: password + readOnly: true + - name: ironic-inspector-basic-auth + mountPath: "/opt/metal3/auth/ironic-inspector/username" + subPath: username + readOnly: true + - name: ironic-inspector-basic-auth + mountPath: "/opt/metal3/auth/ironic-inspector/password" + subPath: password + readOnly: true + {{- end }} + {{- if .Values.global.enable_tls }} + - name: cacert + mountPath: "/opt/metal3/certs/ca" + readOnly: true + {{- end }} + - args: + - --secure-listen-address=0.0.0.0:8443 + - --upstream=http://127.0.0.1:8085/ + - --logtostderr=true + - --v=10 + image: "{{ .Values.images.rbacProxy.repository }}:{{ .Values.images.rbacProxy.tag }}" + imagePullPolicy: {{ .Values.images.rbacProxy.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + name: kube-rbac-proxy + ports: + - containerPort: 8443 + name: https + serviceAccountName: {{ include "baremetal-operator.serviceAccountName" . }} + terminationGracePeriodSeconds: 10 + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: bmo-webhook-server-cert + {{- if .Values.global.enable_basicAuth }} + - name: ironic-basic-auth + secret: + secretName: ironic-basic-auth + - name: ironic-inspector-basic-auth + secret: + secretName: ironic-inspector-basic-auth + {{- end }} + {{- if .Values.global.enable_tls }} + - name: cacert + secret: + secretName: ironic-cacert + {{- end }} + {{- with .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/metal3-chart/charts/baremetal-operator/templates/issuer.yaml b/metal3-chart/charts/baremetal-operator/templates/issuer.yaml new file mode 100644 index 0000000..c9d1522 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/issuer.yaml @@ -0,0 +1,8 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + name: {{ include "baremetal-operator.fullname" . }}-selfsigned-issuer +spec: + selfSigned: {} diff --git a/metal3-chart/charts/baremetal-operator/templates/role.yaml b/metal3-chart/charts/baremetal-operator/templates/role.yaml new file mode 100644 index 0000000..d56496f --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/role.yaml @@ -0,0 +1,45 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "baremetal-operator.fullname" . }}-leader-election-role + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch +- apiGroups: + - "" + resources: + - events + verbs: + - create +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete diff --git a/metal3-chart/charts/baremetal-operator/templates/rolebinding.yaml b/metal3-chart/charts/baremetal-operator/templates/rolebinding.yaml new file mode 100644 index 0000000..5704c6a --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/rolebinding.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "baremetal-operator.fullname" . }}-leader-election-rolebinding + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "baremetal-operator.fullname" . }}-leader-election-role +subjects: +- kind: ServiceAccount + name: {{ include "baremetal-operator.serviceAccountName" . }} diff --git a/metal3-chart/charts/baremetal-operator/templates/service-controller-manager.yaml b/metal3-chart/charts/baremetal-operator/templates/service-controller-manager.yaml new file mode 100644 index 0000000..64f39a6 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/service-controller-manager.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + control-plane: controller-manager + name: {{ include "baremetal-operator.fullname" . }}-controller-manager-metrics-service +spec: + ports: + - name: https + port: 8443 + targetPort: https + selector: + control-plane: controller-manager diff --git a/metal3-chart/charts/baremetal-operator/templates/service-webhook.yaml b/metal3-chart/charts/baremetal-operator/templates/service-webhook.yaml new file mode 100644 index 0000000..67fea7f --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/service-webhook.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + name: {{ include "baremetal-operator.fullname" . }}-webhook-service +spec: + ports: + - port: 443 + targetPort: 9443 + selector: + control-plane: controller-manager + webhook: metal3-io-v1alpha1-baremetalhost diff --git a/metal3-chart/charts/baremetal-operator/templates/serviceaccount.yaml b/metal3-chart/charts/baremetal-operator/templates/serviceaccount.yaml new file mode 100644 index 0000000..14376e8 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "baremetal-operator.serviceAccountName" . }} + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/metal3-chart/charts/baremetal-operator/templates/tests/test-connection.yaml b/metal3-chart/charts/baremetal-operator/templates/tests/test-connection.yaml new file mode 100644 index 0000000..28715fe --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "baremetal-operator.fullname" . }}-test-connection" + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "baremetal-operator.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/metal3-chart/charts/baremetal-operator/templates/validatingwebhookconfiguration.yaml b/metal3-chart/charts/baremetal-operator/templates/validatingwebhookconfiguration.yaml new file mode 100644 index 0000000..1cefe78 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/validatingwebhookconfiguration.yaml @@ -0,0 +1,51 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + annotations: + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "baremetal-operator.fullname" . }}-serving-cert + name: {{ include "baremetal-operator.fullname" . }}-validating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + - v1beta + clientConfig: + service: + name: {{ include "baremetal-operator.fullname" . }}-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metal3-io-v1alpha1-baremetalhost + failurePolicy: Fail + name: baremetalhost.metal3.io + rules: + - apiGroups: + - metal3.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - baremetalhosts + sideEffects: None +- admissionReviewVersions: + - v1 + - v1beta + clientConfig: + service: + name: {{ include "baremetal-operator.fullname" . }}-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metal3-io-v1alpha1-bmceventsubscription + failurePolicy: Fail + name: bmceventsubscription.metal3.io + rules: + - apiGroups: + - metal3.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - bmceventsubscriptions + sideEffects: None diff --git a/metal3-chart/charts/baremetal-operator/values.yaml b/metal3-chart/charts/baremetal-operator/values.yaml new file mode 100644 index 0000000..cf7fad4 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/values.yaml @@ -0,0 +1,90 @@ +# Default values for baremetal-operator. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +global: + # specify comma serparate beginning and end of the range of IP + # addresses the DHCP server will manage. + dhcpRange: 192.168.20.20,192.168.20.80 + + # Network interface on which provisioning network can be accessed + provisioningInterface: ens4 + + # IP Address assigned to network interface on provisioning network + provisioningIP: 192.168.20.5 + + # If running in a multi-node kubernetes cluster, "pin" the baremtal container + # to the same host where the ironic and media containers + # arerunning. Uncomment the nodeSelector and update the hostname accordingly. + #nodeSelector: + #kubernetes.io/hostname: "my-hostname" + + # Comment this out when pinning the baremetal-operator container to a specfic host. + nodeSelector: {} + +replicaCount: 1 + +images: + baremetalOperator: + repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/baremetal-operator + pullPolicy: IfNotPresent + tag: "0.6.1" + rbacProxy: + repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/kube-rbac-proxy + pullPolicy: IfNotPresent + tag: "v0.14.2" + +imagePullSecrets: [] +nameOverride: "manger" +fullnameOverride: "baremetal-operator" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "baremetal-operator-controller-manager" + +podAnnotations: {} + +securityContext: + runAsUser: 11000 + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + runAsNonRoot: true + +service: + type: ClusterIP + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +tolerations: [] + +affinity: {} + +baremetaloperator: + httpPort: "6180" diff --git a/metal3-chart/charts/ironic/.helmignore b/metal3-chart/charts/ironic/.helmignore new file mode 100644 index 0000000..1b9a9cc --- /dev/null +++ b/metal3-chart/charts/ironic/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/metal3-chart/charts/ironic/Chart.yaml b/metal3-chart/charts/ironic/Chart.yaml new file mode 100644 index 0000000..a9d39ec --- /dev/null +++ b/metal3-chart/charts/ironic/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 24.1.2 +description: A Helm chart for Ironic, used by Metal3 +name: ironic +type: application +version: 0.7.0 diff --git a/metal3-chart/charts/ironic/README.md b/metal3-chart/charts/ironic/README.md new file mode 100644 index 0000000..d88fccc --- /dev/null +++ b/metal3-chart/charts/ironic/README.md @@ -0,0 +1,24 @@ +## How to Enable Provisioning Network + +By default PXE boot functionality is disabled, so deployments via e.g redfish-virtualmedia may +be performed without any dedicated provisioning network. + +For PXE boot a dedicated network is required, in this case we run a dnsmasq instance to provide +DHCP and require a dedicated NIC for connectivity to the provisioning network on each host. + +To enable this mode you must provide the following additional configuration (note the values are +examples and will depend on your environment): + +``` +global: + enable_dnsmasq: true + enable_pxe_boot: true + dnsmasqDefaultRouter: 192.168.21.254 + dnsmasqDNSServer: 192.168.20.5 + dhcpRange: 192.168.20.20,192.168.20.80 + provisioningInterface: ens4 + provisioningIP: 192.168.20.5 +``` + +Note that these values *must not* conflict with your controlplane or other networks otherwise unexpected +behavior is likely - a dedicated physical network is required in this configuration. diff --git a/metal3-chart/charts/ironic/templates/NOTES.txt b/metal3-chart/charts/ironic/templates/NOTES.txt new file mode 100644 index 0000000..acc38ed --- /dev/null +++ b/metal3-chart/charts/ironic/templates/NOTES.txt @@ -0,0 +1,16 @@ +1. Get the application URL by running these commands: +{{- if eq .Values.service.type "NodePort" }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ironic.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if eq .Values.service.type "LoadBalancer" }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ironic.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ironic.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:6385 +{{- else if eq .Values.service.type "ClusterIP" }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ironic.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/metal3-chart/charts/ironic/templates/_helpers.tpl b/metal3-chart/charts/ironic/templates/_helpers.tpl new file mode 100644 index 0000000..eb97966 --- /dev/null +++ b/metal3-chart/charts/ironic/templates/_helpers.tpl @@ -0,0 +1,88 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ironic.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ironic.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ironic.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ironic.labels" -}} +helm.sh/chart: {{ include "ironic.chart" . }} +{{ include "ironic.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ironic.selectorLabels" -}} +app.kubernetes.io/component: ironic +app.kubernetes.io/name: {{ include "ironic.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ironic.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ironic.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Shared directory volumeMount +*/}} +{{- define "ironic.sharedVolumeMount" -}} +- mountPath: /shared + name: ironic-data-volume +{{- end }} + +{{/* +Get ironic CA volumeMounts +*/}} +{{- define "ironic.CAVolumeMounts" -}} +- name: cert-ironic-ca + mountPath: "/certs/ca/ironic" + readOnly: true +- name: cert-ironic-inspector-ca + mountPath: "/certs/ca/ironic-inspector" + readOnly: true +{{- if .Values.global.enable_vmedia_tls }} +- name: cert-ironic-vmedia-ca + mountPath: "/certs/ca/vmedia" + readOnly: true +{{- end }} +{{- end }} diff --git a/metal3-chart/charts/ironic/templates/certificates.yaml b/metal3-chart/charts/ironic/templates/certificates.yaml new file mode 100644 index 0000000..f745c34 --- /dev/null +++ b/metal3-chart/charts/ironic/templates/certificates.yaml @@ -0,0 +1,56 @@ +{{- if .Values.global.enable_tls -}} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: ironic-cacert +spec: + commonName: ironic-ca + isCA: true + ipAddresses: + - {{ .Values.global.ironicIP }} + issuerRef: + kind: Issuer + name: selfsigned-issuer + secretName: ironic-cacert +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: ironic-cert +spec: + commonName: ironic-cert + ipAddresses: + - {{ .Values.global.ironicIP }} + issuerRef: + kind: Issuer + name: ca-issuer + secretName: ironic-cert +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: ironic-inspector-cert +spec: + commonName: ironic-inspector-cert + ipAddresses: + - {{ .Values.global.ironicIP }} + issuerRef: + kind: Issuer + name: ca-issuer + secretName: ironic-inspector-cert +{{- if .Values.global.enable_vmedia_tls }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: ironic-vmedia-cert +spec: + commonName: ironic-vmedia-cert + ipAddresses: + - {{ .Values.global.ironicIP }} + issuerRef: + kind: Issuer + name: ca-issuer + secretName: ironic-vmedia-cert +{{- end }} +{{- end }} diff --git a/metal3-chart/charts/ironic/templates/configmap-ipa-downloader.yaml b/metal3-chart/charts/ironic/templates/configmap-ipa-downloader.yaml new file mode 100644 index 0000000..3636717 --- /dev/null +++ b/metal3-chart/charts/ironic/templates/configmap-ipa-downloader.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: ironic-ipa-downloader + labels: + {{- include "ironic.labels" . | nindent 4 }} +data: + {{- with .Values.baremetaloperator }} + {{ if .ipaBaseUri }} + IPA_BASEURI: {{ .ipaBaseUri }} + {{ end }} + {{ end }} diff --git a/metal3-chart/charts/ironic/templates/configmap.yaml b/metal3-chart/charts/ironic/templates/configmap.yaml new file mode 100644 index 0000000..3a66c9d --- /dev/null +++ b/metal3-chart/charts/ironic/templates/configmap.yaml @@ -0,0 +1,86 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: ironic-bmo + labels: + {{- include "ironic.labels" . | nindent 4 }} +data: + {{- $enableTLS := .Values.global.enable_tls }} + {{- $enableVMediaTLS := .Values.global.enable_vmedia_tls }} + {{- $protocol := ternary "https" "http" $enableTLS }} + {{- $ironicIP := .Values.global.ironicIP | default "" }} + {{- $ironicApiHost := print $ironicIP ":6385" }} + {{- $ironicInspectorHost := print $ironicIP ":5050" }} + {{- $ironicBootHost := print $ironicIP ":6180" }} + {{- $ironicCacheHost := print $ironicIP ":6180" }} + + {{- if ( .Values.global.enable_dnsmasq ) }} + DNSMASQ_BOOT_SERVER_ADDRESS: {{ $ironicBootHost }} + DNSMASQ_DNS_SERVER_ADDRESS: {{ .Values.global.dnsmasqDNSServer }} + DNSMASQ_DEFAULT_ROUTER: {{ .Values.global.dnsmasqDefaultRouter }} + DHCP_RANGE: {{ .Values.global.dhcpRange }} + {{- end }} + {{- if .Values.debug.ironicRamdiskSshKey }} + IRONIC_RAMDISK_SSH_KEY: {{ .Values.debug.ironicRamdiskSshKey }} + {{- end }} + HTTP_PORT: "6180" + PREDICTABLE_NIC_NAMES: "{{ .Values.global.predictableNicNames }}" + USE_IRONIC_INSPECTOR: "true" + IRONIC_API_BASE_URL: {{ $protocol }}://{{ $ironicApiHost }} + IRONIC_API_HOST: {{ $ironicApiHost }} + IRONIC_API_HTTPD_SERVER_NAME: {{ $ironicApiHost }} + IRONIC_ENDPOINT: {{ $protocol }}://{{ $ironicApiHost }}/v1/ + IRONIC_INSPECTOR_BASE_URL: {{ $protocol }}://{{ $ironicInspectorHost }} + IRONIC_INSPECTOR_ENDPOINT: {{ $protocol }}://{{ $ironicInspectorHost }}/v1/ + IRONIC_INSPECTOR_HOST: {{ $ironicInspectorHost }} + IRONIC_INSPECTOR_HTTPD_SERVER_NAME: {{ $ironicInspectorHost }} + # Switch VMedia to HTTP if enable_vmedia_tls is false + {{- if and $enableTLS $enableVMediaTLS }} + {{- $ironicBootHost = print $ironicIP ":" .Values.global.vmediaTLSPort }} + {{- $ironicCacheHost = print $ironicIP ":" .Values.global.vmediaTLSPort }} + {{- $protocol = "https" }} + {{- else }} + {{- $protocol = "http" }} + {{- end }} + IRONIC_EXTERNAL_HTTP_URL: {{ $protocol }}://{{ $ironicCacheHost }} + CACHEURL: {{ $protocol }}://{{ $ironicCacheHost }}/images + DEPLOY_KERNEL_URL: {{ $protocol }}://{{ $ironicBootHost }}/images/ironic-python-agent.kernel + DEPLOY_RAMDISK_URL: {{ $protocol }}://{{ $ironicBootHost }}/images/ironic-python-agent.initramfs + IRONIC_BOOT_BASE_URL: {{ $protocol }}://{{ $ironicBootHost }} + IRONIC_VMEDIA_HTTPD_SERVER_NAME: {{ $ironicBootHost }} + ENABLE_PXE_BOOT: "{{ .Values.global.enable_pxe_boot }}" + {{- if .Values.global.provisioningInterface }} + PROVISIONING_INTERFACE: {{ .Values.global.provisioningInterface }} + {{- end }} + {{- if .Values.global.provisioningIP }} + PROVISIONING_IP: {{ .Values.global.provisioningIP }} + {{- end }} + IRONIC_INSPECTOR_VLAN_INTERFACES: all + IRONIC_ILO_USE_SWIFT: "false" + IRONIC_ILO_USE_WEB_SERVER_FOR_IMAGES: "true" + IRONIC_FAST_TRACK: "true" + IRONIC_USE_MARIADB: "true" + LISTEN_ALL_INTERFACES: "true" + {{- if .Values.global.ironicIP }} + IRONIC_IP: {{ .Values.global.ironicIP }} + {{- end }} + {{- if ( .Values.global.enable_tls ) }} + RESTART_CONTAINER_CERTIFICATE_UPDATED: "true" + IRONIC_KERNEL_PARAMS: {{ .Values.global.ironicKernelParams }} tls.enabled=true + IPA_INSECURE: "0" + IRONIC_REVERSE_PROXY_SETUP: "true" + INSPECTOR_REVERSE_PROXY_SETUP: "true" + {{- if ( .Values.global.enable_vmedia_tls ) }} + VMEDIA_TLS_PORT: "{{ .Values.global.vmediaTLSPort }}" + {{- end }} + {{- else }} + RESTART_CONTAINER_CERTIFICATE_UPDATED: "false" + IRONIC_KERNEL_PARAMS: {{ .Values.global.ironicKernelParams }} + IPA_INSECURE: "1" + IRONIC_REVERSE_PROXY_SETUP: "false" + {{- end }} + {{- if ( .Values.global.enable_basicAuth ) }} + AUTH_STRATEGY: "http_basic" + INSPECTOR_AUTH_STRATEGY: "http_basic" + {{- end }} + MARIADB_HOST: {{ .Values.global.databaseServiceName }}.{{ .Release.Namespace }}.svc.cluster.local diff --git a/metal3-chart/charts/ironic/templates/deployment.yaml b/metal3-chart/charts/ironic/templates/deployment.yaml new file mode 100644 index 0000000..7f5e39d --- /dev/null +++ b/metal3-chart/charts/ironic/templates/deployment.yaml @@ -0,0 +1,367 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ironic.fullname" . }} + labels: + {{- include "ironic.labels" . | nindent 4 }} +spec: + minReadySeconds: 10 + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "ironic.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "ironic.selectorLabels" . | nindent 8 }} + spec: + {{- if .Values.podSecurityContext }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- end }} + {{- if .Values.baremetaloperator.ironichostNetwork }} + hostNetwork: {{ .Values.baremetaloperator.ironichostNetwork }} + {{- end }} + containers: + - name: ironic-httpd + image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }} + imagePullPolicy: {{ .Values.images.ironic.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + command: + - /bin/runhttpd + envFrom: + - configMapRef: + name: ironic-bmo + livenessProbe: + exec: + command: + - /bin/sh + - -c + - curl {{ if and .Values.global.enable_tls .Values.global.enable_vmedia_tls }}-sSfk https://127.0.0.1:{{ .Values.global.vmediaTLSPort }}/boot.ipxe {{ else }}-sSf http://127.0.0.1:6180/boot.ipxe{{ end }} + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + ports: + {{- if and .Values.global.enable_tls .Values.global.enable_vmedia_tls }} + - containerPort: {{ .Values.global.vmediaTLSPort }} + name: httpd-tls + protocol: TCP + {{- else }} + - containerPort: 6180 + name: httpd + protocol: TCP + {{- end }} + readinessProbe: + exec: + command: + - /bin/sh + - -c + - curl {{ if and .Values.global.enable_tls .Values.global.enable_vmedia_tls }}-sSfk https://127.0.0.1:{{ .Values.global.vmediaTLSPort }}/boot.ipxe {{ else }}-sSf http://127.0.0.1:6180/boot.ipxe{{ end }} + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + volumeMounts: + {{- include "ironic.sharedVolumeMount" . | nindent 10 }} + {{- if .Values.global.enable_tls }} + {{- include "ironic.CAVolumeMounts" . | nindent 10 }} + - name: cert-ironic + mountPath: "/certs/ironic" + readOnly: true + - name: cert-ironic-inspector + mountPath: "/certs/ironic-inspector" + readOnly: true + {{- if .Values.global.enable_vmedia_tls }} + - name: cert-ironic-vmedia + mountPath: "/certs/vmedia" + readOnly: true + {{- end }} + - mountPath: /shared/html/tstcerts + name: cert-ironic-ca + readOnly: true + {{- end }} + - name: ironic-inspector + image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }} + imagePullPolicy: {{ .Values.images.ironic.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + command: + - /bin/runironic-inspector + envFrom: + - configMapRef: + name: ironic-bmo + env: + {{- if .Values.global.enable_basicAuth }} + - name: INSPECTOR_HTPASSWD + valueFrom: + secretKeyRef: + name: ironic-inspector-basic-auth + key: htpasswd + {{- end }} + - name: MARIADB_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: ironic-mariadb + livenessProbe: + exec: + command: + - /bin/sh + - -c + - curl -sSf http://127.0.0.1:{{ if .Values.global.enable_tls }}5049{{ else }}5050{{ end }} + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + ports: + - containerPort: 5050 + name: inspector + protocol: TCP + readinessProbe: + exec: + command: + - /bin/sh + - -c + - curl -sSf http://127.0.0.1:{{ if .Values.global.enable_tls }}5049{{ else }}5050{{ end }} + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + volumeMounts: + {{- include "ironic.sharedVolumeMount" . | nindent 10 }} + {{- if .Values.global.enable_basicAuth }} + - mountPath: "/auth/ironic/auth-config" + name: ironic-basic-auth + subPath: auth-config + readOnly: true + - mountPath: "/auth/ironic-inspector/auth-config" + name: ironic-inspector-basic-auth + subPath: auth-config + readOnly: true + {{- end }} + {{- if .Values.global.enable_tls }} + {{- include "ironic.CAVolumeMounts" . | nindent 10 }} + - name: cert-ironic-inspector + mountPath: "/certs/ironic-inspector" + readOnly: true + {{- end }} + - name: ironic-log-watch + image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }} + imagePullPolicy: {{ .Values.images.ironic.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + command: + - /bin/runlogwatch.sh + volumeMounts: + {{- include "ironic.sharedVolumeMount" . | nindent 10 }} + - name: ironic + image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }} + imagePullPolicy: {{ .Values.images.ironic.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + command: + - /bin/runironic + envFrom: + - configMapRef: + name: ironic-bmo + env: + {{- if .Values.global.enable_basicAuth }} + - name: IRONIC_HTPASSWD + valueFrom: + secretKeyRef: + name: ironic-basic-auth + key: htpasswd + {{- end }} + - name: MARIADB_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: ironic-mariadb + livenessProbe: + exec: + command: + - /bin/sh + - -c + - curl -sSf http://127.0.0.1:{{ if .Values.global.enable_tls }}6388{{ else }}6385{{ end }} + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + ports: + - containerPort: 6385 + name: api + protocol: TCP + readinessProbe: + exec: + command: + - /bin/sh + - -c + - curl -sSf http://127.0.0.1:{{ if .Values.global.enable_tls }}6388{{ else }}6385{{ end }} + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + volumeMounts: + {{- include "ironic.sharedVolumeMount" . | nindent 10 }} + {{- if .Values.global.enable_basicAuth }} + - mountPath: "/auth/ironic/auth-config" + name: ironic-basic-auth + subPath: auth-config + readOnly: true + - mountPath: "/auth/ironic-inspector/auth-config" + name: ironic-inspector-basic-auth + subPath: auth-config + readOnly: true + {{- end }} + {{- if .Values.global.enable_tls }} + {{- include "ironic.CAVolumeMounts" . | nindent 10 }} + - name: cert-ironic + mountPath: "/certs/ironic" + readOnly: true + - mountPath: /etc/pki/trust/anchors + name: trusted-certs + readOnly: true + lifecycle: + postStart: + exec: + command: + - update-ca-certificates + {{- end }} + {{- if .Values.global.enable_dnsmasq }} + - name: ironic-dnsmasq + image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }} + imagePullPolicy: {{ .Values.images.ironic.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + securityContext: + capabilities: + add: + - NET_ADMIN + - NET_RAW + command: + - /bin/rundnsmasq + envFrom: + - configMapRef: + name: ironic-bmo + livenessProbe: + exec: + command: + - sh + - -c + - ss -lun | grep :67 && ss -lun | grep :69 + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + ports: + - containerPort: 67 + name: dhcp + protocol: UDP + - containerPort: 69 + name: tftp + protocol: UDP + readinessProbe: + exec: + command: + - sh + - -c + - ss -lun | grep :67 && ss -lun | grep :69 + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + volumeMounts: + {{- include "ironic.sharedVolumeMount" . | nindent 10 }} + {{- end }} + initContainers: + - name: ironic-ipa-downloader + image: {{ .Values.images.ironicIPADownloader.repository }}:{{ .Values.images.ironicIPADownloader.tag }} + imagePullPolicy: {{ .Values.images.ironicIPADownloader.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + command: + - /usr/local/bin/get-resource.sh + envFrom: + - configMapRef: + name: ironic-ipa-downloader + volumeMounts: + {{- include "ironic.sharedVolumeMount" . | nindent 10 }} + {{- if .Values.global.enable_tls }} + - mountPath: /tmp/ironic-certificates + name: trusted-certs + {{- end }} + volumes: + - name: ironic-data-volume + persistentVolumeClaim: + claimName: ironic-shared-volume + {{- if .Values.global.enable_basicAuth }} + - name: ironic-basic-auth + secret: + secretName: ironic-basic-auth + - name: ironic-inspector-basic-auth + secret: + secretName: ironic-inspector-basic-auth + {{- if .Values.global.enable_tls }} + - name: trusted-certs + projected: + sources: + - secret: + name: ironic-cacert + {{- if .Values.global.additionalTrustedCAs }} + - secret: + name: tls-ca-additional + {{- end }} + - name: cert-ironic-ca + secret: + secretName: ironic-cacert + - name: cert-ironic + secret: + secretName: ironic-cert + - name: cert-ironic-inspector-ca + secret: + secretName: ironic-cacert + - name: cert-ironic-inspector + secret: + secretName: ironic-inspector-cert + {{- if .Values.global.enable_vmedia_tls }} + - name: cert-ironic-vmedia-ca + secret: + secretName: ironic-cacert + - name: cert-ironic-vmedia + secret: + secretName: ironic-vmedia-cert + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.global.dnsPolicy }} + dnsPolicy: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/metal3-chart/charts/ironic/templates/issuers.yaml b/metal3-chart/charts/ironic/templates/issuers.yaml new file mode 100644 index 0000000..b03cbcc --- /dev/null +++ b/metal3-chart/charts/ironic/templates/issuers.yaml @@ -0,0 +1,16 @@ +{{- if .Values.global.enable_tls -}} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: selfsigned-issuer +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: ca-issuer +spec: + ca: + secretName: ironic-cacert +{{- end }} diff --git a/metal3-chart/charts/ironic/templates/pvc.yaml b/metal3-chart/charts/ironic/templates/pvc.yaml new file mode 100644 index 0000000..e50c856 --- /dev/null +++ b/metal3-chart/charts/ironic/templates/pvc.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: ironic-shared-volume + {{- if .Values.persistence.ironic.keep }} + annotations: + "helm.sh/resource-policy": keep + {{- end }} +spec: + accessModes: + {{- if .Values.persistence.ironic.accessMode }} + - {{ .Values.persistence.ironic.accessMode }} + {{- else if eq (int .Values.replicaCount) 1 }} + - ReadWriteOnce + {{- else }} + - ReadWriteMany + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.ironic.size }} + {{- if .Values.persistence.ironic.storageClass }} + storageClassName: {{ .Values.persistence.ironic.storageClass }} + {{- end }} + volumeMode: Filesystem diff --git a/metal3-chart/charts/ironic/templates/secret-tls.yaml b/metal3-chart/charts/ironic/templates/secret-tls.yaml new file mode 100644 index 0000000..173d2fb --- /dev/null +++ b/metal3-chart/charts/ironic/templates/secret-tls.yaml @@ -0,0 +1,16 @@ +{{- if and (.Values.global.enable_tls) + (ne .Values.tlscerts.crt "") + (ne .Values.tlscerts.key "") + (ne .Values.tlscerts.cacert "") -}} +apiVersion: v1 +kind: Secret +metadata: + name: ironic-cacert + labels: + {{- include "ironic.labels" . | nindent 4 }} +type: Opaque +data: + tls.crt: {{ .Values.tlscerts.crt | toString | b64enc }} + tls.key: {{ .Values.tlscerts.key | toString | b64enc }} + ca.crt: {{ .Values.tlscerts.cacert | toString | b64enc }} +{{- end }} diff --git a/metal3-chart/charts/ironic/templates/secrets-basic-auth.yaml b/metal3-chart/charts/ironic/templates/secrets-basic-auth.yaml new file mode 100644 index 0000000..aa5736d --- /dev/null +++ b/metal3-chart/charts/ironic/templates/secrets-basic-auth.yaml @@ -0,0 +1,62 @@ +{{- if .Values.global.enable_basicAuth }} + +{{- $ironicUsername := "" -}} +{{- $ironicPassword := "" -}} +{{- $ironicSecretName := "ironic-basic-auth" -}} + +# Check if the secret is deployed and has a password +{{- $oldIronicSecret := lookup "v1" "Secret" .Release.Namespace $ironicSecretName }} +{{- if and $oldIronicSecret (index $oldIronicSecret.data "username") (index $oldIronicSecret.data "password") }} +{{- $ironicUsername = b64dec (index $oldIronicSecret.data "username" | toString) -}} +{{- $ironicPassword = b64dec (index $oldIronicSecret.data "password" | toString) -}} +# If not, check if a username and password are provided in values.yaml +{{- else if and (.Values.global.auth.ironicUsername) (.Values.global.auth.ironicPassword) }} +{{- $ironicUsername = .Values.global.auth.ironicUsername -}} +{{- $ironicPassword = .Values.global.auth.ironicPassword -}} +{{- else }} +# If no username and password are provided in values.yaml, generate new ones +{{- $ironicUsername = "ironic" -}} +{{- $ironicPassword = (randAlphaNum 20) -}} +{{- end }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $ironicSecretName }} +type: Opaque +data: + username: {{ $ironicUsername | b64enc }} + password: {{ $ironicPassword | b64enc }} + htpasswd: {{ b64enc (htpasswd $ironicUsername $ironicPassword) }} + auth-config: | + {{- printf "[ironic]\nauth_type=http_basic\nusername: %s\npassword: %s" $ironicUsername $ironicPassword | b64enc | nindent 4 }} +--- +{{- $ironicInspectorUsername := "" -}} +{{- $ironicInspectorPassword := "" -}} +{{- $inspectorSecretName := "ironic-inspector-basic-auth" -}} + +# Check if the secret is deployed and has a password +{{- $oldInspectorSecret := lookup "v1" "Secret" .Release.Namespace $inspectorSecretName }} +{{- if and $oldInspectorSecret (index $oldInspectorSecret.data "username") (index $oldInspectorSecret.data "password") }} +{{- $ironicInspectorUsername = b64dec (index $oldInspectorSecret.data "username" | toString) -}} +{{- $ironicInspectorPassword = b64dec (index $oldInspectorSecret.data "password" | toString) -}} +# If not, check if a username and password are provided in values.yaml +{{- else if and (.Values.global.auth.ironicInspectorUsername) (.Values.global.auth.ironicInspectorPassword) }} +{{- $ironicInspectorUsername = .Values.global.auth.ironicInspectorUsername -}} +{{- $ironicInspectorPassword = .Values.global.auth.ironicInspectorPassword -}} +{{- else }} +# If no username and password are provided in values.yaml, generate new ones +{{- $ironicInspectorUsername = "ironic" -}} +{{- $ironicInspectorPassword = (randAlphaNum 20) -}} +{{- end }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $inspectorSecretName }} +type: Opaque +data: + username: {{ $ironicInspectorUsername | b64enc }} + password: {{ $ironicInspectorPassword | b64enc }} + htpasswd: {{ b64enc (htpasswd $ironicInspectorUsername $ironicInspectorPassword) }} + auth-config: | + {{- printf "[inspector]\nauth_type=http_basic\nusername: %s\npassword: %s" $ironicInspectorUsername $ironicInspectorPassword | b64enc | nindent 4 }} +{{- end }} diff --git a/metal3-chart/charts/ironic/templates/service.yaml b/metal3-chart/charts/ironic/templates/service.yaml new file mode 100644 index 0000000..f3f0b51 --- /dev/null +++ b/metal3-chart/charts/ironic/templates/service.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "ironic.fullname" . }} + labels: + {{- include "ironic.labels" . | nindent 4 }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + {{- $enableTLS := .Values.global.enable_tls }} + {{- $enableVMediaTLS := .Values.global.enable_vmedia_tls }} + {{- range .Values.service.ports }} + {{- if and (eq .name "httpd") (or (not $enableTLS) (not $enableVMediaTLS)) }} + - name: {{ .name }} + port: {{ .port }} + protocol: {{ .protocol }} + targetPort: {{ .targetPort }} + {{- else if and (eq .name "httpd-tls") ($enableTLS) ($enableVMediaTLS) }} + - name: {{ .name }} + port: {{ .port }} + protocol: {{ .protocol }} + targetPort: {{ .targetPort }} + {{- else if and (ne .name "httpd") (ne .name "httpd-tls") }} + - name: {{ .name }} + port: {{ .port }} + protocol: {{ .protocol }} + targetPort: {{ .targetPort }} + {{- end }} + {{- end }} + selector: + {{- include "ironic.selectorLabels" . | nindent 4 }} + {{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }} + externalIPs: + {{- toYaml .Values.service.externalIPs | nindent 4 }} + {{- end }} diff --git a/metal3-chart/charts/ironic/templates/serviceaccount.yaml b/metal3-chart/charts/ironic/templates/serviceaccount.yaml new file mode 100644 index 0000000..c94a90f --- /dev/null +++ b/metal3-chart/charts/ironic/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ironic.serviceAccountName" . }} + labels: + {{- include "ironic.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/metal3-chart/charts/ironic/values.yaml b/metal3-chart/charts/ironic/values.yaml new file mode 100644 index 0000000..2ffb69a --- /dev/null +++ b/metal3-chart/charts/ironic/values.yaml @@ -0,0 +1,153 @@ +# Default values for ironic. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +global: + # whether to enable dnsmasq on the provisioning network (for PXE boot) + enable_dnsmasq: false + + # whether to enable PXE boot capability + # NOTE: enable_dnsmasq must set to 'true' in order for this option to be effective. + enable_pxe_boot: false + + # DNS Policy of the Ironic pod + dnsPolicy: "ClusterFirstWithHostNet" + + # IP address of the router associated with the specified DHCP + # address range + dnsmasqDefaultRouter: "" + + # IP address of the dns server to be provided with DHCP + # response + dnsmasqDNSServer: "" + + # specify comma-delimited xrange of IP addresses the DHCP server will manage. + # e.g 192.168.20.20,192.168.20.80 + dhcpRange: "" + + # Network interface on which provisioning network can be accessed + # Note this must be a dedicated NIC separate from the controlplane network + provisioningInterface: "" + + # IP Address assigned to network interface on provisioning network + provisioningIP: "" + + # Whether the NIC names should be predictable or not + predictableNicNames: "true" + + # The kernel params for Ironic + ironicKernelParams: "console=ttyS0" + + databaseServiceName: "metal3-mariadb" + + # In a multi-node kubernetes cluster, we need to "pin" the + # ironic containers to the given host where the + # provisioningIP exists. Uncomment the nodeSelector + # here and update the hostname accordingly. + #nodeSelector: + #kubernetes.io/hostname: "csrancher-n1" + + # Comment this out when pinning the pdns containers to a specfic host. + nodeSelector: {} + +replicaCount: 1 + +images: + ironic: + repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/ironic + pullPolicy: IfNotPresent + tag: 24.1.2.0 + ironicIPADownloader: + repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/ironic-ipa-downloader + pullPolicy: IfNotPresent + tag: 2.0.0 + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: + runAsUser: 10475 + fsGroup: 10475 + +securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + runAsNonRoot: true + +service: + type: LoadBalancer + annotations: {} + externalIPs: [] + ports: + - name: httpd + port: 6180 + protocol: TCP + targetPort: 6180 + - name: httpd-tls + port: 6185 + protocol: TCP + targetPort: 6185 + - name: inspector + port: 5050 + protocol: TCP + targetPort: 5050 + - name: api + port: 6385 + protocol: TCP + targetPort: 6385 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +tolerations: [] + +affinity: {} + +baremetaloperator: + cloudflareApiToken: "foo" + ironichostNetwork: true + +debug: + ironicRamdiskSshKey: "" + +tlscerts: + cacert: "" + key: "" + crt: "" + +persistence: + ironic: + # storageClass for the ironic shared volume + # Ensure the storageClass is defined + storageClass: "" + # size of the ironic shared volume + size: "1Gi" + # accessMode of the ironic shared volume PVC + # If empty defaults to ReadWriteOnce when replicaCount=1 otherwise ReadWriteMany + accessMode: "" + # flag to indicate to keep pvc upon helm uninstall + keep: false diff --git a/metal3-chart/charts/mariadb/.helmignore b/metal3-chart/charts/mariadb/.helmignore new file mode 100644 index 0000000..f0907ec --- /dev/null +++ b/metal3-chart/charts/mariadb/.helmignore @@ -0,0 +1,24 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ + diff --git a/metal3-chart/charts/mariadb/Chart.yaml b/metal3-chart/charts/mariadb/Chart.yaml new file mode 100644 index 0000000..df93690 --- /dev/null +++ b/metal3-chart/charts/mariadb/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 10.6.7 +description: A Helm chart for MariaDB, used by Metal3 +name: mariadb +type: application +version: 0.5.4 diff --git a/metal3-chart/charts/mariadb/templates/_helpers.tpl b/metal3-chart/charts/mariadb/templates/_helpers.tpl new file mode 100644 index 0000000..d3d47e4 --- /dev/null +++ b/metal3-chart/charts/mariadb/templates/_helpers.tpl @@ -0,0 +1,64 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "mariadb.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "mariadb.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "mariadb.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "mariadb.labels" -}} +helm.sh/chart: {{ include "mariadb.chart" . }} +{{ include "mariadb.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "mariadb.selectorLabels" -}} +app.kubernetes.io/component: mariadb +app.kubernetes.io/name: {{ include "mariadb.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "mariadb.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "mariadb.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + diff --git a/metal3-chart/charts/mariadb/templates/configmap.yaml b/metal3-chart/charts/mariadb/templates/configmap.yaml new file mode 100644 index 0000000..59a2cc1 --- /dev/null +++ b/metal3-chart/charts/mariadb/templates/configmap.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: mariadb-cm + labels: + {{- include "mariadb.labels" . | nindent 4 }} +data: + RESTART_CONTAINER_CERTIFICATE_UPDATED: "false" diff --git a/metal3-chart/charts/mariadb/templates/deployment.yaml b/metal3-chart/charts/mariadb/templates/deployment.yaml new file mode 100644 index 0000000..070c2fb --- /dev/null +++ b/metal3-chart/charts/mariadb/templates/deployment.yaml @@ -0,0 +1,85 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "mariadb.fullname" . }} + labels: + {{- include "mariadb.labels" . | nindent 4 }} +spec: + replicas: {{.Values.replicaCount}} + selector: + matchLabels: + {{- include "mariadb.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "mariadb.selectorLabels" . | nindent 8 }} + spec: + {{- $volmounts := toYaml .Values.volumeMounts | trim | nindent 12 }} + {{- $volumes := toYaml .Values.volumes | trim | nindent 8 }} + serviceAccountName: {{ include "mariadb.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: mariadb + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + env: + - name: MARIADB_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: ironic-mariadb + - name: RESTART_CONTAINER_CERTIFICATE_UPDATED + valueFrom: + configMapKeyRef: + name: mariadb-cm + key: RESTART_CONTAINER_CERTIFICATE_UPDATED + lifecycle: + preStop: + exec: + command: + - sh + - -c + - mysqladmin shutdown -uironic -p$(printenv MARIADB_PASSWORD) + livenessProbe: + exec: + command: + - sh + - -c + - mysqladmin status -uironic -p$(printenv MARIADB_PASSWORD) + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + ports: + - containerPort: 3306 + name: mariadb + protocol: TCP + readinessProbe: + exec: + command: + - sh + - -c + - mysqladmin status -uironic -p$(printenv MARIADB_PASSWORD) + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + volumeMounts: + {{- $volmounts }} + {{- with .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + {{- $volumes }} diff --git a/metal3-chart/charts/mariadb/templates/pvc.yaml b/metal3-chart/charts/mariadb/templates/pvc.yaml new file mode 100644 index 0000000..fa0a176 --- /dev/null +++ b/metal3-chart/charts/mariadb/templates/pvc.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: mariadb-volume-claim + {{- if .Values.persistence.keep }} + annotations: + "helm.sh/resource-policy": keep + {{- end }} +spec: + accessModes: + {{- if .Values.persistence.accessMode }} + - {{ .Values.persistence.accessMode }} + {{- else if eq (int .Values.replicaCount) 1 }} + - ReadWriteOnce + {{- else }} + - ReadWriteMany + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size }} + {{- if .Values.persistence.storageClass }} + storageClassName: {{ .Values.persistence.storageClass }} + {{- end }} + volumeMode: Filesystem diff --git a/metal3-chart/charts/mariadb/templates/secret.yaml b/metal3-chart/charts/mariadb/templates/secret.yaml new file mode 100644 index 0000000..d4b2318 --- /dev/null +++ b/metal3-chart/charts/mariadb/templates/secret.yaml @@ -0,0 +1,21 @@ +{{- $secret_name := "ironic-mariadb" -}} + +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secret_name }} + labels: + {{- include "mariadb.labels" . | nindent 4 }} +type: Opaque +data: + # Check if the secret is deployed and has a password + {{- $old_sec := lookup "v1" "Secret" .Release.Namespace $secret_name }} + {{- if and $old_sec (index $old_sec.data "password") }} + password: {{ index $old_sec.data "password" }} + {{- else if .Values.password }} + # If not, check if a password is provided in values.yaml + password: {{ .Values.password | toString | b64enc }} + {{- else }} + # If no secret and no password in values.yaml, generate a new password + password: {{ randAlphaNum 20 | b64enc }} + {{- end }} \ No newline at end of file diff --git a/metal3-chart/charts/mariadb/templates/service-account.yaml b/metal3-chart/charts/mariadb/templates/service-account.yaml new file mode 100644 index 0000000..5101f01 --- /dev/null +++ b/metal3-chart/charts/mariadb/templates/service-account.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mariadb.serviceAccountName" . }} + labels: + {{- include "mariadb.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + diff --git a/metal3-chart/charts/mariadb/templates/service.yaml b/metal3-chart/charts/mariadb/templates/service.yaml new file mode 100644 index 0000000..5d0d75d --- /dev/null +++ b/metal3-chart/charts/mariadb/templates/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.global.databaseServiceName }} + labels: + {{- include "mariadb.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + selector: + {{- include "mariadb.selectorLabels" . | nindent 4 }} + ports: + {{- with .Values.service.ports }} + {{- toYaml . | nindent 2 }} + {{- end }} \ No newline at end of file diff --git a/metal3-chart/charts/mariadb/values.yaml b/metal3-chart/charts/mariadb/values.yaml new file mode 100644 index 0000000..7d2fbce --- /dev/null +++ b/metal3-chart/charts/mariadb/values.yaml @@ -0,0 +1,67 @@ +global: + databaseServiceName: "metal3-mariadb" + nodeSelector: {} + +replicaCount: 1 + +service: + type: ClusterIP + ports: + - protocol: TCP + port: 3306 + targetPort: 3306 + +image: + repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/suse/mariadb + pullPolicy: IfNotPresent + tag: 10.6.15.1 + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: + runAsUser: 10060 + fsGroup: 10060 + +securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + runAsNonRoot: true + +# Password for the mariadb ironic user +password: "" + +persistence: + # storageClass for the mariadb data volume + storageClass: "" + # size of the mariadb data volume + size: "1Gi" + # accessMode of the mariadb data volume PVC + # If empty defaults to ReadWriteOnce when replicaCount=1 otherwise ReadWriteMany + accessMode: "" + # flag to indicate to keep pvc upon helm uninstall + keep: false + +volumeMounts: + - name: mariadb-data-volume + mountPath: /var/lib/mysql + +volumes: + - name: mariadb-data-volume + persistentVolumeClaim: + claimName: mariadb-volume-claim diff --git a/metal3-chart/charts/media/.helmignore b/metal3-chart/charts/media/.helmignore new file mode 100644 index 0000000..1b9a9cc --- /dev/null +++ b/metal3-chart/charts/media/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/metal3-chart/charts/media/Chart.yaml b/metal3-chart/charts/media/Chart.yaml new file mode 100644 index 0000000..544c704 --- /dev/null +++ b/metal3-chart/charts/media/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 1.16.0 +description: A Helm chart for Media, used by Metal3 +name: media +type: application +version: 0.5.0 diff --git a/metal3-chart/charts/media/templates/NOTES.txt b/metal3-chart/charts/media/templates/NOTES.txt new file mode 100644 index 0000000..c6350f5 --- /dev/null +++ b/metal3-chart/charts/media/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "media.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "media.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "media.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "media.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/metal3-chart/charts/media/templates/_helpers.tpl b/metal3-chart/charts/media/templates/_helpers.tpl new file mode 100644 index 0000000..37c5e87 --- /dev/null +++ b/metal3-chart/charts/media/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "media.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "media.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "media.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "media.labels" -}} +helm.sh/chart: {{ include "media.chart" . }} +{{ include "media.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "media.selectorLabels" -}} +app.kubernetes.io/component: media +app.kubernetes.io/name: {{ include "media.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "media.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "media.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/metal3-chart/charts/media/templates/deployment.yaml b/metal3-chart/charts/media/templates/deployment.yaml new file mode 100644 index 0000000..9dccd57 --- /dev/null +++ b/metal3-chart/charts/media/templates/deployment.yaml @@ -0,0 +1,66 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "media.fullname" . }} + labels: + {{- include "media.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "media.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + rollme: {{ randAlphaNum 5 | quote }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "media.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "media.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + command: + - /usr/sbin/httpd + args: + - -DFOREGROUND + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 80 + protocol: TCP + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/metal3-chart/charts/media/templates/hpa.yaml b/metal3-chart/charts/media/templates/hpa.yaml new file mode 100644 index 0000000..0bd8a10 --- /dev/null +++ b/metal3-chart/charts/media/templates/hpa.yaml @@ -0,0 +1,28 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "media.fullname" . }} + labels: + {{- include "media.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "media.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/metal3-chart/charts/media/templates/ingress.yaml b/metal3-chart/charts/media/templates/ingress.yaml new file mode 100644 index 0000000..576ecb9 --- /dev/null +++ b/metal3-chart/charts/media/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "media.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "media.labels" . | nindent 4 }} + {{- with $_ := merge .Values.ingress.annotations $.Values.global.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ tpl .host $ }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/metal3-chart/charts/media/templates/persistentvolume.yaml b/metal3-chart/charts/media/templates/persistentvolume.yaml new file mode 100644 index 0000000..8ebf28c --- /dev/null +++ b/metal3-chart/charts/media/templates/persistentvolume.yaml @@ -0,0 +1,18 @@ +{{- if eq .Values.mediaVolume.storageClassName "local" }} +--- +kind: PersistentVolume +apiVersion: v1 +metadata: + name: media + labels: + {{- include "media.labels" . | nindent 4 }} +spec: + storageClassName: {{ .Values.mediaVolume.storageClassName }} + accessModes: + {{ toYaml .Values.mediaVolume.accessModes }} + capacity: + storage: {{ .Values.mediaVolume.storage }} + hostPath: + path: {{ .Values.mediaVolume.hostPath }} + type: DirectoryOrCreate +{{- end }} diff --git a/metal3-chart/charts/media/templates/persistentvolumeclaim.yaml b/metal3-chart/charts/media/templates/persistentvolumeclaim.yaml new file mode 100644 index 0000000..7cb52f8 --- /dev/null +++ b/metal3-chart/charts/media/templates/persistentvolumeclaim.yaml @@ -0,0 +1,14 @@ +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: media + labels: + {{- include "media.labels" . | nindent 4 }} +spec: + storageClassName: {{ .Values.mediaVolume.storageClassName }} + accessModes: + {{ toYaml .Values.mediaVolume.accessModes }} + resources: + requests: + storage: {{ .Values.mediaVolume.storage }} diff --git a/metal3-chart/charts/media/templates/service.yaml b/metal3-chart/charts/media/templates/service.yaml new file mode 100644 index 0000000..93598e5 --- /dev/null +++ b/metal3-chart/charts/media/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "media.fullname" . }} + labels: + {{- include "media.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "media.selectorLabels" . | nindent 4 }} diff --git a/metal3-chart/charts/media/templates/serviceaccount.yaml b/metal3-chart/charts/media/templates/serviceaccount.yaml new file mode 100644 index 0000000..3badde4 --- /dev/null +++ b/metal3-chart/charts/media/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "media.serviceAccountName" . }} + labels: + {{- include "media.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/metal3-chart/charts/media/templates/storageclass.yaml b/metal3-chart/charts/media/templates/storageclass.yaml new file mode 100644 index 0000000..6c491aa --- /dev/null +++ b/metal3-chart/charts/media/templates/storageclass.yaml @@ -0,0 +1,9 @@ +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: {{ include "media.fullname" . }} + labels: + {{- include "media.labels" . | nindent 4 }} +provisioner: kubernetes.io/no-provisioner +volumeBindingMode: WaitForFirstConsumer diff --git a/metal3-chart/charts/media/templates/tests/test-connection.yaml b/metal3-chart/charts/media/templates/tests/test-connection.yaml new file mode 100644 index 0000000..f96c62c --- /dev/null +++ b/metal3-chart/charts/media/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "media.fullname" . }}-test-connection" + labels: + {{- include "media.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "media.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/metal3-chart/charts/media/values.yaml b/metal3-chart/charts/media/values.yaml new file mode 100644 index 0000000..9f46ebe --- /dev/null +++ b/metal3-chart/charts/media/values.yaml @@ -0,0 +1,117 @@ +# Default values for media. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +global: + # Global ingress annotations that is shared by all the ingress services. + # For example, use it to override extern-dns records. + ingress: + annotations: {} + # The IP to register with external-dns for this service + #external-dns.alpha.kubernetes.io/target: 192.168.20.5 + + # If running in a multi-node kubernetes cluster, "pin" the media container + # to the given host where the /opt/media volume exists. Uncomment the + # nodeSelector and update the hostname accordingly. + #nodeSelector: + #kubernetes.io/hostname: "my-hostname" + + # Comment this out when pinning the media container to a specfic host. + nodeSelector: {} + +replicaCount: 1 + +image: + repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/ironic + pullPolicy: IfNotPresent + tag: 24.1.2.0 + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: + runAsUser: 10475 + fsGroup: 10475 + +securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + runAsNonRoot: true + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: true + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: media.suse.baremetal + paths: + - path: / + pathType: Prefix + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +tolerations: [] + +affinity: {} + +# volumes +volumes: + - name: assets + persistentVolumeClaim: + claimName: media + +# volume mounts +volumeMounts: + - mountPath: /srv/www/htdocs + name: assets + +# media volume settings +mediaVolume: + storageClassName: local + accessModes: + - ReadOnlyMany + hostPath: /opt/media + storage: 5Gi diff --git a/metal3-chart/templates/NOTES.txt b/metal3-chart/templates/NOTES.txt new file mode 100644 index 0000000..acbebf0 --- /dev/null +++ b/metal3-chart/templates/NOTES.txt @@ -0,0 +1,3 @@ +TBD: Document the deployed application/service endpoints + +You should now be ready to install and configure ClusterAPI. diff --git a/metal3-chart/templates.obscpio b/metal3-chart/templates/_helpers.tpl similarity index 69% rename from metal3-chart/templates.obscpio rename to metal3-chart/templates/_helpers.tpl index a34873e1449e7225f5dc6c7c9de950e43c0a2147a3245fa59b943cc39e5cd868..67024ddf677cb808435db5143bb97fc37e505b9643cc02d4e398560182db87f3 100644 GIT binary patch delta 9 QcmZn=dBeN8h4Bp=025mSxBvhE delta 803 zcmc&xK~BRk5X=drNSxpSn-8QmqDjTA&>kuwKy5CZkQ;AEB-gfL2k0q0iHG$OI7t(6 zfWob7$zzW_TF-cQ_Hj{@*bPc3<77QaiK_`^R}B)HMJ*EA?Hv)-`qdvC^VKPJhfW50KCuLN&gi?YzG&=M14@x9IpEt a$#S~5n=gYPX!^UVJ2={W?EdFJIR65fnT8+$ diff --git a/metallb-chart/charts.obscpio b/metallb-chart/charts.obscpio deleted file mode 100644 index abb1383f99ee8639d46f2cfa69228fefbbb887f5d9a9f27c4092133c548adc90..0000000000000000000000000000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141824 zcmeFa?Rp!zu`W7)kFKI4XRXZ4GAUBBJY((U?4xhXBhfOyWGT;Vr%AR%S|ppp56N;S z=h+u>&du#BIqzElx`Adl*^=$aB$1La$!?%fC=?2XLRF#kL+OW7xm5PsFWQ&w68@f* zgAPAS<;&;tSt>tMpQRt4Kksb*7_7JSZ}U;s<@Bd{9DQDzZ|$x>o=(;-$K%5FkCSik zht^H|ozk-QpFgbq2>+69e-KRle!o>{k2^%d!l8XBeP2L>XI}^hO@p<096F^9(rW<@ zFCK`)i}Z0=n+AhX-=78`hD8g-1*IR$z8e2|ekeP5l-CXXCHzqKGw|3Ydlc{dLH`?n z)N2OgNiQ63c{l4T{%92cEEP+|^0SprFlmo_qp6hH_S*e$*71h^w09GDw`0@@#$I^o z9aO6;-Ea_WdEM!BG}&5P)5Bk!4N-JF35wIpm0p`IEhw?p8~9hjWUU`wg$6?5w%eNq z#nJF;<$Bf%A`JiZ=a*i&Sbk9~6-s|v8TxEokN3(XoQ>PTWNW1mwRY8;c4w_(I~*9m zW`?Xx??$MLzVv%-^eh~%5M$}FP+@b$<=+nGGXC<8S-BjTIlFAk%-EVaWcatbzrA;| zUmSG4`Q}N~$(29+B_f6zt)IU&wCxS9ij!_H=yxW?UbxosJ6FM)E?rQC3%%iGI37rc z{r>-)Oz--^%S&)*Ve-q&9|zxgfA~v1Ntq=ruzbNHWS%y*=ecf4D{+m&P0qfotSsi; zmG8fQ1@;|*`?kLS-urJu#}qF9^UBJTCtgiB%-an+!ODtNA)C!qy=w5wtTzq@!EicR zS@{VJJst)S3R~V^Eq?y%%F3@^H5i4H-ZUKFdB1uU@Ham65PH9^{93U7^pE%%-g_uc zxrYx$Bvc~iO}{@2(Dtw1PXQrw%7*ARK7)1K5A#a0ju>wfz7e4Vlebu{h$LV ztuXB4sr*Po4p(-0Gns7$8g-tdaGR{3f*s)u=irL5>* zUiOB)DT{`!4?&yQ{`GHvpDWhC_3tJ-{jh!Q0-Xcc=}n05ZZMu!!>Qne8V2=Czdwm_ z*Ery#C{n68n)UlBs1JMnBtmhWu|1|%cQNDcI8jkDoJ~Olew#x#hBNg^CJVreV!2pK ztpFAt_u7-4-mtUX>5PL3Il`)0UjG529>RW6?bC2fV)uqZ@*g&T*huRmfGfd^qKgKI z{g?!84E>2h&ISLX{H&Y;UY9NAZKWId{b|<){UfAy67+pXQ8H(4Me1VHwU&C+J{^axVA+HO5Kb(&&ZU}`^)4vg4f~wUdf?|q z-L1&U+4K8*LEpct1z7Aw`sljlQj+j)WoQz;uygNflUW-p{Uin1xq)`uoAw3)=GuIN zb7+QF$H7fNX=Y6uuAV~s-EcS^hy6YjA*d~0pGAw_$!s$9T7ef1@!ut+J9Oc{KK1_E z30ku&eqnun-umMqKLgDC@n5}g?EQ6!NhL9lW z`H4T7LX^aVlh%J-7+Vxh@qQ1o2Aa@ceog|Nji6`+wJ8B#-4(gfap_cr;DWZ%kaE_1 zhiXHjzQIOl-0LJN#pUvp8I7S>PrJcvQpD$dRgwAH?t%_gWIgKjeBt_WO)#r$ zq>p#0-PK(HLP;fL6}zhPx~)!H_+W3~j{;klu=8OpD!v8^1^xskFJ14uIa|~EeQZtZ8>K+o{g&98 z)&(xhy7uBVupaCK#Ywvx4E*AUNjUuGZ!4a+`bYI-b<0~d))Bre=z`(+YOOQ&FQiQpz;0beFho zv>r8XzD4+~j+GUugRcA~Dz<9+r=R>RpSlw1*doOhS+j9x!8B|m=rIVV0}H8_)SfIn z93Yf^SHU+?Gng( zG1qVFU7|awJP70a2z%S%KW-N5t$Y@>^(>6L1-1)@vjNJ-^GrAv+j$XM{Gt9)gw#3YCJ`xrp<7^2QwL?a{{8g z&6ZXUN~)}Xl?K8e-o3e;qbF+^$;9vGFOu=|@=+DB2x00hgfqm>#wMwTqS@7ehzZRn zi8fYa!|xaDUkylT-AiF$*5O||Bdd3KyDdiZ1P4ZMk1i|W^b}?TPTqN(1bzjU zFH3Zrx;ERIXJ$n+zZ3MfMk6k1jl!zC|4)oU#54EheWf`jph?#Z-_I>_d}|>lg+;q| zS4js*8Y?GZSmu*O_~;&5^a488ulT#w0Oq(h(ewI(NfB;NWY1OKEiq$~b zhivA;N*1wX5u_x? z+JYb=E1;xq9Sn3$KZtCL#u*zKv1jNCYPRWS1W{u-wAdj@R#QZ8sik|S+07BahSaw@Aanf>x?K+q)i)yI`%D!Bl_^>^x5-MmlSpS5p_E zBb$|0%jfxRO&PYe zl{sELr1J*1`x4EVeio>mb0R_d7|$hX-&l|n{c>dKbCL!G5#9H|2#|ed+_UMR~ zH#IU@i=2MDK&oM>au0Z&F3*j7>Rg>0Y5;W)cozdrktul)XBpFRmwt0-r%47?$c((H zlF}EnlA)WLN(u{WY}E^Qrlvq%U9w|SU`!uZ(|Zx|Y=jMT2Y6FZ5nW98yznp=(g7vd zwB8NqZ|%kG2KOuvC+yjbOPr(reGVU_*%}Q&(8Q8?$z7zjJStD`c}rZ%@CowSik{WH z5u2GyMHcjBYT%b>BeJ?|rH-=n(sUqQ?z703nMg)mc)(nOkRA9#o;=M9gNViQvOLx* z@qAhg?Q#}?Z$SDU9% zE7%ZsY~u{1OhO*+R`)XZA=zZk+JFPTnH@y&qkAQ#Vo#3ubVXm!KzIukuTPi+-R`k!**h37|Ca9{`$IuV`| z7gv&-QFJAi8D;gU=`gPXrYL~6s9Cni#F$u=b^s*!2Wu&Opb^TEs`X`a5PBZ3XY&IF z+KSiR+#A$O$a$Cki{aWL%kCAQ^Dly(E`#S+5Q|D0!a_An!FOhI@`NV=aW#9%Scq&A zjArH&I72U@X z?ggBLo@-8*?!-HS|L(Q%&FrUP${CWs=4LS(`#h~haWJ< z&%|pT6E^rb-SSWf3LJNTr{nMv-C~oT$4R#3Rh1jF4sQa0$eO7TQ+7zS9XrjZA_*(F z2k_d)M+Y#tvP#!{IEfY7i~wlU^y`2^?||{72&+#Zg^lZ!;9WLj*qGRt*Mg5e!b#yb7FQ`)PJVZTzBI?v3LmTE7^aG)MxG7mZ&qa0mKQ}+DOe-MP3hUFz|dJc7$Pnt9T+Xy zTOPfd6@cC)czgQPQ##4SG>X9DW%s*C)_O$ zkya(u4(o9KGMJa&)#g@0)i6*H+H}{uWb`e#OQa9a+K9A<7Wr|Du#r|{#`ij5Fr55p>UDiYB@=tF*Pu6H z2rt2zDULymjN}t<5<)%lt{BMN19E9K&^Y8$>rWGg@t{%H&hIddqM3w1c)p5(AjfpP z)*Xinkmvy~h@0h=B5>%fdPU_IS&WMn-G;oEFGc#HEJft11rT9$(x&lQ)~f4E3QLcg zkbABWQ;+yY#2_Y|f)SovFgn4gAKvK!`b}|;@N&@=+k?d(GJ)6+k$adIz#r3s);k|j zO5=FIKHjMnAwF6F$j~hatk`o#O|{dQ%tmx34+Ye8wMSNU;E9$4-efjXq6Gpe1)gA` zdBI{+k7CX7ipLg5X+clCP=fs7cOI8CyiR`Xc}yYB6qJA4PqwP zr?hUh;Ug{ZpHMO(aMTC}kE)CADXE5K-#Csdl6h1wq)O~RZj=cYf8xCkTb`KA1s5$W z5I1!dOa-7h6Tv8FxYBc638^Nr5mcGPgFljdBEd;JYpCE{A@SC_JyVA>&&WQat{`oh z7XB|K4?S(<*R&Ls4Y=Wio8nGs23YwpWDsscWK^JHqR68FSSJ^7ZBz>I6R!Z##gbdz zbr6hnry%y=llyVY`xDv!{kI)Iz%eko^sAB()JcBDQt)duZGWYY(67+xrU4dol>Dyv zUw?|ADc_@G3Ccj*@87fD`}aRbU3_@obWQXa@$^=&=9=WZejlq#?}7e%A}zQWYEXEN ze9=?3y#Ep5uc`6BzAb+L-5;Z;ieKIfA8mPr#coBfA$j_UEF!J8yg!zs=Z4<;Jp%OY z`K3i!a>{7^w9UaLS78I|9$NrPG)l!4EZ5izC~db;u=crMG+q^5Lino$%5H(@E<-$U zk396O16R{w^~*?Pt%@WhF*BDek;Is;PrUz|!;6rPXy;#a&r?*u-2AanOkKtt$}V4a z8|X5i!hb4GauPEc18*21vNrW6*ON6EQ9*@*8mBeYuKrcPlvxv4_{YUaF9Q%Yy4^Z9 zIVdF!?<#c{waFPyXdmN>-wY9$ja(DDxP0h6k{tzz=Lw}jRq$$adpF;#TRQ5~L%8@1 z@#4_A)vk@&U1A3(xMEl8s+;;y+`s|)T#%{lQ*&gGsQKtkq-gh)x72c|PI9VIaK@oJ zDlCVS!)#2W?W>@~8lqhgo%uBjqlgV7L!CugMY~hgNXjAzTur+uJO~Dew33L-VAvkt z$)d_N3n0)k0PoyEwbHUbIzhr(`8V-qp}tu(IIntt|9c^ZDE0Y|hF4)H@H?_`TPtqA zH|R}e(kp_uM>A|rN~HnHt0#bq)FSfmq=%=rW2XjW`D$u;I_E&CiD>*8bwzYj#jA6l z-)nb0eFBI4L9i;QjS!fG3mp|?juS*M7pUY>oraIM+wl%vw<5w;_YtdKoc_o2;@l5g z9&p}VZ z!p#n5z6WNhq}c=oz#2%!!$Tx+u`I9P0huq@dA56QiCruzjRUiB^9IQ0(}R)7BhSGIIK;L=l4WRRP~(}N9>D4=4H&XW zVq29%7coVHG40x@tJua`^(nGUm2g54Jp@7$pGaWvtp%oWu!i#GJxO4mDIxHC4ZpHG#UWl=hydU3_j1al)ZK=`s6B z{!GM(wl5{-Gp`N$`9>7_xg{xuaEIYij0sD%kRrl=8{t0GT3+qYyJFtyq>gS$=H%iVd4i$8mT~CzU3b+A={@%&5fD_|C+~;g|S2Y7PlKt*C=&-4?~K~2`UvJB|yvt zYTrrt5NKE|8JHV`#!$wbq48kZM5DhJoOhl_JXPnYPKl~UnW{Ssv8lSI1iQ#ZZGTi* zzJMsSWp(%-Bd8jtG78W}n?+~v6AK428eI*0pCZ_@?PjBr))CT|yLBWS;N%s>bg1-S z1(pBOl0FV3bJ=WY!Ba;!Njy%}_Wd%9w-d0coB6^u6v-8*cWXcphY>9tLyRYD9p)ce zgKf3okK4?g*q*{%vIZjKi~=1&QWs9TLFY*%m>kNg9f3MTvt9^STfdhL57}HXh61H% zLb;D-iG(b2fmhwH)$vsA(ABc11|=>k#_O1do@_ceKBOjgnmk0}aw*~Y9FAbv8HE@O zwaE5+Xbvl1iwZHI{(|Use3^zxa%20%%?9;SNrxi(sNL?-(A$N|-QV@GH*sj;d0%;~ zI4Y9@2Z1V2{FgCWwxmoJR^+vy81WVtTsYmS_c&7yrIFDP6OINSEdh4Z1pu2!7Xp0K zx*FMXfsYbwwsUw&rV{1JZUMu}IoP4D$d@dKcBUbY<&q<{2m?0Qy6l{)V?;+v@s;{> zsIzmhXG$B)j4}&AM1lvBA}RES$D+J}$WKw>FhfOdn%OZ7dRN^RruBR$SVyAb=1Im^ z3Bt{ZPgREh#yv0{Fjy!_nI!GOUPM}G&y%p-Bjq!CMH>(n2aX4lTyQB$@5!=3QRsGH zy=YHQlv>*hv|<@|#s21u(t_@@j^S3Vm#b!gtI?p*6#K#FI9HORAiF8|J2D7e!(7l0 zCph-4gBg+SGvv9}*dI>JsgyD7Mq6R6t0Ocilag#kHp`d+vS2tknMpC!r_gL)Fjj}s z+yacVXiv!4Tp<@MO?T6c^#wQ#{ExlCY_R36Z*n`A^#?NPVhai>=|x%~=|g6@pxq6R zB13pqgZUYr5E3IU*ka*kQy8yyz*9kcz%r2|uxK!+U7Rw@S~R)CDer(2s_l>HRYAGf zg$+x^4T7_9q};<6f;kcw4U1>oJ4A$RmIki;XY=vjy~j{;k1yz3G>Y2P5jSOj%Rh|t z-N}+ygm|AxD|=R$VO&GKTipA!@BNw_e-$d&)_M#W-Rbnpmc^r4B|$s54@U zR0nTZYK(YTKt9-^!V&byU^*Ku9A!m8?JSrHP>)7^+W%5CJOJ@T@(@uYp?TWfhhfkx z1L{a!H=cO=7H!gs3A0FoNKzM4G0=)$^(&_|-J2VDZjBqqRY=fw<--J+Z5PnSK(gF;ykyB0_ zW&~v+Uqo%y^Esv8og{P!gIxTQbNIv`UmLblrZ{N=$=K0J`5L_y9~{iUh5h!YbW)S! z4>7?d7e&ru0d(ubS_U3VaO7gD$_8T;UY;3?habpaw0FA(xR^D>SL6g2@;yrRTJm86UQ|;X;PNLMeG~nebaKZ+gXJT`_#(eu0 zj&AgY^P1Iz@6v@?{!OPsjj~bMd?3}$hE^Tl;1EV1^#HvTDk!WJ+T7Qm2kAKF+dle} zVb)l(C1>H@u2l?4w`(3!fZ+40BdKLrnFl*WxAHUzWZ1TzIzr z;@OMmKdisVwG&fEaxQY_S3cFJ*U3%4qdh}D?)?=vdPjSigA7A~xN9%bL3&6a2jwR} z8mhd(#mo)`209hkJUVY&fSZhs+S%!@ta&%%%PeLjRToYZMRtebjs(+qvZ&1rPRS-c zZXX?t7hY&geEV?JgS1`?8!t*k(Fq ztBc-f`MeNePoj}?Nohq|7)4W#fz&(qUwYv~xw$9PZR=}J^pbdVD&G85l5E;8=@Sv5 zkk@j1De)EJxrCT1x@0v{g&Yx)drivGH7a`fS0;r_-t|e9jtqslRw-S_SPd7gRjR0> zG?m~*wnJ4mHtFA!la|XBeV-Soo zCm7(j;SdoLuqe=(ZZ=vZM^q#CU}b2PRL|FQ&g?sx6dOE!gumWnBwB~E;0L4I#84@e2UzAp!_t6T}D#U&sIiy?x?kkfC zoo7wAgjD9B8iQ+kUB)n@=ZVuoMXdRM!As9KH#Zh(k){&E^0vH=j>r0zfjr+8;VEBJ z&3*fw$7{^I|NPHIWpYs8^Zxr~PNbGl1!Q162sR(LxXcLlHqqsCp#TAypNv_QIk7DL zAkTl$3$uifo?I9#lY`n;eR7&--igy`?AK+6H2u?AdFnI`z`?=M;B?#G$*D{`8W(c( zNz8A?^Upgvy?G|Kb$ofQv{hJ<5%J2P1sbaI%v2x(e*$a|En&FOkfeI71l%%voGKgO zY+BA8Uxg`W)JY0DwA%+(rYd^WktjFxO_^x%@)Q=u9E5{5Bc}R-oGJLY;x4aT%GpK9 zDR?+Wm;&4ltICHl4_hIE#as}YYrRwlH;IPe#@P>VCo+U$VueiN%{63v~?_!lc=%}?Bor_(hlu=s37lX@7ETuUb!c_|}NzjQ%7GI(Y zIbYAR2k9FF>Z+!;YI>im_ninRrS7O7(%c1QBZ;tb5+7 z8x7U+C%txoEw8Erc2p8CE@*3jl4H;i>S%{C!6n6-mDpKu_QW2WKW8^O@J9tz8zC|S$!}uHrG3&Czns1fZS%=^X3YTK zk#Z8|4hHJrVp-)RIVb6J9IY7a5lz6TYnlMO@((YT6F;(Im7j0?xX8mqwGjE4EZevl zhR$ceQWNE2*3euOugOfDGn`^`hO;i&n`sYijRWatABABXlVeU8TNEmbmz-W!X5**g z%T42yj@v>4mWdZ&u0g4R6H#o!&CyB+-pK7KR%)OQDB^M?lRNY8m;4i|8?dfEG^JdAyV3x|h=)FF^ry_a^JVKwlfM#b0^$=#8* z)-RteaoOe6VB{XQd_fK^k#p<*QiQd(RTC5@TAs|&O=CflfdSbA|4RFk=O7pxv3Yqc z>c$<^Mcl~>hg!tGlAh5hsTD<>x%gb2CN3u|o4FrxS%V&pc?N=INnv9k>M;-05>I4R zNB#S-v0+_0lbMkb|4S`b#2Y^Hm$fOFk5&q=GbY%f;R;Y!;fF81g04ybMt4}0E~w{= zu!z{Hzz~`}9^5SIQ@cg(A-fl}ZOHZ?`&<|sVpdR=fQPipd&=?;Hd1}`nQJTGU%@lf z%U$IjLe$`3CQ1HYrPpjL4G0~2hisE8J#>m;Q zQLgobHY{bPv6k`{7P;Wwi_e_Fi3ZjX-=TM|#>rA~Kca{mc7>_^G?DWPsQa%XNZ?@_ z$;X{UII&y2zzOZ{m93sYA!n58d1Xt`y~3g2}0msM&=ty2YbuH@J7|0_+KST@>yx(S{x~E z${$QZn~%Q2Vv!t>y!^x-8cIH{8RD?~mDY@V>>;LMRYj~W=Qd}W)=j--rllOy6}qU3 z2;%8WIFJpkYkXSHV)qkPdSAZ0&*WLB-?9mM(#3c@WEM=(5pLB6>Wj@xkO zqq2r8e=BN7V)xSZ??q|iaV4GtV;=FqgBT}+6wqqHk<=LXp*!IjrRKisA?wCRgzG=v zvm?=Qp~}WZX!-sgrj`=6xg8^4J1q6j&n*%l`^YNG10`IhQ1UFFh85Q|Q|X@j0|HQ7 zoy!9+ZqHP^haw)gmDhlC&qi`<@5^G0RX4FrtB|IJ;svE9!-XYsqNR#0CXHF^7IB9o zIMgyrr*7rfku-mr*f=bn3;Ph6?#)I6@N`V3+#`fk8H|HTfe?yn zXwwaGc+7Z7@ot1R5xKlzWkoC6&fnP8;7m;y6WhYzp z95EcirYblU96U!lpGuZ3It1a8L2>#eC%{%l5q-e|Qw^%q+cdJOBWL5qlIiM=175(G z^g29eSLe|<2A0O>I>X#>xY|eEQNgT-#;G87mNEKPs+Y5%q>=+m1|x%<97?PHKA@|M z_o0I1{zpg&#jfdM!WpJy6{U$AF`+K#F#Uvj{mTq)KDy2cqUKm}Y zQuHagO7~QH@ua5|HT_*Yda4v4r4O5W?NEfR8o|z+J=h5~i>R1KUFH-*_SX~^H;7@O z&CKz@GC9PRlQg-b;N_%`LM`{;E}@Qs zCd`c}yYU!VSs6Hol(Yy*(Ny3~4&(&WRhB*idyjQj7Yr2ogo?Tm1>PL;55r-B`JU7r zV@dd$dT7HY9&?gs|7A9%o2gU!Duiz6# zLB41#7YZcRhg{RaaK&PcE)keY!JEeyc)45{BM z`f{RFq@aoG8?;U%$H=Uiv~+ax2_Xw7wS>S;n^Wv>pzKqb7=H&d^^heNS1T|@IO5yv zciI=m0+ZS^S~5m#fNLwjGHo(_Ookq;Ib3PkW^$E&s+AMUdl-Ol`3nH7;uoCWFqtwM zvcRAOv1m0@$6Bl96rt7-KqxruK<;38(uvG8PDmT5)JsVl)<+URh6qBIvdg$7 z>@r{y^?3obST`^?z|8lRGje%D%;Dbht!Wwa;kgot{i;)LGcukXXY;#L2wNnOifo56S-xwh+$Ytt`!B58D@pl^7Bl@@lf5( zFy~~>yNnmiEXCw9`I?AG$T-a^i8UvOAFuTAxCj0BywW2Q2)VBFh)Ty3pWHmR z6!Ib0zvWAH1d-Bp#+wS3EYnd17lm~BLo9I9;1s%$7O2%=g1FCly~DlZuJD=wFk1#$RbXP$892pkUuY0T`1UJuS^rfda~0xT>#mTa_qB zY|+N!Fy(%SjHyrj*oCUxRF<1Ic5xa%&;=S`Mcq!JkJB4RBC&mQwW+oNFy{(xw*Vbf z<}Wddets|YItE5SxYd&3uc|dql}+{!mri3xF%@;%ERL#!Y2&0KzxDRUp@R_1S!%iA zQNR(Era`Ari`yfY_esOd0ZyHpa}U3$?%FAdE}B<&EtflfKHYU)?zdyvgzn00@7#$^ z*4U9=J1F34>K@c@b@ANa{#Ia~rDBu!aZQSl6}T9w8_Xs}U0mN>Uep(X;<{Dmo;nQ- zdQh>A6hPqwAA|U!x|(WJ197gWW1KN=Dg9e?>n!3A)pdFC-L6I6?y7TD7`!p=apnTn zFJjIGyl<*vaxQqkdcVwgp$w4aEQYmR?c~yG0@Ig*KRzSfrcJzp&)}q zIhDH$<22;0hYv#As=pZF`{PS%&KRboxbxU)G#}tnN*wh1OW=SwC8o^0?{b*dj z72q6cTo12<;Q?$>V79dzf4qjJ1!9tkc_wRaA|5Rb;j98Bw?6fo>uaT`h50D~x0Agv$;F8UV-ticMKZ9)1#6)4m<&SeS zxlG#AC>m7j;lI(`jJp4CJlUdo=XoE(maJPjWu7UH32o^zk>*p=?!$_oDwxX=Lg0j!Y)U9b`8;iz z*#V&v9G&7SW~kB_QtQeJW717k|0JE3uy)#pC1c&f7SM+`!Ss~5xb9oopp#hh^hBA% zC(k;XiO=%N+P8805~d)W4o37-yH;%@KRT89mpx6!Ex&yl?esV`ENisKw?(EL!~x_d zbuU`-{_!fZL_1SBH|NJw8x&+M$r-0crMhSz$K27{mb78Kd?{N;2(dINA}nHB(n^fWsS8n!ihfNj<3?m%i_{ED z)Bolh>&&!M+N5nLx83R4hOs9tIWt}VfpGbkX?MB}THP?bHYcRtd}9k6*jFa8xo8jG zV&NSfX&yE`bW^ez%2{DVryLT-UCYzfK(QH2K4a}G%ps_>8QgmeZ?`|vS;_k&cFM>k zy7e;RPQ5Is*3BLkDgw*nr*uu%a+E~{TW|N$S9;6g$%xE67O(k!7S&K;s6XrFYVyys+FwOY5!P=PF<{KqwMU@!p!_dcxj5bCQW@6>k^oMbPX|{K9 zDln;FauwXHeJ##Qs;>0`uGZvbD3(^CGD9Iu9o{w5C|Zw8&*nCCviXn#>$NI1Gv#EO=|6 zFq0YUxiN zFX@M;XSuNtWigb#9by;BF{>fY_;|i!H3zMxP|#%xZ4@dX3BQzjX?8*}zeMKV_>pB4 zGd##3nep_^P?`(Jik+YqKyT{KHI0WXU4RF%G#rj0S7{q7Aaw_8EJs7S5Xs<|fBd$x zeX?IW-QL~*E+!6%-VOZzv|E7s&KZN32@W5Cp>;d*}%oIO;%*l-E^d!TO3@Itpt884;tEX_d zBC(!g5vx;?wr)_!6bG1$%n$)@#v7PfuY&yvGCT*Xz%GY)h*L3vBT5K%bT614*Rpv!QGQ@}=q2H(RV zab^yub+FNzV(Cv7ifWs?L>x@dd^u z0q`>iCIRgMBjacy@j@cmuq{o5Gf;bL*dxKQO;JP2r6oLZ6ZU5VT%-=o%38~fF@~$5 zHL(UPrlj}UbTC?jGLVo|>hODbCF^LcDa2yK5fnr^t=qmfyTrJgCvlfEI=o2F(fp4n zoWz1L#ipIXGAHmufh%?TTdWz@Fz70LXmHZt(`y^p(Hc@<(AJi?Fk;z)KOFH2aAy>vGUp??{&JNMj@?nIOBk7_i5N{QX_M@Ig)+$Y(oaXHgvyG4~^ko z4f#X1$I0&cok34xmd6O=lW;zWn_|*N4BfYftH@yLJW~dsUHdw(1>*zNT~~~RIHW>+ z6WEI0UV+z{^+DrO4Q_hDtyZFC8WcS61a^@KrybJGG4gKHyl3XXvH{{8Svp7&=W6Xw zcOszo5|<T=YNaUe3_&Ow%7nuMyP%pjQ8yf*lems1 zTT!D@>@kZ(wpkqs&6PWrQ=T4CJ)6oDG`dH^flBPh>rcVkt?qBv_vK~5Yn<+x9|?Uy z+H-M79mfCf%YAQ9isi5~Xvq44Prykcl)XaJ#f;2vb%L1>2$cgO&$0dEfn zoB^B`^(|Ov+G;6g^DW8|b$$`Gl_I{HAHb^<1p8Iy>=R^(09SKxa46mHD_>>~4DXnPVG`l3Jp{ezY8+GPqjJQ3qG8k& z-3`mj$_}6y5;gXwHs=Knb}pgO^9B%Idu=uuuT5Yn3D&^%H2AIQk({i#?QGZU`<439 zn~IX|rg=&5;kTy<+LahjU!!XvuH4P_54a;S18@yGM%7j9#@rX6xrG;tCwUDyLw6!C<4B*3fc9AjjVSm^~qdziIgJb zxg|w}740(f9aRi!m6s6YNN)cI+CB6W9YgxWYarmj=s-#c02(cORFeo5{h*qqH7H8W znI!De-9%{$0SfcRkSA!sQe-Q2MxT%-=oA{%0smZuxRNSP64dcH!dT% z7Kg4?R(E)_GOs1qO;3>O1~=d773gI9-TQ;R+RJij{h6kbtYeHCCM}E>0Qn(nfUHH1 z7`uX{o+h!V>s%7G#M6zK)gvB#GajWavZW@8-K1js05G;;2*dzZ)#<*nYr z>2MWs2aeokCGttDDA-;q zam6NIu8OXMBd|47Uh^8G*bJT=w^fYjdxa&(3%?Bc+-9L8Tw;h3ouf}ppP)fg*J{ox zhXXnCOW_I#b-jW?fIUR?#ejPc(Ger^fWdHHhe5%>$s&c^a4e0rfP*4JAAv!`ODL89 zC7hx6;Id$#84PGaO7Ywusu#*o$#JUu!BRve$47`2YK;A%+GE8UoHUK0^sk|HsT>!; zPwO~}N&eu~n6~8($YSVJn>gd>c*uGox2>uB&!FZZPr+DUBTtQliy|a|_hV66$@om0 z&oGN)0U@1al0s_vaHE<*EXXtLIxx+qD&G&znw4TLOE_SOYR9M6J?nmd&e#Pjj_oxg zgHcO0dM)3T0IT2IPJ|X0?s0xYw;0({#c^;L3fi+~BM5b5H;{}~`k>W)M*D1h!qHSw zbm_HYrw1Kf#+s20*EQ3n_~i(OiA|rWbSxomu49sAs?KBd0~?rayOK-h99;dHceJ@L zKGq2cjYv7e>OO-NRMi|_Ql^b)EFQgqKoTvXzp^FYoHbBXR)XnmIKFm{;xdmlFvkj$ zuzihCEs?7nM1&GD)!kkXPGiU!qaM*f8QDe)vRuzb(L3=n!h!?)kzsUIO;uSgJ|#Rg z3Ds_qi;LCVLJScogl(GTSh1u>n4^r4Tnt_&YAo8I&Z3%x`0DEQ;~M+~c$s}<#g2)l z%gh~|rkx|%M@68VIdRO@q9Y7B1XS#Hq1TENpmnbG1Qx#$TtsA**KQDc1=sqo9P?5A z7$b|-l%5cgkwo+p>~3jFLIO}ZWL6phn>54L9?7VRJ<_6Wruz?gv6#;VC@y&qHz3YM z#}CitRCph5Pa2r6xB;$Y<`cU^>potIuRPzyZdB^NLhKW^yuYljQQ3qo=qdco+WfaY z@(SbQOHaw2OB5EQk>I{k&Dw1glHoSP`4c}k}>M{`kNCdjUrg22#faJGjX2+Er`{1@)@X;yZEkb~kPrHRn_mrmjfwN5)z3``tH{gQLUu2S>;1 z|Ep_|5j-e)aw7(OzzdMphR`J!P$8`vz*ns1XT2 z$77mSv*Hl*fU+lo7`63Vd1psXG3+V-3RDY~{z#5-R*rd{G|5ziphP52L+RBGOHtIh zbdGafbghgzgvCFnfUU(n%#qld@(bq&o8|^<2?Z>9Vo#XgzlSo9ZDC=Qn zt4|AM-OcdB+wM^+ofLP z3--x4&&U~vLTWCJB!NopkNj57aFt}R3JjnfD~65ox!_gy>+h@EXVDsywYxS8t6AZr z3ItN;qup48 z%G{ZtFJIFFlP+W9MjyOOSq36yb~!3%tkTtwDo5{YjU6~!p6*v2^5Yt?TYcVeQ-{^goVnsq5!x>f$4#spPOZmxlCHt~ zPn-|qC?02b+Jy}ME&3=8CO(`lAitNKa6|nQKR@_QMQA)RSFJ>KdXwRwrXEb7adVh|4mA->jw!Nt99Nt3P`Ki48 zh%*1yCaeL<_HYR7$ys#2*W&(!o_9DcOWO(!p1^CQEe``%yv;uTRtGdzzlnsNWyDjs;G~DV1Y}IAGP2AQ;keg z@k?V2yK@WoE;(XS9as)qESxiD!I{&D9`yzHq$jBnihCW#^J&1J^gR&#J za;U!9c25KGtIK!8s}PLF;v4niAH}Xlb>LZ&VG%9sg+ugri#uFHxM&roHwCUBDMnRm zC7548m;)li{v917=U!2WfOTL@?6M7k^HArpTVM$MT~8BD(TKmezNgKSWVr?U&x!Il z_|2vXRpA0Nt1&mo$M}}K`Ke-Abaj5ak9XNAIZ{jW0M^p#q>YSIrqufB+rYHB0tI*q zgDhM<+>KL#DOTW!SfEF2FpRUHSf*a9X;oN{$voe3Rv}H^6#JUNOR9leYikcWeX*L< zyrLUhvv`ZGArEn(-5bG+vM`z9a>mI^IG4QN-`#t)|Grw=et&jUfAxNQzxKYo{^R?@ z-IMpVSKI5G&!5JnPRUo1pQlEu2aS@7qzIzA5qA_65LsWK zQ^`w_vYL`>C{e_lsI|DBB>hRR(6$mFr0gN?B?7JfEMcff5GpA^mWmHYQ#V0Om50r- zBaWeyjAnF58CZRWWJ1{47^w%=ODDbPg%t>X0y8M{U`f)OE$;vpJ;;UYdU%ZO^PAy5 zulI=RJ#5I9Npn49bIwrnVpW%n@S*56hDFE0O{pZ7>mi3QOq1H|kfGj&wAr zIoZ!CTUXsQHQ{7+3#aYF*~ds?l1;`%{8B^Ihc46H$6mmYl+<^7*+m zBzN{5EaRhZQ0qq0VfX6YC$ zZA|*%kW>1YqkD5CB!l4q64CUG0M^-#=Hbi5Kx4^8l)zb2D;01u)BZeMolV^rXOR2B zHyM&rvNg@OgR^3td`YJZ`h4b#QZy|?fbN6B)R-1brc;QKNzVlJndrwXS}5H21_Vo@ z@LY?&ftdanqdYe{m+{s?l zid>2w7iHN>2$EE}YGRe6>yg}MDi9+Nk}1)2m3^aVq6yV7Q^lidy)drX(IN>tZ9D4r zqiEfnpmvVd1GRA^pp;GHe2h5@YCB^hKb+h#o12$@cxLYWSjJ0|n~zMFnM3b=H|XP> ze^Q)|`q2B=zDFLs!4@-)NGvC>HF`O~Wl=t|%Wiq!uYqk?YGwc9$T(tAn9ylToU$aD z`id@B(D%bcJi?-@GMh*X<5s3qu#;t?JqJs^(di|Sd=-&Y!?yQ)L%#L~wHb2oee_lf zs~i)Xu7cdI=*7r5VOrp#e}`QdbSos9?~qGm$t|v&A*UK)L+OS`6I&puCWuRH`%LmN zL9DL#6VAZY{j*XFltGFqIE*1vg=BfL@@{;q6T<9OYAj0!IYwuES6n$_5)hSEkexFp zqR0$Gnkm4@q;lIs9uZ~_n-EW?%^>m`+bp`qN)06y>0xc(%*%+Jx`^4{&Arb^L=Lvi;q=m5{f|lEKX`FW)w<%!Q;p_< zh&8}vv@D*p29xu{WGlfy%7B`5K{Dhb$cmYhML@-~CE1f*nQ9f8H0pa(r$+e|jE3~h zZKSCAuT^jL{p$TE5VGzd$BL4)nFty|OrC=n8Nh#KO^_BZrKIAmyCXSDb$qVDTKL0dU4^oikrdhlYXrE`8BFd8PpcSom<9i4 za)P^Nvdx%pZAqkD65Z04Lc(z|LgZVE-{W`2UX#mm4?Ui2Jb&KV{4rQJ`k@qK zN%f_yKh0zFSvL2BnYCTpunJ66yk@ksiGxc?aLBD^AW4{RZ5b{}oz=lb%|v5cbke%6 zll!&ULY7w~8+=xLu>vEQBv6EzXUjXGY3_IjS#|d&D_yL{Tb`VH!;?a{Qk)IpL_5a) z^V7?f9(ZM8i8VPmovgtDBs35TNT51Js55K`99eY*4UVC$2|s^=<2b`MA@44`n0W>RI|uzto`aIvyu2XAe9Gl(t20@u!Y=uusx#m zQ))Ws{0-8w`qQrU9BU!~41+5njfY7dK#_x{BbxXhzAJhR{6QXIsY#TWJ%k5I$i-LO ztG%xw4m1FWUA00rcWWM!y-ik%7?L&lSE0XBY<(Kz0sb`)x>xw!y)r*1H^a3U5FHti zV^3uq`Mx;09j$y{Z28yt7Z+OKUswpQR=)p#P^0O?TN*izkM{P_E_^q5%i>BAdC>ed zRUD62iZ_!s%(-iG`$m~7`N!MOsp~J62M9{pJJ~M|Iv8tV>XkqIC7O4_mm5ESYvxsN zaD}B@bX-`(*IIt(Dp=E{3#xFzNssnFC(}DP)m&oC3lnJBKBFuwoZ`)@|vrKiW?;zJMG+VI$rAwNHr;!pNJ4b0&@aa zDy~^88114YHq!ZGCd%}+^Xqf(#a+6jNsicMkSWtqi0*()mdYtMQ9t zJQKsj2sbkM{VmUGSDrJs^9(6D?KgM0hYTyIsBp#KrBLWG#*#Uau>O(2FOr|O-Tc&QesRtWo?Ka48PgGSE1 z;bhR89uXBB1Vlv*{JJjSrIb*OuoqWOa+xIlNQ)T&{}c#nSgY#&=QPp5!B~5G0q8JEb`z>)^v-%JNb7E^HNO@tdU{^WVcfgn zzzio{D)J4M7>3y)?X%k3YqxWHtg61F?gR3c}bXd;p71UcGz5>+Qltj}by z20$FUhR_gP@rFyC=B|FT=DX9z;{K2rB!k|OLapXaVqzlFY>zcx(N1+tV)%5&m2QCk zA{BiocNp7kOcs1;OilB=|!%Ys>CY-HGy3;Z82dhN8PZ>>^ z=oVZFkurB2a8>taLkl7%0bD8PaXEoXBKbmN#S^04$V2+}Lqnb3sk<0@Eu_;OPu4oT z;c{)#yDIo&C{5&1xE-&7+zi=7#(Rp&30CYU(eY^lQN^NgE(UuzuSA+TPnHiB1)U`O zMLt~u)QN~AX5=H1vASQYgE&ej#uJR28X}8t=P6`Hi)t>xbCOBvYtlyHy-w{yiFcyAZqmT^~Dy1XVl;$FDke z9HU8r0}{LGD#S8Jk7|TD#Wa23r>dZc?R3Meadu%x*2Kc4hUJhu>}WEgT#t$P#Or`F zF)o{=RhEEYvq>2ndsM|pIVdH>pDDGg9WAt|P+&0+aFe$Y-`t__Ij^U(*E|CPk_@Um z%-8*Jf{R@0;Mp7n86mmzPXw98rqb4o$^xgN^<#CaN&^E z?uKT?{X!#!!N9({FQ7qhS=1eZry$9+HhK_bArq0HZVja*lC%fNhz_RgLQ1P3a&Q9d z<2@X@GBiAmteyu=lQtZY{F|jga^jH+xoI!PniSlnzZ@J~gl5PZe=aA#-1L@GGtVU1 zmrU`HyGVT9n=os6Ic-!FMUqOVp_ry-ecFF0J05@-GJ}bTQExyZ7!$U5(jx9#>Ut*K zSZXg+UVZenUO$$^2GBrYZwyiAilWh^0MIfft*5zJYkl)s3Jx)2rMz6sSJqzOp=3Pq z$Jd5>Dj$MuFR+V8kL7FhR?exwASq}@xdA9Av9drflXX3okvtj^08AnwgvJ=j1qw=d zr_EU=q=&k|>kY8pgUoVkR|_}b!ED6?k2?%f+K4RXJuR$0R~~Ym(PNiatff*;p+j~{ zPy|r#Df@7N+8}i@=4R2aA^nou%7?P5P4M)U{aXmeiT9yL%ch%(z&)Nf~SZA4P?r1$dg$%u6|@;lteLc!q` zG1&e^j>#)V&Ch4bIy~LBAqnSM2Cc;Fd9zj$69Hfuw-WF1`fHiEdLx};^%N#6dtp%K zm?LzwgAt!3Un>?$Y>(&7Tn>11j=Q88cv|+M?PD8n&FGx%$@M%|HPwq#UfN?l%?Zp7 zow2JcpcU$OX{h386~`G(A*vgogtb8qBk6!VlyBrm_;D14N$L8 zhw2bFE-T1|o-lSjMFBCP2{2@Mf-wLqf-$H$Flife=8dgSWNm;SEo70+?a@N^Xd%0& zb(2EpA8#Q`$f6u}vP2DAP*5Ap5*B>tUtJ**L#*7#!SD*FIgSuw5t`IwBfjOO8iyQZ zjH<8&v(Oiyu@sft=Jc(V2osvfEoT4cfB(M>sPbl`|MS29KM{><8|zeTDSu%t$E9+( zU{;Rji>@ZSUi8k8R8L(Vdvtp9j3-xIfzxc`IczP)kd;g@M=Gc#iFP9U9EorEXLVW; zviW==DUtIcmC}~G$(N!fn#w~=6iZO^`R7q{F~Q7P#M~*5qNl@E875j1h|8n}irakN znwU6h;@V8}JiKc~n=N|#@FK=7zPLDA-!kmeJTUC|<4yz*&L48nl`>F@mvAxZ#rDB_}*7$gWwN z4nF>f<-ttR#?zcTOkhgo3+pzy z)DuTF&{7JH^^~PN{1XTB?aCgn4c#89tF@9CNgWt~Nfot~$DzkIt^@7c2lh6rCAwq) zV6062ROVl_prxaq#-XaDL;bm4DIJPgEvmD(KZ!=3nvMX=O9u=NE@k%C;t zBvK_)7{tO)*fwSzbyjcO-IbzD0fxjw%Gl1sZk)jT(4WBHe!5}RG%Wsg+U^esWGZzu zm1^)awU&>eDhY_$gQto(Lr4rTYMhm7y!b#H*UbJ5y%OIpBAs%OYfx05OQdC7*ih_V z=q?#lLN{<}SjKb|ZwwhLWJ6ZIjhLU^-be(Jnf_V3pBP>Bt;rDIs0lUAkA_dZN(g70 zr{4ZY@IIbmNcX~Ef~WE%O~TobbJI+r`K2kQpbFDtN##Pu>1#U^KrmrVAd^JY1=HYo z9;~6do;hhvKUrBfq?%x85_OMZI4sD;eyMF}ilQBxpidv(oNh`^(G()+3C|!9bkXrT zGx4CHawGSa_UwGmrYr6z&WLe|vxL(x8|S40OhL}g4o1mNS3X=cKNjLFFOngzpqhcu z8Z7LkmWzp$`z~<$w?S|$9F;=EI}3^_oKg(ic6%D}RE^7&dr)^}Jv)~BV6*3#?d!+c zFzgX0`!BVAr{kJ$|#hef<8k zx_`iw_G9|z1z^7(x2kc}9!s|9KqvtXxJaG`^zI;i4WWmwifHKK0#xh}1X&tW2$G*j zI|`!7?t!rm;+l!;QS72=q+E7ds0fy2E^$r^mXeL92hrhyWt^9YSD8_SCtfyYmrs|0 zAw0sBH;CC@9^*#c9ly`mv@v#Vuy-Jji`va#cIw@nf`v;Nc=RoLya6gvuo2WWsw`lz zJdBW{#$%Ko_jzd?!qq6bVaqC)a5_y^<5U2VANP6gO7H%9+~+BJm}Nbi*HpQD^F5}q zf%~}6gTZOb%UCL7dg)s#VcO;f^>Lra)#`Dd7xTyCJ};&Pzdi2r9`|_>M|{bBp12XE zt%iA4K=C$GscV$gwsnOI+n}A#`QG&4)eXA<_s`K*Z$v*V6irjbJx94`wLY}}R;>N2 zg+m<*I>$NKU@5dBZ|#&=o`vT72X7`-#T0vy_8Lr>8ypG)ZO36KpF3otQj(Gx2&Fv! z_i&07W>52l1g|g(kh+Tuk~X-)vF$8qb;Iylp6W!JX125?zHC>50?aesCc1+=0{d_# zJ+76e$F=fqwb6N9@9peWo39(S#>MNmrGrLQ-j$|%Z%36{qknkTukO7q?cbgZIy;?G zfA{TK=XJBOd00IwziZb|HcpzOpE`%vr_t$x3?F~>H*&Ewsd{K-9wv=#&zec)$E@)hn4HM zrPurCAC5kD%Kdkhdh>Pl-PP^cb#>>Waj|jos$cQ1_dnH})p4ivqEUa>uLRed-RiJ? z8#KzlyscL&&BM+H;GQ=3%bWFgqc`V`@2OinJbQb6a8qwIZX1J-eyef* z@%*}5y(sVBy?IytP%T}QFPfFz`dRf=<6UQXQRfdpcePbdBBPp$IBd2O&csSZw_oquTd0e9f9UtGK$p0BqMnbbZj zUk7KKr^oA~?%BbP|8`J)TdV!J?jLmCH1>9`JI$`&*`J;@N)?Rv=mFxQ64)~({rg^rxS-t*oy)mp#&kimcfZOX_f1K3!n&&~i zymQ%>JGQf)&FlKR{muH} z>*LCx^Hb&1!SnO$i(&0u^V#0puzXw|z58kX_1LfPtXKP^{@L}5i#L0XkFD}((!M@u zR6f1FIoUgUR(VyapPjv!RZ62*7tM?7^NmW_7I}Xn!vG6`kt)6 z9@O>@&Rb{a<%_+ypX#N`8ODBwd9z+QYx-{vfBY1jHIMy`i*f7v;%(!w`TC^sVyE?? zbJ*JJg9$2?>UyX9=J3F;9hNbdr<})=<4^sQ+Mu&{{$XeMb}&7ymrhD&!{)OV=B2-1 z{i#{r|8zEdy<6KDoxJT=8W-;>Xt{q}Y4&g1@2Y3b=Jk60RrRiV_TnJuH|sx@`xC&u zJsWo3ov%0Fp1tb73SOOTUNowc>PElP9K0R-XXQ=wx85i>Zkoez{bca*`N{BNx3*rc z)Zgt~pZ7a^Z_m23P6>7D&0iYpox76{RS26=DFB}w-%Zvl8=cLcK6Phr`$rq#|6iK* zgQNPe)2x2j`4sF|&pP|J92~rA z-hp2HUaw+KR*=N#VyE(IXXowUN63}VG2m9uKUBNt8>2zcY);zy{hc?>gRnL@m|X0i zZ`3wAr?pqjK4n0)Q5jd>U6tzV)0^hr&dphKRO);>=v7OvKU5E=KI&}L8dc2KgI&PA zIcbzPnvgFS`>%)f{>2e+IH(Rf)#llYQlnovY7AZ+oz?g6ss|U(AQN^w``uBie6@Zt zfINNIIfC5VZ}yLF{p;7ekd23}(m|7OI|r}pwS(6;wS()AC)d@pU>{>Kglsx{ab6i* z^sA81)mNPhz^$De5TC0X$QZ~sJZ~J`K>odf{2RB=x?{i5-t2tZA-+3}ca_7pje}FH zBSXNbwXR2#v$N`llls9c$i|On!|wAc=5=)gYtH&;ud?1etM}h-_|5ZjXXEIu^{#){ zdeu2S@4fIFX9xR!>Ek)^Z9?aG(`>%0mz(|CyVv#3r^a1puQPbtz`N%5E#y@1{QBf3 zXdaCl<^C^?!|n}m=`~+qiq2pSlN ze)lA3Oy3-@S2q3Yay8hi9{V45j!q7)O0Bck&s(3G7nR2J)7jbdyxAz-yxBiE?VMel zv>|P4<;r36@M>J!KcM{eTjjT#=fjIvwe?NEGpwNR)ANgi1I)Q@$-nOUjStOVe%fek zTpUi{zNx?70l${32Nl0n`*DoP_N=u&-TA5X;&tm&rv_Tx)?QWKQSMySJC*a&LB08| zI&GB?-c;Xpo_D}&SSS7J+1v7)!|6}w9~$Fksd?5qtbFo^Soen2dh65v_+ou?3OV;n zwY)PqIlKB;UGFwqA1Kd8SV#M3)#1+3*}Id?^RuvA!5Uusa9uuWzP*7gKJm{!4(k2p z&>!v`zb&=Ptzo}ZYfLwS!N=~KSCwh!uz%ValpB@((Ru3~@V!1-2foi*gU+jJvp;JB zr$+t!_Uz#G`kVc3t#&vnHxFOzR$pO}*sqS8d)w>P^6Nv$&@$HIgX%hHaD6d4d3SMs z*7$ggHQ)?u#rny+>Q98*X?7ab^60kG@9))`ult?;&M&P`SDP1iQ}EO4n%_J)Z`8Z5 zJEabIYJam`s$%`<|5E?3U8;TPG>^;G8}Q+%@@jvhIqXlW;9mz@^d)pkg@9KvK;hWlve&bW;;-qm=K5taVSl3T44$FQ2u)OnTclt}`Rpr7TyvBG} zH%|uT+FAdg)M#9M0(~2ea}sD&+acHU%$P2TWZ#t`~5@e4$b`rbVcZkZ(qKQwh2_qdq~6=JusO@bTm(t zOI;UClv|j68_DaU{iK{lZF$Tq!Jr}iBG!qkk_Er16lCixu;95lOnC6Fo-htQZ+sDV zYtkf5_&QIH+QS{=fxL;5NVJort+S@|!z zVZT#Ho|vVrR#h$}xQ?)SR+IcPPbEoa^t+7@$AL(AJ$(i zOu=*i95DBD#mP99l~k!v_n3Kz)R4#w;Yp-w(at%{5GS4&l2cVt28o=>6v;nj;73q% z8pRg)*esfks*R-UN7^8(k_(zq1(r9a%E4DKyA@Sr;iOPS)W60_;EMrNF3iioEv3ah zy8+Lg-tb65l)SW9JG;w@Hp^Us$0{1*xAE$gU5aGjOXXgh7%4|N_v@T6>_5bZR}p?e z2bL6AG;mDea~qCRhs#;qwwwneK1-R-Q5LNGudIqckM@>! zff|%5j7;97XB2d()>4FHfE81aTS!5b7*pF8mf}!TnW5n&!k9m{OO57Bj%l`tE_kAF z&2_LK{l*l`dZUm{yj4U=kz4uB&`&|?Tu0|DnAA@)+D>`A=(zmS$Au8OS4)!!QCdAP zV>9L390?yyQcUo9Pm>g_mHc~X4(3Obl*z#?qDQ=S9j^jnFFMY2x())^M; zs<+|rPZCATGzPO#a(ShQRcmR6%C1ci4=^7^#tRs~o+68f5B`46gFvMJbS48TKnyUWocix|0 zdS&lF|8rrP|9-ikktJA@^oWOqFFOJ+5$vf=Y}h>ME+o`FV$HuS%ulQ=%|QP@kZ7({ z@?O65<`sIKefZ=wjoeWdBwIUEO{;(1>BEej$nk&a-9n2-E>99(!}m^3g`FfVf#jZ@ z!0gHRY{aB7hY|LQ`0`xs3B2GVu0$DLA-+vAA^`}_8(?O$CRM7POih$5L+`yz%=M@@ zdNxz{O))nYy-E;tu;r#$IH*=tUS|fjX3ykI1SPlh;TUo3xL2*p+vs!b1~crFDp7R; zn297LA-Tcg5RvDyg6)x?isPWQ`tfao{eS(_38)ip<4& zcg5I$p;RQdW6_%mx)vqX{sLq683HVQgpizxYXu~kngfWyyoAjM7e@s`z|<}oSwP{% ziH@_08othzeLU-+;Cejku!OiH!!u;b@8ql_52}yx#Mam@Jgima@}CYl)K6BUkbaCO ze#{$%%gg7lM6x-O-}4^nIUJWEnrzqxE))W!d3ekl<=%2;Q_6f-XQ48AALEH1^F|rA z(4X1I7k0tNyiqna?C%ThHl|>HA!nV7tL64FZ`3UKm&hAs&iK=fFjiXGf2ePOc0_<( zY#b~UOTb?E?9DwIk)duRB}X(kR2%Ec1&c`l_XeVf{gnKdypi{ z3XnUBc{UWLP^{$KJPkQEvsCCs4Ww~9AX1*B_+4^;mi zh^^{O%E3DEOqhO_=8mJm?a{eLQBM8qjI=(NS61WS*tte$`!E0SB4z40SU&pRWNh$$ zZ@xE3mNb5Ndcw&1Z=Gd`!CaCBQr2KW;(7$1AsVxhj){r?#+R_&!*)xHxwwPzs`L3j zABSwnW(WjRUM~=!*$VliKao)RU+qpZ>z;?S3>>+l1*3}-gxBJD!RYy1#Guux)QN)z z%^T(k&J#Asm3S)=@c2-Np@c#ip|AErIA&rpRBDaT{Nz>%93S$4$KZ@>H(V{C0f#i+ zbUW17Pl$?#;}+gXp;Bv_BY&kEMpHg<0Y#Qd_82Mm7%BG{DaQb5mDm@-Eo+_NCg`tC zdRGO1-0mXCqCK6BgEdT*0?OTxT=4xU4mwY`4F1F2k|H6qJXS6$>I#{~0dtmYO4|)B z2tvscIiS70?r#N4`R9ILmd&A6PqqhTX+H_*Kj8h zWt*ON9?nEGa#d9sCPr{R)ga}Zgo`E~QL@UlICnTg!F3wEQe)Ef$Kna=2vY?ZYbumc zdP>tp7FYbpwVVRj$l?IU8Za#S-tN&}RW2;)eS9h!C(=28#8r&#o=G=lV5(2?f-Nxa zR>2d2?+9yCe!<2fWz90R_^Do}X_^?vXjM-iNNr`eG&vh`u7QqP@GkrQ6$3UUk1^bR zxOY@%a{V0@i%fLrblm2kaCL){k~$)^62aXWBbmkw>8gRj+_x2uh275OM4!drb}M8F z_7+SWt>qYW?s~*JT`Y+|eQ|v=J>&tax-o3w;-H6iTBZa{t<8<);jo-s{kw6`u^nzHs8?>*ZO}~EM z>-VN|mmt(-Z-U@-HbL4+hw&p7_XG~$GD8PkTE(CSLb)7=0|6!1G=cgUWJ2amOp_^l zmkK-TaiS62UZh4<&J6c-#8D16A$Jx{n5|A`voI3{~>X5XW zMiSOuuvGAM-oF0ke%VA$nAE!2POi54;&=M8C3n1xIN%-3%4UoB-v8Xe=^cjL5kBCm84u0jqwF7+X0 z+ottwR*y9Md|Q-gA2Nyd9}xuZGT>9AujJJ`b8~2b>ngBo%!uG#D)@4+yeg92QM1j< zS~H!=a%wj9rk1BphiU#XHU|~Nj$g6Kh~206v!s>J+9fGOdHi*inzjsPKLsG#>g7Ut zfr3;^z>9`1p(N9EqIQlN1G8^*hBQ+M>!B7ynM9{XZmK}dNYzWqpzGrM=3Fh}5V&uI8C?elTZ__$|$+%s}!{Dbz4 z3!2Tg{74R7TThIyI7ek_=SRdsUEQW~(zPwYiN7I$NIQ#_+Ee zcGO>w(s8SUAbodQu@|oJ9G*&BuGpjFb?1I&AuKl$>c+Cf+he?t66WTzBpUKEc2-Ti z#@nyuuG$-ID^H749?AAIZs8SDppb<+2C504)^EFDJ~v!2ijh;v&MWvm`d-lQK&Y< zUa+&#P!#jevxE+9W`dls1#nnmBA|({=ZOF4agKYCcmUVAw0%9VMw78GpHgc4fSnz% zvjcYaRbyu(fs#khMlbkcf@@7mR4}daJU7k#C3=4gplxXpD8yK#PYnM-u-37F=_a4) zMc|-pE(1=_iDz?|E+FPwLUC2d@(A!Qk&#V^*Cs$VJnmbWD+FP1mb@)V+Txwd@-~ z#$fs1uwmQT`15_JO;CUb3%YRUSg?$=R4)1L?Ct5Xrg;N)Go9+w-HRRnYA?92;x<$3 z`mS5-AU1ohR&_zLR_+<&l`L-O_^u7?^jQI>BffYzIOCta`A}l+J3x(axh}*2S z*8R@gE4@{9Wj)K`wKlc87xiYjkn?!d<#wO=tb<~++=9Sr z9R`<`9c|eR!7wYpV)YH(Kv~EuW|t7CoX6^=?VB4#51XzDBZOLIZ~Wm_BbGJY&C^bH zIISo!`&o-wFdJwFY^;EunQbxu1xF;xdD2tMn^QjFu6Z~6^9XJ4UPC%DTV#nl9(|L` zIB_S@3y}V`#;CO58bp5=@&0HPR-fvItrgTLxryoQNih?u+J^xlH&^hhLaz$8OuF4g z)`S-sM+5%FwR{{8zL0?XQbOQ%w(o<|(&I4FH1hAKIWDYKcgjY~OEhs7(ipjBB!`AB zkDUQhFV2mwUC-(oZ?rpymO*LJ4sdIfCAHjEh`-C`d;5l?J18x1xi;@|Y}-oz8kClQ z0T>NR3rEqQw8XQ@{XZxz&_Q4uL&$e*9g~ZDYsGq-N=s5dDnRW-$5%zTo#>r-6P{ql zc>D$+Ikoe~Vyu0EP!ro?a=xnL$YiX2B(s5j~VloO>RbswM{ ziAQ)$?M{kUIj8WDQy0l>L{-yEHicja#!<3$70#hWd#@|?x_KmYgO|7sZHZyx(dZTs z=P*jqmv#e*sq5wj1~#wjS%nxR)V3?cX+=!_$5nO97%VynshcjA)%3brR5&DVBC+t= zR;XStv(;FxL-i+i>f~d9ybO?+0rK*yAuo~q$U|PD7kn{6iEb?PD(F@E#7cXhq}QR| zq7tCU-_Gx7U4%$mUOxzuSA>~FeTs6&{G>z|nQEaaF^(@0qzW@X?#gv zyC`e2N*OF`YQWt&R$b{HzC$)}bJO#3^|NhZ1ms$!Y@lw?M37r8N57M!%1^dWqqyJ5 zb}x4wQOEMVpi8yC3;NVp@%_34=M^xa%yDlwt9KafO`ZmWudj7vN4H56X`s8X zoj5b}Ii?3CS>152wS^Kh(s;~@?!xur-N{G%d^joll;(@6UAqUD7pG^FFBeBgNAD7! Ezp`dB+5i9m diff --git a/metallb-chart/charts/frr-k8s/Chart.yaml b/metallb-chart/charts/frr-k8s/Chart.yaml new file mode 100644 index 0000000..2fa4501 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/Chart.yaml @@ -0,0 +1,11 @@ +apiVersion: v2 +appVersion: v0.0.14 +description: A cloud native wrapper of FRR +home: https://metallb.universe.tf +icon: https://metallb.universe.tf/images/logo/metallb-white.png +kubeVersion: '>= 1.19.0-0' +name: frr-k8s +sources: +- https://github.com/metallb/frr-k8s +type: application +version: 0.0.15 diff --git a/metallb-chart/charts/frr-k8s/README.md b/metallb-chart/charts/frr-k8s/README.md new file mode 100644 index 0000000..0418d64 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/README.md @@ -0,0 +1,96 @@ +# frr-k8s + +![Version: 0.0.14](https://img.shields.io/badge/Version-0.0.14-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.0.14](https://img.shields.io/badge/AppVersion-v0.0.14-informational?style=flat-square) + +A cloud native wrapper of FRR + +**Homepage:** + +## Source Code + +* + +## Requirements + +Kubernetes: `>= 1.19.0-0` + +| Repository | Name | Version | +|------------|------|---------| +| | crds | 0.0.14 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| crds.enabled | bool | `true` | | +| crds.validationFailurePolicy | string | `"Fail"` | | +| frrk8s.affinity | object | `{}` | | +| frrk8s.alwaysBlock | string | `""` | | +| frrk8s.disableCertRotation | bool | `false` | | +| frrk8s.frr.image.pullPolicy | string | `nil` | | +| frrk8s.frr.image.repository | string | `"quay.io/frrouting/frr"` | | +| frrk8s.frr.image.tag | string | `"9.1.0"` | | +| frrk8s.frr.metricsBindAddress | string | `"127.0.0.1"` | | +| frrk8s.frr.metricsPort | int | `7573` | | +| frrk8s.frr.resources | object | `{}` | | +| frrk8s.frr.secureMetricsPort | int | `9141` | | +| frrk8s.frrMetrics.resources | object | `{}` | | +| frrk8s.healthPort | int | `8081` | | +| frrk8s.image.pullPolicy | string | `nil` | | +| frrk8s.image.repository | string | `"quay.io/metallb/frr-k8s"` | | +| frrk8s.image.tag | string | `nil` | | +| frrk8s.labels.app | string | `"frr-k8s"` | | +| frrk8s.livenessProbe.enabled | bool | `true` | | +| frrk8s.livenessProbe.failureThreshold | int | `3` | | +| frrk8s.livenessProbe.initialDelaySeconds | int | `10` | | +| frrk8s.livenessProbe.periodSeconds | int | `10` | | +| frrk8s.livenessProbe.successThreshold | int | `1` | | +| frrk8s.livenessProbe.timeoutSeconds | int | `1` | | +| frrk8s.logLevel | string | `"info"` | Controller log level. Must be one of: `all`, `debug`, `info`, `warn`, `error` or `none` | +| frrk8s.nodeSelector | object | `{}` | | +| frrk8s.podAnnotations | object | `{}` | | +| frrk8s.priorityClassName | string | `""` | | +| frrk8s.readinessProbe.enabled | bool | `true` | | +| frrk8s.readinessProbe.failureThreshold | int | `3` | | +| frrk8s.readinessProbe.initialDelaySeconds | int | `10` | | +| frrk8s.readinessProbe.periodSeconds | int | `10` | | +| frrk8s.readinessProbe.successThreshold | int | `1` | | +| frrk8s.readinessProbe.timeoutSeconds | int | `1` | | +| frrk8s.reloader.resources | object | `{}` | | +| frrk8s.resources | object | `{}` | | +| frrk8s.restartOnRotatorSecretRefresh | bool | `false` | | +| frrk8s.runtimeClassName | string | `""` | | +| frrk8s.serviceAccount.annotations | object | `{}` | | +| frrk8s.serviceAccount.create | bool | `true` | | +| frrk8s.serviceAccount.name | string | `""` | | +| frrk8s.startupProbe.enabled | bool | `true` | | +| frrk8s.startupProbe.failureThreshold | int | `30` | | +| frrk8s.startupProbe.periodSeconds | int | `5` | | +| frrk8s.tolerateMaster | bool | `true` | | +| frrk8s.tolerations | list | `[]` | | +| frrk8s.updateStrategy.type | string | `"RollingUpdate"` | | +| fullnameOverride | string | `""` | | +| nameOverride | string | `""` | | +| prometheus.metricsBindAddress | string | `"127.0.0.1"` | | +| prometheus.metricsPort | int | `7572` | | +| prometheus.metricsTLSSecret | string | `""` | | +| prometheus.namespace | string | `""` | | +| prometheus.rbacPrometheus | bool | `false` | | +| prometheus.rbacProxy.pullPolicy | string | `nil` | | +| prometheus.rbacProxy.repository | string | `"gcr.io/kubebuilder/kube-rbac-proxy"` | | +| prometheus.rbacProxy.tag | string | `"v0.12.0"` | | +| prometheus.scrapeAnnotations | bool | `false` | | +| prometheus.secureMetricsPort | int | `9140` | | +| prometheus.serviceAccount | string | `""` | | +| prometheus.serviceMonitor.additionalLabels | object | `{}` | | +| prometheus.serviceMonitor.annotations | object | `{}` | | +| prometheus.serviceMonitor.enabled | bool | `false` | | +| prometheus.serviceMonitor.interval | string | `nil` | | +| prometheus.serviceMonitor.jobLabel | string | `"app.kubernetes.io/name"` | | +| prometheus.serviceMonitor.metricRelabelings | list | `[]` | | +| prometheus.serviceMonitor.relabelings | list | `[]` | | +| prometheus.serviceMonitor.tlsConfig.insecureSkipVerify | bool | `true` | | +| rbac.create | bool | `true` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.10.0](https://github.com/norwoodj/helm-docs/releases/v1.10.0) diff --git a/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrconfigurations.yaml b/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrconfigurations.yaml new file mode 100644 index 0000000..2813767 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrconfigurations.yaml @@ -0,0 +1,462 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: frrconfigurations.frrk8s.metallb.io +spec: + group: frrk8s.metallb.io + names: + kind: FRRConfiguration + listKind: FRRConfigurationList + plural: frrconfigurations + singular: frrconfiguration + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: FRRConfiguration is a piece of FRR configuration. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: FRRConfigurationSpec defines the desired state of FRRConfiguration. + properties: + bgp: + description: BGP is the configuration related to the BGP protocol. + properties: + bfdProfiles: + description: BFDProfiles is the list of bfd profiles to be used + when configuring the neighbors. + items: + description: |- + BFDProfile is the configuration related to the BFD protocol associated + to a BGP session. + properties: + detectMultiplier: + description: |- + Configures the detection multiplier to determine + packet loss. The remote transmission interval will be multiplied + by this value to determine the connection loss detection timer. + format: int32 + maximum: 255 + minimum: 2 + type: integer + echoInterval: + description: |- + Configures the minimal echo receive transmission + interval that this system is capable of handling in milliseconds. + Defaults to 50ms + format: int32 + maximum: 60000 + minimum: 10 + type: integer + echoMode: + description: |- + Enables or disables the echo transmission mode. + This mode is disabled by default, and not supported on multi + hops setups. + type: boolean + minimumTtl: + description: |- + For multi hop sessions only: configure the minimum + expected TTL for an incoming BFD control packet. + format: int32 + maximum: 254 + minimum: 1 + type: integer + name: + description: |- + The name of the BFD Profile to be referenced in other parts + of the configuration. + type: string + passiveMode: + description: |- + Mark session as passive: a passive session will not + attempt to start the connection and will wait for control packets + from peer before it begins replying. + type: boolean + receiveInterval: + description: |- + The minimum interval that this system is capable of + receiving control packets in milliseconds. + Defaults to 300ms. + format: int32 + maximum: 60000 + minimum: 10 + type: integer + transmitInterval: + description: |- + The minimum transmission interval (less jitter) + that this system wants to use to send BFD control packets in + milliseconds. Defaults to 300ms + format: int32 + maximum: 60000 + minimum: 10 + type: integer + required: + - name + type: object + type: array + routers: + description: Routers is the list of routers we want FRR to configure + (one per VRF). + items: + description: Router represent a neighbor router we want FRR + to connect to. + properties: + asn: + description: ASN is the AS number to use for the local end + of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + id: + description: ID is the BGP router ID + type: string + imports: + description: Imports is the list of imported VRFs we want + for this router / vrf. + items: + description: Import represents the possible imported VRFs + to a given router. + properties: + vrf: + description: Vrf is the vrf we want to import from + type: string + type: object + type: array + neighbors: + description: Neighbors is the list of neighbors we want + to establish BGP sessions with. + items: + description: Neighbor represents a BGP Neighbor we want + FRR to connect to. + properties: + address: + description: Address is the IP address to establish + the session with. + type: string + asn: + description: ASN is the AS number to use for the local + end of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + bfdProfile: + description: |- + BFDProfile is the name of the BFD Profile to be used for the BFD session associated + to the BGP session. If not set, the BFD session won't be set up. + type: string + connectTime: + description: Requested BGP connect time, controls + how long BGP waits between connection attempts to + a neighbor. + type: string + x-kubernetes-validations: + - message: connect time should be between 1 seconds + to 65535 + rule: duration(self).getSeconds() >= 1 && duration(self).getSeconds() + <= 65535 + - message: connect time should contain a whole number + of seconds + rule: duration(self).getMilliseconds() % 1000 == + 0 + disableMP: + default: false + description: To set if we want to disable MP BGP that + will separate IPv4 and IPv6 route exchanges into + distinct BGP sessions. + type: boolean + ebgpMultiHop: + description: EBGPMultiHop indicates if the BGPPeer + is multi-hops away. + type: boolean + enableGracefulRestart: + description: |- + EnableGracefulRestart allows BGP peer to continue to forward data packets along + known routes while the routing protocol information is being restored. If + the session is already established, the configuration will have effect + after reconnecting to the peer + type: boolean + holdTime: + description: |- + HoldTime is the requested BGP hold time, per RFC4271. + Defaults to 180s. + type: string + keepaliveTime: + description: |- + KeepaliveTime is the requested BGP keepalive time, per RFC4271. + Defaults to 60s. + type: string + password: + description: |- + Password to be used for establishing the BGP session. + Password and PasswordSecret are mutually exclusive. + type: string + passwordSecret: + description: |- + PasswordSecret is name of the authentication secret for the neighbor. + the secret must be of type "kubernetes.io/basic-auth", and created in the + same namespace as the frr-k8s daemon. The password is stored in the + secret as the key "password". + Password and PasswordSecret are mutually exclusive. + properties: + name: + description: name is unique within a namespace + to reference a secret resource. + type: string + namespace: + description: namespace defines the space within + which the secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + port: + description: |- + Port is the port to dial when establishing the session. + Defaults to 179. + maximum: 16384 + minimum: 0 + type: integer + sourceaddress: + description: |- + SourceAddress is the IPv4 or IPv6 source address to use for the BGP + session to this neighbour, may be specified as either an IP address + directly or as an interface name + type: string + toAdvertise: + description: |- + ToAdvertise represents the list of prefixes to advertise to the given neighbor + and the associated properties. + properties: + allowed: + description: |- + Allowed is is the list of prefixes allowed to be propagated to + this neighbor. They must match the prefixes defined in the router. + properties: + mode: + default: filtered + description: |- + Mode is the mode to use when handling the prefixes. + When set to "filtered", only the prefixes in the given list will be allowed. + When set to "all", all the prefixes configured on the router will be allowed. + enum: + - all + - filtered + type: string + prefixes: + items: + type: string + type: array + type: object + withCommunity: + description: |- + PrefixesWithCommunity is a list of prefixes that are associated to a + bgp community when being advertised. The prefixes associated to a given local pref + must be in the prefixes allowed to be advertised. + items: + description: CommunityPrefixes is a list of + prefixes associated to a community. + properties: + community: + description: Community is the community + associated to the prefixes. + type: string + prefixes: + description: Prefixes is the list of prefixes + associated to the community. + format: cidr + items: + type: string + minItems: 1 + type: array + type: object + type: array + withLocalPref: + description: |- + PrefixesWithLocalPref is a list of prefixes that are associated to a local + preference when being advertised. The prefixes associated to a given local pref + must be in the prefixes allowed to be advertised. + items: + description: LocalPrefPrefixes is a list of + prefixes associated to a local preference. + properties: + localPref: + description: LocalPref is the local preference + associated to the prefixes. + format: int32 + type: integer + prefixes: + description: Prefixes is the list of prefixes + associated to the local preference. + format: cidr + items: + type: string + minItems: 1 + type: array + type: object + type: array + type: object + toReceive: + description: ToReceive represents the list of prefixes + to receive from the given neighbor. + properties: + allowed: + description: |- + Allowed is the list of prefixes allowed to be received from + this neighbor. + properties: + mode: + default: filtered + description: |- + Mode is the mode to use when handling the prefixes. + When set to "filtered", only the prefixes in the given list will be allowed. + When set to "all", all the prefixes configured on the router will be allowed. + enum: + - all + - filtered + type: string + prefixes: + items: + description: PrefixSelector is a filter + of prefixes to receive. + properties: + ge: + description: |- + The prefix length modifier. This selector accepts any matching prefix with length + greater or equal the given value. + format: int32 + maximum: 128 + minimum: 1 + type: integer + le: + description: |- + The prefix length modifier. This selector accepts any matching prefix with length + less or equal the given value. + format: int32 + maximum: 128 + minimum: 1 + type: integer + prefix: + format: cidr + type: string + type: object + type: array + type: object + type: object + required: + - address + - asn + type: object + type: array + prefixes: + description: Prefixes is the list of prefixes we want to + advertise from this router instance. + items: + type: string + type: array + vrf: + description: VRF is the host vrf used to establish sessions + from this router. + type: string + required: + - asn + type: object + type: array + type: object + nodeSelector: + description: |- + NodeSelector limits the nodes that will attempt to apply this config. + When specified, the configuration will be considered only on nodes + whose labels match the specified selectors. + When it is not specified all nodes will attempt to apply this config. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + raw: + description: |- + Raw is a snippet of raw frr configuration that gets appended to the + one rendered translating the type safe API. + properties: + priority: + description: |- + Priority is the order with this configuration is appended to the + bottom of the rendered configuration. A higher value means the + raw config is appended later in the configuration file. + type: integer + rawConfig: + description: |- + Config is a raw FRR configuration to be appended to the configuration + rendered via the k8s api. + type: string + type: object + type: object + status: + description: FRRConfigurationStatus defines the observed state of FRRConfiguration. + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrnodestates.yaml b/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrnodestates.yaml new file mode 100644 index 0000000..66f4196 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrnodestates.yaml @@ -0,0 +1,65 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: frrnodestates.frrk8s.metallb.io +spec: + group: frrk8s.metallb.io + names: + kind: FRRNodeState + listKind: FRRNodeStateList + plural: frrnodestates + singular: frrnodestate + scope: Cluster + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: FRRNodeState exposes the status of the FRR instance running on + each node. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: FRRNodeStateSpec defines the desired state of FRRNodeState. + type: object + status: + description: FRRNodeStateStatus defines the observed state of FRRNodeState. + properties: + lastConversionResult: + description: LastConversionResult is the status of the last translation + between the `FRRConfiguration`s resources and FRR's configuration, + contains "success" or an error. + type: string + lastReloadResult: + description: LastReloadResult represents the status of the last configuration + update operation by FRR, contains "success" or an error. + type: string + runningConfig: + description: RunningConfig represents the current FRR running config, + which is the configuration the FRR instance is currently running + with. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metallb-chart/charts/frr-k8s/templates/NOTES.txt b/metallb-chart/charts/frr-k8s/templates/NOTES.txt new file mode 100644 index 0000000..813ab8a --- /dev/null +++ b/metallb-chart/charts/frr-k8s/templates/NOTES.txt @@ -0,0 +1,4 @@ +FRR-k8s is now running in the cluster. + +Now you can configure it via its CRs. Please refer to the frr-k8s official docs +on how to use the CRs. diff --git a/metallb-chart/charts/frr-k8s/templates/_helpers.tpl b/metallb-chart/charts/frr-k8s/templates/_helpers.tpl new file mode 100644 index 0000000..8b728d2 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "frrk8s.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "frrk8s.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "frrk8s.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "frrk8s.labels" -}} +helm.sh/chart: {{ include "frrk8s.chart" . }} +{{ include "frrk8s.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "frrk8s.selectorLabels" -}} +app.kubernetes.io/name: {{ include "frrk8s.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the frrk8s service account to use +*/}} +{{- define "frrk8s.serviceAccountName" -}} +{{- if .Values.frrk8s.serviceAccount.create }} +{{- default (printf "%s-controller" (include "frrk8s.fullname" .)) .Values.frrk8s.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.frrk8s.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/metallb-chart/charts/frr-k8s/templates/controller.yaml b/metallb-chart/charts/frr-k8s/templates/controller.yaml new file mode 100644 index 0000000..50badde --- /dev/null +++ b/metallb-chart/charts/frr-k8s/templates/controller.yaml @@ -0,0 +1,431 @@ +# FRR expects to have these files owned by frr:frr on startup. +# Having them in a ConfigMap allows us to modify behaviors: for example enabling more daemons on startup. +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "frrk8s.fullname" . }}-frr-startup + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "frrk8s.labels" . | nindent 4 }} + app.kubernetes.io/component: frr-k8s +data: + daemons: | + # This file tells the frr package which daemons to start. + # + # Sample configurations for these daemons can be found in + # /usr/share/doc/frr/examples/. + # + # ATTENTION: + # + # When activating a daemon for the first time, a config file, even if it is + # empty, has to be present *and* be owned by the user and group "frr", else + # the daemon will not be started by /etc/init.d/frr. The permissions should + # be u=rw,g=r,o=. + # When using "vtysh" such a config file is also needed. It should be owned by + # group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too. + # + # The watchfrr and zebra daemons are always started. + # + bgpd=yes + ospfd=no + ospf6d=no + ripd=no + ripngd=no + isisd=no + pimd=no + ldpd=no + nhrpd=no + eigrpd=no + babeld=no + sharpd=no + pbrd=no + bfdd=yes + fabricd=no + vrrpd=no + + # + # If this option is set the /etc/init.d/frr script automatically loads + # the config via "vtysh -b" when the servers are started. + # Check /etc/pam.d/frr if you intend to use "vtysh"! + # + vtysh_enable=yes + zebra_options=" -A 127.0.0.1 -s 90000000" + bgpd_options=" -A 127.0.0.1" + ospfd_options=" -A 127.0.0.1" + ospf6d_options=" -A ::1" + ripd_options=" -A 127.0.0.1" + ripngd_options=" -A ::1" + isisd_options=" -A 127.0.0.1" + pimd_options=" -A 127.0.0.1" + ldpd_options=" -A 127.0.0.1" + nhrpd_options=" -A 127.0.0.1" + eigrpd_options=" -A 127.0.0.1" + babeld_options=" -A 127.0.0.1" + sharpd_options=" -A 127.0.0.1" + pbrd_options=" -A 127.0.0.1" + staticd_options="-A 127.0.0.1" + bfdd_options=" -A 127.0.0.1" + fabricd_options="-A 127.0.0.1" + vrrpd_options=" -A 127.0.0.1" + + # configuration profile + # + #frr_profile="traditional" + #frr_profile="datacenter" + + # + # This is the maximum number of FD's that will be available. + # Upon startup this is read by the control files and ulimit + # is called. Uncomment and use a reasonable value for your + # setup if you are expecting a large number of peers in + # say BGP. + #MAX_FDS=1024 + + # The list of daemons to watch is automatically generated by the init script. + #watchfrr_options="" + + # for debugging purposes, you can specify a "wrap" command to start instead + # of starting the daemon directly, e.g. to use valgrind on ospfd: + # ospfd_wrap="/usr/bin/valgrind" + # or you can use "all_wrap" for all daemons, e.g. to use perf record: + # all_wrap="/usr/bin/perf record --call-graph -" + # the normal daemon command is added to this at the end. + vtysh.conf: |+ + service integrated-vtysh-config + frr.conf: |+ + ! This file gets overriden the first time the speaker renders a config. + ! So anything configured here is only temporary. + frr version 8.0 + frr defaults traditional + hostname Router + line vty + log file /etc/frr/frr.log informational +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ template "frrk8s.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "frrk8s.labels" . | nindent 4 }} + app.kubernetes.io/component: frr-k8s + {{- range $key, $value := .Values.frrk8s.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + {{- if .Values.frrk8s.updateStrategy }} + updateStrategy: {{- toYaml .Values.frrk8s.updateStrategy | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "frrk8s.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: frr-k8s + template: + metadata: + labels: + {{- include "frrk8s.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: frr-k8s + {{- range $key, $value := .Values.frrk8s.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + spec: + {{- if .Values.frrk8s.runtimeClassName }} + runtimeClassName: {{ .Values.frrk8s.runtimeClassName }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "frrk8s.serviceAccountName" . }} + terminationGracePeriodSeconds: 0 + hostNetwork: true + volumes: + - name: frr-sockets + emptyDir: {} + - name: frr-startup + configMap: + name: {{ template "frrk8s.fullname" . }}-frr-startup + - name: frr-conf + emptyDir: {} + - name: reloader + emptyDir: {} + - name: metrics + emptyDir: {} + {{- if .Values.prometheus.metricsTLSSecret }} + - name: metrics-certs + secret: + secretName: {{ .Values.prometheus.metricsTLSSecret }} + {{- end }} + initContainers: + # Copies the initial config files with the right permissions to the shared volume. + - name: cp-frr-files + image: {{ .Values.frrk8s.frr.image.repository }}:{{ .Values.frrk8s.frr.image.tag | default .Chart.AppVersion }} + securityContext: + runAsUser: 100 + runAsGroup: 101 + command: ["/bin/sh", "-c", "cp -rLf /tmp/frr/* /etc/frr/"] + volumeMounts: + - name: frr-startup + mountPath: /tmp/frr + - name: frr-conf + mountPath: /etc/frr + # Copies the reloader to the shared volume between the speaker and reloader. + - name: cp-reloader + image: {{ .Values.frrk8s.image.repository }}:{{ .Values.frrk8s.image.tag | default .Chart.AppVersion }} + command: ["/bin/sh", "-c", "cp -f /frr-reloader.sh /etc/frr_reloader/"] + volumeMounts: + - name: reloader + mountPath: /etc/frr_reloader + # Copies the metrics exporter + - name: cp-metrics + image: {{ .Values.frrk8s.image.repository }}:{{ .Values.frrk8s.image.tag | default .Chart.AppVersion }} + command: ["/bin/sh", "-c", "cp -f /frr-metrics /etc/frr_metrics/"] + volumeMounts: + - name: metrics + mountPath: /etc/frr_metrics + shareProcessNamespace: true + containers: + - name: controller + image: {{ .Values.frrk8s.image.repository }}:{{ .Values.frrk8s.image.tag | default .Chart.AppVersion }} + {{- if .Values.frrk8s.image.pullPolicy }} + imagePullPolicy: {{ .Values.frrk8s.image.pullPolicy }} + {{- end }} + command: + - /frr-k8s + args: + - "--node-name=$(NODE_NAME)" + - "--namespace=$(NAMESPACE)" + - "--metrics-bind-address={{.Values.prometheus.metricsBindAddress}}:{{ .Values.prometheus.metricsPort }}" + {{- with .Values.frrk8s.logLevel }} + - --log-level={{ . }} + {{- end }} + - --health-probe-bind-address={{.Values.prometheus.metricsBindAddress}}:{{ .Values.frrk8s.healthPort }} + {{- if .Values.frrk8s.alwaysBlock }} + - --always-block={{ .Values.frrk8s.alwaysBlock }} + {{- end }} + env: + - name: FRR_CONFIG_FILE + value: /etc/frr_reloader/frr.conf + - name: FRR_RELOADER_PID_FILE + value: /etc/frr_reloader/reloader.pid + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + ports: + - containerPort: {{ .Values.prometheus.metricsPort }} + name: monitoring + {{- if .Values.frrk8s.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /healthz + port: {{ .Values.frrk8s.healthPort }} + host: {{ .Values.prometheus.metricsBindAddress }} + initialDelaySeconds: {{ .Values.frrk8s.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.frrk8s.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.frrk8s.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.frrk8s.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.frrk8s.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.frrk8s.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: /healthz + port: {{ .Values.frrk8s.healthPort }} + host: {{ .Values.prometheus.metricsBindAddress }} + initialDelaySeconds: {{ .Values.frrk8s.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.frrk8s.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.frrk8s.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.frrk8s.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.frrk8s.readinessProbe.failureThreshold }} + {{- end }} + {{- with .Values.frrk8s.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + add: + - NET_RAW + volumeMounts: + - name: reloader + mountPath: /etc/frr_reloader + - name: frr + securityContext: + capabilities: + add: + - NET_ADMIN + - NET_RAW + - SYS_ADMIN + - NET_BIND_SERVICE + image: {{ .Values.frrk8s.frr.image.repository }}:{{ .Values.frrk8s.frr.image.tag | default .Chart.AppVersion }} + {{- if .Values.frrk8s.frr.image.pullPolicy }} + imagePullPolicy: {{ .Values.frrk8s.frr.image.pullPolicy }} + {{- end }} + env: + - name: TINI_SUBREAPER + value: "true" + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + # The command is FRR's default entrypoint & waiting for the log file to appear and tailing it. + # If the log file isn't created in 60 seconds the tail fails and the container is restarted. + # This workaround is needed to have the frr logs as part of kubectl logs -c frr < controller_pod_name >. + command: + - /bin/sh + - -c + - | + /sbin/tini -- /usr/lib/frr/docker-start & + attempts=0 + until [[ -f /etc/frr/frr.log || $attempts -eq 60 ]]; do + sleep 1 + attempts=$(( $attempts + 1 )) + done + tail -f /etc/frr/frr.log + {{- with .Values.frrk8s.frr.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.frrk8s.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /livez + port: {{ .Values.frrk8s.frr.metricsPort }} + host: {{ .Values.frrk8s.frr.metricsBindAddress }} + periodSeconds: {{ .Values.frrk8s.livenessProbe.periodSeconds }} + failureThreshold: {{ .Values.frrk8s.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.frrk8s.startupProbe.enabled }} + startupProbe: + httpGet: + path: /livez + port: {{ .Values.frrk8s.frr.metricsPort }} + host: {{ .Values.frrk8s.frr.metricsBindAddress }} + failureThreshold: {{ .Values.frrk8s.startupProbe.failureThreshold }} + periodSeconds: {{ .Values.frrk8s.startupProbe.periodSeconds }} + {{- end }} + - name: reloader + image: {{ .Values.frrk8s.frr.image.repository }}:{{ .Values.frrk8s.frr.image.tag | default .Chart.AppVersion }} + {{- if .Values.frrk8s.frr.image.pullPolicy }} + imagePullPolicy: {{ .Values.frrk8s.frr.image.pullPolicy }} + {{- end }} + command: ["/etc/frr_reloader/frr-reloader.sh"] + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + - name: reloader + mountPath: /etc/frr_reloader + {{- with .Values.frrk8s.reloader.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: frr-metrics + image: {{ .Values.frrk8s.frr.image.repository }}:{{ .Values.frrk8s.frr.image.tag | default .Chart.AppVersion }} + command: ["/etc/frr_metrics/frr-metrics"] + args: + - --metrics-port={{ .Values.frrk8s.frr.metricsPort }} + - --metrics-bind-address={{ .Values.frrk8s.frr.metricsBindAddress }} + ports: + - containerPort: {{ .Values.frrk8s.frr.metricsPort }} + name: monitoring + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + - name: metrics + mountPath: /etc/frr_metrics + {{- with .Values.frrk8s.frrMetrics.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: kube-rbac-proxy + image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag }} + imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }} + args: + - --logtostderr + - --secure-listen-address=:{{ .Values.prometheus.secureMetricsPort }} + - --upstream=http://{{.Values.prometheus.metricsBindAddress}}:{{ .Values.prometheus.metricsPort }}/ + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + {{- if .Values.prometheus.metricsTLSSecret }} + - --tls-private-key-file=/etc/metrics/tls.key + - --tls-cert-file=/etc/metrics/tls.crt + {{- end }} + ports: + - containerPort: {{ .Values.prometheus.secureMetricsPort }} + name: metricshttps + resources: + requests: + cpu: 10m + memory: 20Mi + terminationMessagePolicy: FallbackToLogsOnError + {{- if .Values.prometheus.metricsTLSSecret }} + volumeMounts: + - name: metrics-certs + mountPath: /etc/metrics + readOnly: true + {{- end }} + - name: kube-rbac-proxy-frr + image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }} + args: + - --logtostderr + - --secure-listen-address=:{{ .Values.frrk8s.frr.secureMetricsPort }} + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + - --upstream=http://{{ .Values.frrk8s.frr.metricsBindAddress }}:{{ .Values.frrk8s.frr.metricsPort }}/ + {{- if .Values.prometheus.metricsTLSSecret }} + - --tls-private-key-file=/etc/metrics/tls.key + - --tls-cert-file=/etc/metrics/tls.crt + {{- end }} + ports: + - containerPort: {{ .Values.frrk8s.frr.secureMetricsPort }} + name: metricshttps + resources: + requests: + cpu: 10m + memory: 20Mi + terminationMessagePolicy: FallbackToLogsOnError + {{- if .Values.prometheus.metricsTLSSecret }} + volumeMounts: + - name: metrics-certs + mountPath: /etc/metrics + readOnly: true + {{- end }} + nodeSelector: + "kubernetes.io/os": linux + {{- with .Values.frrk8s.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.frrk8s.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.frrk8s.tolerateMaster .Values.frrk8s.tolerations }} + tolerations: + {{- if .Values.frrk8s.tolerateMaster }} + - key: node-role.kubernetes.io/master + effect: NoSchedule + operator: Exists + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + operator: Exists + {{- end }} + {{- with .Values.frrk8s.tolerations }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} + {{- with .Values.frrk8s.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} diff --git a/metallb-chart/charts/frr-k8s/templates/rbac.yaml b/metallb-chart/charts/frr-k8s/templates/rbac.yaml new file mode 100644 index 0000000..5c0b9d6 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/templates/rbac.yaml @@ -0,0 +1,73 @@ +{{- if .Values.rbac.create -}} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "frrk8s.fullname" . }}-controller + labels: {{- include "frrk8s.labels" . | nindent 4 }} +rules: +- apiGroups: ["frrk8s.metallb.io"] + resources: ["frrconfigurations"] + verbs: ["get", "list", "watch"] +- apiGroups: ["frrk8s.metallb.io"] + resources: ["frrnodestates"] + verbs: ["get", "list", "watch", "create", "delete", "patch", "update"] +- apiGroups: ["frrk8s.metallb.io"] + resources: ["frrnodestates/status"] + verbs: ["get", "patch", "update"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations"] + verbs: ["get", "list", "watch"] +- apiGroups: ["admissionregistration.k8s.io"] + resourceNames: ["frr-k8s-validating-webhook-configuration"] + resources: ["validatingwebhookconfigurations"] + verbs: ["update"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "frrk8s.fullname" . }}-controller + labels: {{- include "frrk8s.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "frrk8s.fullname" . }}-controller +subjects: +- kind: ServiceAccount + name: {{ include "frrk8s.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "frrk8s.fullname" . }}-controller + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "frrk8s.labels" . | nindent 4 }} +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch","update"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "frrk8s.fullname" . }}-controller + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "frrk8s.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "frrk8s.fullname" . }}-controller +subjects: +- kind: ServiceAccount + name: {{ include "frrk8s.serviceAccountName" . }} +{{ end -}} diff --git a/metallb-chart/charts/frr-k8s/templates/service-accounts.yaml b/metallb-chart/charts/frr-k8s/templates/service-accounts.yaml new file mode 100644 index 0000000..c3d7423 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/templates/service-accounts.yaml @@ -0,0 +1,16 @@ +{{- if .Values.frrk8s.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "frrk8s.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "frrk8s.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.frrk8s.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + diff --git a/metallb-chart/charts/frr-k8s/templates/service-monitor.yaml b/metallb-chart/charts/frr-k8s/templates/service-monitor.yaml new file mode 100644 index 0000000..323c442 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/templates/service-monitor.yaml @@ -0,0 +1,128 @@ +{{- if .Values.prometheus.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "frrk8s.fullname" . }}-frr-k8s-monitor + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "frrk8s.labels" . | nindent 4 }} + app.kubernetes.io/component: frr-k8s + {{- if .Values.prometheus.serviceMonitor.additionalLabels }} +{{ toYaml .Values.prometheus.serviceMonitor.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.annotations }} + annotations: +{{ toYaml .Values.prometheus.serviceMonitor.annotations | indent 4 }} + {{- end }} +spec: + endpoints: + - port: "metricshttps" + honorLabels: true + {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.serviceMonitor.metricRelabelings | nindent 8 }} + {{- end -}} + {{- if .Values.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.serviceMonitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end -}} +{{ if .Values.prometheus.secureMetricsPort }} + bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token" + scheme: "https" +{{- if .Values.prometheus.serviceMonitor.tlsConfig }} + tlsConfig: +{{ toYaml .Values.prometheus.serviceMonitor.tlsConfig | indent 8 }} +{{- end }} +{{ end }} +{{ if .Values.frrk8s.frr.secureMetricsPort }} + - port: "frrmetricshttps" + honorLabels: true + {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.serviceMonitor.metricRelabelings | nindent 8 }} + {{- end -}} + {{- if .Values.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.serviceMonitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end }} + bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token" + scheme: "https" +{{- if .Values.prometheus.serviceMonitor.tlsConfig }} + tlsConfig: +{{ toYaml .Values.prometheus.serviceMonitor.tlsConfig | indent 8 }} +{{- end }} +{{- end }} + jobLabel: {{ .Values.prometheus.serviceMonitor.jobLabel | quote }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + name: {{ template "frrk8s.fullname" . }}-frr-k8s-monitor-service +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/scrape: "true" + {{- if .Values.prometheus.serviceMonitor.annotations }} +{{ toYaml .Values.prometheus.serviceMonitor.annotations | indent 4 }} + {{- end }} + labels: + name: {{ template "frrk8s.fullname" . }}-frr-k8s-monitor-service + name: {{ template "frrk8s.fullname" . }}-frr-k8s-monitor-service + namespace: {{ .Release.Namespace | quote }} +spec: + selector: + {{- include "frrk8s.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: frr-k8s + clusterIP: None + ports: + - name: "metricshttps" + port: {{ .Values.prometheus.secureMetricsPort }} + targetPort: {{ .Values.prometheus.secureMetricsPort }} + - name: frrmetricshttps + port: {{ .Values.frrk8s.frr.secureMetricsPort }} + targetPort: {{ .Values.frrk8s.frr.secureMetricsPort }} + sessionAffinity: None + type: ClusterIP +--- +{{- if .Values.prometheus.rbacPrometheus }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "frrk8s.fullname" . }}-prometheus + namespace: {{ .Release.Namespace | quote }} +rules: + - apiGroups: + - "" + resources: + - pods + - services + - endpoints + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "frrk8s.fullname" . }}-prometheus + namespace: {{ .Release.Namespace | quote }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "frrk8s.fullname" . }}-prometheus +subjects: + - kind: ServiceAccount + name: {{ required ".Values.prometheus.serviceAccount must be defined when .Values.prometheus.serviceMonitor.enabled == true" .Values.prometheus.serviceAccount }} + namespace: {{ required ".Values.prometheus.namespace must be defined when .Values.prometheus.serviceMonitor.enabled == true" .Values.prometheus.namespace }} +{{- end }} +{{- end }} diff --git a/metallb-chart/charts/frr-k8s/templates/webhooks.yaml b/metallb-chart/charts/frr-k8s/templates/webhooks.yaml new file mode 100644 index 0000000..a84b3b6 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/templates/webhooks.yaml @@ -0,0 +1,163 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "frrk8s.fullname" . }}-webhook-server + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "frrk8s.labels" . | nindent 4 }} + app.kubernetes.io/component: frr-k8s-webhook-server + {{- range $key, $value := .Values.frrk8s.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + selector: + matchLabels: + app.kubernetes.io/component: frr-k8s-webhook-server + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: frr-k8s-webhook-server + labels: + app.kubernetes.io/component: frr-k8s-webhook-server + spec: + {{- if .Values.frrk8s.runtimeClassName }} + runtimeClassName: {{ .Values.frrk8s.runtimeClassName }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.podSecurityContext }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- end }} + containers: + - command: + - /frr-k8s + args: + {{- with .Values.frrk8s.logLevel }} + - --log-level={{ . }} + {{- end }} + - "--webhook-mode=onlywebhook" + {{- if .Values.frrk8s.disableCertRotation }} + - "--disable-cert-rotation=true" + {{- end }} + {{- if .Values.frrk8s.restartOnRotatorSecretRefresh }} + - "--restart-on-rotator-secret-refresh=true" + {{- end }} + - "--namespace=$(NAMESPACE)" + - --health-probe-bind-address=:8081 + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: {{ .Values.frrk8s.image.repository }}:{{ .Values.frrk8s.image.tag | default .Chart.AppVersion }} + {{- if .Values.frrk8s.image.pullPolicy }} + imagePullPolicy: {{ .Values.frrk8s.image.pullPolicy }} + {{- end }} + name: frr-k8s-webhook-server + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + {{- if .Values.frrk8s.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: {{ .Values.frrk8s.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.frrk8s.livenessProbe.periodSeconds }} + failureThreshold: {{ .Values.frrk8s.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.frrk8s.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: {{ .Values.frrk8s.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.frrk8s.readinessProbe.periodSeconds }} + failureThreshold: {{ .Values.frrk8s.readinessProbe.failureThreshold }} + {{- end }} + {{- with .Values.frrk8s.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + volumeMounts: + - name: cert + mountPath: /tmp/k8s-webhook-server/serving-certs + readOnly: true + {{- with .Values.frrk8s.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.frrk8s.tolerateMaster .Values.frrk8s.tolerations }} + tolerations: + {{- if .Values.frrk8s.tolerateMaster }} + - key: node-role.kubernetes.io/master + effect: NoSchedule + operator: Exists + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + operator: Exists + {{- end }} + {{- with .Values.frrk8s.tolerations }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} + {{- with .Values.frrk8s.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: frr-k8s-webhook-server-cert + serviceAccountName: {{ template "frrk8s.serviceAccountName" . }} + terminationGracePeriodSeconds: 10 +--- +apiVersion: v1 +kind: Secret +metadata: + name: frr-k8s-webhook-server-cert + namespace: {{ .Release.Namespace | quote }} +--- +apiVersion: v1 +kind: Service +metadata: + name: frr-k8s-webhook-service + namespace: {{ .Release.Namespace | quote }} +spec: + ports: + - port: 443 + targetPort: 9443 + selector: + app.kubernetes.io/component: frr-k8s-webhook-server +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: frr-k8s-validating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: frr-k8s-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-frrk8s-metallb-io-v1beta1-frrconfiguration + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: frrconfigurationsvalidationwebhook.metallb.io + rules: + - apiGroups: + - frrk8s.metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - frrconfigurations + sideEffects: None diff --git a/metallb-chart/charts/frr-k8s/values.schema.json b/metallb-chart/charts/frr-k8s/values.schema.json new file mode 100644 index 0000000..67ec727 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/values.schema.json @@ -0,0 +1,387 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema#", + "title": "Values", + "type": "object", + "definitions": { + "prometheusAlert": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "required": [ + "enabled" + ] + }, + "probe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "failureThreshold": { + "type": "integer" + }, + "initialDelaySeconds": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + }, + "successThreshold": { + "type": "integer" + }, + "timeoutSeconds": { + "type": "integer" + } + }, + "required": [ + "failureThreshold", + "initialDelaySeconds", + "periodSeconds", + "successThreshold", + "timeoutSeconds" + ] + }, + "component": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "logLevel": { + "type": "string", + "enum": [ + "all", + "debug", + "info", + "warn", + "error", + "none" + ] + }, + "image": { + "type": "object", + "properties": { + "repository": { + "type": "string" + }, + "tag": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "pullPolicy": { + "anyOf": [ + { + "type": "null" + }, + { + "type": "string", + "enum": [ + "Always", + "IfNotPresent", + "Never" + ] + } + ] + } + } + }, + "serviceAccount": { + "type": "object", + "properties": { + "create": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "annotations": { + "type": "object" + } + } + }, + "resources": { + "type": "object" + }, + "nodeSelector": { + "type": "object" + }, + "tolerations": { + "type": "array", + "items": { + "type": "object" + } + }, + "priorityClassName": { + "type": "string" + }, + "runtimeClassName": { + "type": "string" + }, + "affinity": { + "type": "object" + }, + "podAnnotations": { + "type": "object" + }, + "livenessProbe": { + "$ref": "#/definitions/probe" + }, + "readinessProbe": { + "$ref": "#/definitions/probe" + } + }, + "required": [ + "image", + "serviceAccount" + ] + } + }, + "properties": { + "imagePullSecrets": { + "description": "Secrets used for pulling images", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ], + "additionalProperties": false + } + }, + "nameOverride": { + "description": "Override chart name", + "type": "string" + }, + "fullNameOverride": { + "description": "Override fully qualified app name", + "type": "string" + }, + "rbac": { + "description": "RBAC configuration", + "type": "object", + "properties": { + "create": { + "description": "Enable RBAC", + "type": "boolean" + } + } + }, + "prometheus": { + "description": "Prometheus monitoring config", + "type": "object", + "properties": { + "scrapeAnnotations": { + "type": "boolean" + }, + "metricsPort": { + "type": "integer" + }, + "secureMetricsPort": { + "type": "integer" + }, + "rbacPrometheus": { + "type": "boolean" + }, + "serviceAccount": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "rbacProxy": { + "description": "kube-rbac-proxy configuration", + "type": "object", + "properties": { + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "serviceMonitor": { + "description": "Prometheus Operator ServiceMonitors", + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "jobLabel": { + "type": "string" + }, + "interval": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "metricRelabelings": { + "type": "array", + "items": { + "type": "object" + } + }, + "relabelings": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + }, + "frrk8s": { + "allOf": [ + { + "$ref": "#/definitions/component" + }, + { + "description": "FRR-K8s controller", + "type": "object", + "properties": { + "tolerateMaster": { + "type": "boolean" + }, + "updateStrategy": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "runtimeClassName": { + "type": "string" + }, + "secretName": { + "type": "string" + }, + "frr": { + "description": "The FRR properties in the controller", + "type": "object", + "properties": { + "image": { + "$ref": "#/definitions/component/properties/image" + }, + "metricsPort": { + "type": "integer" + }, + "secureMetricsPort": { + "type": "integer" + }, + "resources:": { + "type": "object" + } + }, + "required": [ + "enabled" + ] + }, + "command": { + "type": "string" + }, + "reloader": { + "type": "object", + "properties": { + "resources": { + "type": "object" + } + } + }, + "frrMetrics": { + "type": "object", + "properties": { + "resources": { + "type": "object" + } + } + } + }, + "required": [ + "tolerateMaster" + ] + } + ] + }, + "crds": { + "description": "CRD configuration", + "type": "object", + "properties": { + "enabled": { + "description": "Enable CRDs", + "type": "boolean" + }, + "validationFailurePolicy": { + "description": "Failure policy to use with validating webhooks", + "type": "string", + "enum": [ + "Ignore", + "Fail" + ] + } + } + } + }, + "frrk8s": { + "allOf": [ + { + "$ref": "#/definitions/component" + }, + { + "description": "FRRk8s Controller", + "type": "object", + "properties": { + "strategy": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "command": { + "type": "string" + }, + "webhookMode": { + "type": "string" + } + } + } + ] + } + }, + "required": [ + "frrk8s" + ] +} \ No newline at end of file diff --git a/metallb-chart/charts/frr-k8s/values.yaml b/metallb-chart/charts/frr-k8s/values.yaml new file mode 100644 index 0000000..87731fe --- /dev/null +++ b/metallb-chart/charts/frr-k8s/values.yaml @@ -0,0 +1,176 @@ +# Default values for frr-k8s. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +nameOverride: "" +fullnameOverride: "" + +rbac: + # create specifies whether to install and use RBAC rules. + create: true + +podSecurityContext: + seccompProfile: + type: RuntimeDefault + +prometheus: + # scrape annotations specifies whether to add Prometheus metric + # auto-collection annotations to pods. See + # https://github.com/prometheus/prometheus/blob/release-2.1/documentation/examples/prometheus-kubernetes.yml + # for a corresponding Prometheus configuration. Alternatively, you + # may want to use the Prometheus Operator + # (https://github.com/coreos/prometheus-operator) for more powerful + # monitoring configuration. If you use the Prometheus operator, this + # can be left at false. + scrapeAnnotations: false + + # bind addr frr-k8s will use for metrics + metricsBindAddress: 127.0.0.1 + + # port frr-k8s will listen on for metrics + metricsPort: 7572 + + # if set, enables rbac proxy on frr-k8s to expose + # the metrics via tls. + secureMetricsPort: 9140 + + # the name of the secret to be mounted in the frr-k8s pod + # to expose the metrics securely. If not present, a self signed + # certificate to be used. + metricsTLSSecret: "" + + # prometheus doens't have the permission to scrape all namespaces so we give it permission to scrape metallb's one + rbacPrometheus: false + + # the service account used by prometheus + # required when " .Values.prometheus.rbacPrometheus == true " and " prometheus.serviceMonitor.enabled=true " + serviceAccount: "" + + # the namespace where prometheus is deployed + # required when " .Values.prometheus.rbacPrometheus == true " and " prometheus.serviceMonitor.enabled=true " + namespace: "" + + # the image to be used for the kuberbacproxy container + rbacProxy: + repository: "registry.opensuse.org/isv/suse/edge/metallb/images/kube-rbac-proxy" + tag: "v0.18.0" + pullPolicy: IfNotPresent + + # Prometheus Operator ServiceMonitors. + serviceMonitor: + # enable support for Prometheus Operator + enabled: false + + additionalLabels: {} + # optional additional annotations for the controller serviceMonitor + annotations: {} + # optional tls configuration for the controller serviceMonitor, in case + # secure metrics are enabled. + tlsConfig: + insecureSkipVerify: true + + # Job label for scrape target + jobLabel: "app.kubernetes.io/name" + + # Scrape interval. If not set, the Prometheus default scrape interval is used. + interval: + + # metric relabel configs to apply to samples before ingestion. + metricRelabelings: [] + # - action: keep + # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' + # sourceLabels: [__name__] + + # relabel configs to apply to samples before ingestion. + relabelings: [] + # - sourceLabels: [__meta_kubernetes_pod_node_name] + # separator: ; + # regex: ^(.*)$ + # target_label: nodename + # replacement: $1 + # action: replace + +# controller contains configuration specific to the FRRK8s controller +# daemonset. +frrk8s: + # -- Controller log level. Must be one of: `all`, `debug`, `info`, `warn`, `error` or `none` + logLevel: info + tolerateMaster: true + image: + repository: "registry.opensuse.org/isv/suse/edge/metallb/images/frr-k8s" + tag: "v0.0.14" + pullPolicy: IfNotPresent + ## @param controller.updateStrategy.type FRR-K8s controller daemonset strategy type + ## ref: https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/ + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate or OnDelete + ## + type: RollingUpdate + serviceAccount: + # Specifies whether a ServiceAccount should be created + create: true + # The name of the ServiceAccount to use. If not set and create is + # true, a name is generated using the fullname template + name: "" + annotations: {} + ## Defines a secret name for the controller to generate a memberlist encryption secret + ## By default secretName: {{ "metallb.fullname" }}-memberlist + ## + # secretName: + resources: {} + # limits: + # cpu: 100m + # memory: 100Mi + nodeSelector: {} + tolerations: [] + priorityClassName: "" + affinity: {} + ## Selects which runtime class will be used by the pod. + runtimeClassName: "" + podAnnotations: {} + labels: + app: frr-k8s + healthPort: 8081 + livenessProbe: + enabled: true + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + enabled: true + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + startupProbe: + enabled: true + failureThreshold: 30 + periodSeconds: 5 + ## A comma separated list of cidrs we want always to block for incoming routes + alwaysBlock: "" + ## Specifies whether the cert rotator works as part of the webhook. + disableCertRotation: false + ## Specifies whether the pod restarts when the rotator refreshes the cert secret. + ## Enabling this proved useful for the webhook's stability when it is redeployed multiple times in succession. + restartOnRotatorSecretRefresh: false + # frr contains configuration specific to the FRR container, + frr: + image: + repository: "registry.opensuse.org/isv/suse/edge/metallb/images/frr" + tag: "8.4" + pullPolicy: IfNotPresent + metricsBindAddress: 127.0.0.1 + metricsPort: 7573 + resources: {} + secureMetricsPort: 9141 + reloader: + resources: {} + frrMetrics: + resources: {} +crds: + validationFailurePolicy: Fail diff --git a/metallb-chart/charts/metallb-crds/.helmignore b/metallb-chart/charts/metallb-crds/.helmignore new file mode 100644 index 0000000..1b9a9cc --- /dev/null +++ b/metallb-chart/charts/metallb-crds/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/metallb-chart/charts/metallb-crds/Chart.yaml b/metallb-chart/charts/metallb-crds/Chart.yaml new file mode 100644 index 0000000..6d070fc --- /dev/null +++ b/metallb-chart/charts/metallb-crds/Chart.yaml @@ -0,0 +1,10 @@ +apiVersion: v2 +appVersion: v0.14.9 +description: MetalLB CRDs +home: https://metallb.universe.tf +icon: https://metallb.universe.tf/images/logo/metallb-white.png +name: metallb-crds +sources: +- https://github.com/metallb/metallb +type: application +version: 0.14.8 diff --git a/metallb-chart/charts/metallb-crds/README.md b/metallb-chart/charts/metallb-crds/README.md new file mode 100644 index 0000000..58cf71b --- /dev/null +++ b/metallb-chart/charts/metallb-crds/README.md @@ -0,0 +1,11 @@ +# crds + +![Version: 0.14.3](https://img.shields.io/badge/Version-0.14.3-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.14.3](https://img.shields.io/badge/AppVersion-v0.14.3-informational?style=flat-square) + +MetalLB CRDs + +**Homepage:** + +## Source Code + +* diff --git a/metallb-chart/charts/metallb-crds/templates/crds.yaml b/metallb-chart/charts/metallb-crds/templates/crds.yaml new file mode 100644 index 0000000..9341bb4 --- /dev/null +++ b/metallb-chart/charts/metallb-crds/templates/crds.yaml @@ -0,0 +1,1205 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: bfdprofiles.metallb.io +spec: + group: metallb.io + names: + kind: BFDProfile + listKind: BFDProfileList + plural: bfdprofiles + singular: bfdprofile + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.passiveMode + name: Passive Mode + type: boolean + - jsonPath: .spec.transmitInterval + name: Transmit Interval + type: integer + - jsonPath: .spec.receiveInterval + name: Receive Interval + type: integer + - jsonPath: .spec.detectMultiplier + name: Multiplier + type: integer + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + BFDProfile represents the settings of the bfd session that can be + optionally associated with a BGP session. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: BFDProfileSpec defines the desired state of BFDProfile. + properties: + detectMultiplier: + description: |- + Configures the detection multiplier to determine + packet loss. The remote transmission interval will be multiplied + by this value to determine the connection loss detection timer. + format: int32 + maximum: 255 + minimum: 2 + type: integer + echoInterval: + description: |- + Configures the minimal echo receive transmission + interval that this system is capable of handling in milliseconds. + Defaults to 50ms + format: int32 + maximum: 60000 + minimum: 10 + type: integer + echoMode: + description: |- + Enables or disables the echo transmission mode. + This mode is disabled by default, and not supported on multi + hops setups. + type: boolean + minimumTtl: + description: |- + For multi hop sessions only: configure the minimum + expected TTL for an incoming BFD control packet. + format: int32 + maximum: 254 + minimum: 1 + type: integer + passiveMode: + description: |- + Mark session as passive: a passive session will not + attempt to start the connection and will wait for control packets + from peer before it begins replying. + type: boolean + receiveInterval: + description: |- + The minimum interval that this system is capable of + receiving control packets in milliseconds. + Defaults to 300ms. + format: int32 + maximum: 60000 + minimum: 10 + type: integer + transmitInterval: + description: |- + The minimum transmission interval (less jitter) + that this system wants to use to send BFD control packets in + milliseconds. Defaults to 300ms + format: int32 + maximum: 60000 + minimum: 10 + type: integer + type: object + status: + description: BFDProfileStatus defines the observed state of BFDProfile. + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: bgpadvertisements.metallb.io +spec: + group: metallb.io + names: + kind: BGPAdvertisement + listKind: BGPAdvertisementList + plural: bgpadvertisements + singular: bgpadvertisement + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.ipAddressPools + name: IPAddressPools + type: string + - jsonPath: .spec.ipAddressPoolSelectors + name: IPAddressPool Selectors + type: string + - jsonPath: .spec.peers + name: Peers + type: string + - jsonPath: .spec.nodeSelectors + name: Node Selectors + priority: 10 + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + BGPAdvertisement allows to advertise the IPs coming + from the selected IPAddressPools via BGP, setting the parameters of the + BGP Advertisement. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: BGPAdvertisementSpec defines the desired state of BGPAdvertisement. + properties: + aggregationLength: + default: 32 + description: The aggregation-length advertisement option lets you “roll up” the /32s into a larger prefix. Defaults to 32. Works for IPv4 addresses. + format: int32 + minimum: 1 + type: integer + aggregationLengthV6: + default: 128 + description: The aggregation-length advertisement option lets you “roll up” the /128s into a larger prefix. Defaults to 128. Works for IPv6 addresses. + format: int32 + type: integer + communities: + description: |- + The BGP communities to be associated with the announcement. Each item can be a standard community of the + form 1234:1234, a large community of the form large:1234:1234:1234 or the name of an alias defined in the + Community CRD. + items: + type: string + type: array + ipAddressPoolSelectors: + description: |- + A selector for the IPAddressPools which would get advertised via this advertisement. + If no IPAddressPool is selected by this or by the list, the advertisement is applied to all the IPAddressPools. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: array + ipAddressPools: + description: The list of IPAddressPools to advertise via this advertisement, selected by name. + items: + type: string + type: array + localPref: + description: |- + The BGP LOCAL_PREF attribute which is used by BGP best path algorithm, + Path with higher localpref is preferred over one with lower localpref. + format: int32 + type: integer + nodeSelectors: + description: NodeSelectors allows to limit the nodes to announce as next hops for the LoadBalancer IP. When empty, all the nodes having are announced as next hops. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: array + peers: + description: |- + Peers limits the bgppeer to advertise the ips of the selected pools to. + When empty, the loadbalancer IP is announced to all the BGPPeers configured. + items: + type: string + type: array + type: object + status: + description: BGPAdvertisementStatus defines the observed state of BGPAdvertisement. + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: bgppeers.metallb.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGWlRDQ0EwMmdBd0lCQWdJVU5GRW1XcTM3MVpKdGkrMmlSQzk1WmpBV1MxZ3dEUVlKS29aSWh2Y05BUUVMDQpCUUF3UWpFTE1Ba0dBMVVFQmhNQ1dGZ3hGVEFUQmdOVkJBY01ERVJsWm1GMWJIUWdRMmwwZVRFY01Cb0dBMVVFDQpDZ3dUUkdWbVlYVnNkQ0JEYjIxd1lXNTVJRXgwWkRBZUZ3MHlNakEzTVRrd09UTXlNek5hRncweU1qQTRNVGd3DQpPVE15TXpOYU1FSXhDekFKQmdOVkJBWVRBbGhZTVJVd0V3WURWUVFIREF4RVpXWmhkV3gwSUVOcGRIa3hIREFhDQpCZ05WQkFvTUUwUmxabUYxYkhRZ1EyOXRjR0Z1ZVNCTWRHUXdnZ0lpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElDDQpEd0F3Z2dJS0FvSUNBUUNxVFpxMWZRcC9vYkdlenhES0o3OVB3Ny94azJwellualNzMlkzb1ZYSm5sRmM4YjVlDQpma2ZZQnY2bndscW1keW5PL2phWFBaQmRQSS82aFdOUDBkdVhadEtWU0NCUUpyZzEyOGNXb3F0MGNTN3pLb1VpDQpvcU1tQ0QvRXVBeFFNZjhRZDF2c1gvVllkZ0poVTZBRXJLZEpIaXpFOUJtUkNkTDBGMW1OVW55Rk82UnRtWFZUDQpidkxsTDVYeTc2R0FaQVBLOFB4aVlDa0NtbDdxN0VnTWNiOXlLWldCYmlxQ3VkTXE5TGJLNmdKNzF6YkZnSXV4DQo1L1pXK2JraTB2RlplWk9ZODUxb1psckFUNzJvMDI4NHNTWW9uN0pHZVZkY3NoUnh5R1VpSFpSTzdkaXZVTDVTDQpmM2JmSDFYbWY1ZDQzT0NWTWRuUUV2NWVaOG8zeWVLa3ZrbkZQUGVJMU9BbjdGbDlFRVNNR2dhOGFaSG1URSttDQpsLzlMSmdDYjBnQmtPT0M0WnV4bWh2aERKV1EzWnJCS3pMQlNUZXN0NWlLNVlwcXRWVVk2THRyRW9FelVTK1lsDQpwWndXY2VQWHlHeHM5ZURsR3lNVmQraW15Y3NTU1UvVno2Mmx6MnZCS21NTXBkYldDQWhud0RsRTVqU2dyMjRRDQp0eGNXLys2N3d5KzhuQlI3UXdqVTFITndVRjBzeERWdEwrZ1NHVERnSEVZSlhZelYvT05zMy94TkpoVFNPSkxNDQpoeXNVdyttaGdackdhbUdXcHVIVU1DUitvTWJzMTc1UkcrQjJnUFFHVytPTjJnUTRyOXN2b0ZBNHBBQm8xd1dLDQpRYjRhY3pmeVVscElBOVFoSmFsZEY3S3dPSHVlV3gwRUNrNXg0T2tvVDBvWVp0dzFiR0JjRGtaSmF3SURBUUFCDQpvMU13VVRBZEJnTlZIUTRFRmdRVW90UlNIUm9IWTEyRFZ4R0NCdEhpb1g2ZmVFQXdId1lEVlIwakJCZ3dGb0FVDQpvdFJTSFJvSFkxMkRWeEdDQnRIaW9YNmZlRUF3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCDQpBUXNGQUFPQ0FnRUFSbkpsWWRjMTFHd0VxWnh6RDF2R3BDR2pDN2VWTlQ3aVY1d3IybXlybHdPYi9aUWFEa0xYDQpvVStaOVVXT1VlSXJTdzUydDdmQUpvVVAwSm5iYkMveVIrU1lqUGhvUXNiVHduOTc2ZldBWTduM3FMOXhCd1Y0DQphek41OXNjeUp0dlhMeUtOL2N5ak1ReDRLajBIMFg0bWJ6bzVZNUtzWWtYVU0vOEFPdWZMcEd0S1NGVGgrSEFDDQpab1Q5YnZHS25adnNHd0tYZFF0Wnh0akhaUjVqK3U3ZGtQOTJBT051RFNabS8rWVV4b2tBK09JbzdSR3BwSHNXDQo1ZTdNY0FTVXRtb1FORXd6dVFoVkJaRWQ1OGtKYjUrV0VWbGNzanlXNnRTbzErZ25tTWNqR1BsMWgxR2hVbjV4DQpFY0lWRnBIWXM5YWo1NmpBSjk1MVQvZjhMaWxmTlVnanBLQ0c1bnl0SUt3emxhOHNtdGlPdm1UNEpYbXBwSkI2DQo4bmdHRVluVjUrUTYwWFJ2OEhSSGp1VG9CRHVhaERrVDA2R1JGODU1d09FR2V4bkZpMXZYWUxLVllWb1V2MXRKDQo4dVdUR1pwNllDSVJldlBqbzg5ZytWTlJSaVFYUThJd0dybXE5c0RoVTlqTjA0SjdVL1RvRDFpNHE3VnlsRUc5DQorV1VGNkNLaEdBeTJIaEhwVncyTGFoOS9lUzdZMUZ1YURrWmhPZG1laG1BOCtqdHNZamJadnR5Mm1SWlF0UUZzDQpUU1VUUjREbUR2bVVPRVRmeStpRHdzK2RkWXVNTnJGeVVYV2dkMnpBQU4ydVl1UHFGY2pRcFNPODFzVTJTU3R3DQoxVzAyeUtYOGJEYmZFdjBzbUh3UzliQnFlSGo5NEM1Mjg0YXpsdTBmaUdpTm1OUEM4ckJLRmhBPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ== + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /convert + conversionReviewVersions: + - v1beta1 + - v1beta2 + group: metallb.io + names: + kind: BGPPeer + listKind: BGPPeerList + plural: bgppeers + singular: bgppeer + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.peerAddress + name: Address + type: string + - jsonPath: .spec.peerASN + name: ASN + type: string + - jsonPath: .spec.bfdProfile + name: BFD Profile + type: string + - jsonPath: .spec.ebgpMultiHop + name: Multi Hops + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: BGPPeer is the Schema for the peers API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: BGPPeerSpec defines the desired state of Peer. + properties: + bfdProfile: + type: string + ebgpMultiHop: + description: EBGP peer is multi-hops away + type: boolean + holdTime: + description: Requested BGP hold time, per RFC4271. + type: string + keepaliveTime: + description: Requested BGP keepalive time, per RFC4271. + type: string + myASN: + description: AS number to use for the local end of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + nodeSelectors: + description: |- + Only connect to this peer on nodes that match one of these + selectors. + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + minItems: 1 + type: array + required: + - key + - operator + - values + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + type: array + password: + description: Authentication password for routers enforcing TCP MD5 authenticated sessions + type: string + peerASN: + description: AS number to expect from the remote end of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + peerAddress: + description: Address to dial when establishing the session. + type: string + peerPort: + description: Port to dial when establishing the session. + maximum: 16384 + minimum: 0 + type: integer + routerID: + description: BGP router ID to advertise to the peer + type: string + sourceAddress: + description: Source address to use when establishing the session. + type: string + required: + - myASN + - peerASN + - peerAddress + type: object + status: + description: BGPPeerStatus defines the observed state of Peer. + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.peerAddress + name: Address + type: string + - jsonPath: .spec.peerASN + name: ASN + type: string + - jsonPath: .spec.bfdProfile + name: BFD Profile + type: string + - jsonPath: .spec.ebgpMultiHop + name: Multi Hops + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: BGPPeer is the Schema for the peers API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: BGPPeerSpec defines the desired state of Peer. + properties: + bfdProfile: + description: The name of the BFD Profile to be used for the BFD session associated to the BGP session. If not set, the BFD session won't be set up. + type: string + connectTime: + description: Requested BGP connect time, controls how long BGP waits between connection attempts to a neighbor. + type: string + x-kubernetes-validations: + - message: connect time should be between 1 seconds to 65535 + rule: duration(self).getSeconds() >= 1 && duration(self).getSeconds() <= 65535 + - message: connect time should contain a whole number of seconds + rule: duration(self).getMilliseconds() % 1000 == 0 + disableMP: + default: false + description: To set if we want to disable MP BGP that will separate IPv4 and IPv6 route exchanges into distinct BGP sessions. + type: boolean + ebgpMultiHop: + description: To set if the BGPPeer is multi-hops away. Needed for FRR mode only. + type: boolean + enableGracefulRestart: + description: |- + EnableGracefulRestart allows BGP peer to continue to forward data packets along + known routes while the routing protocol information is being restored. + This field is immutable because it requires restart of the BGP session + Supported for FRR mode only. + type: boolean + x-kubernetes-validations: + - message: EnableGracefulRestart cannot be changed after creation + rule: self == oldSelf + holdTime: + description: Requested BGP hold time, per RFC4271. + type: string + keepaliveTime: + description: Requested BGP keepalive time, per RFC4271. + type: string + myASN: + description: AS number to use for the local end of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + nodeSelectors: + description: |- + Only connect to this peer on nodes that match one of these + selectors. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: array + password: + description: Authentication password for routers enforcing TCP MD5 authenticated sessions + type: string + passwordSecret: + description: |- + passwordSecret is name of the authentication secret for BGP Peer. + the secret must be of type "kubernetes.io/basic-auth", and created in the + same namespace as the MetalLB deployment. The password is stored in the + secret as the key "password". + properties: + name: + description: name is unique within a namespace to reference a secret resource. + type: string + namespace: + description: namespace defines the space within which the secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + peerASN: + description: AS number to expect from the remote end of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + peerAddress: + description: Address to dial when establishing the session. + type: string + peerPort: + default: 179 + description: Port to dial when establishing the session. + maximum: 16384 + minimum: 0 + type: integer + routerID: + description: BGP router ID to advertise to the peer + type: string + sourceAddress: + description: Source address to use when establishing the session. + type: string + vrf: + description: |- + To set if we want to peer with the BGPPeer using an interface belonging to + a host vrf + type: string + required: + - myASN + - peerASN + - peerAddress + type: object + status: + description: BGPPeerStatus defines the observed state of Peer. + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: communities.metallb.io +spec: + group: metallb.io + names: + kind: Community + listKind: CommunityList + plural: communities + singular: community + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: |- + Community is a collection of aliases for communities. + Users can define named aliases to be used in the BGPPeer CRD. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: CommunitySpec defines the desired state of Community. + properties: + communities: + items: + properties: + name: + description: The name of the alias for the community. + type: string + value: + description: |- + The BGP community value corresponding to the given name. Can be a standard community of the form 1234:1234 + or a large community of the form large:1234:1234:1234. + type: string + type: object + type: array + type: object + status: + description: CommunityStatus defines the observed state of Community. + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: ipaddresspools.metallb.io +spec: + group: metallb.io + names: + kind: IPAddressPool + listKind: IPAddressPoolList + plural: ipaddresspools + singular: ipaddresspool + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.autoAssign + name: Auto Assign + type: boolean + - jsonPath: .spec.avoidBuggyIPs + name: Avoid Buggy IPs + type: boolean + - jsonPath: .spec.addresses + name: Addresses + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + IPAddressPool represents a pool of IP addresses that can be allocated + to LoadBalancer services. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IPAddressPoolSpec defines the desired state of IPAddressPool. + properties: + addresses: + description: |- + A list of IP address ranges over which MetalLB has authority. + You can list multiple ranges in a single pool, they will all share the + same settings. Each range can be either a CIDR prefix, or an explicit + start-end range of IPs. + items: + type: string + type: array + autoAssign: + default: true + description: |- + AutoAssign flag used to prevent MetallB from automatic allocation + for a pool. + type: boolean + avoidBuggyIPs: + default: false + description: |- + AvoidBuggyIPs prevents addresses ending with .0 and .255 + to be used by a pool. + type: boolean + serviceAllocation: + description: |- + AllocateTo makes ip pool allocation to specific namespace and/or service. + The controller will use the pool with lowest value of priority in case of + multiple matches. A pool with no priority set will be used only if the + pools with priority can't be used. If multiple matching IPAddressPools are + available it will check for the availability of IPs sorting the matching + IPAddressPools by priority, starting from the highest to the lowest. If + multiple IPAddressPools have the same priority, choice will be random. + properties: + namespaceSelectors: + description: |- + NamespaceSelectors list of label selectors to select namespace(s) for ip pool, + an alternative to using namespace list. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: array + namespaces: + description: Namespaces list of namespace(s) on which ip pool can be attached. + items: + type: string + type: array + priority: + description: Priority priority given for ip pool while ip allocation on a service. + type: integer + serviceSelectors: + description: |- + ServiceSelectors list of label selector to select service(s) for which ip pool + can be used for ip allocation. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: array + type: object + required: + - addresses + type: object + status: + description: IPAddressPoolStatus defines the observed state of IPAddressPool. + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: l2advertisements.metallb.io +spec: + group: metallb.io + names: + kind: L2Advertisement + listKind: L2AdvertisementList + plural: l2advertisements + singular: l2advertisement + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.ipAddressPools + name: IPAddressPools + type: string + - jsonPath: .spec.ipAddressPoolSelectors + name: IPAddressPool Selectors + type: string + - jsonPath: .spec.interfaces + name: Interfaces + type: string + - jsonPath: .spec.nodeSelectors + name: Node Selectors + priority: 10 + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + L2Advertisement allows to advertise the LoadBalancer IPs provided + by the selected pools via L2. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: L2AdvertisementSpec defines the desired state of L2Advertisement. + properties: + interfaces: + description: |- + A list of interfaces to announce from. The LB IP will be announced only from these interfaces. + If the field is not set, we advertise from all the interfaces on the host. + items: + type: string + type: array + ipAddressPoolSelectors: + description: |- + A selector for the IPAddressPools which would get advertised via this advertisement. + If no IPAddressPool is selected by this or by the list, the advertisement is applied to all the IPAddressPools. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: array + ipAddressPools: + description: The list of IPAddressPools to advertise via this advertisement, selected by name. + items: + type: string + type: array + nodeSelectors: + description: NodeSelectors allows to limit the nodes to announce as next hops for the LoadBalancer IP. When empty, all the nodes having are announced as next hops. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: array + type: object + status: + description: L2AdvertisementStatus defines the observed state of L2Advertisement. + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: servicel2statuses.metallb.io +spec: + group: metallb.io + names: + kind: ServiceL2Status + listKind: ServiceL2StatusList + plural: servicel2statuses + singular: servicel2status + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.node + name: Allocated Node + type: string + - jsonPath: .status.serviceName + name: Service Name + type: string + - jsonPath: .status.serviceNamespace + name: Service Namespace + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: ServiceL2Status reveals the actual traffic status of loadbalancer services in layer2 mode. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ServiceL2StatusSpec defines the desired state of ServiceL2Status. + type: object + status: + description: MetalLBServiceL2Status defines the observed state of ServiceL2Status. + properties: + interfaces: + description: Interfaces indicates the interfaces that receive the directed traffic + items: + description: InterfaceInfo defines interface info of layer2 announcement. + properties: + name: + description: Name the name of network interface card + type: string + type: object + type: array + node: + description: Node indicates the node that receives the directed traffic + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + serviceName: + description: ServiceName indicates the service this status represents + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + serviceNamespace: + description: ServiceNamespace indicates the namespace of the service + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metallb-chart/policy.obscpio b/metallb-chart/policy.obscpio deleted file mode 100644 index 09b648f40e16e9bd2ec34efe3330313becc9ce053978835af1711318a06d888f..0000000000000000000000000000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3072 zcmdT`YfsxS6y-TAkmTn1y+d<461EfL8z@JO{J>b2dtDo5?$l93Q)_Q#hE! z;|FdsjpHWHJk#Oy+04d6?t9K+Ureae5OBx0wnFO6=pB%NdaPP~N4``_bIXfd(;Ug=X4M0)c zfHoKnAP&A=To#iF72N$@C?R+|j1q#SFshcf~skAws1j4Q#3 zgr^p9kcZ<-Vb{2O5^A=u=T#+%m1e<$8*Bv$>vHvHnmsFX`zdRhH3HP93AFvaaT- zt|W-L=fJt+@Q5i*!}TJ%gwW@U0GQIJR{ol_&y4O6AE%)p2z}IVBYrD~;~JWm<%w8| z0(_tn>ROxi6~f2_AVc9XHQllD(pRlndoOGGc?DEC_h>4ZrvjHCBoSD9WLQpSw43N8 zLyd71k;LpA#YL(rNhXo!E3~H{_rQpQ7R3X?8ETITAfe!M&jt5)@J%$UU2FxKI*Go? zVQ9^w2?z!XWW(e89Q`GR(DzvMppVKpMFF7V_c*K3==KOYl{mU9FcndX=@D)%3%w9fTa(qXw|~urrC6I;>ll8oaA?`5helCoJLDHciF$Cb+2fV&`x2)oz-SW1lT z``PcW=h*`cu-GN_u#T9DMPgn(-90`1nwgESH@@E3+}Mo9-%d8a-oVc{o6(o_@5biU zSMuMDP4zdveD&4jFW>Kl$X7XrBBS=S7muwna3VCI$VP$Ja?w=23~?2QR-V21z!&-F);inN7CEk5QUT zP&B*#N%ggt&90K`g{uB&8kZ4@qwPmR%%W+$E$B;{UiS6S{jpbHh%~y4(}L;?@yjoL zk<7;FViJpf^9YRqs~DWcX&e>t-~=<3p9w6Qh!FFryxA7RTZOK; zZ_tor{oBn;;AE?Rc|D)UagGL8QIan5_%utC@tx`#cwWTCV4P2if$jw4c+M-T!4#Ht zU#_M`&cI+X$uLg7NMnr?Q2x6-Tg)})`-V;+ww!_E3|m9PEsL{xtSD|v_s$M>FAij3 zU;J>oZ~n;RB3tBRHLehSp+PNBwMZuM!PQkfE{kn(lFj1ZB_%ie$vm1&FwtV3Whv%$ ze|ma7z6Gk%3K8NSRP_MvJ@>Vk<;L|Nds2u`?=D2JLu_7@g)tjRq6dz{Ckm=vC>D^*XN6QJSJs) zp5@R7@k?L+x-Gu^^3V87h%(BrdT|1sdmuWm9 zmg0P@JA?H(7-xB$!9dEU&N$WFtvd-214f%MhMj?VwMbJU2eHO)zxBa}(aSjR>#^P< zt(G#P22C!8&ZyLl1~5?)GU=mKtpvg?;UoJQzJLxSY3%1$*zC?Kr%4cO@k~-r8}(gi zZU>mnvQl~<3MEn^_hEZIkX;9GBKXiUSOI_(KmdK7B{L<2oEWMyPo9j6LHv526*21P zrQ;zeJK z3=hz;BzQqvoNIp>M|qrIWG~~{b11aiq6fE9KFk-hVG+}=Qw;sBOUu$|JkA!ga#&K! zp60z`d;>EUecY7gyyyWSxZJw%qFJ3~S|}%)1JHh2Z*|({Zfz3p5#tFV0o1Yt$g{tB zP#f5;@_fK{4r*_7h_=OxW*yhBPd+{@DA7c}&M2<4j`?zL-m?qgBQr4;s{bm)zp_gy zvOA*OR0r=eCD>|r=bnB#jmq)O38~XY?DgCH$VPKjm1SeSo9M+%!$>$+RciWLM6~I% z(mC$wP~JXFi;GD?Xw1bpkLDy=XsaW6)0y$jLSh4ubfGo7vUbvKtM}s$_s1h)Lr%AI z^uh!js)C7vC4+XA)KYIXGXhwa>W$AT-X`fj>7u|BL>G*AFMq2D4{(_JN zEP~yutAw1NmO$klt>ZmIxSEuB8)ld@x<438%uVUu##mcdRSRcbdyJ34q^eXUn514! z>1*h;3NvFD0Dn5w1ab&fqT9Mh$sq@ZzR;`zIW9FmvwcKxH6lQ0f zFixUPI%Ji%aYUn5|9&XaY&khI%Cf2bwDuacJuJ7)*uG+v;txxQcDOb>l2yc7+`?~B zjdlPIn0#JUlWypxMMAHuOuLb42wg=xZt2GC9Y&v3Vp^{Es-kYHtgrGqIDY3^?`n!+ zv-Hd_qw%SA@e?0%Up|!%qD6U=<;j1-$!2F6;{w-0U)SlTc$|8vwyrIe?d+A?ufW& z@N>gw{MPXYnw`a0w9-IrnPavs8bL-a6_}KyUS-uY0vC(Rf5{v&^w!t?ohu6LDj%rC zs5Q{?_}_~pM|7#ztWfBNVhZC`T*hJ&!$v}rS2yvjL$JhnA$NA9;~$1wW5~;lq<3wf zS6e}~Ro^6(ZV&*-lqvRWCC2zI#R9v=7&o>yWPLPQlFzzj^IVO$s~Eet6T-787yYwc;aSyksYYXtL?Eb{%4Yn5ds}N zkuC7|_>%oGSxl#QuIx6+d1?CEt9*<2uB)47pV=;v8S4tl#VmDyU8R6BW*;cNfh^10 z!qpkiSo2vniPLNxrIQ&|alDBfXD|L8t;Cxf-&|3B{4C*3o2$Lyc=P1N#liWYd|d*D zV`7J+XCf)YEPI7K+!->NuMvq9h<+On+2GNm6BOQM3o(vnlyx8zt7DOr;x>u!Pa*cs zih($lj3e^+D$ZeT%04v1i44A+af0|2NLW0|W(Y#QqB@Hrmi4HEM?OwuUU}E`x;dFl z6iSxjMB@s&*fVbz_gxAm;KOl6?)X;1=(@pDGwx^|`8S1%ONx7kW;F-W+zykTm zPgP{vM3XD@Q@s+AUM1y??S?Tz)6}UYXCcNYEDs?t95u53Z0d#Yo2J*=nG(ZjA!E-Q zZL_HOuH4bb?V7Ez(j9 z_HLrQ9PG~L`rwtLxnhto($t`Hu!=hQ#9LWj2_1^E`Iv*YE^6p%gN4%I$y{I}RDW_@ zO4ely zAAEW1l^}oz{5Y8f_?jk?QM?I6q$`$WgAMgFqR}@_r#J zGy~JrO#qyDcI)_`%E20|Sk=>bill0CYH@R#7@2-d^#AzaV)y9i+35Iabbf$?gcqZe z-D7o@P*s!~uasSZt(;QeNd9}Wyx#f#!RgV9pN|htF6?3w!gXBVI4VgPj<0O{0Kznm zj0R=A4uOn;5CWckcRITG`7|(fbkJc~rj()qo!vEdlmWSS*@oezNnd#+h^jf_lqerMNxO7nLJGH~eRe=~X> zN0S$`6p0rsJGgC^N|W1ohNO+tJiCl7ZP}jXRd6d8QBS0MeixVg6ZC&I6}{Ei=@WQF zKOEjx>GL8F=6f0u4F;VNhS;>e8pz#P5wX-E2{= z1ft)@@2^;l;T9||Zs7gD$x9=A8D~xVk+Tu;Yryo|+~6$(OkFdq zoPdJoJ$rSUC%4F!zm5+I_=TlWw~d4OX<<%bP<=uG3E;CVD=D|WxI?Pqv?7kNK}GZE zGD#u!T;{GCZjxtnJ{wXypvq`zSy2YqZYH4*r~4bFNcy}faMnk=*K{&j{YaC?lRd0o zs*la#^9&&&4er) zx&?uRCQ{CExkU*APj^UCZ4ZZ=TVD@0@W0K5E`5t@Xc4Y@tLxVnN9Uu1z5VYGMrY@{ zqn{2hz8~!#oR2oQz8QVDcRV`(es}9HUp;lTPxdv_?p*@0vrA&B{#$XYFt+(Vj6Dm<3FInmwfM+p0Em*9fubKn*Mk zDV}@r2%1#SKWUW}y={S$d5hO}>eNxwuE_iJR}r5<*a51{f*PiphKh7fw;RTMaog4M zL2FoPn_Y>_4}B?+8)|-QYB-&m?@zI)bXZd8)uoyE0jSC?s!{=QZ{mDqYFk>;w@f&+dY!yL1% zIE(@gCdt*o1IG-F)ii$dcaz!E(v;D&)6hzCA~~yi=Dt=yvAmkz5f&}Aw$;_UDwO;L zytdoerxhS$ty*BJ=C?aC2k+rHy{}BvZgcFOZ%`n*LAnZ`Rd3K>Y*~|}Rk@>Ju=-sm zUS-1XqckMtX~`DoDE?6tHffoRXX{c+i<(-&3IeCrwngl8S_E8zy(LlD443x5VUl#K z5iQDha^&IOhZqng`yHK7z~x;38_yiDrE0>w@7Z~S6(O`znHEk(CDJ=%C7)a7B6qbZ z|MF#Ln^NA%?dLA*%|jWKux%?sz!X;^{kqm#fq806F&WVdbxvs*CYrBLDhvgDT`I1R zD}!(N;J4o2kN<5-7~aijvN^VBcWjFPK690kGva5o_z@CrnYUq`rGJ%$Gp_tjB9aPQ)< zPy{#c3`4V#_&(6-2uT;;0jAT}bAhgGmya@&&fe4klg@gUIf~!UqR58@(iY<(PD%_hI1UrZ9*dzr&hEtpa)u6HoG9zv4F3}y1dGNc zMLme{ksi=Mfa&EpI!3YIrzlil$~iw3$ioZ2JV&g7 z?z(@11^I+#U>TXPh4UP_%*48;Tiitt6X>C16W)9*QL0b?cXXQK+=)ELCK0LDgACA6 zPR3wD^B;gJ7?olX@>Y;SAj@HqPBg**z+xwV_4Iltf12%R6bXq1h!!BAcU#^SH$8#S z^o>7ZI`)FVYbIuKJc%a*aaiiU`Ly&nZa(O*C#P7%z$1>ZVCYvE8&k^`*Ea*PcN33a z3OS8=G*z>Bikg{EK$@03Nl6?=((OO-Wp2m?$gp6e^i_0+36od=fC?1(U)*{<*}0Q< zBjbMbVtzH*nW-D{>5s4MUwMLhx&*(^uI*n*kreiic`~)XrxVv?c9Xk5;^dnBbxDp0 z+lW}!)tq1Ewgh(+J4mmhOQh@DvfErYVl#Uz4zGYp&?cMHy^usDiD{s#!Wsg{8j^V_ za9THmwqSfLG+* zx+-7s&QN80ds7t>m+kEKzrgaUL#P27;i}x$&b8FeWHp>S)Fc?Z{}Aqh*}%&KPN7t#zqk5y+^zcwTWWU(&Cy%uaoIwDrO7Hx5X(y z@qGV}R1}p;{6l<4x6mc&T3sW&f4~LDMio+$0KHMzmb4|kqUqvetw@pRT%^e~Q3uo? zlfWQJKob3j8KuC}b|q_JrAE|Kf$L^5ph~lqJ0q5~3Sd7bVS}AZFLRQ@N{dsQX-aoJ zv+2-FDTUj>6p6 zh+V3Uk)}@jq85945VM6i>Kl53B^(W!fliV!(C?=SPm0Y1H9dr^d;lwH<<)b5!yMeze5i&| z9O0!H8Niy5M-4d#GA8p5)>0jBtl9@2`7^x+PXDMA<45wg3_mTx8?W^suVXkhZ-Ql= z)vmzou;R^p7zO}?T=}L5j9q1h>KR=lWawcx|6H#ZCpRRkR&vd2xTg;u*=<7b`TKFG z*UU-p_v{p~cM6PUR)$aXDtgm~dJ>nfvizl&tw?AH&;dzP9S{4e?)?>^6BOMH{LWlj z598k&fhyT)6+oGI(8C2jmKA}g(M;H$3Criv4L~VW4zVV8H zdes%~2#`XC%T$LBf*U*6Zt(+TJtfrhoLXI^Z<)h`x@EgYz262uT6)2d60 z=7so9aIFF4c-EgJnoaR)D6Y@C3B!I(DcVl+jE>@-n1t4v*2WZTcD}rp&98aW((dge zzCr0xbPk`YlVxXm*PP;`x(5}qF-4*i%VX+Mx83;+;l8W`6< zAoxHxq8Nb#f7b_b9g3OHt7ry&0l{u(xDoRE{b|}qnR9U}N(Io}#BA4azsC9w$fIYB z+SGd@OU+G|xbMZ1e)$O85NUoONzHX_fZIImrUvfglryy5vqBH7`o9j<}VoRJoC zYAtUxP3cnOUA(paLi_0br9kA^76z}lP3GC*$^K|}fB(!vX0LqV?lQB&7<|E@RK$W% z4j!Uhi*<*;531pL^DynZ(VSw+&~UW-?BM7;fP=bMj8I4`q-GaWfwG97)>}c^tH)Az zG%6jYs+?!2a{A(|#({V{DzKH*sB#Kb3Yc#lL*FCxw}YQYr@I&52j;$PB<1P)TYN|B z${Q}Qz#DiMVj{%p1}8{e8|}R~d4Bla==tH%K^@4TUMs^_wl44M?BM9d?*75q==5;E zbB{*X9n2FIe!-AA@wZTN!+~TK#g& zO<9XN}4M2%vz3YZL71nyZ1jJ=q=!LfhX_qQm|N@&!A{Y#7jDD*1u4Lf*6PK8R0 ztkSO>z7&MkBt2bIfG6rY5|stk9(@j+z@yLfGnX6|--90Yg33s^0N-m2W!rN3$$zsD;3b?LF%hW8i{NA$@HD!Pdm$O?l)hj$RXX@$BlC%jo? z`GdGDN(p7;JMkTaw1pGghk3U9Q+1nXDwRPbS2vAbWy;+CZZ*$u9Qo4bLUSZC=Xdh8QSo0$8Af(C(mD0fB9~o>U@Kf9aimU_z(|rOz;K?1 z4Rc6mEMnItDQ15x1yT%TvM~;veYHV11JMohvLf{&5B(vvl#V?}D768mT$J9~2|}p*FN>WG?=vMorQ+{@7kxx@b*PlO8c@dTufK}VOgqt!|4j)0$3OlL-pBF! zKmz)Kro(0FrG*OD?Do5$sm~Sz9UE z;w=NqyFu9aHr?;i+@&e}$D)~Np={lN3PGrDaHlN4>DVYaKFS`zuJAj&pIPDeb#JS} z@9qJN3ctfOY>I#xtP?U2CJtYd&C9vE{r)&?2rCc4!c}|*?K+N*LA3>!B3*1^ud_zh zt;r*!4Aj)?kJ=asFc*2Jd?vlg+2oU!beH!~`Eq(&jo38NfZk>&YK3~^-f6mg;~S`9 zSnMFR6rOj-vqnART%z~4hGZQ-2SaLZW$~I`o0touI8|;%G zFMdA%e)Rp}`9&qDX6=*VB)%QakU?YFiSz>&q9H6Sk9)LY!6w|+pHO(Om!xJEidPL%jfLY&FA|-X;-2=XFfpTUhc)c*{GPvk!7hL){6D0apu2&(V%jh zG_gursaCk_*^an|p&^r1m*`y9U~=ilU7&6wKlCopWm~Aet6`(1w5m*$zH-{N+QyxB zZF~HIznkH<{x#m>Fe`y~==--g>@358oy859qSPqp$Tx3pxG~HZH;v^ZQjHKn0vQ1M zxsCWZ!hJICUIa65_8Nx+iG4Is(TD-JYNdBe@V>y?KHIp&WfJ%4F4lqnO3G9MWB2#? z>IyNZZE=#Fk8k41LSKzU!Y6~jFv9!8+v4Cg?(Q)sD3|n4mO6&*&+$yH3&E^DOc2jO zx-yhGJSxU8jL(>-jkUXvS$oRFja(~IUS5FE{CYPVxN@gzyvjQro6(lMgB5L-z0>g} z^-DkI>~1k6ZO&Y%TH!faq~fHa4^HFvXUZ~MMt6f}U;ZO6vl-9{5L|`fZq~$wr&s}J z;Kudd<=EC-g*R=$x%@H;325hcIrLS`eT0e=c}^8KhyJ}M51G1+3}5t31_d2YrI@RH zsG*Sc)Md=5gX@W?n69;=f8~u-sIjzfT9}otWFH-x8nA|N>*Jt@50AP}rV9jg<7HWC zt%yq#L6YkDrru37(N|IC@inFl$$)E%G^HgV9s+T%Rf5}b5UJO%y@G)3W>6Xj7vi>5 zp!18S#}lFe5egftJTGrvko7wCvEk-3!Og2>Oe0n(rY4H-8guxqfr#&5?v~A#@D~`F zvh-*4;x%4%lMAm-jxp9>HZ}M}VucKgqJ>x0;u*JBLi?5{(kUKGILCU%kyBjF7)=0L znG`WyFjsiRa#Nu?@_sn4sF$GO1OOCsoE!F=_0p}DPJ84;U(hSJvDb_k#3Jcosr>*b zwUAZGR}rk-$O)avt4I?Pvp_rU{A^u)W%e?j#gq=Pz`0OlG-|?sE1s+-ySkaiZR`Tch|VS?Wk#j%w1m+ zR-|5oh^rHOtzCji3ogMG_t0zH<2c|^<8T32NffK_m5HU(OmHBnq&iEtC)Wy4Az>n>|W z<7qTstG_k|Vp@ZogWUtWf!f-&)+rvk->T;E(EZo+rH3BCSF0YnccyxE>l*i#u4o#r zzuv*fZSldRZ)=ZYpn>QC3W;~!2c73I%R;;8>RbRYrwGOnSDs&U* zQb`S|39-J;6JiXV?U4FnhC3J6&{)~1_aov%n5_4spxMiQU*t1*TZ49_eY6s-wo&@5 zgPhE_ZFH=+G^Cnk;>jTepm|=auv86QOF8OY5X}jyw`D259ip*$-HT|hpJqXB{CgA) zs=h6MMRBFB?*MN6`RgsJkDnzmD^rcfthA)+!zGEscJN2vMbotY9$@2)21?bY=v|c) zZS<M;#Vodx2s z`rUcMM<77u*FebI-ncYuy>`^T|jlr8CnIE@S zYqhfsh&Rj=U`u4crj#utER6nH3|$OGdgP1<_=Nb0F_Eh_aKD}*;en@9a_@z^j0cx| z<#ATvpQ#IKpW;G5^|CN^vYz4&hPdCF?mS0C-}JLqNAh(Bl6Yi-XFo$=+M5&|VyZZ* zwO{|qbPsP!xN#*AXLz(j2F41wYGJ-0QYPwR2CG88?I7Pal*dd=9&87f#6Yr`T*vY^ zm7~*{3W$89@tzEYbFQOB4o?wWS;)jWCSSnrE#Mv0J#VrUcco}STHV5S9Yf0DLG=N0O6mPfG&xnjy=xBD^J?VF zIr3%2KY#np2OhiaAMge)J&(PFaX)Y6LXUNaD{!v(LOh}OH?R}?kZF7pY1Pj7CfU(! zmX)or6LTWYa1MchytREird?&tDlg%hSyua9GYz1@ML`mHPnO|bRFY*AOlTQj7&QrK z80oG?i}~t`(Y^P;3LV}CyL439b6x zHr=>1j;AHI>DJd|m(q{3O%Vpgv#fNzlvaWdXY@E|lZ~qM5mkqzDovNJ01-Wy1IW6h zi?3iliQA3A=AQ=}S|iu>>7uC&3fb%$Tv#mTbc~*!13pdh_Afp89SeDWXnQ!+%r`(@ zC9*V%cu-yqA0z$y<*O*4;PS31a$}QAT%kp;zE_dC@iqR3=Y68_x05Z2o6fi#fBP4O zp=G|l%>XV(H*t#XqZpKPa`Aog%P+$x;x?IX)8obRHKy`z9`8({EJZlWuq~bpCFsK^ zj}BhX%>`cMvZKqk3V&-ag1JWwc%*0+mi|JLRtK_xl^{dDPfdSo~ynqa5mKlMZ@pm{bfFx=h&6GC z!}oLjxb*(XIn^ZwBm4M^!J|WZP*`z}>;$YyMk8LCrrE2G@hbDH1aA`KJ!=dOILTHd z;5D?3h;`8h@*fj&*_L4nEk1P>gX>y(7kumY0cfbtcZN8CH7f!13yOt9e1I zas?u!$rKM(4JFjliC^=|>In@LE<;%})dx=rI&VpAoR$ z%QTun6`k}iaqx@OLBlmVbW!02#Q^76-D4P1OOa;Y9zN2~x~c;}^UAq0T2x^yQi*!3 zA~1h?YdxBcRZ|Q135hMAfjzDz;VoCO5#%-(410mhG8Q@_1Z{yhxtS$sMXSI^FxVB4 zPmL{DK!T`cr1|G;A-J|Z@p+BkjAR40zWBoKEv`)kLiw7X5^m!1^wxxpB?+E ziH}z7>o~*8s1L^{i1tp1uzew1y#vy9!|oVw7)f%R;mS_v?$XhUxQQTJdXOp*5f|7iy 1 minute'`}} + expr: metallb_k8s_client_config_stale_bool{job=~"{{ template "metallb.fullname" . }}.*"} == 1 + for: 1m + {{- with .Values.prometheus.prometheusRule.staleConfig.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.prometheus.prometheusRule.configNotLoaded.enabled }} + - alert: MetalLBConfigNotLoaded + annotations: + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod + }} has not loaded for > 1 minute'`}} + expr: metallb_k8s_client_config_loaded_bool{job=~"{{ template "metallb.fullname" . }}.*"} == 0 + for: 1m + {{- with .Values.prometheus.prometheusRule.configNotLoaded.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.prometheus.prometheusRule.addressPoolExhausted.enabled }} + - alert: MetalLBAddressPoolExhausted + annotations: + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod + }} has exhausted address pool {{ $labels.pool }} for > 1 minute'`}} + expr: metallb_allocator_addresses_in_use_total >= on(pool) metallb_allocator_addresses_total + for: 1m + {{- with .Values.prometheus.prometheusRule.addressPoolExhausted.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + + {{- if .Values.prometheus.prometheusRule.addressPoolUsage.enabled }} + {{- range .Values.prometheus.prometheusRule.addressPoolUsage.thresholds }} + - alert: MetalLBAddressPoolUsage{{ .percent }}Percent + annotations: + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod + }} has address pool {{ $labels.pool }} past `}}{{ .percent }}{{`% usage for > 1 minute'`}} + expr: ( metallb_allocator_addresses_in_use_total / on(pool) metallb_allocator_addresses_total ) * 100 > {{ .percent }} + {{- with .labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.prometheus.prometheusRule.bgpSessionDown.enabled }} + - alert: MetalLBBGPSessionDown + annotations: + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod + }} has BGP session {{ $labels.peer }} down for > 1 minute'`}} + expr: metallb_bgp_session_up{job=~"{{ template "metallb.fullname" . }}.*"} == 0 + for: 1m + {{- with .Values.prometheus.prometheusRule.bgpSessionDown.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- with .Values.prometheus.prometheusRule.extraAlerts }} + {{- toYaml . | nindent 4 }} + {{- end}} +{{- end }} diff --git a/metallb-chart/templates/rbac.yaml b/metallb-chart/templates/rbac.yaml new file mode 100644 index 0000000..8c66b80 --- /dev/null +++ b/metallb-chart/templates/rbac.yaml @@ -0,0 +1,212 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "metallb.fullname" . }}:controller + labels: + {{- include "metallb.labels" . | nindent 4 }} +rules: +- apiGroups: [""] + resources: ["services", "namespaces"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["list"] +- apiGroups: [""] + resources: ["services/status"] + verbs: ["update"] +- apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + resourceNames: ["metallb-webhook-configuration"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + verbs: ["list", "watch"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + resourceNames: ["bfdprofiles.metallb.io","bgpadvertisements.metallb.io", + "bgppeers.metallb.io","ipaddresspools.metallb.io","l2advertisements.metallb.io","communities.metallb.io"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["list", "watch"] +{{- if .Values.prometheus.secureMetricsPort }} +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] +{{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "metallb.fullname" . }}:speaker + labels: + {{- include "metallb.labels" . | nindent 4 }} +rules: +- apiGroups: [""] + resources: ["services", "endpoints", "nodes", "namespaces"] + verbs: ["get", "list", "watch"] +- apiGroups: ["discovery.k8s.io"] + resources: ["endpointslices"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] +- apiGroups: ["metallb.io"] + resources: ["servicel2statuses","servicel2statuses/status"] + verbs: ["*"] +{{- if .Values.prometheus.secureMetricsPort }} +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] +{{- end }} +{{- if or .Values.frrk8s.enabled .Values.frrk8s.external }} +- apiGroups: ["frrk8s.metallb.io"] + resources: ["frrconfigurations"] + verbs: ["get", "list", "watch","create","update"] +{{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "metallb.fullname" . }}-pod-lister + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "metallb.labels" . | nindent 4 }} +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["list", "get"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["bfdprofiles"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["bgppeers"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["l2advertisements"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["bgpadvertisements"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["ipaddresspools"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["communities"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "metallb.fullname" . }}-controller + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "metallb.labels" . | nindent 4 }} +rules: +{{- if .Values.speaker.memberlist.enabled }} +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "list", "watch"] +- apiGroups: [""] + resources: ["secrets"] + resourceNames: [{{ include "metallb.secretName" . | quote }}] + verbs: ["list"] +- apiGroups: ["apps"] + resources: ["deployments"] + resourceNames: ["{{ template "metallb.fullname" . }}-controller"] + verbs: ["get"] +{{- end }} +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] +- apiGroups: ["metallb.io"] + resources: ["ipaddresspools"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["bgppeers"] + verbs: ["get", "list"] +- apiGroups: ["metallb.io"] + resources: ["bgpadvertisements"] + verbs: ["get", "list"] +- apiGroups: ["metallb.io"] + resources: ["l2advertisements"] + verbs: ["get", "list"] +- apiGroups: ["metallb.io"] + resources: ["communities"] + verbs: ["get", "list","watch"] +- apiGroups: ["metallb.io"] + resources: ["bfdprofiles"] + verbs: ["get", "list","watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "metallb.fullname" . }}:controller + labels: + {{- include "metallb.labels" . | nindent 4 }} +subjects: +- kind: ServiceAccount + name: {{ template "metallb.controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "metallb.fullname" . }}:controller +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "metallb.fullname" . }}:speaker + labels: + {{- include "metallb.labels" . | nindent 4 }} +subjects: +- kind: ServiceAccount + name: {{ template "metallb.speaker.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "metallb.fullname" . }}:speaker +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "metallb.fullname" . }}-pod-lister + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "metallb.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "metallb.fullname" . }}-pod-lister +subjects: +- kind: ServiceAccount + name: {{ include "metallb.speaker.serviceAccountName" . }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "metallb.fullname" . }}-controller + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "metallb.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "metallb.fullname" . }}-controller +subjects: +- kind: ServiceAccount + name: {{ include "metallb.controller.serviceAccountName" . }} +{{- end -}} diff --git a/metallb-chart/templates/service-accounts.yaml b/metallb-chart/templates/service-accounts.yaml new file mode 100644 index 0000000..c2157ff --- /dev/null +++ b/metallb-chart/templates/service-accounts.yaml @@ -0,0 +1,30 @@ +{{- if .Values.controller.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "metallb.controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +{{- if .Values.speaker.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "metallb.speaker.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker + {{- with .Values.speaker.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/metallb-chart/templates/servicemonitor.yaml b/metallb-chart/templates/servicemonitor.yaml new file mode 100644 index 0000000..0aacf85 --- /dev/null +++ b/metallb-chart/templates/servicemonitor.yaml @@ -0,0 +1,194 @@ +{{- if .Values.prometheus.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "metallb.fullname" . }}-speaker-monitor + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker + {{- if .Values.prometheus.serviceMonitor.speaker.additionalLabels }} +{{ toYaml .Values.prometheus.serviceMonitor.speaker.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.speaker.annotations }} + annotations: +{{ toYaml .Values.prometheus.serviceMonitor.speaker.annotations | indent 4 }} + {{- end }} +spec: + endpoints: + - port: {{ template "metrics.exposedportname" . }} + honorLabels: true + {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.serviceMonitor.metricRelabelings | nindent 8 }} + {{- end -}} + {{- if .Values.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.serviceMonitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end -}} +{{ if .Values.prometheus.secureMetricsPort }} + bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token" + scheme: "https" +{{- if .Values.prometheus.serviceMonitor.speaker.tlsConfig }} + tlsConfig: +{{ toYaml .Values.prometheus.serviceMonitor.speaker.tlsConfig | indent 8 }} +{{- end }} +{{ end }} +{{- if .Values.speaker.frr.enabled }} + - port: {{ template "metrics.exposedfrrportname" . }} + honorLabels: true +{{ if .Values.speaker.frr.secureMetricsPort }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end }} + bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token" + scheme: "https" +{{- if .Values.prometheus.serviceMonitor.speaker.tlsConfig }} + tlsConfig: +{{ toYaml .Values.prometheus.serviceMonitor.speaker.tlsConfig | indent 8 }} +{{- end }} +{{- end }} +{{- end }} + jobLabel: {{ .Values.prometheus.serviceMonitor.jobLabel | quote }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + name: {{ template "metallb.fullname" . }}-speaker-monitor-service +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/scrape: "true" + {{- if .Values.prometheus.serviceMonitor.speaker.annotations }} +{{ toYaml .Values.prometheus.serviceMonitor.speaker.annotations | indent 4 }} + {{- end }} + labels: + name: {{ template "metallb.fullname" . }}-speaker-monitor-service + {{- include "metallb.labels" . | nindent 4 }} + name: {{ template "metallb.fullname" . }}-speaker-monitor-service + namespace: {{ .Release.Namespace | quote }} +spec: + selector: + {{- include "metallb.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: speaker + clusterIP: None + ports: + - name: {{ template "metrics.exposedportname" . }} + port: {{ template "metrics.exposedport" . }} + targetPort: {{ template "metrics.exposedport" . }} +{{- if .Values.speaker.frr.enabled }} + - name: {{ template "metrics.exposedfrrportname" . }} + port: {{ template "metrics.exposedfrrport" . }} + targetPort: {{ template "metrics.exposedfrrport" . }} +{{- end }} + sessionAffinity: None + type: ClusterIP +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "metallb.fullname" . }}-controller-monitor + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker + {{- if .Values.prometheus.serviceMonitor.controller.additionalLabels }} +{{ toYaml .Values.prometheus.serviceMonitor.controller.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.controller.annotations }} + annotations: +{{ toYaml .Values.prometheus.serviceMonitor.controller.annotations | indent 4 }} + {{- end }} +spec: + endpoints: + - port: {{ template "metrics.exposedportname" . }} + {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.serviceMonitor.metricRelabelings | nindent 8 }} + {{- end -}} + {{- if .Values.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.serviceMonitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end }} + honorLabels: true +{{- if .Values.prometheus.secureMetricsPort }} + bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token" + scheme: "https" +{{- if .Values.prometheus.serviceMonitor.controller.tlsConfig }} + tlsConfig: +{{ toYaml .Values.prometheus.serviceMonitor.controller.tlsConfig | indent 8 }} +{{- end }} +{{- end }} + jobLabel: {{ .Values.prometheus.serviceMonitor.jobLabel | quote }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + name: {{ template "metallb.fullname" . }}-controller-monitor-service +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/scrape: "true" + {{- if .Values.prometheus.serviceMonitor.controller.annotations }} +{{ toYaml .Values.prometheus.serviceMonitor.controller.annotations | indent 4 }} + {{- end }} + labels: + name: {{ template "metallb.fullname" . }}-controller-monitor-service + name: {{ template "metallb.fullname" . }}-controller-monitor-service +spec: + selector: + {{- include "metallb.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: controller + clusterIP: None + ports: + - name: {{ template "metrics.exposedportname" . }} + port: {{ template "metrics.exposedport" . }} + targetPort: {{ template "metrics.exposedport" . }} + sessionAffinity: None + type: ClusterIP +--- +{{- if .Values.prometheus.rbacPrometheus }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "metallb.fullname" . }}-prometheus + namespace: {{ .Release.Namespace | quote }} +rules: + - apiGroups: + - "" + resources: + - pods + - services + - endpoints + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "metallb.fullname" . }}-prometheus + namespace: {{ .Release.Namespace | quote }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "metallb.fullname" . }}-prometheus +subjects: + - kind: ServiceAccount + name: {{ required ".Values.prometheus.serviceAccount must be defined when .Values.prometheus.serviceMonitor.enabled == true" .Values.prometheus.serviceAccount }} + namespace: {{ required ".Values.prometheus.namespace must be defined when .Values.prometheus.serviceMonitor.enabled == true" .Values.prometheus.namespace }} +{{- end }} +{{- end }} diff --git a/metallb-chart/templates/speaker.yaml b/metallb-chart/templates/speaker.yaml new file mode 100644 index 0000000..567d820 --- /dev/null +++ b/metallb-chart/templates/speaker.yaml @@ -0,0 +1,568 @@ +{{- if .Values.speaker.frr.enabled }} +{{- if or .Values.frrk8s.enabled .Values.frrk8s.external }} +{{- fail "speaker.frr.enabled and frrk8s.enabled / external are mutually exclusive!" }} +{{- end }} +{{- end }} + +{{- if and .Values.frrk8s.enabled .Values.frrk8s.external }} +{{- fail "frrk8s.enabled frrk8s.external are mutually exclusive!" }} +{{- end }} + +{{- if .Values.speaker.frr.enabled }} + +# FRR expects to have these files owned by frr:frr on startup. +# Having them in a ConfigMap allows us to modify behaviors: for example enabling more daemons on startup. +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "metallb.fullname" . }}-frr-startup + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker +data: + daemons: | + # This file tells the frr package which daemons to start. + # + # Sample configurations for these daemons can be found in + # /usr/share/doc/frr/examples/. + # + # ATTENTION: + # + # When activating a daemon for the first time, a config file, even if it is + # empty, has to be present *and* be owned by the user and group "frr", else + # the daemon will not be started by /etc/init.d/frr. The permissions should + # be u=rw,g=r,o=. + # When using "vtysh" such a config file is also needed. It should be owned by + # group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too. + # + # The watchfrr and zebra daemons are always started. + # + bgpd=yes + ospfd=no + ospf6d=no + ripd=no + ripngd=no + isisd=no + pimd=no + ldpd=no + nhrpd=no + eigrpd=no + babeld=no + sharpd=no + pbrd=no + bfdd=yes + fabricd=no + vrrpd=no + + # + # If this option is set the /etc/init.d/frr script automatically loads + # the config via "vtysh -b" when the servers are started. + # Check /etc/pam.d/frr if you intend to use "vtysh"! + # + vtysh_enable=yes + zebra_options=" -A 127.0.0.1 -s 90000000" + bgpd_options=" -A 127.0.0.1 -p 0" + ospfd_options=" -A 127.0.0.1" + ospf6d_options=" -A ::1" + ripd_options=" -A 127.0.0.1" + ripngd_options=" -A ::1" + isisd_options=" -A 127.0.0.1" + pimd_options=" -A 127.0.0.1" + ldpd_options=" -A 127.0.0.1" + nhrpd_options=" -A 127.0.0.1" + eigrpd_options=" -A 127.0.0.1" + babeld_options=" -A 127.0.0.1" + sharpd_options=" -A 127.0.0.1" + pbrd_options=" -A 127.0.0.1" + staticd_options="-A 127.0.0.1" + bfdd_options=" -A 127.0.0.1" + fabricd_options="-A 127.0.0.1" + vrrpd_options=" -A 127.0.0.1" + + # configuration profile + # + #frr_profile="traditional" + #frr_profile="datacenter" + + # + # This is the maximum number of FD's that will be available. + # Upon startup this is read by the control files and ulimit + # is called. Uncomment and use a reasonable value for your + # setup if you are expecting a large number of peers in + # say BGP. + #MAX_FDS=1024 + + # The list of daemons to watch is automatically generated by the init script. + #watchfrr_options="" + + # for debugging purposes, you can specify a "wrap" command to start instead + # of starting the daemon directly, e.g. to use valgrind on ospfd: + # ospfd_wrap="/usr/bin/valgrind" + # or you can use "all_wrap" for all daemons, e.g. to use perf record: + # all_wrap="/usr/bin/perf record --call-graph -" + # the normal daemon command is added to this at the end. + vtysh.conf: |+ + service integrated-vtysh-config + frr.conf: |+ + ! This file gets overriden the first time the speaker renders a config. + ! So anything configured here is only temporary. + frr version 8.0 + frr defaults traditional + hostname Router + line vty + log file /etc/frr/frr.log informational +{{- end }} +--- +{{- if .Values.speaker.enabled }} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ template "metallb.fullname" . }}-speaker + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker + {{- range $key, $value := .Values.speaker.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + {{- if .Values.speaker.updateStrategy }} + updateStrategy: {{- toYaml .Values.speaker.updateStrategy | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "metallb.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: speaker + template: + metadata: + {{- if or .Values.prometheus.scrapeAnnotations .Values.speaker.podAnnotations }} + annotations: + {{- if .Values.prometheus.scrapeAnnotations }} + prometheus.io/scrape: "true" + {{- if not .Values.speaker.frr.enabled }} + prometheus.io/port: "{{ .Values.prometheus.metricsPort }}" + {{- end }} + {{- end }} + {{- with .Values.speaker.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + labels: + {{- include "metallb.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: speaker + {{- range $key, $value := .Values.speaker.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + spec: + {{- if .Values.speaker.runtimeClassName }} + runtimeClassName: {{ .Values.speaker.runtimeClassName }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "metallb.speaker.serviceAccountName" . }} + terminationGracePeriodSeconds: 0 + hostNetwork: true + {{- if .Values.speaker.securityContext }} + securityContext: + {{- toYaml .Values.speaker.securityContext | nindent 8 }} + {{- end }} + volumes: + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + - name: metrics-certs + secret: + secretName: {{ .Values.prometheus.speakerMetricsTLSSecret }} + {{- end }} + {{- if .Values.speaker.memberlist.enabled }} + - name: memberlist + secret: + secretName: {{ include "metallb.secretName" . }} + defaultMode: 420 + {{- end }} + {{- if .Values.speaker.excludeInterfaces.enabled }} + - name: metallb-excludel2 + configMap: + defaultMode: 256 + name: metallb-excludel2 + {{- end }} + {{- if .Values.speaker.frr.enabled }} + - name: frr-sockets + emptyDir: {} + - name: frr-startup + configMap: + name: {{ template "metallb.fullname" . }}-frr-startup + - name: frr-conf + emptyDir: {} + - name: reloader + emptyDir: {} + - name: metrics + emptyDir: {} + initContainers: + # Copies the initial config files with the right permissions to the shared volume. + - name: cp-frr-files + image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }} + securityContext: + runAsUser: 100 + runAsGroup: 101 + command: ["/bin/sh", "-c", "cp -rLf /tmp/frr/* /etc/frr/"] + volumeMounts: + - name: frr-startup + mountPath: /tmp/frr + - name: frr-conf + mountPath: /etc/frr + # Copies the reloader to the shared volume between the speaker and reloader. + - name: cp-reloader + image: {{ .Values.speaker.image.repository }}:{{ .Values.speaker.image.tag | default .Chart.AppVersion }} + command: ["/cp-tool","/frr-reloader.sh","/etc/frr_reloader/frr-reloader.sh"] + volumeMounts: + - name: reloader + mountPath: /etc/frr_reloader + # Copies the metrics exporter + - name: cp-metrics + image: {{ .Values.speaker.image.repository }}:{{ .Values.speaker.image.tag | default .Chart.AppVersion }} + command: ["/cp-tool","/frr-metrics","/etc/frr_metrics/frr-metrics"] + volumeMounts: + - name: metrics + mountPath: /etc/frr_metrics + shareProcessNamespace: true + {{- end }} + containers: + - name: speaker + image: {{ .Values.speaker.image.repository }}:{{ .Values.speaker.image.tag | default .Chart.AppVersion }} + {{- if .Values.speaker.image.pullPolicy }} + imagePullPolicy: {{ .Values.speaker.image.pullPolicy }} + {{- end }} + {{- if .Values.speaker.command }} + command: + - {{ .Values.speaker.command }} + {{- end }} + args: + - --port={{ .Values.prometheus.metricsPort }} + {{- with .Values.speaker.logLevel }} + - --log-level={{ . }} + {{- end }} + {{- if .Values.loadBalancerClass }} + - --lb-class={{ .Values.loadBalancerClass }} + {{- end }} + {{- if .Values.speaker.wanConfig }} + - --ml-wan-config + {{- end }} + {{- if .Values.speaker.ignoreExcludeLB}} + - --ignore-exclude-lb + {{- end }} + {{- if .Values.prometheus.secureMetricsPort }} + - --host=localhost + {{- end }} + {{- if .Values.frrk8s.external }} + - --frrk8s-namespace={{ required "namespace is required when frrk8s is external" .Values.frrk8s.namespace }} + {{- end }} + env: + - name: METALLB_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: METALLB_HOST + valueFrom: + fieldRef: + fieldPath: status.hostIP + {{- if .Values.speaker.memberlist.enabled }} + {{- if .Values.speaker.memberlist.mlBindAddrOverride }} + - name: METALLB_ML_BIND_ADDR + value: "{{ .Values.speaker.memberlist.mlBindAddrOverride }}" + {{ else }} + - name: METALLB_ML_BIND_ADDR + valueFrom: + fieldRef: + fieldPath: status.podIP + {{ end }} + - name: METALLB_ML_LABELS + value: "app.kubernetes.io/name={{ include "metallb.name" . }},app.kubernetes.io/component=speaker" + - name: METALLB_ML_BIND_PORT + value: "{{ .Values.speaker.memberlist.mlBindPort }}" + - name: METALLB_ML_SECRET_KEY_PATH + value: "{{ .Values.speaker.memberlist.mlSecretKeyPath }}" + {{- end }} + {{- if .Values.speaker.frr.enabled }} + - name: FRR_CONFIG_FILE + value: /etc/frr_reloader/frr.conf + - name: FRR_RELOADER_PID_FILE + value: /etc/frr_reloader/reloader.pid + - name: METALLB_BGP_TYPE + value: frr + {{- end }} + {{- if or .Values.frrk8s.enabled .Values.frrk8s.external }} + - name: METALLB_BGP_TYPE + value: frr-k8s + {{- end }} + - name: METALLB_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + ports: + - name: monitoring + containerPort: {{ .Values.prometheus.metricsPort }} + {{- if .Values.speaker.memberlist.enabled }} + - name: memberlist-tcp + containerPort: {{ .Values.speaker.memberlist.mlBindPort }} + protocol: TCP + - name: memberlist-udp + containerPort: {{ .Values.speaker.memberlist.mlBindPort }} + protocol: UDP + {{- end }} + {{- if .Values.speaker.livenessProbe.enabled }} + livenessProbe: + httpGet: + {{- if .Values.prometheus.secureMetricsPort }} + host: localhost + {{- end }} + path: /metrics + port: monitoring + initialDelaySeconds: {{ .Values.speaker.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.speaker.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.speaker.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.speaker.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.speaker.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.speaker.readinessProbe.enabled }} + readinessProbe: + httpGet: + {{- if .Values.prometheus.secureMetricsPort }} + host: localhost + {{- end }} + path: /metrics + port: monitoring + initialDelaySeconds: {{ .Values.speaker.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.speaker.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.speaker.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.speaker.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.speaker.readinessProbe.failureThreshold }} + {{- end }} + {{- with .Values.speaker.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + add: + - NET_RAW + {{- if or .Values.speaker.frr.enabled .Values.speaker.memberlist.enabled .Values.speaker.excludeInterfaces.enabled }} + volumeMounts: + {{- if .Values.speaker.memberlist.enabled }} + - name: memberlist + mountPath: {{ .Values.speaker.memberlist.mlSecretKeyPath }} + {{- end }} + {{- if .Values.speaker.frr.enabled }} + - name: reloader + mountPath: /etc/frr_reloader + {{- end }} + {{- if .Values.speaker.excludeInterfaces.enabled }} + - name: metallb-excludel2 + mountPath: /etc/metallb + {{- end }} + {{- end }} + {{- if .Values.speaker.frr.enabled }} + - name: frr + securityContext: + capabilities: + add: + - NET_ADMIN + - NET_RAW + - SYS_ADMIN + - NET_BIND_SERVICE + image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }} + {{- if .Values.speaker.frr.image.pullPolicy }} + imagePullPolicy: {{ .Values.speaker.frr.image.pullPolicy }} + {{- end }} + env: + - name: TINI_SUBREAPER + value: "true" + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + # The command is FRR's default entrypoint & waiting for the log file to appear and tailing it. + # If the log file isn't created in 60 seconds the tail fails and the container is restarted. + # This workaround is needed to have the frr logs as part of kubectl logs -c frr < speaker_pod_name >. + command: + - /bin/sh + - -c + - | + /sbin/tini -- /usr/lib/frr/docker-start & + attempts=0 + until [[ -f /etc/frr/frr.log || $attempts -eq 60 ]]; do + sleep 1 + attempts=$(( $attempts + 1 )) + done + tail -f /etc/frr/frr.log + {{- with .Values.speaker.frr.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.speaker.livenessProbe.enabled }} + livenessProbe: + httpGet: + {{- if .Values.prometheus.secureMetricsPort }} + host: localhost + {{- end }} + path: livez + port: {{ .Values.speaker.frr.metricsPort }} + initialDelaySeconds: {{ .Values.speaker.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.speaker.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.speaker.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.speaker.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.speaker.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.speaker.startupProbe.enabled }} + startupProbe: + httpGet: + {{- if .Values.prometheus.secureMetricsPort }} + host: localhost + {{- end }} + path: /livez + port: {{ .Values.speaker.frr.metricsPort }} + failureThreshold: {{ .Values.speaker.startupProbe.failureThreshold }} + periodSeconds: {{ .Values.speaker.startupProbe.periodSeconds }} + {{- end }} + - name: reloader + image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }} + {{- if .Values.speaker.frr.image.pullPolicy }} + imagePullPolicy: {{ .Values.speaker.frr.image.pullPolicy }} + {{- end }} + command: ["/etc/frr_reloader/frr-reloader.sh"] + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + - name: reloader + mountPath: /etc/frr_reloader + {{- with .Values.speaker.reloader.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: frr-metrics + image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }} + command: ["/etc/frr_metrics/frr-metrics"] + args: + - --metrics-port={{ .Values.speaker.frr.metricsPort }} + {{- if .Values.prometheus.secureMetricsPort }} + - --host=localhost + {{- end }} + env: + - name: VTYSH_HISTFILE + value: /dev/null + ports: + - containerPort: {{ .Values.speaker.frr.metricsPort }} + name: monitoring + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + - name: metrics + mountPath: /etc/frr_metrics + {{- with .Values.speaker.frrMetrics.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.prometheus.secureMetricsPort }} + - name: kube-rbac-proxy + image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag }} + imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }} + args: + - --logtostderr + - --secure-listen-address=:{{ .Values.prometheus.secureMetricsPort }} + - --upstream=http://localhost:{{ .Values.prometheus.metricsPort }}/ + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + - --tls-private-key-file=/etc/metrics/tls.key + - --tls-cert-file=/etc/metrics/tls.crt + {{- end }} + ports: + - containerPort: {{ .Values.prometheus.secureMetricsPort }} + name: metricshttps + resources: + requests: + cpu: 10m + memory: 20Mi + terminationMessagePolicy: FallbackToLogsOnError + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + volumeMounts: + - name: metrics-certs + mountPath: /etc/metrics + readOnly: true + {{- end }} + {{ end }} + {{- if .Values.speaker.frr.enabled }} + {{- if .Values.speaker.frr.secureMetricsPort }} + - name: kube-rbac-proxy-frr + image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }} + args: + - --logtostderr + - --secure-listen-address=:{{ .Values.speaker.frr.secureMetricsPort }} + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + - --upstream=http://localhost:{{ .Values.speaker.frr.metricsPort }}/ + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + - --tls-private-key-file=/etc/metrics/tls.key + - --tls-cert-file=/etc/metrics/tls.crt + {{- end }} + ports: + - containerPort: {{ .Values.speaker.frr.secureMetricsPort }} + name: frrmetricshttps + env: + - name: METALLB_HOST + valueFrom: + fieldRef: + fieldPath: status.hostIP + resources: + requests: + cpu: 10m + memory: 20Mi + terminationMessagePolicy: FallbackToLogsOnError + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + volumeMounts: + - name: metrics-certs + mountPath: /etc/metrics + readOnly: true + {{- end }} + {{ end }} + {{- end }} + {{- if .Values.speaker.extraContainers }} + {{- toYaml .Values.speaker.extraContainers | nindent 6 }} + {{- end }} + nodeSelector: + "kubernetes.io/os": linux + {{- with .Values.speaker.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.speaker.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.speaker.tolerateMaster .Values.speaker.tolerations }} + tolerations: + {{- if .Values.speaker.tolerateMaster }} + - key: node-role.kubernetes.io/master + effect: NoSchedule + operator: Exists + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + operator: Exists + {{- end }} + {{- with .Values.speaker.tolerations }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} + {{- with .Values.speaker.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} +{{- end }} diff --git a/metallb-chart/templates/webhooks.yaml b/metallb-chart/templates/webhooks.yaml new file mode 100644 index 0000000..3cdac01 --- /dev/null +++ b/metallb-chart/templates/webhooks.yaml @@ -0,0 +1,150 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: metallb-webhook-configuration + labels: + {{- include "metallb.labels" . | nindent 4 }} +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta2-bgppeer + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: bgppeervalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta2 + operations: + - CREATE + - UPDATE + resources: + - bgppeers + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-ipaddresspool + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: ipaddresspoolvalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - ipaddresspools + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-bgpadvertisement + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: bgpadvertisementvalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - bgpadvertisements + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-community + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: communityvalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - communities + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-bfdprofile + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: bfdprofilevalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - DELETE + resources: + - bfdprofiles + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-l2advertisement + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: l2advertisementvalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - l2advertisements + sideEffects: None +--- +apiVersion: v1 +kind: Service +metadata: + name: metallb-webhook-service + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} +spec: + ports: + - port: 443 + targetPort: 9443 + selector: + {{- include "metallb.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: controller +--- +apiVersion: v1 +kind: Secret +metadata: + name: metallb-webhook-cert + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} diff --git a/sriov-crd-chart/templates.obscpio b/sriov-crd-chart/templates.obscpio deleted file mode 100644 index 3995b9fa48d11b897bcfbe85f5cbccf97c6c80c8704b0a4056481bc687b148ed..0000000000000000000000000000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47104 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 diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_ovsnetworks.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_ovsnetworks.yaml new file mode 100644 index 0000000..7e7d9ba --- /dev/null +++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_ovsnetworks.yaml @@ -0,0 +1,105 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: ovsnetworks.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: OVSNetwork + listKind: OVSNetworkList + plural: ovsnetworks + singular: ovsnetwork + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: OVSNetwork is the Schema for the ovsnetworks API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: OVSNetworkSpec defines the desired state of OVSNetwork + properties: + bridge: + description: |- + name of the OVS bridge, if not set OVS will automatically select bridge + based on VF PCI address + type: string + capabilities: + description: |- + Capabilities to be configured for this network. + Capabilities supported: (mac|ips), e.g. '{"mac": true}' + type: string + interfaceType: + description: The type of interface on ovs. + type: string + ipam: + description: IPAM configuration to be used for this network. + type: string + metaPlugins: + description: MetaPluginsConfig configuration to be used in order to + chain metaplugins + type: string + mtu: + description: Mtu for the OVS port + type: integer + networkNamespace: + description: Namespace of the NetworkAttachmentDefinition custom resource + type: string + resourceName: + description: OVS Network device plugin endpoint resource name + type: string + trunk: + description: Trunk configuration for the OVS port + items: + description: TrunkConfig contains configuration for bridge trunk + properties: + id: + maximum: 4095 + minimum: 0 + type: integer + maxID: + maximum: 4095 + minimum: 0 + type: integer + minID: + maximum: 4095 + minimum: 0 + type: integer + type: object + type: array + vlan: + description: Vlan to assign for the OVS port + maximum: 4095 + minimum: 0 + type: integer + required: + - resourceName + type: object + status: + description: OVSNetworkStatus defines the observed state of OVSNetwork + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovibnetworks.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovibnetworks.yaml new file mode 100644 index 0000000..8a4f88c --- /dev/null +++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovibnetworks.yaml @@ -0,0 +1,78 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: sriovibnetworks.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovIBNetwork + listKind: SriovIBNetworkList + plural: sriovibnetworks + singular: sriovibnetwork + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovIBNetwork is the Schema for the sriovibnetworks API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SriovIBNetworkSpec defines the desired state of SriovIBNetwork + properties: + capabilities: + description: |- + Capabilities to be configured for this network. + Capabilities supported: (infinibandGUID), e.g. '{"infinibandGUID": true}' + type: string + ipam: + description: IPAM configuration to be used for this network. + type: string + linkState: + description: VF link state (enable|disable|auto) + enum: + - auto + - enable + - disable + type: string + metaPlugins: + description: |- + MetaPluginsConfig configuration to be used in order to chain metaplugins to the sriov interface returned + by the operator. + type: string + networkNamespace: + description: Namespace of the NetworkAttachmentDefinition custom resource + type: string + resourceName: + description: SRIOV Network device plugin endpoint resource name + type: string + required: + - resourceName + type: object + status: + description: SriovIBNetworkStatus defines the observed state of SriovIBNetwork + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml new file mode 100644 index 0000000..47aacdd --- /dev/null +++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml @@ -0,0 +1,209 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: sriovnetworknodepolicies.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovNetworkNodePolicy + listKind: SriovNetworkNodePolicyList + plural: sriovnetworknodepolicies + singular: sriovnetworknodepolicy + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovNetworkNodePolicy is the Schema for the sriovnetworknodepolicies + API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SriovNetworkNodePolicySpec defines the desired state of SriovNetworkNodePolicy + properties: + bridge: + description: |- + contains bridge configuration for matching PFs, + valid only for eSwitchMode==switchdev + properties: + ovs: + description: contains configuration for the OVS bridge, + properties: + bridge: + description: contains bridge level settings + properties: + datapathType: + description: configure datapath_type field in the Bridge + table in OVSDB + type: string + externalIDs: + additionalProperties: + type: string + description: IDs to inject to external_ids field in the + Bridge table in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: additional options to inject to other_config + field in the bridge table in OVSDB + type: object + type: object + uplink: + description: contains settings for uplink (PF) + properties: + interface: + description: contains settings for PF interface in the + OVS bridge + properties: + externalIDs: + additionalProperties: + type: string + description: external_ids field in the Interface table + in OVSDB + type: object + options: + additionalProperties: + type: string + description: options field in the Interface table + in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: other_config field in the Interface table + in OVSDB + type: object + type: + description: type field in the Interface table in + OVSDB + type: string + type: object + type: object + type: object + type: object + deviceType: + default: netdevice + description: The driver type for configured VFs. Allowed value "netdevice", + "vfio-pci". Defaults to netdevice. + enum: + - netdevice + - vfio-pci + type: string + eSwitchMode: + description: NIC Device Mode. Allowed value "legacy","switchdev". + enum: + - legacy + - switchdev + type: string + excludeTopology: + description: Exclude device's NUMA node when advertising this resource + by SRIOV network device plugin. Default to false. + type: boolean + externallyManaged: + description: don't create the virtual function only allocated them + to the device plugin. Defaults to false. + type: boolean + isRdma: + description: RDMA mode. Defaults to false. + type: boolean + linkType: + description: NIC Link Type. Allowed value "eth", "ETH", "ib", and + "IB". + enum: + - eth + - ETH + - ib + - IB + type: string + mtu: + description: MTU of VF + minimum: 1 + type: integer + needVhostNet: + description: mount vhost-net device. Defaults to false. + type: boolean + nicSelector: + description: NicSelector selects the NICs to be configured + properties: + deviceID: + description: The device hex code of SR-IoV device. Allowed value + "0d58", "1572", "158b", "1013", "1015", "1017", "101b". + type: string + netFilter: + description: Infrastructure Networking selection filter. Allowed + value "openstack/NetworkID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + type: string + pfNames: + description: Name of SR-IoV PF. + items: + type: string + type: array + rootDevices: + description: PCI address of SR-IoV PF. + items: + type: string + type: array + vendor: + description: The vendor hex code of SR-IoV device. Allowed value + "8086", "15b3". + type: string + type: object + nodeSelector: + additionalProperties: + type: string + description: NodeSelector selects the nodes to be configured + type: object + numVfs: + description: Number of VFs for each PF + minimum: 0 + type: integer + priority: + description: Priority of the policy, higher priority policies can + override lower ones. + maximum: 99 + minimum: 0 + type: integer + resourceName: + description: SRIOV Network device plugin endpoint resource name + type: string + vdpaType: + description: VDPA device type. Allowed value "virtio", "vhost" + enum: + - virtio + - vhost + type: string + required: + - nicSelector + - nodeSelector + - numVfs + - resourceName + type: object + status: + description: SriovNetworkNodePolicyStatus defines the observed state of + SriovNetworkNodePolicy + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodestates.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodestates.yaml new file mode 100644 index 0000000..6ed2486 --- /dev/null +++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodestates.yaml @@ -0,0 +1,343 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: sriovnetworknodestates.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovNetworkNodeState + listKind: SriovNetworkNodeStateList + plural: sriovnetworknodestates + singular: sriovnetworknodestate + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.syncStatus + name: Sync Status + type: string + - jsonPath: .metadata.annotations.sriovnetwork\.openshift\.io/desired-state + name: Desired Sync State + type: string + - jsonPath: .metadata.annotations.sriovnetwork\.openshift\.io/current-state + name: Current Sync State + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: SriovNetworkNodeState is the Schema for the sriovnetworknodestates + API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SriovNetworkNodeStateSpec defines the desired state of SriovNetworkNodeState + properties: + bridges: + description: Bridges contains list of bridges + properties: + ovs: + items: + description: OVSConfigExt contains configuration for the concrete + OVS bridge + properties: + bridge: + description: bridge-level configuration for the bridge + properties: + datapathType: + description: configure datapath_type field in the Bridge + table in OVSDB + type: string + externalIDs: + additionalProperties: + type: string + description: IDs to inject to external_ids field in + the Bridge table in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: additional options to inject to other_config + field in the bridge table in OVSDB + type: object + type: object + name: + description: name of the bridge + type: string + uplinks: + description: |- + uplink-level bridge configuration for each uplink(PF). + currently must contain only one element + items: + description: OVSUplinkConfigExt contains configuration + for the concrete OVS uplink(PF) + properties: + interface: + description: configuration from the Interface OVS + table for the PF + properties: + externalIDs: + additionalProperties: + type: string + description: external_ids field in the Interface + table in OVSDB + type: object + options: + additionalProperties: + type: string + description: options field in the Interface table + in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: other_config field in the Interface + table in OVSDB + type: object + type: + description: type field in the Interface table + in OVSDB + type: string + type: object + name: + description: name of the PF interface + type: string + pciAddress: + description: pci address of the PF + type: string + required: + - pciAddress + type: object + type: array + required: + - name + type: object + type: array + type: object + interfaces: + items: + properties: + eSwitchMode: + type: string + externallyManaged: + type: boolean + linkType: + type: string + mtu: + type: integer + name: + type: string + numVfs: + type: integer + pciAddress: + type: string + vfGroups: + items: + properties: + deviceType: + type: string + isRdma: + type: boolean + mtu: + type: integer + policyName: + type: string + resourceName: + type: string + vdpaType: + type: string + vfRange: + type: string + type: object + type: array + required: + - pciAddress + type: object + type: array + type: object + status: + description: SriovNetworkNodeStateStatus defines the observed state of + SriovNetworkNodeState + properties: + bridges: + description: Bridges contains list of bridges + properties: + ovs: + items: + description: OVSConfigExt contains configuration for the concrete + OVS bridge + properties: + bridge: + description: bridge-level configuration for the bridge + properties: + datapathType: + description: configure datapath_type field in the Bridge + table in OVSDB + type: string + externalIDs: + additionalProperties: + type: string + description: IDs to inject to external_ids field in + the Bridge table in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: additional options to inject to other_config + field in the bridge table in OVSDB + type: object + type: object + name: + description: name of the bridge + type: string + uplinks: + description: |- + uplink-level bridge configuration for each uplink(PF). + currently must contain only one element + items: + description: OVSUplinkConfigExt contains configuration + for the concrete OVS uplink(PF) + properties: + interface: + description: configuration from the Interface OVS + table for the PF + properties: + externalIDs: + additionalProperties: + type: string + description: external_ids field in the Interface + table in OVSDB + type: object + options: + additionalProperties: + type: string + description: options field in the Interface table + in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: other_config field in the Interface + table in OVSDB + type: object + type: + description: type field in the Interface table + in OVSDB + type: string + type: object + name: + description: name of the PF interface + type: string + pciAddress: + description: pci address of the PF + type: string + required: + - pciAddress + type: object + type: array + required: + - name + type: object + type: array + type: object + interfaces: + items: + properties: + Vfs: + items: + properties: + Vlan: + type: integer + assigned: + type: string + deviceID: + type: string + driver: + type: string + guid: + type: string + mac: + type: string + mtu: + type: integer + name: + type: string + pciAddress: + type: string + representorName: + type: string + vdpaType: + type: string + vendor: + type: string + vfID: + type: integer + required: + - pciAddress + - vfID + type: object + type: array + deviceID: + type: string + driver: + type: string + eSwitchMode: + type: string + externallyManaged: + type: boolean + linkAdminState: + type: string + linkSpeed: + type: string + linkType: + type: string + mac: + type: string + mtu: + type: integer + name: + type: string + netFilter: + type: string + numVfs: + type: integer + pciAddress: + type: string + totalvfs: + type: integer + vendor: + type: string + required: + - pciAddress + type: object + type: array + lastSyncError: + type: string + syncStatus: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml new file mode 100644 index 0000000..502e0eb --- /dev/null +++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml @@ -0,0 +1,123 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: sriovnetworkpoolconfigs.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovNetworkPoolConfig + listKind: SriovNetworkPoolConfigList + plural: sriovnetworkpoolconfigs + singular: sriovnetworkpoolconfig + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovNetworkPoolConfig is the Schema for the sriovnetworkpoolconfigs + API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SriovNetworkPoolConfigSpec defines the desired state of SriovNetworkPoolConfig + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: |- + maxUnavailable defines either an integer number or percentage + of nodes in the pool that can go Unavailable during an update. + + + A value larger than 1 will mean multiple nodes going unavailable during + the update, which may affect your workload stress on the remaining nodes. + Drain will respect Pod Disruption Budgets (PDBs) such as etcd quorum guards, + even if maxUnavailable is greater than one. + x-kubernetes-int-or-string: true + nodeSelector: + description: nodeSelector specifies a label selector for Nodes + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + ovsHardwareOffloadConfig: + description: OvsHardwareOffloadConfig describes the OVS HWOL configuration + for selected Nodes + properties: + name: + description: |- + Name is mandatory and must be unique. + On Kubernetes: + Name is the name of OvsHardwareOffloadConfig + On OpenShift: + Name is the name of MachineConfigPool to be enabled with OVS hardware offload + type: string + type: object + type: object + status: + description: SriovNetworkPoolConfigStatus defines the observed state of + SriovNetworkPoolConfig + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworks.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworks.yaml new file mode 100644 index 0000000..cd807f9 --- /dev/null +++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworks.yaml @@ -0,0 +1,136 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: sriovnetworks.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovNetwork + listKind: SriovNetworkList + plural: sriovnetworks + singular: sriovnetwork + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovNetwork is the Schema for the sriovnetworks API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SriovNetworkSpec defines the desired state of SriovNetwork + properties: + capabilities: + description: |- + Capabilities to be configured for this network. + Capabilities supported: (mac|ips), e.g. '{"mac": true}' + type: string + ipam: + description: IPAM configuration to be used for this network. + type: string + linkState: + description: VF link state (enable|disable|auto) + enum: + - auto + - enable + - disable + type: string + logFile: + description: |- + LogFile sets the log file of the SRIOV CNI plugin logs. If unset (default), this will log to stderr and thus + to multus and container runtime logs. + type: string + logLevel: + default: info + description: |- + LogLevel sets the log level of the SRIOV CNI plugin - either of panic, error, warning, info, debug. Defaults + to info if left blank. + enum: + - panic + - error + - warning + - info + - debug + - "" + type: string + maxTxRate: + description: Maximum tx rate, in Mbps, for the VF. Defaults to 0 (no + rate limiting) + minimum: 0 + type: integer + metaPlugins: + description: |- + MetaPluginsConfig configuration to be used in order to chain metaplugins to the sriov interface returned + by the operator. + type: string + minTxRate: + description: Minimum tx rate, in Mbps, for the VF. Defaults to 0 (no + rate limiting). min_tx_rate should be <= max_tx_rate. + minimum: 0 + type: integer + networkNamespace: + description: Namespace of the NetworkAttachmentDefinition custom resource + type: string + resourceName: + description: SRIOV Network device plugin endpoint resource name + type: string + spoofChk: + description: VF spoof check, (on|off) + enum: + - "on" + - "off" + type: string + trust: + description: VF trust mode (on|off) + enum: + - "on" + - "off" + type: string + vlan: + description: VLAN ID to assign for the VF. Defaults to 0. + maximum: 4096 + minimum: 0 + type: integer + vlanProto: + description: VLAN proto to assign for the VF. Defaults to 802.1q. + enum: + - 802.1q + - 802.1Q + - 802.1ad + - 802.1AD + type: string + vlanQoS: + description: VLAN QoS ID to assign for the VF. Defaults to 0. + maximum: 7 + minimum: 0 + type: integer + required: + - resourceName + type: object + status: + description: SriovNetworkStatus defines the observed state of SriovNetwork + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml new file mode 100644 index 0000000..49d5429 --- /dev/null +++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml @@ -0,0 +1,114 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: sriovoperatorconfigs.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovOperatorConfig + listKind: SriovOperatorConfigList + plural: sriovoperatorconfigs + singular: sriovoperatorconfig + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovOperatorConfig is the Schema for the sriovoperatorconfigs + API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SriovOperatorConfigSpec defines the desired state of SriovOperatorConfig + properties: + configDaemonNodeSelector: + additionalProperties: + type: string + description: NodeSelector selects the nodes to be configured + type: object + configurationMode: + description: |- + Flag to enable the sriov-network-config-daemon to use a systemd service to configure SR-IOV devices on boot + Default mode: daemon + enum: + - daemon + - systemd + type: string + disableDrain: + description: Flag to disable nodes drain during debugging + type: boolean + disablePlugins: + description: DisablePlugins is a list of sriov-network-config-daemon + plugins to disable + items: + description: PluginNameValue defines the plugin name + enum: + - mellanox + type: string + type: array + enableInjector: + description: Flag to control whether the network resource injector + webhook shall be deployed + type: boolean + enableOperatorWebhook: + description: Flag to control whether the operator admission controller + webhook shall be deployed + type: boolean + enableOvsOffload: + description: Flag to enable OVS hardware offload. Set to 'true' to + provision switchdev-configuration.service and enable OpenvSwitch + hw-offload on nodes. + type: boolean + featureGates: + additionalProperties: + type: boolean + description: FeatureGates to enable experimental features + type: object + logLevel: + description: Flag to control the log verbose level of the operator. + Set to '0' to show only the basic logs. And set to '2' to show all + the available logs. + maximum: 2 + minimum: 0 + type: integer + useCDI: + description: Flag to enable Container Device Interface mode for SR-IOV + Network Device Plugin + type: boolean + type: object + status: + description: SriovOperatorConfigStatus defines the observed state of SriovOperatorConfig + properties: + injector: + description: Show the runtime status of the network resource injector + webhook + type: string + operatorWebhook: + description: Show the runtime status of the operator admission controller + webhook + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/sriov-network-operator-chart/charts.obscpio b/sriov-network-operator-chart/charts.obscpio deleted file mode 100644 index 829a2b43ad300e0c36883a1df78a297e772ffb6a170d27eae45cf79ec982f851..0000000000000000000000000000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90112 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 diff --git a/sriov-network-operator-chart/charts/sriov-nfd/.helmignore b/sriov-network-operator-chart/charts/sriov-nfd/.helmignore new file mode 100644 index 0000000..1b9a9cc --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/sriov-network-operator-chart/charts/sriov-nfd/Chart.yaml b/sriov-network-operator-chart/charts/sriov-nfd/Chart.yaml new file mode 100644 index 0000000..5415b0d --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +appVersion: v0.15.6 +description: Detects hardware features available on each node in a Kubernetes cluster, + and advertises those features using node labels +home: https://github.com/kubernetes-sigs/node-feature-discovery +keywords: +- feature-discovery +- feature-detection +- node-labels +name: sriov-nfd +sources: +- https://github.com/kubernetes-sigs/node-feature-discovery +type: application +version: 0.15.6 diff --git a/sriov-network-operator-chart/charts/sriov-nfd/README.md b/sriov-network-operator-chart/charts/sriov-nfd/README.md new file mode 100644 index 0000000..9aa6c75 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/README.md @@ -0,0 +1,10 @@ +# Node Feature Discovery + +Node Feature Discovery (NFD) is a Kubernetes add-on for detecting hardware +features and system configuration. Detected features are advertised as node +labels. NFD provides flexible configuration and extension points for a wide +range of vendor and application specific node labeling needs. + +See +[NFD documentation](https://kubernetes-sigs.github.io/node-feature-discovery/v0.15/deployment/helm.html) +for deployment instructions. diff --git a/sriov-network-operator-chart/charts/sriov-nfd/crds/nfd-api-crds.yaml b/sriov-network-operator-chart/charts/sriov-nfd/crds/nfd-api-crds.yaml new file mode 100644 index 0000000..0339f35 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/crds/nfd-api-crds.yaml @@ -0,0 +1,426 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: nodefeatures.nfd.k8s-sigs.io +spec: + group: nfd.k8s-sigs.io + names: + kind: NodeFeature + listKind: NodeFeatureList + plural: nodefeatures + singular: nodefeature + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: NodeFeature resource holds the features discovered for one node + in the cluster. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: NodeFeatureSpec describes a NodeFeature object. + properties: + features: + description: Features is the full "raw" features data that has been + discovered. + properties: + attributes: + additionalProperties: + description: AttributeFeatureSet is a set of features having + string value. + properties: + elements: + additionalProperties: + type: string + type: object + required: + - elements + type: object + description: Attributes contains all the attribute-type features + of the node. + type: object + flags: + additionalProperties: + description: FlagFeatureSet is a set of simple features only + containing names without values. + properties: + elements: + additionalProperties: + description: Nil is a dummy empty struct for protobuf + compatibility + type: object + type: object + required: + - elements + type: object + description: Flags contains all the flag-type features of the + node. + type: object + instances: + additionalProperties: + description: InstanceFeatureSet is a set of features each of + which is an instance having multiple attributes. + properties: + elements: + items: + description: InstanceFeature represents one instance of + a complex features, e.g. a device. + properties: + attributes: + additionalProperties: + type: string + type: object + required: + - attributes + type: object + type: array + required: + - elements + type: object + description: Instances contains all the instance-type features + of the node. + type: object + type: object + labels: + additionalProperties: + type: string + description: Labels is the set of node labels that are requested to + be created. + type: object + type: object + required: + - spec + type: object + served: true + storage: true +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: nodefeaturerules.nfd.k8s-sigs.io +spec: + group: nfd.k8s-sigs.io + names: + kind: NodeFeatureRule + listKind: NodeFeatureRuleList + plural: nodefeaturerules + shortNames: + - nfr + singular: nodefeaturerule + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: NodeFeatureRule resource specifies a configuration for feature-based + customization of node objects, such as node labeling. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: NodeFeatureRuleSpec describes a NodeFeatureRule. + properties: + rules: + description: Rules is a list of node customization rules. + items: + description: Rule defines a rule for node customization such as + labeling. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to create if the rule matches. + type: object + extendedResources: + additionalProperties: + type: string + description: ExtendedResources to create if the rule matches. + type: object + labels: + additionalProperties: + type: string + description: Labels to create if the rule matches. + type: object + labelsTemplate: + description: LabelsTemplate specifies a template to expand for + dynamically generating multiple labels. Data (after template + expansion) must be keys with an optional value ([=]) + separated by newlines. + type: string + matchAny: + description: MatchAny specifies a list of matchers one of which + must match. + items: + description: MatchAnyElem specifies one sub-matcher of MatchAny. + properties: + matchFeatures: + description: MatchFeatures specifies a set of matcher + terms all of which must match. + items: + description: FeatureMatcherTerm defines requirements + against one feature set. All requirements (specified + as MatchExpressions) are evaluated against each element + in the feature set. + properties: + feature: + description: Feature is the name of the feature + set to match against. + type: string + matchExpressions: + additionalProperties: + description: MatchExpression specifies an expression + to evaluate against a set of input values. It + contains an operator that is applied when matching + the input and an array of values that the operator + evaluates the input against. + properties: + op: + description: Op is the operator to be applied. + enum: + - In + - NotIn + - InRegexp + - Exists + - DoesNotExist + - Gt + - Lt + - GtLt + - IsTrue + - IsFalse + type: string + value: + description: Value is the list of values that + the operand evaluates the input against. + Value should be empty if the operator is + Exists, DoesNotExist, IsTrue or IsFalse. + Value should contain exactly one element + if the operator is Gt or Lt and exactly + two elements if the operator is GtLt. In + other cases Value should contain at least + one element. + items: + type: string + type: array + required: + - op + type: object + description: MatchExpressions is the set of per-element + expressions evaluated. These match against the + value of the specified elements. + type: object + matchName: + description: MatchName in an expression that is + matched against the name of each element in the + feature set. + properties: + op: + description: Op is the operator to be applied. + enum: + - In + - NotIn + - InRegexp + - Exists + - DoesNotExist + - Gt + - Lt + - GtLt + - IsTrue + - IsFalse + type: string + value: + description: Value is the list of values that + the operand evaluates the input against. Value + should be empty if the operator is Exists, + DoesNotExist, IsTrue or IsFalse. Value should + contain exactly one element if the operator + is Gt or Lt and exactly two elements if the + operator is GtLt. In other cases Value should + contain at least one element. + items: + type: string + type: array + required: + - op + type: object + required: + - feature + type: object + type: array + required: + - matchFeatures + type: object + type: array + matchFeatures: + description: MatchFeatures specifies a set of matcher terms + all of which must match. + items: + description: FeatureMatcherTerm defines requirements against + one feature set. All requirements (specified as MatchExpressions) + are evaluated against each element in the feature set. + properties: + feature: + description: Feature is the name of the feature set to + match against. + type: string + matchExpressions: + additionalProperties: + description: MatchExpression specifies an expression + to evaluate against a set of input values. It contains + an operator that is applied when matching the input + and an array of values that the operator evaluates + the input against. + properties: + op: + description: Op is the operator to be applied. + enum: + - In + - NotIn + - InRegexp + - Exists + - DoesNotExist + - Gt + - Lt + - GtLt + - IsTrue + - IsFalse + type: string + value: + description: Value is the list of values that the + operand evaluates the input against. Value should + be empty if the operator is Exists, DoesNotExist, + IsTrue or IsFalse. Value should contain exactly + one element if the operator is Gt or Lt and exactly + two elements if the operator is GtLt. In other + cases Value should contain at least one element. + items: + type: string + type: array + required: + - op + type: object + description: MatchExpressions is the set of per-element + expressions evaluated. These match against the value + of the specified elements. + type: object + matchName: + description: MatchName in an expression that is matched + against the name of each element in the feature set. + properties: + op: + description: Op is the operator to be applied. + enum: + - In + - NotIn + - InRegexp + - Exists + - DoesNotExist + - Gt + - Lt + - GtLt + - IsTrue + - IsFalse + type: string + value: + description: Value is the list of values that the + operand evaluates the input against. Value should + be empty if the operator is Exists, DoesNotExist, + IsTrue or IsFalse. Value should contain exactly + one element if the operator is Gt or Lt and exactly + two elements if the operator is GtLt. In other cases + Value should contain at least one element. + items: + type: string + type: array + required: + - op + type: object + required: + - feature + type: object + type: array + name: + description: Name of the rule. + type: string + taints: + description: Taints to create if the rule matches. + items: + description: The node this Taint is attached to has the "effect" + on any pod that does not tolerate the Taint. + properties: + effect: + description: Required. The effect of the taint on pods + that do not tolerate the taint. Valid effects are NoSchedule, + PreferNoSchedule and NoExecute. + type: string + key: + description: Required. The taint key to be applied to + a node. + type: string + timeAdded: + description: TimeAdded represents the time at which the + taint was added. It is only written for NoExecute taints. + format: date-time + type: string + value: + description: The taint value corresponding to the taint + key. + type: string + required: + - effect + - key + type: object + type: array + vars: + additionalProperties: + type: string + description: Vars is the variables to store if the rule matches. + Variables do not directly inflict any changes in the node + object. However, they can be referenced from other rules enabling + more complex rule hierarchies, without exposing intermediary + output values as labels. + type: object + varsTemplate: + description: VarsTemplate specifies a template to expand for + dynamically generating multiple variables. Data (after template + expansion) must be keys with an optional value ([=]) + separated by newlines. + type: string + required: + - name + type: object + type: array + required: + - rules + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/_helpers.tpl b/sriov-network-operator-chart/charts/sriov-nfd/templates/_helpers.tpl new file mode 100644 index 0000000..f8b1e30 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/_helpers.tpl @@ -0,0 +1,107 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "node-feature-discovery.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "node-feature-discovery.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "node-feature-discovery.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "node-feature-discovery.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "node-feature-discovery.labels" -}} +helm.sh/chart: {{ include "node-feature-discovery.chart" . }} +{{ include "node-feature-discovery.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "node-feature-discovery.selectorLabels" -}} +app.kubernetes.io/name: {{ include "node-feature-discovery.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account which the nfd master will use +*/}} +{{- define "node-feature-discovery.master.serviceAccountName" -}} +{{- if .Values.master.serviceAccount.create -}} + {{ default (include "node-feature-discovery.fullname" .) .Values.master.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.master.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account which the nfd worker will use +*/}} +{{- define "node-feature-discovery.worker.serviceAccountName" -}} +{{- if .Values.worker.serviceAccount.create -}} + {{ default (printf "%s-worker" (include "node-feature-discovery.fullname" .)) .Values.worker.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.worker.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account which topologyUpdater will use +*/}} +{{- define "node-feature-discovery.topologyUpdater.serviceAccountName" -}} +{{- if .Values.topologyUpdater.serviceAccount.create -}} + {{ default (printf "%s-topology-updater" (include "node-feature-discovery.fullname" .)) .Values.topologyUpdater.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.topologyUpdater.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account which nfd-gc will use +*/}} +{{- define "node-feature-discovery.gc.serviceAccountName" -}} +{{- if .Values.gc.serviceAccount.create -}} + {{ default (printf "%s-gc" (include "node-feature-discovery.fullname" .)) .Values.gc.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.gc.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-certs.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-certs.yaml new file mode 100644 index 0000000..43a647a --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-certs.yaml @@ -0,0 +1,68 @@ +{{- if .Values.tls.certManager }} +{{- if .Values.master.enable }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: nfd-master-cert + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + secretName: nfd-master-cert + subject: + organizations: + - node-feature-discovery + commonName: nfd-master + dnsNames: + # must match the service name + - {{ include "node-feature-discovery.fullname" . }}-master + # first one is configured for use by the worker; below are for completeness + - {{ include "node-feature-discovery.fullname" . }}-master.{{ include "node-feature-discovery.namespace" . }}.svc + - {{ include "node-feature-discovery.fullname" . }}-master.{{ include "node-feature-discovery.namespace" . }}.svc.cluster.local + issuerRef: + name: nfd-ca-issuer + kind: Issuer + group: cert-manager.io +{{- end }} +--- +{{- if .Values.worker.enable }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: nfd-worker-cert + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + secretName: nfd-worker-cert + subject: + organizations: + - node-feature-discovery + commonName: nfd-worker + dnsNames: + - {{ include "node-feature-discovery.fullname" . }}-worker.{{ include "node-feature-discovery.namespace" . }}.svc.cluster.local + issuerRef: + name: nfd-ca-issuer + kind: Issuer + group: cert-manager.io +{{- end }} + +{{- if .Values.topologyUpdater.enable }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: nfd-topology-updater-cert + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + secretName: nfd-topology-updater-cert + subject: + organizations: + - node-feature-discovery + commonName: nfd-topology-updater + dnsNames: + - {{ include "node-feature-discovery.fullname" . }}-topology-updater.{{ include "node-feature-discovery.namespace" . }}.svc.cluster.local + issuerRef: + name: nfd-ca-issuer + kind: Issuer + group: cert-manager.io +{{- end }} + +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-issuer.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-issuer.yaml new file mode 100644 index 0000000..742ebe1 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-issuer.yaml @@ -0,0 +1,42 @@ +{{- if .Values.tls.certManager }} +# See https://cert-manager.io/docs/configuration/selfsigned/#bootstrapping-ca-issuers +# - Create a self signed issuer +# - Use this to create a CA cert +# - Use this to now create a CA issuer +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: nfd-ca-bootstrap + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + selfSigned: {} + +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: nfd-ca-cert + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + isCA: true + secretName: nfd-ca-cert + subject: + organizations: + - node-feature-discovery + commonName: nfd-ca-cert + issuerRef: + name: nfd-ca-bootstrap + kind: Issuer + group: cert-manager.io + +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: nfd-ca-issuer + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + ca: + secretName: nfd-ca-cert +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrole.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrole.yaml new file mode 100644 index 0000000..8853613 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrole.yaml @@ -0,0 +1,119 @@ +{{- if and .Values.master.enable .Values.master.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "node-feature-discovery.fullname" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - nodes + - nodes/status + verbs: + - get + - patch + - update + - list +- apiGroups: + - nfd.k8s-sigs.io + resources: + - nodefeatures + - nodefeaturerules + verbs: + - get + - list + - watch +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create +- apiGroups: + - coordination.k8s.io + resources: + - leases + resourceNames: + - "nfd-master.nfd.kubernetes.io" + verbs: + - get + - update +{{- end }} + +{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.rbac.create }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list +- apiGroups: + - "" + resources: + - nodes/proxy + verbs: + - get +- apiGroups: + - "" + resources: + - pods + verbs: + - get +- apiGroups: + - topology.node.k8s.io + resources: + - noderesourcetopologies + verbs: + - create + - get + - update +{{- end }} + +{{- if and .Values.gc.enable .Values.gc.rbac.create (or .Values.enableNodeFeatureApi .Values.topologyUpdater.enable) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-gc + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - nodes + verbs: + - list + - watch +- apiGroups: + - "" + resources: + - nodes/proxy + verbs: + - get +- apiGroups: + - topology.node.k8s.io + resources: + - noderesourcetopologies + verbs: + - delete + - list +- apiGroups: + - nfd.k8s-sigs.io + resources: + - nodefeatures + verbs: + - delete + - list +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrolebinding.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrolebinding.yaml new file mode 100644 index 0000000..1d49ec5 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrolebinding.yaml @@ -0,0 +1,52 @@ +{{- if and .Values.master.enable .Values.master.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "node-feature-discovery.fullname" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "node-feature-discovery.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ include "node-feature-discovery.master.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} +{{- end }} + +{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.rbac.create }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater +subjects: +- kind: ServiceAccount + name: {{ include "node-feature-discovery.topologyUpdater.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} +{{- end }} + +{{- if and .Values.gc.enable .Values.gc.rbac.create (or .Values.enableNodeFeatureApi .Values.topologyUpdater.enable) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-gc + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "node-feature-discovery.fullname" . }}-gc +subjects: +- kind: ServiceAccount + name: {{ include "node-feature-discovery.gc.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/master.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/master.yaml new file mode 100644 index 0000000..19b543a --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/master.yaml @@ -0,0 +1,145 @@ +{{- if .Values.master.enable }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-master + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: master + {{- with .Values.master.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.master.replicaCount }} + selector: + matchLabels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }} + role: master + template: + metadata: + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }} + role: master + {{- with .Values.master.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "node-feature-discovery.master.serviceAccountName" . }} + enableServiceLinks: false + securityContext: + {{- toYaml .Values.master.podSecurityContext | nindent 8 }} + containers: + - name: master + securityContext: + {{- toYaml .Values.master.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + livenessProbe: + grpc: + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 10 + readinessProbe: + grpc: + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 10 + failureThreshold: 10 + ports: + - containerPort: {{ .Values.master.port | default "8080" }} + name: grpc + - containerPort: {{ .Values.master.metricsPort | default "8081" }} + name: metrics + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + command: + - "nfd-master" + resources: + {{- toYaml .Values.master.resources | nindent 12 }} + args: + {{- if .Values.master.instance | empty | not }} + - "-instance={{ .Values.master.instance }}" + {{- end }} + {{- if not .Values.enableNodeFeatureApi }} + - "-port={{ .Values.master.port | default "8080" }}" + - "-enable-nodefeature-api=false" + {{- else if gt (int .Values.master.replicaCount) 1 }} + - "-enable-leader-election" + {{- end }} + {{- if .Values.master.extraLabelNs | empty | not }} + - "-extra-label-ns={{- join "," .Values.master.extraLabelNs }}" + {{- end }} + {{- if .Values.master.denyLabelNs | empty | not }} + - "-deny-label-ns={{- join "," .Values.master.denyLabelNs }}" + {{- end }} + {{- if .Values.master.resourceLabels | empty | not }} + - "-resource-labels={{- join "," .Values.master.resourceLabels }}" + {{- end }} + {{- if .Values.master.enableTaints }} + - "-enable-taints" + {{- end }} + {{- if .Values.master.crdController | kindIs "invalid" | not }} + - "-crd-controller={{ .Values.master.crdController }}" + {{- else }} + ## By default, disable crd controller for other than the default instances + - "-crd-controller={{ .Values.master.instance | empty }}" + {{- end }} + {{- if .Values.master.featureRulesController | kindIs "invalid" | not }} + - "-featurerules-controller={{ .Values.master.featureRulesController }}" + {{- end }} + {{- if .Values.master.resyncPeriod }} + - "-resync-period={{ .Values.master.resyncPeriod }}" + {{- end }} + {{- if .Values.master.nfdApiParallelism | empty | not }} + - "-nfd-api-parallelism={{ .Values.master.nfdApiParallelism }}" + {{- end }} + {{- if .Values.tls.enable }} + - "-ca-file=/etc/kubernetes/node-feature-discovery/certs/ca.crt" + - "-key-file=/etc/kubernetes/node-feature-discovery/certs/tls.key" + - "-cert-file=/etc/kubernetes/node-feature-discovery/certs/tls.crt" + {{- end }} + - "-metrics={{ .Values.master.metricsPort | default "8081" }}" + volumeMounts: + {{- if .Values.tls.enable }} + - name: nfd-master-cert + mountPath: "/etc/kubernetes/node-feature-discovery/certs" + readOnly: true + {{- end }} + - name: nfd-master-conf + mountPath: "/etc/kubernetes/node-feature-discovery" + readOnly: true + volumes: + {{- if .Values.tls.enable }} + - name: nfd-master-cert + secret: + secretName: nfd-master-cert + {{- end }} + - name: nfd-master-conf + configMap: + name: {{ include "node-feature-discovery.fullname" . }}-master-conf + items: + - key: nfd-master.conf + path: nfd-master.conf + {{- with .Values.master.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.master.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.master.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-gc.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-gc.yaml new file mode 100644 index 0000000..641202b --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-gc.yaml @@ -0,0 +1,77 @@ +{{- if and .Values.gc.enable (or .Values.enableNodeFeatureApi .Values.topologyUpdater.enable) -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-gc + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: gc + {{- with .Values.gc.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.gc.replicaCount | default 1 }} + selector: + matchLabels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }} + role: gc + template: + metadata: + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }} + role: gc + {{- with .Values.gc.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "node-feature-discovery.gc.serviceAccountName" . }} + dnsPolicy: ClusterFirstWithHostNet + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.gc.podSecurityContext | nindent 8 }} + containers: + - name: gc + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + command: + - "nfd-gc" + args: + {{- if .Values.gc.interval | empty | not }} + - "-gc-interval={{ .Values.gc.interval }}" + {{- end }} + resources: + {{- toYaml .Values.gc.resources | nindent 12 }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ "ALL" ] + readOnlyRootFilesystem: true + runAsNonRoot: true + ports: + - name: metrics + containerPort: {{ .Values.gc.metricsPort | default "8081"}} + + {{- with .Values.gc.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.gc.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.gc.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-master-conf.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-master-conf.yaml new file mode 100644 index 0000000..be92601 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-master-conf.yaml @@ -0,0 +1,12 @@ +{{- if .Values.master.enable }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-master-conf + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +data: + nfd-master.conf: |- + {{- .Values.master.config | toYaml | nindent 4 }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-topologyupdater-conf.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-topologyupdater-conf.yaml new file mode 100644 index 0000000..1680d69 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-topologyupdater-conf.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater-conf + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +data: + nfd-topology-updater.conf: |- + {{- .Values.topologyUpdater.config | toYaml | nindent 4 }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-worker-conf.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-worker-conf.yaml new file mode 100644 index 0000000..3e1148d --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-worker-conf.yaml @@ -0,0 +1,12 @@ +{{- if .Values.worker.enable }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-worker-conf + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +data: + nfd-worker.conf: |- + {{- .Values.worker.config | toYaml | nindent 4 }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/prometheus.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/prometheus.yaml new file mode 100644 index 0000000..cbc8f85 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/prometheus.yaml @@ -0,0 +1,26 @@ +{{- if .Values.prometheus.enable }} +# Prometheus Monitor Service (Metrics) +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ include "node-feature-discovery.fullname" . }} + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 4 }} + {{- with .Values.prometheus.labels }} + {{ toYaml . | nindent 4 }} + {{- end }} +spec: + podMetricsEndpoints: + - honorLabels: true + interval: 10s + path: /metrics + port: metrics + scheme: http + namespaceSelector: + matchNames: + - {{ include "node-feature-discovery.namespace" . }} + selector: + matchExpressions: + - {key: app.kubernetes.io/instance, operator: In, values: ["{{ .Release.Name }}"]} + - {key: app.kubernetes.io/name, operator: In, values: ["{{ include "node-feature-discovery.name" . }}"]} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/role.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/role.yaml new file mode 100644 index 0000000..06ca73e --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/role.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.worker.enable .Values.worker.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-worker + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +rules: +- apiGroups: + - nfd.k8s-sigs.io + resources: + - nodefeatures + verbs: + - create + - get + - update +- apiGroups: + - "" + resources: + - pods + verbs: + - get +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/rolebinding.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/rolebinding.yaml new file mode 100644 index 0000000..46ac7f7 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/rolebinding.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.worker.enable .Values.worker.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-worker + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "node-feature-discovery.fullname" . }}-worker +subjects: +- kind: ServiceAccount + name: {{ include "node-feature-discovery.worker.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} +{{- end }} + diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/service.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/service.yaml new file mode 100644 index 0000000..a82c22d --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/service.yaml @@ -0,0 +1,20 @@ +{{- if and (not .Values.enableNodeFeatureApi) .Values.master.enable }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-master + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: master +spec: + type: {{ .Values.master.service.type }} + ports: + - port: {{ .Values.master.service.port | default "8080" }} + targetPort: grpc + protocol: TCP + name: grpc + selector: + {{- include "node-feature-discovery.selectorLabels" . | nindent 4 }} + role: master +{{- end}} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/serviceaccount.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/serviceaccount.yaml new file mode 100644 index 0000000..52706f7 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/serviceaccount.yaml @@ -0,0 +1,58 @@ +{{- if and .Values.master.enable .Values.master.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "node-feature-discovery.master.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + {{- with .Values.master.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "node-feature-discovery.topologyUpdater.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + {{- with .Values.topologyUpdater.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +{{- if and .Values.gc.enable .Values.gc.serviceAccount.create (or .Values.enableNodeFeatureApi .Values.topologyUpdater.enable) }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "node-feature-discovery.gc.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + {{- with .Values.gc.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +{{- if and .Values.worker.enable .Values.worker.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "node-feature-discovery.worker.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + {{- with .Values.worker.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater-crds.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater-crds.yaml new file mode 100644 index 0000000..94b7b35 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater-crds.yaml @@ -0,0 +1,278 @@ +{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.createCRDs -}} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes/enhancements/pull/1870 + controller-gen.kubebuilder.io/version: v0.11.2 + creationTimestamp: null + name: noderesourcetopologies.topology.node.k8s.io +spec: + group: topology.node.k8s.io + names: + kind: NodeResourceTopology + listKind: NodeResourceTopologyList + plural: noderesourcetopologies + shortNames: + - node-res-topo + singular: noderesourcetopology + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: NodeResourceTopology describes node resources and their topology. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + topologyPolicies: + items: + type: string + type: array + zones: + description: ZoneList contains an array of Zone objects. + items: + description: Zone represents a resource topology zone, e.g. socket, + node, die or core. + properties: + attributes: + description: AttributeList contains an array of AttributeInfo objects. + items: + description: AttributeInfo contains one attribute of a Zone. + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + costs: + description: CostList contains an array of CostInfo objects. + items: + description: CostInfo describes the cost (or distance) between + two Zones. + properties: + name: + type: string + value: + format: int64 + type: integer + required: + - name + - value + type: object + type: array + name: + type: string + parent: + type: string + resources: + description: ResourceInfoList contains an array of ResourceInfo + objects. + items: + description: ResourceInfo contains information about one resource + type. + properties: + allocatable: + anyOf: + - type: integer + - type: string + description: Allocatable quantity of the resource, corresponding + to allocatable in node status, i.e. total amount of this + resource available to be used by pods. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + available: + anyOf: + - type: integer + - type: string + description: Available is the amount of this resource currently + available for new (to be scheduled) pods, i.e. Allocatable + minus the resources reserved by currently running pods. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + capacity: + anyOf: + - type: integer + - type: string + description: Capacity of the resource, corresponding to capacity + in node status, i.e. total amount of this resource that + the node has. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + name: + description: Name of the resource. + type: string + required: + - allocatable + - available + - capacity + - name + type: object + type: array + type: + type: string + required: + - name + - type + type: object + type: array + required: + - topologyPolicies + - zones + type: object + served: true + storage: false + - name: v1alpha2 + schema: + openAPIV3Schema: + description: NodeResourceTopology describes node resources and their topology. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + attributes: + description: AttributeList contains an array of AttributeInfo objects. + items: + description: AttributeInfo contains one attribute of a Zone. + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + topologyPolicies: + description: 'DEPRECATED (to be removed in v1beta1): use top level attributes + if needed' + items: + type: string + type: array + zones: + description: ZoneList contains an array of Zone objects. + items: + description: Zone represents a resource topology zone, e.g. socket, + node, die or core. + properties: + attributes: + description: AttributeList contains an array of AttributeInfo objects. + items: + description: AttributeInfo contains one attribute of a Zone. + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + costs: + description: CostList contains an array of CostInfo objects. + items: + description: CostInfo describes the cost (or distance) between + two Zones. + properties: + name: + type: string + value: + format: int64 + type: integer + required: + - name + - value + type: object + type: array + name: + type: string + parent: + type: string + resources: + description: ResourceInfoList contains an array of ResourceInfo + objects. + items: + description: ResourceInfo contains information about one resource + type. + properties: + allocatable: + anyOf: + - type: integer + - type: string + description: Allocatable quantity of the resource, corresponding + to allocatable in node status, i.e. total amount of this + resource available to be used by pods. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + available: + anyOf: + - type: integer + - type: string + description: Available is the amount of this resource currently + available for new (to be scheduled) pods, i.e. Allocatable + minus the resources reserved by currently running pods. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + capacity: + anyOf: + - type: integer + - type: string + description: Capacity of the resource, corresponding to capacity + in node status, i.e. total amount of this resource that + the node has. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + name: + description: Name of the resource. + type: string + required: + - allocatable + - available + - capacity + - name + type: object + type: array + type: + type: string + required: + - name + - type + type: object + type: array + required: + - zones + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater.yaml new file mode 100644 index 0000000..28ed58b --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater.yaml @@ -0,0 +1,156 @@ +{{- if .Values.topologyUpdater.enable -}} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: topology-updater + {{- with .Values.topologyUpdater.daemonsetAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }} + role: topology-updater + template: + metadata: + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }} + role: topology-updater + {{- with .Values.topologyUpdater.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "node-feature-discovery.topologyUpdater.serviceAccountName" . }} + dnsPolicy: ClusterFirstWithHostNet + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.topologyUpdater.podSecurityContext | nindent 8 }} + containers: + - name: topology-updater + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: NODE_ADDRESS + valueFrom: + fieldRef: + fieldPath: status.hostIP + command: + - "nfd-topology-updater" + args: + - "-podresources-socket=/host-var/lib/kubelet-podresources/kubelet.sock" + {{- if .Values.topologyUpdater.updateInterval | empty | not }} + - "-sleep-interval={{ .Values.topologyUpdater.updateInterval }}" + {{- else }} + - "-sleep-interval=3s" + {{- end }} + {{- if .Values.topologyUpdater.watchNamespace | empty | not }} + - "-watch-namespace={{ .Values.topologyUpdater.watchNamespace }}" + {{- else }} + - "-watch-namespace=*" + {{- end }} + {{- if .Values.tls.enable }} + - "-ca-file=/etc/kubernetes/node-feature-discovery/certs/ca.crt" + - "-key-file=/etc/kubernetes/node-feature-discovery/certs/tls.key" + - "-cert-file=/etc/kubernetes/node-feature-discovery/certs/tls.crt" + {{- end }} + {{- if .Values.topologyUpdater.podSetFingerprint }} + - "-pods-fingerprint" + {{- end }} + {{- if .Values.topologyUpdater.kubeletConfigPath | empty | not }} + - "-kubelet-config-uri=file:///host-var/kubelet-config" + {{- end }} + {{- if .Values.topologyUpdater.kubeletStateDir | empty }} + # Disable kubelet state tracking by giving an empty path + - "-kubelet-state-dir=" + {{- end }} + - -metrics={{ .Values.topologyUpdater.metricsPort | default "8081"}} + ports: + - name: metrics + containerPort: {{ .Values.topologyUpdater.metricsPort | default "8081"}} + volumeMounts: + {{- if .Values.topologyUpdater.kubeletConfigPath | empty | not }} + - name: kubelet-config + mountPath: /host-var/kubelet-config + {{- end }} + - name: kubelet-podresources-sock + mountPath: /host-var/lib/kubelet-podresources/kubelet.sock + - name: host-sys + mountPath: /host-sys + {{- if .Values.topologyUpdater.kubeletStateDir | empty | not }} + - name: kubelet-state-files + mountPath: /host-var/lib/kubelet + readOnly: true + {{- end }} + {{- if .Values.tls.enable }} + - name: nfd-topology-updater-cert + mountPath: "/etc/kubernetes/node-feature-discovery/certs" + readOnly: true + {{- end }} + - name: nfd-topology-updater-conf + mountPath: "/etc/kubernetes/node-feature-discovery" + readOnly: true + + resources: + {{- toYaml .Values.topologyUpdater.resources | nindent 12 }} + securityContext: + {{- toYaml .Values.topologyUpdater.securityContext | nindent 12 }} + volumes: + - name: host-sys + hostPath: + path: "/sys" + {{- if .Values.topologyUpdater.kubeletConfigPath | empty | not }} + - name: kubelet-config + hostPath: + path: {{ .Values.topologyUpdater.kubeletConfigPath }} + {{- end }} + - name: kubelet-podresources-sock + hostPath: + {{- if .Values.topologyUpdater.kubeletPodResourcesSockPath | empty | not }} + path: {{ .Values.topologyUpdater.kubeletPodResourcesSockPath }} + {{- else }} + path: /var/lib/kubelet/pod-resources/kubelet.sock + {{- end }} + {{- if .Values.topologyUpdater.kubeletStateDir | empty | not }} + - name: kubelet-state-files + hostPath: + path: {{ .Values.topologyUpdater.kubeletStateDir }} + {{- end }} + - name: nfd-topology-updater-conf + configMap: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater-conf + items: + - key: nfd-topology-updater.conf + path: nfd-topology-updater.conf + {{- if .Values.tls.enable }} + - name: nfd-topology-updater-cert + secret: + secretName: nfd-topology-updater-cert + {{- end }} + + + {{- with .Values.topologyUpdater.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologyUpdater.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologyUpdater.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/worker.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/worker.yaml new file mode 100644 index 0000000..124e1a0 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/worker.yaml @@ -0,0 +1,162 @@ +{{- if .Values.worker.enable }} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-worker + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: worker + {{- with .Values.worker.daemonsetAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }} + role: worker + template: + metadata: + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }} + role: worker + {{- with .Values.worker.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + dnsPolicy: ClusterFirstWithHostNet + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "node-feature-discovery.worker.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.worker.podSecurityContext | nindent 8 }} + containers: + - name: worker + securityContext: + {{- toYaml .Values.worker.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_UID + valueFrom: + fieldRef: + fieldPath: metadata.uid + resources: + {{- toYaml .Values.worker.resources | nindent 12 }} + command: + - "nfd-worker" + args: + {{- if not .Values.enableNodeFeatureApi }} + - "-server={{ include "node-feature-discovery.fullname" . }}-master:{{ .Values.master.service.port }}" + - "-enable-nodefeature-api=false" + {{- end }} +{{- if .Values.tls.enable }} + - "-ca-file=/etc/kubernetes/node-feature-discovery/certs/ca.crt" + - "-key-file=/etc/kubernetes/node-feature-discovery/certs/tls.key" + - "-cert-file=/etc/kubernetes/node-feature-discovery/certs/tls.crt" +{{- end }} + - "-metrics={{ .Values.worker.metricsPort | default "8081"}}" + ports: + - name: metrics + containerPort: {{ .Values.worker.metricsPort | default "8081"}} + volumeMounts: + - name: host-boot + mountPath: "/host-boot" + readOnly: true + - name: host-os-release + mountPath: "/host-etc/os-release" + readOnly: true + - name: host-sys + mountPath: "/host-sys" + readOnly: true + - name: host-usr-lib + mountPath: "/host-usr/lib" + readOnly: true + - name: host-lib + mountPath: "/host-lib" + readOnly: true + {{- if .Values.worker.mountUsrSrc }} + - name: host-usr-src + mountPath: "/host-usr/src" + readOnly: true + {{- end }} + - name: source-d + mountPath: "/etc/kubernetes/node-feature-discovery/source.d/" + readOnly: true + - name: features-d + mountPath: "/etc/kubernetes/node-feature-discovery/features.d/" + readOnly: true + - name: nfd-worker-conf + mountPath: "/etc/kubernetes/node-feature-discovery" + readOnly: true +{{- if .Values.tls.enable }} + - name: nfd-worker-cert + mountPath: "/etc/kubernetes/node-feature-discovery/certs" + readOnly: true +{{- end }} + volumes: + - name: host-boot + hostPath: + path: "/boot" + - name: host-os-release + hostPath: + path: "/etc/os-release" + - name: host-sys + hostPath: + path: "/sys" + - name: host-usr-lib + hostPath: + path: "/usr/lib" + - name: host-lib + hostPath: + path: "/lib" + {{- if .Values.worker.mountUsrSrc }} + - name: host-usr-src + hostPath: + path: "/usr/src" + {{- end }} + - name: source-d + hostPath: + path: "/etc/kubernetes/node-feature-discovery/source.d/" + - name: features-d + hostPath: + path: "/etc/kubernetes/node-feature-discovery/features.d/" + - name: nfd-worker-conf + configMap: + name: {{ include "node-feature-discovery.fullname" . }}-worker-conf + items: + - key: nfd-worker.conf + path: nfd-worker.conf +{{- if .Values.tls.enable }} + - name: nfd-worker-cert + secret: + secretName: nfd-worker-cert +{{- end }} + {{- with .Values.worker.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.worker.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.worker.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.worker.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/values.yaml b/sriov-network-operator-chart/charts/sriov-nfd/values.yaml new file mode 100644 index 0000000..9d9aa94 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/values.yaml @@ -0,0 +1,534 @@ +image: + repository: rancher/hardened-node-feature-discovery + # This should be set to 'IfNotPresent' for released version + pullPolicy: IfNotPresent + # tag, if defined will use the given image tag, else Chart.AppVersion will be used + tag: v0.15.6-build20240822 +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" +namespaceOverride: "" + +enableNodeFeatureApi: true + +master: + enable: true + config: ### + # noPublish: false + # autoDefaultNs: true + # extraLabelNs: ["added.ns.io","added.kubernets.io"] + # denyLabelNs: ["denied.ns.io","denied.kubernetes.io"] + # resourceLabels: ["vendor-1.com/feature-1","vendor-2.io/feature-2"] + # enableTaints: false + # labelWhiteList: "foo" + # resyncPeriod: "2h" + # klog: + # addDirHeader: false + # alsologtostderr: false + # logBacktraceAt: + # logtostderr: true + # skipHeaders: false + # stderrthreshold: 2 + # v: 0 + # vmodule: + ## NOTE: the following options are not dynamically run-time configurable + ## and require a nfd-master restart to take effect after being changed + # logDir: + # logFile: + # logFileMaxSize: 1800 + # skipLogHeaders: false + # leaderElection: + # leaseDuration: 15s + # # this value has to be lower than leaseDuration and greater than retryPeriod*1.2 + # renewDeadline: 10s + # # this value has to be greater than 0 + # retryPeriod: 2s + # nfdApiParallelism: 10 + ### + # The TCP port that nfd-master listens for incoming requests. Default: 8080 + # Deprecated this parameter is related to the deprecated gRPC API and will + # be removed with it in a future release + port: 8080 + metricsPort: 8081 + instance: + featureApi: + resyncPeriod: + denyLabelNs: [] + extraLabelNs: [] + resourceLabels: [] + enableTaints: false + crdController: null + featureRulesController: null + nfdApiParallelism: null + deploymentAnnotations: {} + replicaCount: 1 + + podSecurityContext: {} + # fsGroup: 2000 + + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ "ALL" ] + readOnlyRootFilesystem: true + runAsNonRoot: true + # runAsUser: 1000 + + serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: + + rbac: + create: true + + service: + type: ClusterIP + port: 8080 + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + nodeSelector: {} + + tolerations: + - key: "node-role.kubernetes.io/master" + operator: "Equal" + value: "" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/control-plane" + operator: "Equal" + value: "" + effect: "NoSchedule" + + annotations: {} + + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + preference: + matchExpressions: + - key: "node-role.kubernetes.io/master" + operator: In + values: [""] + - weight: 1 + preference: + matchExpressions: + - key: "node-role.kubernetes.io/control-plane" + operator: In + values: [""] + +worker: + enable: true + config: ### + #core: + # labelWhiteList: + # noPublish: false + # sleepInterval: 60s + # featureSources: [all] + # labelSources: [all] + # klog: + # addDirHeader: false + # alsologtostderr: false + # logBacktraceAt: + # logtostderr: true + # skipHeaders: false + # stderrthreshold: 2 + # v: 0 + # vmodule: + ## NOTE: the following options are not dynamically run-time configurable + ## and require a nfd-worker restart to take effect after being changed + # logDir: + # logFile: + # logFileMaxSize: 1800 + # skipLogHeaders: false + #sources: + # cpu: + # cpuid: + ## NOTE: whitelist has priority over blacklist + # attributeBlacklist: + # - "BMI1" + # - "BMI2" + # - "CLMUL" + # - "CMOV" + # - "CX16" + # - "ERMS" + # - "F16C" + # - "HTT" + # - "LZCNT" + # - "MMX" + # - "MMXEXT" + # - "NX" + # - "POPCNT" + # - "RDRAND" + # - "RDSEED" + # - "RDTSCP" + # - "SGX" + # - "SSE" + # - "SSE2" + # - "SSE3" + # - "SSE4" + # - "SSE42" + # - "SSSE3" + # - "TDX_GUEST" + # attributeWhitelist: + # kernel: + # kconfigFile: "/path/to/kconfig" + # configOpts: + # - "NO_HZ" + # - "X86" + # - "DMI" + # pci: + # deviceClassWhitelist: + # - "0200" + # - "03" + # - "12" + # deviceLabelFields: + # - "class" + # - "vendor" + # - "device" + # - "subsystem_vendor" + # - "subsystem_device" + # usb: + # deviceClassWhitelist: + # - "0e" + # - "ef" + # - "fe" + # - "ff" + # deviceLabelFields: + # - "class" + # - "vendor" + # - "device" + # local: + # hooksEnabled: false + # custom: + # # The following feature demonstrates the capabilities of the matchFeatures + # - name: "my custom rule" + # labels: + # "vendor.io/my-ng-feature": "true" + # # matchFeatures implements a logical AND over all matcher terms in the + # # list (i.e. all of the terms, or per-feature matchers, must match) + # matchFeatures: + # - feature: cpu.cpuid + # matchExpressions: + # AVX512F: {op: Exists} + # - feature: cpu.cstate + # matchExpressions: + # enabled: {op: IsTrue} + # - feature: cpu.pstate + # matchExpressions: + # no_turbo: {op: IsFalse} + # scaling_governor: {op: In, value: ["performance"]} + # - feature: cpu.rdt + # matchExpressions: + # RDTL3CA: {op: Exists} + # - feature: cpu.sst + # matchExpressions: + # bf.enabled: {op: IsTrue} + # - feature: cpu.topology + # matchExpressions: + # hardware_multithreading: {op: IsFalse} + # + # - feature: kernel.config + # matchExpressions: + # X86: {op: Exists} + # LSM: {op: InRegexp, value: ["apparmor"]} + # - feature: kernel.loadedmodule + # matchExpressions: + # e1000e: {op: Exists} + # - feature: kernel.selinux + # matchExpressions: + # enabled: {op: IsFalse} + # - feature: kernel.version + # matchExpressions: + # major: {op: In, value: ["5"]} + # minor: {op: Gt, value: ["10"]} + # + # - feature: storage.block + # matchExpressions: + # rotational: {op: In, value: ["0"]} + # dax: {op: In, value: ["0"]} + # + # - feature: network.device + # matchExpressions: + # operstate: {op: In, value: ["up"]} + # speed: {op: Gt, value: ["100"]} + # + # - feature: memory.numa + # matchExpressions: + # node_count: {op: Gt, value: ["2"]} + # - feature: memory.nv + # matchExpressions: + # devtype: {op: In, value: ["nd_dax"]} + # mode: {op: In, value: ["memory"]} + # + # - feature: system.osrelease + # matchExpressions: + # ID: {op: In, value: ["fedora", "centos"]} + # - feature: system.name + # matchExpressions: + # nodename: {op: InRegexp, value: ["^worker-X"]} + # + # - feature: local.label + # matchExpressions: + # custom-feature-knob: {op: Gt, value: ["100"]} + # + # # The following feature demonstrates the capabilities of the matchAny + # - name: "my matchAny rule" + # labels: + # "vendor.io/my-ng-feature-2": "my-value" + # # matchAny implements a logical IF over all elements (sub-matchers) in + # # the list (i.e. at least one feature matcher must match) + # matchAny: + # - matchFeatures: + # - feature: kernel.loadedmodule + # matchExpressions: + # driver-module-X: {op: Exists} + # - feature: pci.device + # matchExpressions: + # vendor: {op: In, value: ["8086"]} + # class: {op: In, value: ["0200"]} + # - matchFeatures: + # - feature: kernel.loadedmodule + # matchExpressions: + # driver-module-Y: {op: Exists} + # - feature: usb.device + # matchExpressions: + # vendor: {op: In, value: ["8086"]} + # class: {op: In, value: ["02"]} + # + # - name: "avx wildcard rule" + # labels: + # "my-avx-feature": "true" + # matchFeatures: + # - feature: cpu.cpuid + # matchName: {op: InRegexp, value: ["^AVX512"]} + # + # # The following features demonstreate label templating capabilities + # - name: "my template rule" + # labelsTemplate: | + # {{ range .system.osrelease }}vendor.io/my-system-feature.{{ .Name }}={{ .Value }} + # {{ end }} + # matchFeatures: + # - feature: system.osrelease + # matchExpressions: + # ID: {op: InRegexp, value: ["^open.*"]} + # VERSION_ID.major: {op: In, value: ["13", "15"]} + # + # - name: "my template rule 2" + # labelsTemplate: | + # {{ range .pci.device }}vendor.io/my-pci-device.{{ .class }}-{{ .device }}=with-cpuid + # {{ end }} + # matchFeatures: + # - feature: pci.device + # matchExpressions: + # class: {op: InRegexp, value: ["^06"]} + # vendor: ["8086"] + # - feature: cpu.cpuid + # matchExpressions: + # AVX: {op: Exists} + # + # # The following examples demonstrate vars field and back-referencing + # # previous labels and vars + # - name: "my dummy kernel rule" + # labels: + # "vendor.io/my.kernel.feature": "true" + # matchFeatures: + # - feature: kernel.version + # matchExpressions: + # major: {op: Gt, value: ["2"]} + # + # - name: "my dummy rule with no labels" + # vars: + # "my.dummy.var": "1" + # matchFeatures: + # - feature: cpu.cpuid + # matchExpressions: {} + # + # - name: "my rule using backrefs" + # labels: + # "vendor.io/my.backref.feature": "true" + # matchFeatures: + # - feature: rule.matched + # matchExpressions: + # vendor.io/my.kernel.feature: {op: IsTrue} + # my.dummy.var: {op: Gt, value: ["0"]} + # + # - name: "kconfig template rule" + # labelsTemplate: | + # {{ range .kernel.config }}kconfig-{{ .Name }}={{ .Value }} + # {{ end }} + # matchFeatures: + # - feature: kernel.config + # matchName: {op: In, value: ["SWAP", "X86", "ARM"]} +### + + metricsPort: 8081 + daemonsetAnnotations: {} + podSecurityContext: {} + # fsGroup: 2000 + + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ "ALL" ] + readOnlyRootFilesystem: true + runAsNonRoot: true + # runAsUser: 1000 + + serviceAccount: + # Specifies whether a service account should be created. + # We create this by default to make it easier for downstream users to apply PodSecurityPolicies. + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: + + rbac: + create: true + + # Allow users to mount the hostPath /usr/src, useful for RHCOS on s390x + # Does not work on systems without /usr/src AND a read-only /usr, such as Talos + mountUsrSrc: false + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + nodeSelector: {} + + tolerations: [] + + annotations: {} + + affinity: {} + + priorityClassName: "" + +topologyUpdater: + config: ### + ## key = node name, value = list of resources to be excluded. + ## use * to exclude from all nodes. + ## an example for how the exclude list should looks like + #excludeList: + # node1: [cpu] + # node2: [memory, example/deviceA] + # *: [hugepages-2Mi] +### + + enable: false + createCRDs: false + + serviceAccount: + create: true + annotations: {} + name: + rbac: + create: true + + metricsPort: 8081 + kubeletConfigPath: + kubeletPodResourcesSockPath: + updateInterval: 60s + watchNamespace: "*" + kubeletStateDir: /var/lib/kubelet + + podSecurityContext: {} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ "ALL" ] + readOnlyRootFilesystem: true + runAsUser: 0 + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + nodeSelector: {} + tolerations: [] + annotations: {} + daemonsetAnnotations: {} + affinity: {} + podSetFingerprint: true + +gc: + enable: true + replicaCount: 1 + + serviceAccount: + create: true + annotations: {} + name: + rbac: + create: true + + interval: 1h + + podSecurityContext: {} + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + metricsPort: 8081 + + nodeSelector: {} + tolerations: [] + annotations: {} + deploymentAnnotations: {} + affinity: {} + +# Optionally use encryption for worker <--> master comms +# TODO: verify hostname is not yet supported +# +# If you do not enable certManager (and have it installed) you will +# need to manually, or otherwise, provision the TLS certs as secrets +tls: + enable: false + certManager: false + +prometheus: + enable: false + labels: {} diff --git a/sriov-network-operator-chart/templates.obscpio b/sriov-network-operator-chart/templates.obscpio deleted file mode 100644 index 036de0ba4fc00771549e1ace83e428a12c4e5b298880775a34aa9d7ac9cdf305..0000000000000000000000000000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28160 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≧!=j#$NoXL4#;_C!oL87XR(g;EO?zKN-MX zYOz}i+%-V=2z0+3)Ee9x(4<9ep+$vMkiuz#!M#>n7=>a`>(E3zC1`O8ss#Gjgof^{ zgWgNY=wMC?Ku^whI{T30H}~m3C(eYgdeHyR)-nAloiP zwwFcbB*@-`fjvdOu{H5;W9v=-q`SA%-myBju%R@R9lpcbyHiZn?o@DerNJJwdmjxD zze!u{bz6|HmXL#Aak<`gtl#*QTfZLfP;DQpD`8uEgt$vx>=}T8LHtLelWWnoTBWUaXhL?{)at|zQ5L|nPW$Hrr1YGB>LCC2_3kGj z$$NWKHbJn)qS zE&{ev^zD|3AE^LrV#_AvEMyb%lf`y$iyJ4yqrOV(r_F+N^9=_h>r>3Y{p$4xUQes$ z80a%*!>6z=xrex~IyF}3#)I1hZO*9h5^Y6TFq5%PQ9Y>SOfxxxPqq)#G%Yr)k9JGW zbklrCYIcfK*U&{>(BE+myTnl>7Bu?k&c{pKK)Gf0MxA(Qa1fty;@zi`qnwUm)k!iH z5WPbt5GoKM+kJ{Uo(nOiX6++RsR_4$kEsU=&eFNIV^bBOD8R^nL4m0dDuVNF!3mKu zFQdYqJ9p_+9B0WQwEF_bzr?Y_;h114*iE6hm(AMI3}@)FQjtIcKaMU|L@HD)p1CoO zpHUbIr^)CXbfObR#4Box50Y1zo)%1{;5YFHJ8ivJ(k~PCDv;9mRoJicsi>>xVkmT+ zq_}^-$xaDQI3zJ<0+f2*vk&h{sXi_KA!_^(<<5lFFsfjbHKPnEG(KhoQXUEj_K;>l zyvbtGEQ{Gzq9dWijj^)Sfz=rojZ!_!kF1}T{8Ht=KB&%rr_2tI&cEybjS~s0et&I4 zEjEloUU92z7bLi(7}jUrj4rptAVl0Ey%SV;6{o3&D@-U%=_YW*pTup!V{t_gGp)sk z)I#zmn~w_v(WJ6+QtL&5W63WWRat3b1PzSIU&Vr=b-3g;ZA_4WXGS!~vH-azi%x%_ z2U2)&C?SZyFNgDkCR4CV5lLeumJ^`j+$t7v7)IGVnNbbVq;N>eKjkVwR)E?RS3iWWxDA}JnYlK|&`K_8$eOGGHHHLe z29p`L66HUu`JV1tG2q zOM;=lWTMO~+9Z*i)L$=OtJUH$K9$@pk2j6{8}w4y+^*1vIG?CJe^6d|q!ukF^j8+d z1ysl*_;Y}wo|&{@eayNks;uEEtqnP1^KtXXn%4DMzH&qa6Kh|+ElG0E2H;9 ze=EnUcP16}z9@HOMd1-Umy(Hk3ta248O2^JE`{fAo3u42pViJ)9?c}&Ln|MmZCX<| zX*5kl#xfEApWGyoEqK)FUMJ(<^2DyEyBg)|r*M4_RgBW3PnLFS(uAX`wbWCkDP73q zT3Xb_dOj7kV9DQhS+~9_8%lw>%|FUV+6cEzbd5r+^xrYM1=F-_EDa&*m1VsQ-fQCCWJM+yq!`=P0 z;iG|Z2Y#keztc9&?YaTal1XeK4YS>p(lD1IX)HCH?IyXqZN}?F#Ot(rWRBw)hSkAA z$QE6vO{~7<5`AC=Hp`p>A(Op*5VAIjXdJ{qq7Wb!L(-)#4hhR-P6KL)UCSnpSUAgy zd772Gqq3uy^H`}1!$A6sBRT@VCsBL0_ON$3+>evOzCK8)XbWp*o0Yu zLqqAYiasN57s;^5^1To{p5yJHt%qA{Xd@vX-P^oBV2X#kq=imeBFIp}J_RMDaUBbb zpvqp7KFW8hWw%8YZ^{r%Q_>65z_R}HC~8Dz@Od>uqn0fO#3h&!y^B34kA*r^5mEQ} zn~!5-Vq>*Yu{G9Xq-ObDg;8R)c>azux)^2gfyoaQF^?Cx0swzf zoXhG+goD@XB7OlOATEI6^mexT3`QZrJdKb=iQtMK73TS`+AaR4GMOb|*nfZ%6>Mic zO8p=t_G(~t;u`|Y zsc=9poC-Ff#IuQK^WR_BFO5)8nZ7*jEiGx_OB@kJ$yn6s5@@ABt4 zF}m;xl*`f;qUA&!v9`IeumGtuBL77`7oGpdi!45q F`43Q8n*aa+ diff --git a/upgrade-controller-chart/templates.obscpio b/upgrade-controller-chart/templates.obscpio deleted file mode 100644 index c619dbc6961143b7d8de8e011c4c4f7de40271cf8df71cde346a23656836a5e0..0000000000000000000000000000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12800 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 diff --git a/upgrade-controller-chart/templates/NOTES.txt b/upgrade-controller-chart/templates/NOTES.txt new file mode 100644 index 0000000..473a0f4 diff --git a/upgrade-controller-chart/templates/_helpers.tpl b/upgrade-controller-chart/templates/_helpers.tpl new file mode 100644 index 0000000..892acbd --- /dev/null +++ b/upgrade-controller-chart/templates/_helpers.tpl @@ -0,0 +1,83 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "upgrade-controller.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "upgrade-controller.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "upgrade-controller.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "upgrade-controller.labels" -}} +helm.sh/chart: {{ include "upgrade-controller.chart" . }} +{{ include "upgrade-controller.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "upgrade-controller.selectorLabels" -}} +app.kubernetes.io/name: {{ include "upgrade-controller.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "upgrade-controller.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "upgrade-controller.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Webhook service name +*/}} +{{- define "upgrade-controller.webhookServiceName" -}} +{{ .Release.Name }}-webhook +{{- end }} + +{{/* +Certificate issuer name +*/}} +{{- define "upgrade-controller.certificateIssuer" -}} +{{ .Release.Name }}-self-signed-issuer +{{- end }} + +{{/* +Certificate name +*/}} +{{- define "upgrade-controller.certificate" -}} +{{ .Release.Name }}-serving-cert +{{- end }} diff --git a/upgrade-controller-chart/templates/certificate.yaml b/upgrade-controller-chart/templates/certificate.yaml new file mode 100644 index 0000000..6805cdd --- /dev/null +++ b/upgrade-controller-chart/templates/certificate.yaml @@ -0,0 +1,28 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} + name: {{ include "upgrade-controller.certificateIssuer" . }} + namespace: {{ .Release.Namespace }} +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} + app.kubernetes.io/component: certificate + name: {{ include "upgrade-controller.certificate" . }} + namespace: {{ .Release.Namespace }} +spec: + dnsNames: + - {{ include "upgrade-controller.webhookServiceName" . }}.{{ .Release.Namespace }}.svc + - {{ include "upgrade-controller.webhookServiceName" . }}.{{ .Release.Namespace }}.svc.cluster.local + issuerRef: + kind: Issuer + name: {{ include "upgrade-controller.certificateIssuer" . }} + {{- with first .Values.volumes }} + secretName: {{ .secret.secretName }} + {{- end }} diff --git a/upgrade-controller-chart/templates/clusterrole.yaml b/upgrade-controller-chart/templates/clusterrole.yaml new file mode 100644 index 0000000..8e9c6e7 --- /dev/null +++ b/upgrade-controller-chart/templates/clusterrole.yaml @@ -0,0 +1,114 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "upgrade-controller.fullname" . }} + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - nodes + verbs: + - list + - watch +- apiGroups: + - "" + resources: + - secrets + verbs: + - create + - delete + - get + - list + - watch +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get +- apiGroups: + - batch + resources: + - jobs + verbs: + - create + - get + - list + - watch +- apiGroups: + - batch + resources: + - jobs/status + verbs: + - get +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - helm.cattle.io + resources: + - helmcharts + verbs: + - create + - get + - list + - update + - watch +- apiGroups: + - helm.cattle.io + resources: + - helmcharts/status + verbs: + - get +- apiGroups: + - lifecycle.suse.com + resources: + - releasemanifests + verbs: + - create + - get + - list + - watch +- apiGroups: + - lifecycle.suse.com + resources: + - upgradeplans + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - lifecycle.suse.com + resources: + - upgradeplans/finalizers + verbs: + - update +- apiGroups: + - lifecycle.suse.com + resources: + - upgradeplans/status + verbs: + - get + - patch + - update +- apiGroups: + - upgrade.cattle.io + resources: + - plans + verbs: + - create + - delete + - get + - list + - watch diff --git a/upgrade-controller-chart/templates/clusterrole_binding.yaml b/upgrade-controller-chart/templates/clusterrole_binding.yaml new file mode 100644 index 0000000..5ef4e17 --- /dev/null +++ b/upgrade-controller-chart/templates/clusterrole_binding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "upgrade-controller.fullname" . }} + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "upgrade-controller.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ include "upgrade-controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/upgrade-controller-chart/templates/deployment.yaml b/upgrade-controller-chart/templates/deployment.yaml new file mode 100644 index 0000000..4488189 --- /dev/null +++ b/upgrade-controller-chart/templates/deployment.yaml @@ -0,0 +1,85 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "upgrade-controller.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "upgrade-controller.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "upgrade-controller.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "upgrade-controller.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - --leader-elect + - --health-probe-bind-address=:8081 + env: + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: RELEASE_MANIFEST_IMAGE + value: {{ .Values.env.releaseManifest.image }} + - name: KUBECTL_IMAGE + value: {{ .Values.env.kubectl.image }} + - name: KUBECTL_VERSION + value: {{ .Values.env.kubectl.version }} + - name: SERVICE_ACCOUNT_NAME + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + ports: + - name: {{ .Values.webhookService.name }} + containerPort: {{ .Values.webhookService.targetPort }} + protocol: TCP + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/upgrade-controller-chart/templates/leader_election_role.yaml b/upgrade-controller-chart/templates/leader_election_role.yaml new file mode 100644 index 0000000..acebc4f --- /dev/null +++ b/upgrade-controller-chart/templates/leader_election_role.yaml @@ -0,0 +1,40 @@ +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "upgrade-controller.fullname" . }}-leader-election + namespace: {{ .Release.Namespace }} + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/upgrade-controller-chart/templates/leader_election_role_binding.yaml b/upgrade-controller-chart/templates/leader_election_role_binding.yaml new file mode 100644 index 0000000..1a0e7d2 --- /dev/null +++ b/upgrade-controller-chart/templates/leader_election_role_binding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "upgrade-controller.fullname" . }}-leader-election + namespace: {{ .Release.Namespace }} + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "upgrade-controller.fullname" . }}-leader-election +subjects: +- kind: ServiceAccount + name: {{ include "upgrade-controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/upgrade-controller-chart/templates/serviceaccount.yaml b/upgrade-controller-chart/templates/serviceaccount.yaml new file mode 100644 index 0000000..f860a12 --- /dev/null +++ b/upgrade-controller-chart/templates/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "upgrade-controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/upgrade-controller-chart/templates/validating_webhook_configuration.yaml b/upgrade-controller-chart/templates/validating_webhook_configuration.yaml new file mode 100644 index 0000000..43ad580 --- /dev/null +++ b/upgrade-controller-chart/templates/validating_webhook_configuration.yaml @@ -0,0 +1,29 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: {{ include "upgrade-controller.fullname" . }}-validating-webhook-configuration + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} + annotations: + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "upgrade-controller.certificate" . }} +webhooks: + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "upgrade-controller.webhookServiceName" . }} + namespace: {{ .Release.Namespace }} + path: /validate-lifecycle-suse-com-v1alpha1-upgradeplan + failurePolicy: Fail + name: upgrade-plan-policy.suse.com + rules: + - apiGroups: + - lifecycle.suse.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - upgradeplans + sideEffects: None diff --git a/upgrade-controller-chart/templates/webhook_service.yaml b/upgrade-controller-chart/templates/webhook_service.yaml new file mode 100644 index 0000000..f8b48fe --- /dev/null +++ b/upgrade-controller-chart/templates/webhook_service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "upgrade-controller.webhookServiceName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} +spec: + type: {{ .Values.webhookService.type }} + ports: + - port: {{ .Values.webhookService.port }} + targetPort: {{ .Values.webhookService.targetPort }} + protocol: TCP + selector: + {{- include "upgrade-controller.selectorLabels" . | nindent 4 }}