mirror of
https://github.com/clastix/kamaji.git
synced 2026-02-27 00:03:50 +00:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c57c07693f | ||
|
|
fa560446f1 | ||
|
|
6ba4b4abac | ||
|
|
45d0869b91 | ||
|
|
511a08889e | ||
|
|
6217f2ca25 | ||
|
|
e51df96777 | ||
|
|
f235689bf5 | ||
|
|
aed48e1bf0 | ||
|
|
0037e6e689 | ||
|
|
56071434e6 | ||
|
|
2d39c9ab0b | ||
|
|
b2fbb52361 | ||
|
|
a2236e76cf | ||
|
|
b1ea75f9c0 | ||
|
|
6aea80ce45 | ||
|
|
5ebe123994 | ||
|
|
d1910cd389 | ||
|
|
203e168397 | ||
|
|
b29a79da36 | ||
|
|
5ec586960f | ||
|
|
90aef60c18 | ||
|
|
9ce8da0b37 | ||
|
|
9d73905965 | ||
|
|
32383be1d0 | ||
|
|
6ffd6bbdfd | ||
|
|
b7169215ae | ||
|
|
f8a0206785 | ||
|
|
1d548665ee | ||
|
|
37616865b4 | ||
|
|
d31b3eab0a | ||
|
|
28a098af21 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -32,5 +32,8 @@ bin
|
||||
**/*.key
|
||||
**/*.pem
|
||||
**/*.csr
|
||||
**/server-csr.json
|
||||
.DS_Store
|
||||
|
||||
**/server-csr.json
|
||||
!deploy/kine/mysql/server-csr.json
|
||||
!deploy/kine/nats/server-csr.json
|
||||
|
||||
@@ -37,6 +37,8 @@ linters:
|
||||
- funlen
|
||||
- dupl
|
||||
- cyclop
|
||||
- gocognit
|
||||
- nestif
|
||||
# deprecated linters
|
||||
- deadcode
|
||||
- golint
|
||||
|
||||
@@ -7,12 +7,15 @@ Feel free to open a Pull-Request to get yours listed.
|
||||
|
||||
| Type | Name | Since | Website | Use-Case |
|
||||
|:-|:-|:-|:-|:-|
|
||||
| End-user | Sicuro Tech Lab | 2024 | [link](https://sicurotechlab.it/) | Sicuro Tech Lab offers cloud infrastructure for Web Agencies and uses kamaji to provide managed k8s services. |
|
||||
| R&D | TIM | 2024 | [link](https://www.gruppotim.it) | TIM is an Italian telecommunications company using Kamaji for experimental research and development purposes. |
|
||||
| End-user | KINX | 2024 | [link](https://kinx.net/?lang=en) | KINX is an Internet infrastructure service provider and will use kamaji for its new [Managed Kubernetes Service](https://kinx.net/service/cloud/kubernetes/intro/?lang=en). |
|
||||
| End-user | sevensphere | 2023 | [link](https://www.sevensphere.io) | Sevensphere provides consulting services for end-user companies / cloud providers and uses Kamaji for designing cloud/on-premises Kubernetes-as-a-Service platform. |
|
||||
| Vendor | Ænix | 2023 | [link](https://aenix.io/) | Ænix provides consulting services for cloud providers and uses Kamaji for running Kubernetes-as-a-Service in free PaaS platform [Cozystack](https://cozystack.io). |
|
||||
| Vendor | Netsons | 2023 | [link](https://www.netsons.com) | Netsons is an Italian hosting and cloud provider and uses Kamaji in its [Managed Kubernetes](https://www.netsons.com/kubernetes) offering. |
|
||||
| Vendor | Aknostic | 2023 | [link](https://aknostic.com) | Aknostic is a cloud-native consultancy company using Kamaji to build a Kubernetes based PaaS. |
|
||||
|
||||
|
||||
### Adopter Types
|
||||
|
||||
**End-user**: The organization runs Kamaji in production in some way.
|
||||
@@ -20,3 +23,5 @@ Feel free to open a Pull-Request to get yours listed.
|
||||
**Integration**: The organization has a product that integrates with Kamaji, but does not contain Kamaji.
|
||||
|
||||
**Vendor**: The organization packages Kamaji in their product and sells it as part of their product.
|
||||
|
||||
**R&D**: Company that exploring innovative technologies and solutions for research and development purposes.
|
||||
|
||||
18
Makefile
18
Makefile
@@ -3,7 +3,7 @@
|
||||
# To re-generate a bundle for another specific version without changing the standard setup, you can:
|
||||
# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2)
|
||||
# - use environment variables to overwrite this value (e.g export VERSION=0.0.2)
|
||||
VERSION ?= 0.5.0
|
||||
VERSION ?= 0.6.1
|
||||
|
||||
# CHANNELS define the bundle channels used in the bundle.
|
||||
# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable")
|
||||
@@ -132,7 +132,11 @@ datastore-postgres:
|
||||
$(MAKE) NAME=gold _datastore-postgres
|
||||
|
||||
_datastore-etcd:
|
||||
$(HELM) upgrade --install etcd-$(NAME) clastix/kamaji-etcd --create-namespace -n etcd-system --set datastore.enabled=true
|
||||
$(HELM) upgrade --install etcd-$(NAME) clastix/kamaji-etcd --create-namespace -n etcd-system --set datastore.enabled=true --set fullnameOverride=etcd-$(NAME)
|
||||
|
||||
_datastore-nats:
|
||||
$(MAKE) NAME=$(NAME) NAMESPACE=nats-system -C deploy/kine/nats nats
|
||||
kubectl apply -f $(shell pwd)/config/samples/kamaji_v1alpha1_datastore_nats_$(NAME).yaml
|
||||
|
||||
datastore-etcd: helm
|
||||
$(HELM) repo add clastix https://clastix.github.io/charts
|
||||
@@ -141,7 +145,15 @@ datastore-etcd: helm
|
||||
$(MAKE) NAME=silver _datastore-etcd
|
||||
$(MAKE) NAME=gold _datastore-etcd
|
||||
|
||||
datastores: datastore-mysql datastore-etcd datastore-postgres ## Install all Kamaji DataStores with multiple drivers, and different tiers.
|
||||
datastore-nats: helm
|
||||
$(HELM) repo add nats https://nats-io.github.io/k8s/helm/charts/
|
||||
$(HELM) repo update
|
||||
$(MAKE) NAME=bronze _datastore-nats
|
||||
$(MAKE) NAME=silver _datastore-nats
|
||||
$(MAKE) NAME=gold _datastore-nats
|
||||
$(MAKE) NAME=notls _datastore-nats
|
||||
|
||||
datastores: datastore-mysql datastore-etcd datastore-postgres datastore-nats ## Install all Kamaji DataStores with multiple drivers, and different tiers.
|
||||
|
||||
##@ Build
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ The state is managed by the `Datastore` API, a cluster-scoped resource which can
|
||||
- **Managing core addons**: Kamaji allows configuring automatically `kube-proxy`, `CoreDNS`, and `konnectivity`, with automatic remediation in case of user errors (e.g.: deleting the `CoreDNS` deployment).
|
||||
- **Auto Healing**: the `TenantControlPlane` objects in the management cluster are tracked by Kamaji, in case of deletion of those, everything is created in an idempotent way.
|
||||
- **Datastore multi-tenancy**: optionally, Kamaji allows running multiple Control Planes on the same _Datastore_ instance leveraging on the multi-tenancy of each driver, decreasing operations and optimizing costs.
|
||||
- **Overcoming `etcd` limitations**: optionally, Kamaji allows using a different _Datastore_ thanks to [`kine`](https://github.com/k3s-io/kine) by supporting `MySQL` or `PostgreSQL` as an alternative.
|
||||
- **Overcoming `etcd` limitations**: optionally, Kamaji allows using a different _Datastore_ thanks to [`kine`](https://github.com/k3s-io/kine) by supporting `MySQL`, `PostgreSQL`, or `NATS` as an alternative.
|
||||
- **Simplifying mixed-networks setup**: thanks to [`Konnectivity`](https://kubernetes.io/docs/tasks/extend-kubernetes/setup-konnectivity/),
|
||||
the Tenant Control Plane is connected to the worker nodes hosted in a different network, overcoming the no-NAT availability when dealing with nodes with a non routable IP address
|
||||
(e.g.: worker nodes in a different infrastructure).
|
||||
@@ -104,7 +104,7 @@ Since Kamaji is just focusing on the Control Plane a [Kamaji's Cluster API Contr
|
||||
- [x] Dynamic address on Load Balancer
|
||||
- [x] Zero Downtime Tenant Control Plane upgrade
|
||||
- [x] [Join worker nodes from anywhere thanks to Konnectivity](https://kamaji.clastix.io/concepts/#konnectivity)
|
||||
- [x] [Alternative datastore MySQL and PostgreSQL](https://kamaji.clastix.io/guides/alternative-datastore/)
|
||||
- [x] [Alternative datastore MySQL, PostgreSQL, NATS](https://kamaji.clastix.io/guides/alternative-datastore/)
|
||||
- [x] [Pool of multiple datastores](https://kamaji.clastix.io/concepts/#datastores)
|
||||
- [x] [Seamless migration between datastores](https://kamaji.clastix.io/guides/datastore-migration/)
|
||||
- [ ] Automatic assignment to a datastore
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +kubebuilder:validation:Enum=etcd;MySQL;PostgreSQL
|
||||
// +kubebuilder:validation:Enum=etcd;MySQL;PostgreSQL;NATS
|
||||
|
||||
type Driver string
|
||||
|
||||
@@ -16,6 +16,7 @@ var (
|
||||
EtcdDriver Driver = "etcd"
|
||||
KineMySQLDriver Driver = "MySQL"
|
||||
KinePostgreSQLDriver Driver = "PostgreSQL"
|
||||
KineNatsDriver Driver = "NATS"
|
||||
)
|
||||
|
||||
// +kubebuilder:validation:MinItems=1
|
||||
@@ -33,7 +34,8 @@ type DataStoreSpec struct {
|
||||
// This value is optional.
|
||||
BasicAuth *BasicAuth `json:"basicAuth,omitempty"`
|
||||
// Defines the TLS/SSL configuration required to connect to the data store in a secure way.
|
||||
TLSConfig TLSConfig `json:"tlsConfig"`
|
||||
// This value is optional.
|
||||
TLSConfig *TLSConfig `json:"tlsConfig,omitempty"`
|
||||
}
|
||||
|
||||
// TLSConfig contains the information used to connect to the data store using a secured connection.
|
||||
@@ -42,7 +44,7 @@ type TLSConfig struct {
|
||||
// The key reference is required since etcd authentication is based on certificates, and Kamaji is responsible in creating this.
|
||||
CertificateAuthority CertKeyPair `json:"certificateAuthority"`
|
||||
// Specifies the SSL/TLS key and private key pair used to connect to the data store.
|
||||
ClientCertificate ClientCertificate `json:"clientCertificate"`
|
||||
ClientCertificate *ClientCertificate `json:"clientCertificate,omitempty"`
|
||||
}
|
||||
|
||||
type ClientCertificate struct {
|
||||
|
||||
@@ -43,20 +43,22 @@ func (d *DatastoreUsedSecret) ExtractValue() client.IndexerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
if ds.Spec.TLSConfig.CertificateAuthority.Certificate.SecretRef != nil {
|
||||
res = append(res, d.namespacedName(*ds.Spec.TLSConfig.CertificateAuthority.Certificate.SecretRef))
|
||||
}
|
||||
if ds.Spec.TLSConfig != nil {
|
||||
if ds.Spec.TLSConfig.CertificateAuthority.Certificate.SecretRef != nil {
|
||||
res = append(res, d.namespacedName(*ds.Spec.TLSConfig.CertificateAuthority.Certificate.SecretRef))
|
||||
}
|
||||
|
||||
if ds.Spec.TLSConfig.CertificateAuthority.PrivateKey != nil && ds.Spec.TLSConfig.CertificateAuthority.PrivateKey.SecretRef != nil {
|
||||
res = append(res, d.namespacedName(*ds.Spec.TLSConfig.CertificateAuthority.PrivateKey.SecretRef))
|
||||
}
|
||||
if ds.Spec.TLSConfig.CertificateAuthority.PrivateKey != nil && ds.Spec.TLSConfig.CertificateAuthority.PrivateKey.SecretRef != nil {
|
||||
res = append(res, d.namespacedName(*ds.Spec.TLSConfig.CertificateAuthority.PrivateKey.SecretRef))
|
||||
}
|
||||
|
||||
if ds.Spec.TLSConfig.ClientCertificate.Certificate.SecretRef != nil {
|
||||
res = append(res, d.namespacedName(*ds.Spec.TLSConfig.ClientCertificate.Certificate.SecretRef))
|
||||
}
|
||||
if ds.Spec.TLSConfig.ClientCertificate.Certificate.SecretRef != nil {
|
||||
res = append(res, d.namespacedName(*ds.Spec.TLSConfig.ClientCertificate.Certificate.SecretRef))
|
||||
}
|
||||
|
||||
if ds.Spec.TLSConfig.ClientCertificate.PrivateKey.SecretRef != nil {
|
||||
res = append(res, d.namespacedName(*ds.Spec.TLSConfig.ClientCertificate.PrivateKey.SecretRef))
|
||||
if ds.Spec.TLSConfig.ClientCertificate.PrivateKey.SecretRef != nil {
|
||||
res = append(res, d.namespacedName(*ds.Spec.TLSConfig.ClientCertificate.PrivateKey.SecretRef))
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
|
||||
@@ -141,8 +141,9 @@ type DeploymentSpec struct {
|
||||
// such as kube-apiserver, controller-manager, and scheduler. WARNING - This option
|
||||
// can override existing parameters and cause components to misbehave in unxpected ways.
|
||||
// Only modify if you know what you are doing.
|
||||
ExtraArgs *ControlPlaneExtraArgs `json:"extraArgs,omitempty"`
|
||||
AdditionalMetadata AdditionalMetadata `json:"additionalMetadata,omitempty"`
|
||||
ExtraArgs *ControlPlaneExtraArgs `json:"extraArgs,omitempty"`
|
||||
AdditionalMetadata AdditionalMetadata `json:"additionalMetadata,omitempty"`
|
||||
PodAdditionalMetadata AdditionalMetadata `json:"podAdditionalMetadata,omitempty"`
|
||||
// AdditionalInitContainers allows adding additional init containers to the Control Plane deployment.
|
||||
AdditionalInitContainers []corev1.Container `json:"additionalInitContainers,omitempty"`
|
||||
// AdditionalContainers allows adding additional containers to the Control Plane deployment.
|
||||
@@ -152,6 +153,9 @@ type DeploymentSpec struct {
|
||||
// AdditionalVolumeMounts allows to mount an additional volume into each component of the Control Plane
|
||||
// (kube-apiserver, controller-manager, and scheduler).
|
||||
AdditionalVolumeMounts *AdditionalVolumeMounts `json:"additionalVolumeMounts,omitempty"`
|
||||
// +kubebuilder:default="default"
|
||||
// ServiceAccountName allows to specify the service account to be mounted to the pods of the Control plane deployment
|
||||
ServiceAccountName string `json:"serviceAccountName,omitempty"`
|
||||
}
|
||||
|
||||
// AdditionalVolumeMounts allows mounting additional volumes to the Control Plane components.
|
||||
@@ -216,8 +220,12 @@ type KonnectivityAgentSpec struct {
|
||||
Image string `json:"image,omitempty"`
|
||||
// Version for Konnectivity agent.
|
||||
// +kubebuilder:default=v0.0.32
|
||||
Version string `json:"version,omitempty"`
|
||||
ExtraArgs ExtraArgs `json:"extraArgs,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
// Tolerations for the deployed agent.
|
||||
// Can be customized to start the konnectivity-agent even if the nodes are not ready or tainted.
|
||||
// +kubebuilder:default={{key: "CriticalAddonsOnly", operator: "Exists"}}
|
||||
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
|
||||
ExtraArgs ExtraArgs `json:"extraArgs,omitempty"`
|
||||
}
|
||||
|
||||
// KonnectivitySpec defines the spec for Konnectivity.
|
||||
@@ -258,7 +266,7 @@ type TenantControlPlaneSpec struct {
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:subresource:scale:specpath=.spec.controlPlane.deployment.replicas,statuspath=.status.kubernetesResources.deployment.replicas,selectorpath=.status.kubernetesResources.deployment.selector
|
||||
// +kubebuilder:resource:shortName=tcp
|
||||
// +kubebuilder:resource:categories=kamaji,shortName=tcp
|
||||
// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".spec.kubernetes.version",description="Kubernetes version"
|
||||
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.kubernetesResources.version.status",description="Status"
|
||||
// +kubebuilder:printcolumn:name="Control-Plane endpoint",type="string",JSONPath=".status.controlPlaneEndpoint",description="Tenant Control Plane Endpoint (API server)"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
@@ -526,7 +525,11 @@ func (in *DataStoreSpec) DeepCopyInto(out *DataStoreSpec) {
|
||||
*out = new(BasicAuth)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
in.TLSConfig.DeepCopyInto(&out.TLSConfig)
|
||||
if in.TLSConfig != nil {
|
||||
in, out := &in.TLSConfig, &out.TLSConfig
|
||||
*out = new(TLSConfig)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataStoreSpec.
|
||||
@@ -578,6 +581,11 @@ func (in *DatastoreUsedSecret) DeepCopy() *DatastoreUsedSecret {
|
||||
func (in *DeploymentSpec) DeepCopyInto(out *DeploymentSpec) {
|
||||
*out = *in
|
||||
out.RegistrySettings = in.RegistrySettings
|
||||
if in.Replicas != nil {
|
||||
in, out := &in.Replicas, &out.Replicas
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
if in.NodeSelector != nil {
|
||||
in, out := &in.NodeSelector, &out.NodeSelector
|
||||
*out = make(map[string]string, len(*in))
|
||||
@@ -616,6 +624,7 @@ func (in *DeploymentSpec) DeepCopyInto(out *DeploymentSpec) {
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
in.AdditionalMetadata.DeepCopyInto(&out.AdditionalMetadata)
|
||||
in.PodAdditionalMetadata.DeepCopyInto(&out.PodAdditionalMetadata)
|
||||
if in.AdditionalInitContainers != nil {
|
||||
in, out := &in.AdditionalInitContainers, &out.AdditionalInitContainers
|
||||
*out = make([]v1.Container, len(*in))
|
||||
@@ -775,6 +784,13 @@ func (in *IngressSpec) DeepCopy() *IngressSpec {
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KonnectivityAgentSpec) DeepCopyInto(out *KonnectivityAgentSpec) {
|
||||
*out = *in
|
||||
if in.Tolerations != nil {
|
||||
in, out := &in.Tolerations, &out.Tolerations
|
||||
*out = make([]v1.Toleration, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.ExtraArgs != nil {
|
||||
in, out := &in.ExtraArgs, &out.ExtraArgs
|
||||
*out = make(ExtraArgs, len(*in))
|
||||
@@ -1196,7 +1212,11 @@ func (in *StorageStatus) DeepCopy() *StorageStatus {
|
||||
func (in *TLSConfig) DeepCopyInto(out *TLSConfig) {
|
||||
*out = *in
|
||||
in.CertificateAuthority.DeepCopyInto(&out.CertificateAuthority)
|
||||
in.ClientCertificate.DeepCopyInto(&out.ClientCertificate)
|
||||
if in.ClientCertificate != nil {
|
||||
in, out := &in.ClientCertificate, &out.ClientCertificate
|
||||
*out = new(ClientCertificate)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSConfig.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
apiVersion: v2
|
||||
appVersion: v0.5.0
|
||||
appVersion: v0.6.1
|
||||
description: Kamaji is the Hosted Control Plane Manager for Kubernetes.
|
||||
home: https://github.com/clastix/kamaji
|
||||
icon: https://github.com/clastix/kamaji/raw/master/assets/logo-colored.png
|
||||
@@ -17,7 +17,7 @@ name: kamaji
|
||||
sources:
|
||||
- https://github.com/clastix/kamaji
|
||||
type: application
|
||||
version: 0.15.2
|
||||
version: 0.16.1
|
||||
annotations:
|
||||
catalog.cattle.io/certified: partner
|
||||
catalog.cattle.io/release-name: kamaji
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# kamaji
|
||||
|
||||
  
|
||||
  
|
||||
|
||||
Kamaji is the Hosted Control Plane Manager for Kubernetes.
|
||||
|
||||
@@ -77,7 +77,7 @@ Here the values you can override:
|
||||
| datastore.driver | string | `"etcd"` | (string) The Kamaji Datastore driver, supported: etcd, MySQL, PostgreSQL (defaults=etcd). |
|
||||
| datastore.enabled | bool | `true` | (bool) Enable the Kamaji Datastore creation (default=true) |
|
||||
| datastore.endpoints | list | `[]` | (array) List of endpoints of the selected Datastore. When letting the Chart install the etcd datastore, this field is populated automatically. |
|
||||
| datastore.nameOverride | string | `nil` | The Datastore name override, if empty and enabled=true defaults to `default`, if enabled=false, this is the name of the Datastore to connect to. |
|
||||
| datastore.nameOverride | string | `nil` | The Datastore name override, if empty and enabled=true defaults to `default`, if enabled=false, this is the name of the Datastore to connect to. |
|
||||
| datastore.tlsConfig.certificateAuthority.certificate.keyPath | string | `nil` | Key of the Secret which contains the content of the certificate. |
|
||||
| datastore.tlsConfig.certificateAuthority.certificate.name | string | `nil` | Name of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore. |
|
||||
| datastore.tlsConfig.certificateAuthority.certificate.namespace | string | `nil` | Namespace of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore. |
|
||||
@@ -90,6 +90,7 @@ Here the values you can override:
|
||||
| datastore.tlsConfig.clientCertificate.privateKey.keyPath | string | `nil` | Key of the Secret which contains the content of the private key. |
|
||||
| datastore.tlsConfig.clientCertificate.privateKey.name | string | `nil` | Name of the Secret containing the client certificate private key required to establish the mandatory SSL/TLS connection to the datastore. |
|
||||
| datastore.tlsConfig.clientCertificate.privateKey.namespace | string | `nil` | Namespace of the Secret containing the client certificate private key required to establish the mandatory SSL/TLS connection to the datastore. |
|
||||
| datastore.tlsConfig.enabled | bool | `true` | |
|
||||
| etcd.compactionInterval | int | `0` | ETCD Compaction interval (e.g. "5m0s"). (default: "0" (disabled)) |
|
||||
| etcd.deploy | bool | `true` | Install an etcd with enabled multi-tenancy along with Kamaji |
|
||||
| etcd.image | object | `{"pullPolicy":"IfNotPresent","repository":"quay.io/coreos/etcd","tag":"v3.5.6"}` | Install specific etcd image |
|
||||
|
||||
@@ -71,10 +71,12 @@ spec:
|
||||
minLength: 1
|
||||
type: string
|
||||
name:
|
||||
description: name is unique within a namespace to reference a secret resource.
|
||||
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.
|
||||
description: namespace defines the space within which
|
||||
the secret name must be unique.
|
||||
type: string
|
||||
required:
|
||||
- keyPath
|
||||
@@ -98,10 +100,12 @@ spec:
|
||||
minLength: 1
|
||||
type: string
|
||||
name:
|
||||
description: name is unique within a namespace to reference a secret resource.
|
||||
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.
|
||||
description: namespace defines the space within which
|
||||
the secret name must be unique.
|
||||
type: string
|
||||
required:
|
||||
- keyPath
|
||||
@@ -118,6 +122,7 @@ spec:
|
||||
- etcd
|
||||
- MySQL
|
||||
- PostgreSQL
|
||||
- NATS
|
||||
type: string
|
||||
endpoints:
|
||||
description: |-
|
||||
@@ -128,7 +133,9 @@ spec:
|
||||
minItems: 1
|
||||
type: array
|
||||
tlsConfig:
|
||||
description: Defines the TLS/SSL configuration required to connect to the data store in a secure way.
|
||||
description: |-
|
||||
Defines the TLS/SSL configuration required to connect to the data store in a secure way.
|
||||
This value is optional.
|
||||
properties:
|
||||
certificateAuthority:
|
||||
description: |-
|
||||
@@ -152,10 +159,12 @@ spec:
|
||||
minLength: 1
|
||||
type: string
|
||||
name:
|
||||
description: name is unique within a namespace to reference a secret resource.
|
||||
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.
|
||||
description: namespace defines the space within which
|
||||
the secret name must be unique.
|
||||
type: string
|
||||
required:
|
||||
- keyPath
|
||||
@@ -179,10 +188,12 @@ spec:
|
||||
minLength: 1
|
||||
type: string
|
||||
name:
|
||||
description: name is unique within a namespace to reference a secret resource.
|
||||
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.
|
||||
description: namespace defines the space within which
|
||||
the secret name must be unique.
|
||||
type: string
|
||||
required:
|
||||
- keyPath
|
||||
@@ -193,7 +204,8 @@ spec:
|
||||
- certificate
|
||||
type: object
|
||||
clientCertificate:
|
||||
description: Specifies the SSL/TLS key and private key pair used to connect to the data store.
|
||||
description: Specifies the SSL/TLS key and private key pair used
|
||||
to connect to the data store.
|
||||
properties:
|
||||
certificate:
|
||||
properties:
|
||||
@@ -212,10 +224,12 @@ spec:
|
||||
minLength: 1
|
||||
type: string
|
||||
name:
|
||||
description: name is unique within a namespace to reference a secret resource.
|
||||
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.
|
||||
description: namespace defines the space within which
|
||||
the secret name must be unique.
|
||||
type: string
|
||||
required:
|
||||
- keyPath
|
||||
@@ -239,10 +253,12 @@ spec:
|
||||
minLength: 1
|
||||
type: string
|
||||
name:
|
||||
description: name is unique within a namespace to reference a secret resource.
|
||||
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.
|
||||
description: namespace defines the space within which
|
||||
the secret name must be unique.
|
||||
type: string
|
||||
required:
|
||||
- keyPath
|
||||
@@ -255,18 +271,17 @@ spec:
|
||||
type: object
|
||||
required:
|
||||
- certificateAuthority
|
||||
- clientCertificate
|
||||
type: object
|
||||
required:
|
||||
- driver
|
||||
- endpoints
|
||||
- tlsConfig
|
||||
type: object
|
||||
status:
|
||||
description: DataStoreStatus defines the observed state of DataStore.
|
||||
properties:
|
||||
usedBy:
|
||||
description: List of the Tenant Control Planes, namespaced named, using this data store.
|
||||
description: List of the Tenant Control Planes, namespaced named,
|
||||
using this data store.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,9 +20,14 @@ spec:
|
||||
secretReference:
|
||||
{{- .Values.datastore.basicAuth.passwordSecret | toYaml | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.datastore.tlsConfig.enabled }}
|
||||
tlsConfig:
|
||||
certificateAuthority:
|
||||
{{- include "datastore.certificateAuthority" . | indent 6 }}
|
||||
|
||||
{{- if .Values.datastore.tlsConfig.clientCertificate }}
|
||||
clientCertificate:
|
||||
{{- include "datastore.clientCertificate" . | indent 6 }}
|
||||
{{- end }}
|
||||
{{- end}}
|
||||
{{- end}}
|
||||
|
||||
@@ -60,7 +60,7 @@ etcd:
|
||||
# -- The custom annotations to add to the PVC
|
||||
customAnnotations: {}
|
||||
# volumeType: local
|
||||
|
||||
|
||||
# -- (array) Kubernetes affinity rules to apply to Kamaji etcd pods
|
||||
tolerations: []
|
||||
|
||||
@@ -162,7 +162,7 @@ loggingDevel:
|
||||
datastore:
|
||||
# -- (bool) Enable the Kamaji Datastore creation (default=true)
|
||||
enabled: true
|
||||
# -- (string) The Datastore name override, if empty and enabled=true defaults to `default`, if enabled=false, this is the name of the Datastore to connect to.
|
||||
# -- (string) The Datastore name override, if empty and enabled=true defaults to `default`, if enabled=false, this is the name of the Datastore to connect to.
|
||||
nameOverride:
|
||||
# -- (string) The Kamaji Datastore driver, supported: etcd, MySQL, PostgreSQL (defaults=etcd).
|
||||
driver: etcd
|
||||
@@ -184,6 +184,7 @@ datastore:
|
||||
# -- The Secret key where the data is stored.
|
||||
keyPath:
|
||||
tlsConfig:
|
||||
enabled: true
|
||||
certificateAuthority:
|
||||
certificate:
|
||||
# -- Name of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore.
|
||||
|
||||
@@ -175,7 +175,9 @@ func NewCmd(scheme *runtime.Scheme) *cobra.Command {
|
||||
handlers.Freeze{},
|
||||
},
|
||||
routes.TenantControlPlaneDefaults{}: {
|
||||
handlers.TenantControlPlaneDefaults{DefaultDatastore: datastore},
|
||||
handlers.TenantControlPlaneDefaults{
|
||||
DefaultDatastore: datastore,
|
||||
},
|
||||
},
|
||||
routes.TenantControlPlaneValidate{}: {
|
||||
handlers.TenantControlPlaneName{},
|
||||
@@ -192,6 +194,7 @@ func NewCmd(scheme *runtime.Scheme) *cobra.Command {
|
||||
Scheme: *mgr.GetScheme(),
|
||||
},
|
||||
},
|
||||
handlers.TenantControlPlaneServiceCIDR{},
|
||||
},
|
||||
routes.DataStoreValidate{}: {
|
||||
handlers.DataStoreValidation{Client: mgr.GetClient()},
|
||||
|
||||
@@ -121,6 +121,7 @@ spec:
|
||||
- etcd
|
||||
- MySQL
|
||||
- PostgreSQL
|
||||
- NATS
|
||||
type: string
|
||||
endpoints:
|
||||
description: |-
|
||||
@@ -131,8 +132,9 @@ spec:
|
||||
minItems: 1
|
||||
type: array
|
||||
tlsConfig:
|
||||
description: Defines the TLS/SSL configuration required to connect
|
||||
to the data store in a secure way.
|
||||
description: |-
|
||||
Defines the TLS/SSL configuration required to connect to the data store in a secure way.
|
||||
This value is optional.
|
||||
properties:
|
||||
certificateAuthority:
|
||||
description: |-
|
||||
@@ -268,12 +270,10 @@ spec:
|
||||
type: object
|
||||
required:
|
||||
- certificateAuthority
|
||||
- clientCertificate
|
||||
type: object
|
||||
required:
|
||||
- driver
|
||||
- endpoints
|
||||
- tlsConfig
|
||||
type: object
|
||||
status:
|
||||
description: DataStoreStatus defines the observed state of DataStore.
|
||||
|
||||
@@ -8,6 +8,8 @@ metadata:
|
||||
spec:
|
||||
group: kamaji.clastix.io
|
||||
names:
|
||||
categories:
|
||||
- kamaji
|
||||
kind: TenantControlPlane
|
||||
listKind: TenantControlPlaneList
|
||||
plural: tenantcontrolplanes
|
||||
@@ -109,6 +111,50 @@ spec:
|
||||
description: AgentImage defines the container image for
|
||||
Konnectivity's agent.
|
||||
type: string
|
||||
tolerations:
|
||||
default:
|
||||
- key: CriticalAddonsOnly
|
||||
operator: Exists
|
||||
description: |-
|
||||
Tolerations for the deployed agent.
|
||||
Can be customized to start the konnectivity-agent even if the nodes are not ready or tainted.
|
||||
items:
|
||||
description: |-
|
||||
The pod this Toleration is attached to tolerates any taint that matches
|
||||
the triple <key,value,effect> using the matching operator <operator>.
|
||||
properties:
|
||||
effect:
|
||||
description: |-
|
||||
Effect indicates the taint effect to match. Empty means match all taint effects.
|
||||
When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.
|
||||
type: string
|
||||
key:
|
||||
description: |-
|
||||
Key is the taint key that the toleration applies to. Empty means match all taint keys.
|
||||
If the key is empty, operator must be Exists; this combination means to match all values and all keys.
|
||||
type: string
|
||||
operator:
|
||||
description: |-
|
||||
Operator represents a key's relationship to the value.
|
||||
Valid operators are Exists and Equal. Defaults to Equal.
|
||||
Exists is equivalent to wildcard for value, so that a pod can
|
||||
tolerate all taints of a particular category.
|
||||
type: string
|
||||
tolerationSeconds:
|
||||
description: |-
|
||||
TolerationSeconds represents the period of time the toleration (which must be
|
||||
of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default,
|
||||
it is not set, which means tolerate the taint forever (do not evict). Zero and
|
||||
negative values will be treated as 0 (evict immediately) by the system.
|
||||
format: int64
|
||||
type: integer
|
||||
value:
|
||||
description: |-
|
||||
Value is the taint value the toleration matches to.
|
||||
If the operator is Exists, the value should be empty, otherwise just a regular string.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
version:
|
||||
default: v0.0.32
|
||||
description: Version for Konnectivity agent.
|
||||
@@ -301,10 +347,15 @@ spec:
|
||||
description: The key to select.
|
||||
type: string
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the ConfigMap
|
||||
@@ -367,10 +418,15 @@ spec:
|
||||
key.
|
||||
type: string
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the Secret
|
||||
@@ -404,10 +460,15 @@ spec:
|
||||
description: The ConfigMap to select from
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the ConfigMap
|
||||
@@ -423,10 +484,15 @@ spec:
|
||||
description: The Secret to select from
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the Secret must
|
||||
@@ -1727,10 +1793,15 @@ spec:
|
||||
description: The key to select.
|
||||
type: string
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the ConfigMap
|
||||
@@ -1793,10 +1864,15 @@ spec:
|
||||
key.
|
||||
type: string
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the Secret
|
||||
@@ -1830,10 +1906,15 @@ spec:
|
||||
description: The ConfigMap to select from
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the ConfigMap
|
||||
@@ -1849,10 +1930,15 @@ spec:
|
||||
description: The Secret to select from
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the Secret must
|
||||
@@ -3438,10 +3524,15 @@ spec:
|
||||
More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -3477,10 +3568,15 @@ spec:
|
||||
to OpenStack.
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -3547,10 +3643,15 @@ spec:
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: optional specify whether the ConfigMap
|
||||
@@ -3583,10 +3684,15 @@ spec:
|
||||
secret object contains more than one secret, all secret references are passed.
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -4068,10 +4174,15 @@ spec:
|
||||
scripts.
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -4263,10 +4374,15 @@ spec:
|
||||
target and initiator authentication
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -4531,10 +4647,15 @@ spec:
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: optional specify whether
|
||||
@@ -4670,10 +4791,15 @@ spec:
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: optional field specify whether
|
||||
@@ -4804,10 +4930,15 @@ spec:
|
||||
More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -4851,10 +4982,15 @@ spec:
|
||||
sensitive information. If this is not provided, Login operation will fail.
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -4971,10 +5107,15 @@ spec:
|
||||
credentials. If not specified, default values will be attempted.
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -5991,6 +6132,20 @@ spec:
|
||||
Selector which must match a node's labels for the pod to be scheduled on that node.
|
||||
More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
|
||||
type: object
|
||||
podAdditionalMetadata:
|
||||
description: AdditionalMetadata defines which additional metadata,
|
||||
such as labels and annotations, must be attached to the
|
||||
created resource.
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
registrySettings:
|
||||
default:
|
||||
apiServerImage: kube-apiserver
|
||||
@@ -6266,6 +6421,11 @@ spec:
|
||||
empty definition that uses the default runtime handler.
|
||||
More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class
|
||||
type: string
|
||||
serviceAccountName:
|
||||
default: default
|
||||
description: ServiceAccountName allows to specify the service
|
||||
account to be mounted to the pods of the Control plane deployment
|
||||
type: string
|
||||
strategy:
|
||||
default:
|
||||
rollingUpdate:
|
||||
|
||||
@@ -127,6 +127,7 @@ spec:
|
||||
- etcd
|
||||
- MySQL
|
||||
- PostgreSQL
|
||||
- NATS
|
||||
type: string
|
||||
endpoints:
|
||||
description: |-
|
||||
@@ -137,7 +138,9 @@ spec:
|
||||
minItems: 1
|
||||
type: array
|
||||
tlsConfig:
|
||||
description: Defines the TLS/SSL configuration required to connect to the data store in a secure way.
|
||||
description: |-
|
||||
Defines the TLS/SSL configuration required to connect to the data store in a secure way.
|
||||
This value is optional.
|
||||
properties:
|
||||
certificateAuthority:
|
||||
description: |-
|
||||
@@ -264,12 +267,10 @@ spec:
|
||||
type: object
|
||||
required:
|
||||
- certificateAuthority
|
||||
- clientCertificate
|
||||
type: object
|
||||
required:
|
||||
- driver
|
||||
- endpoints
|
||||
- tlsConfig
|
||||
type: object
|
||||
status:
|
||||
description: DataStoreStatus defines the observed state of DataStore.
|
||||
@@ -308,6 +309,8 @@ spec:
|
||||
- v1
|
||||
group: kamaji.clastix.io
|
||||
names:
|
||||
categories:
|
||||
- kamaji
|
||||
kind: TenantControlPlane
|
||||
listKind: TenantControlPlaneList
|
||||
plural: tenantcontrolplanes
|
||||
@@ -406,6 +409,50 @@ spec:
|
||||
default: registry.k8s.io/kas-network-proxy/proxy-agent
|
||||
description: AgentImage defines the container image for Konnectivity's agent.
|
||||
type: string
|
||||
tolerations:
|
||||
default:
|
||||
- key: CriticalAddonsOnly
|
||||
operator: Exists
|
||||
description: |-
|
||||
Tolerations for the deployed agent.
|
||||
Can be customized to start the konnectivity-agent even if the nodes are not ready or tainted.
|
||||
items:
|
||||
description: |-
|
||||
The pod this Toleration is attached to tolerates any taint that matches
|
||||
the triple <key,value,effect> using the matching operator <operator>.
|
||||
properties:
|
||||
effect:
|
||||
description: |-
|
||||
Effect indicates the taint effect to match. Empty means match all taint effects.
|
||||
When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.
|
||||
type: string
|
||||
key:
|
||||
description: |-
|
||||
Key is the taint key that the toleration applies to. Empty means match all taint keys.
|
||||
If the key is empty, operator must be Exists; this combination means to match all values and all keys.
|
||||
type: string
|
||||
operator:
|
||||
description: |-
|
||||
Operator represents a key's relationship to the value.
|
||||
Valid operators are Exists and Equal. Defaults to Equal.
|
||||
Exists is equivalent to wildcard for value, so that a pod can
|
||||
tolerate all taints of a particular category.
|
||||
type: string
|
||||
tolerationSeconds:
|
||||
description: |-
|
||||
TolerationSeconds represents the period of time the toleration (which must be
|
||||
of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default,
|
||||
it is not set, which means tolerate the taint forever (do not evict). Zero and
|
||||
negative values will be treated as 0 (evict immediately) by the system.
|
||||
format: int64
|
||||
type: integer
|
||||
value:
|
||||
description: |-
|
||||
Value is the taint value the toleration matches to.
|
||||
If the operator is Exists, the value should be empty, otherwise just a regular string.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
version:
|
||||
default: v0.0.32
|
||||
description: Version for Konnectivity agent.
|
||||
@@ -587,10 +634,15 @@ spec:
|
||||
description: The key to select.
|
||||
type: string
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the ConfigMap or its key must be defined
|
||||
@@ -643,10 +695,15 @@ spec:
|
||||
description: The key of the secret to select from. Must be a valid secret key.
|
||||
type: string
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the Secret or its key must be defined
|
||||
@@ -678,10 +735,15 @@ spec:
|
||||
description: The ConfigMap to select from
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the ConfigMap must be defined
|
||||
@@ -695,10 +757,15 @@ spec:
|
||||
description: The Secret to select from
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the Secret must be defined
|
||||
@@ -1941,10 +2008,15 @@ spec:
|
||||
description: The key to select.
|
||||
type: string
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the ConfigMap or its key must be defined
|
||||
@@ -1997,10 +2069,15 @@ spec:
|
||||
description: The key of the secret to select from. Must be a valid secret key.
|
||||
type: string
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the Secret or its key must be defined
|
||||
@@ -2032,10 +2109,15 @@ spec:
|
||||
description: The ConfigMap to select from
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the ConfigMap must be defined
|
||||
@@ -2049,10 +2131,15 @@ spec:
|
||||
description: The Secret to select from
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the Secret must be defined
|
||||
@@ -3565,10 +3652,15 @@ spec:
|
||||
More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -3604,10 +3696,15 @@ spec:
|
||||
to OpenStack.
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -3672,10 +3769,15 @@ spec:
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: optional specify whether the ConfigMap or its keys must be defined
|
||||
@@ -3705,10 +3807,15 @@ spec:
|
||||
secret object contains more than one secret, all secret references are passed.
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -4159,10 +4266,15 @@ spec:
|
||||
scripts.
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -4347,10 +4459,15 @@ spec:
|
||||
description: secretRef is the CHAP Secret for iSCSI target and initiator authentication
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -4601,10 +4718,15 @@ spec:
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: optional specify whether the ConfigMap or its keys must be defined
|
||||
@@ -4715,10 +4837,15 @@ spec:
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
optional:
|
||||
description: optional field specify whether the Secret or its key must be defined
|
||||
@@ -4845,10 +4972,15 @@ spec:
|
||||
More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -4889,10 +5021,15 @@ spec:
|
||||
sensitive information. If this is not provided, Login operation will fail.
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -5003,10 +5140,15 @@ spec:
|
||||
credentials. If not specified, default values will be attempted.
|
||||
properties:
|
||||
name:
|
||||
default: ""
|
||||
description: |-
|
||||
Name of the referent.
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.
|
||||
type: string
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
@@ -5966,6 +6108,18 @@ spec:
|
||||
Selector which must match a node's labels for the pod to be scheduled on that node.
|
||||
More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
|
||||
type: object
|
||||
podAdditionalMetadata:
|
||||
description: AdditionalMetadata defines which additional metadata, such as labels and annotations, must be attached to the created resource.
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
registrySettings:
|
||||
default:
|
||||
apiServerImage: kube-apiserver
|
||||
@@ -6234,6 +6388,10 @@ spec:
|
||||
empty definition that uses the default runtime handler.
|
||||
More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class
|
||||
type: string
|
||||
serviceAccountName:
|
||||
default: default
|
||||
description: ServiceAccountName allows to specify the service account to be mounted to the pods of the Control plane deployment
|
||||
type: string
|
||||
strategy:
|
||||
default:
|
||||
rollingUpdate:
|
||||
@@ -7858,7 +8016,7 @@ spec:
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.serviceAccountName
|
||||
image: clastix/kamaji:v0.5.0
|
||||
image: clastix/kamaji:v0.6.1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -13,4 +13,4 @@ kind: Kustomization
|
||||
images:
|
||||
- name: controller
|
||||
newName: clastix/kamaji
|
||||
newTag: v0.5.0
|
||||
newTag: v0.6.1
|
||||
|
||||
34
config/samples/kamaji_v1alpha1_datastore_nats_bronze.yaml
Normal file
34
config/samples/kamaji_v1alpha1_datastore_nats_bronze.yaml
Normal file
@@ -0,0 +1,34 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: DataStore
|
||||
metadata:
|
||||
name: nats-bronze
|
||||
spec:
|
||||
driver: NATS
|
||||
endpoints:
|
||||
- bronze-nats.nats-system.svc:4222
|
||||
basicAuth:
|
||||
username:
|
||||
content: YWRtaW4=
|
||||
password:
|
||||
secretReference:
|
||||
name: nats-bronze-config
|
||||
namespace: nats-system
|
||||
keyPath: password
|
||||
tlsConfig:
|
||||
certificateAuthority:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: nats-bronze-config
|
||||
namespace: nats-system
|
||||
keyPath: ca.crt
|
||||
clientCertificate:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: nats-bronze-config
|
||||
namespace: nats-system
|
||||
keyPath: server.crt
|
||||
privateKey:
|
||||
secretReference:
|
||||
name: nats-bronze-config
|
||||
namespace: nats-system
|
||||
keyPath: server.key
|
||||
34
config/samples/kamaji_v1alpha1_datastore_nats_gold.yaml
Normal file
34
config/samples/kamaji_v1alpha1_datastore_nats_gold.yaml
Normal file
@@ -0,0 +1,34 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: DataStore
|
||||
metadata:
|
||||
name: nats-gold
|
||||
spec:
|
||||
driver: NATS
|
||||
endpoints:
|
||||
- nats-gold.nats-system.svc:4222
|
||||
basicAuth:
|
||||
username:
|
||||
content: YWRtaW4=
|
||||
password:
|
||||
secretReference:
|
||||
name: nats-gold-config
|
||||
namespace: nats-system
|
||||
keyPath: password
|
||||
tlsConfig:
|
||||
certificateAuthority:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: nats-gold-config
|
||||
namespace: nats-system
|
||||
keyPath: ca.crt
|
||||
clientCertificate:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: nats-gold-config
|
||||
namespace: nats-system
|
||||
keyPath: server.crt
|
||||
privateKey:
|
||||
secretReference:
|
||||
name: nats-gold-config
|
||||
namespace: nats-system
|
||||
keyPath: server.key
|
||||
17
config/samples/kamaji_v1alpha1_datastore_nats_notls.yaml
Normal file
17
config/samples/kamaji_v1alpha1_datastore_nats_notls.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: DataStore
|
||||
metadata:
|
||||
name: nats-notls
|
||||
spec:
|
||||
driver: NATS
|
||||
endpoints:
|
||||
- notls-nats.nats-system.svc:4222
|
||||
basicAuth:
|
||||
username:
|
||||
content: YWRtaW4=
|
||||
password:
|
||||
secretReference:
|
||||
name: nats-notls-config
|
||||
namespace: nats-system
|
||||
keyPath: password
|
||||
|
||||
34
config/samples/kamaji_v1alpha1_datastore_nats_silver.yaml
Normal file
34
config/samples/kamaji_v1alpha1_datastore_nats_silver.yaml
Normal file
@@ -0,0 +1,34 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: DataStore
|
||||
metadata:
|
||||
name: nats-silver
|
||||
spec:
|
||||
driver: NATS
|
||||
endpoints:
|
||||
- nats-silver.nats-system.svc:4222
|
||||
basicAuth:
|
||||
username:
|
||||
content: YWRtaW4=
|
||||
password:
|
||||
secretReference:
|
||||
name: nats-silver-config
|
||||
namespace: nats-system
|
||||
keyPath: password
|
||||
tlsConfig:
|
||||
certificateAuthority:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: nats-silver-config
|
||||
namespace: nats-system
|
||||
keyPath: ca.crt
|
||||
clientCertificate:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: nats-silver-config
|
||||
namespace: nats-system
|
||||
keyPath: server.crt
|
||||
privateKey:
|
||||
secretReference:
|
||||
name: nats-silver-config
|
||||
namespace: nats-system
|
||||
keyPath: server.key
|
||||
@@ -205,6 +205,9 @@ func getKubeconfigResources(c client.Client, tcpReconcilerConfig TenantControlPl
|
||||
|
||||
func getKubernetesStorageResources(c client.Client, dbConnection datastore.Connection, datastore kamajiv1alpha1.DataStore) []resources.Resource {
|
||||
return []resources.Resource{
|
||||
&ds.MultiTenancy{
|
||||
DataStore: datastore,
|
||||
},
|
||||
&ds.Config{
|
||||
Client: c,
|
||||
ConnString: dbConnection.GetConnectionString(),
|
||||
|
||||
@@ -26,7 +26,7 @@ nodes:
|
||||
## expose port 31132 of the node to port 31132 on the host for konnectivity
|
||||
- containerPort: 31132
|
||||
hostPort: 31132
|
||||
protocol: TCP
|
||||
protocol: TCP
|
||||
## expose port 31443 of the node to port 31443 on the host
|
||||
- containerPort: 31443
|
||||
hostPort: 31443
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"CN": "bronze.mysql-system.svc.cluster.local",
|
||||
"key": {
|
||||
"algo": "rsa",
|
||||
"size": 2048
|
||||
},
|
||||
"hosts": [
|
||||
"127.0.0.1",
|
||||
"localhost",
|
||||
"bronze",
|
||||
"bronze.mysql-system.svc",
|
||||
"bronze.mysql-system.svc.cluster.local"
|
||||
]
|
||||
}
|
||||
40
deploy/kine/nats/Makefile
Normal file
40
deploy/kine/nats/Makefile
Normal file
@@ -0,0 +1,40 @@
|
||||
ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
NAME:=default
|
||||
NAMESPACE:=nats-system
|
||||
|
||||
.PHONY: helm
|
||||
HELM = $(shell pwd)/../../../bin/helm
|
||||
helm: ## Download helm locally if necessary.
|
||||
$(call go-install-tool,$(HELM),helm.sh/helm/v3/cmd/helm@v3.9.0)
|
||||
|
||||
nats: nats-certificates nats-secret nats-deployment
|
||||
|
||||
nats-certificates:
|
||||
rm -rf $(ROOT_DIR)/certs/$(NAME) && mkdir -p $(ROOT_DIR)/certs/$(NAME)
|
||||
cfssl gencert -initca $(ROOT_DIR)/ca-csr.json | cfssljson -bare $(ROOT_DIR)/certs/$(NAME)/ca
|
||||
@mv $(ROOT_DIR)/certs/$(NAME)/ca.pem $(ROOT_DIR)/certs/$(NAME)/ca.crt
|
||||
@mv $(ROOT_DIR)/certs/$(NAME)/ca-key.pem $(ROOT_DIR)/certs/$(NAME)/ca.key
|
||||
@NAME=$(NAME) NAMESPACE=$(NAMESPACE) envsubst < server-csr.json > $(ROOT_DIR)/certs/$(NAME)/server-csr.json
|
||||
cfssl gencert -ca=$(ROOT_DIR)/certs/$(NAME)/ca.crt -ca-key=$(ROOT_DIR)/certs/$(NAME)/ca.key \
|
||||
-config=$(ROOT_DIR)/config.json -profile=server \
|
||||
$(ROOT_DIR)/certs/$(NAME)/server-csr.json | cfssljson -bare $(ROOT_DIR)/certs/$(NAME)/server
|
||||
@mv $(ROOT_DIR)/certs/$(NAME)/server.pem $(ROOT_DIR)/certs/$(NAME)/server.crt
|
||||
@mv $(ROOT_DIR)/certs/$(NAME)/server-key.pem $(ROOT_DIR)/certs/$(NAME)/server.key
|
||||
chmod 644 $(ROOT_DIR)/certs/$(NAME)/*
|
||||
|
||||
nats-secret:
|
||||
@kubectl create namespace $(NAMESPACE) || true
|
||||
@kubectl -n $(NAMESPACE) create secret generic nats-$(NAME)-config \
|
||||
--from-file=$(ROOT_DIR)/certs/$(NAME)/ca.crt --from-file=$(ROOT_DIR)/certs/$(NAME)/ca.key \
|
||||
--from-file=$(ROOT_DIR)/certs/$(NAME)/server.key --from-file=$(ROOT_DIR)/certs/$(NAME)/server.crt \
|
||||
--from-literal=password=password \
|
||||
--dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
nats-deployment:
|
||||
@VALUES_FILE=$(if $(findstring notls,$(NAME)),values-notls.yaml,values.yaml); \
|
||||
NAME=$(NAME) envsubst < $(ROOT_DIR)/$$VALUES_FILE | $(HELM) upgrade --install $(NAME) nats/nats --create-namespace -n nats-system -f -
|
||||
|
||||
|
||||
nats-destroy:
|
||||
@NAME=$(NAME) envsubst < $(ROOT_DIR)/nats.yaml | kubectl -n $(NAMESPACE) delete --ignore-not-found -f -
|
||||
@kubectl delete -n $(NAMESPACE) secret mysql-$(NAME)config --ignore-not-found
|
||||
18
deploy/kine/nats/ca-csr.json
Normal file
18
deploy/kine/nats/ca-csr.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"CN": "Clastix CA",
|
||||
"key": {
|
||||
"algo": "rsa",
|
||||
"size": 2048
|
||||
},
|
||||
"names": [
|
||||
{
|
||||
"C": "IT",
|
||||
"ST": "Italy",
|
||||
"L": "Milan"
|
||||
}
|
||||
],
|
||||
"hosts": [
|
||||
"127.0.0.1",
|
||||
"localhost"
|
||||
]
|
||||
}
|
||||
18
deploy/kine/nats/config.json
Normal file
18
deploy/kine/nats/config.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"signing": {
|
||||
"default": {
|
||||
"expiry": "8760h"
|
||||
},
|
||||
"profiles": {
|
||||
"server": {
|
||||
"expiry": "8760h",
|
||||
"usages": [
|
||||
"signing",
|
||||
"key encipherment",
|
||||
"server auth",
|
||||
"client auth"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14
deploy/kine/nats/server-csr.json
Normal file
14
deploy/kine/nats/server-csr.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"CN": "$NAME.$NAMESPACE.svc.cluster.local",
|
||||
"key": {
|
||||
"algo": "rsa",
|
||||
"size": 2048
|
||||
},
|
||||
"hosts": [
|
||||
"127.0.0.1",
|
||||
"localhost",
|
||||
"$NAME-nats",
|
||||
"$NAME-nats.$NAMESPACE.svc",
|
||||
"$NAME-nats.$NAMESPACE.svc.cluster.local"
|
||||
]
|
||||
}
|
||||
14
deploy/kine/nats/values-notls.yaml
Normal file
14
deploy/kine/nats/values-notls.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
config:
|
||||
merge:
|
||||
accounts:
|
||||
private:
|
||||
jetstream: enabled
|
||||
users:
|
||||
- {user: admin, password: "password", permissions: {subscribe: [">"], publish: [">"]}}
|
||||
cluster:
|
||||
enabled: no
|
||||
jetstream:
|
||||
enabled: true
|
||||
fileStore:
|
||||
pvc:
|
||||
size: 32Mi
|
||||
20
deploy/kine/nats/values.yaml
Normal file
20
deploy/kine/nats/values.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
config:
|
||||
merge:
|
||||
accounts:
|
||||
private:
|
||||
jetstream: enabled
|
||||
users:
|
||||
- {user: admin, password: "password", permissions: {subscribe: [">"], publish: [">"]}}
|
||||
cluster:
|
||||
enabled: no
|
||||
nats:
|
||||
tls:
|
||||
enabled: true
|
||||
secretName: nats-$NAME-config
|
||||
cert: server.crt
|
||||
key: server.key
|
||||
jetstream:
|
||||
enabled: true
|
||||
fileStore:
|
||||
pvc:
|
||||
size: 32Mi
|
||||
@@ -1,39 +1,28 @@
|
||||
# Use Alternative Datastores
|
||||
|
||||
Kamaji offers the possibility of having a different storage system than `etcd` thanks to [kine](https://github.com/k3s-io/kine) integration. One of the implementations is [PostgreSQL](https://www.postgresql.org/).
|
||||
Kamaji offers the possibility of having a different storage system than `etcd` thanks to [kine](https://github.com/k3s-io/kine) integration.
|
||||
|
||||
## Install the datastore
|
||||
## Installing Drivers
|
||||
|
||||
On the Management Cluster, install one of the alternative supported datastore:
|
||||
The following `make` recipes help you to setup alternative `Datastore` resources.
|
||||
|
||||
- **MySQL** install it with command:
|
||||
> The default settings are not production grade:
|
||||
> the following scripts are just used to test the Kamaji usage of different drivers.
|
||||
|
||||
`$ make -C deploy/kine/mysql mariadb`
|
||||
On the Management Cluster, you can use the following commands:
|
||||
|
||||
- **PostgreSQL** install it with command:
|
||||
- **MySQL**: `$ make -C deploy/kine/mysql mariadb`
|
||||
|
||||
`$ make -C deploy/kine/postgresql postgresql`
|
||||
- **PostgreSQL**: `$ make -C deploy/kine/postgresql postgresql`
|
||||
|
||||
## Install Cert Manager
|
||||
- **NATS**: `$ make -C deploy/kine/nats nats`
|
||||
|
||||
As prerequisite for Kamaji, install the Cert Manager
|
||||
## Defining a default Datastore upon Kamaji installation
|
||||
|
||||
```bash
|
||||
helm repo add jetstack https://charts.jetstack.io
|
||||
helm repo update
|
||||
helm install \
|
||||
cert-manager jetstack/cert-manager \
|
||||
--namespace cert-manager \
|
||||
--create-namespace \
|
||||
--version v1.11.0 \
|
||||
--set installCRDs=true
|
||||
```
|
||||
Use Helm to install the Kamaji Operator and make sure it uses a datastore with the proper driver `datastore.driver=<MySQL|PostgreSQL|NATS>`.
|
||||
Please refer to the Chart available values for more information on supported options.
|
||||
|
||||
## Install Kamaji
|
||||
|
||||
Use Helm to install the Kamaji Operator and make sure it uses a datastore with the proper driver `datastore.driver=<MySQL|PostgreSQL>`.
|
||||
|
||||
For example, with a PostreSQL datastore installed:
|
||||
For example, with a PostgreSQL datastore installed:
|
||||
|
||||
```bash
|
||||
helm install kamaji charts/kamaji -n kamaji-system --create-namespace \
|
||||
@@ -60,4 +49,19 @@ helm install kamaji charts/kamaji -n kamaji-system --create-namespace \
|
||||
--set datastore.tlsConfig.clientCertificate.privateKey.keyPath=tls.key
|
||||
```
|
||||
|
||||
Once installed, you will able to create Tenant Control Planes using an alternative datastore.
|
||||
Once installed, you will be able to create Tenant Control Planes using an alternative datastore.
|
||||
|
||||
## Defining specific Datastore per Tenant Control Plane
|
||||
|
||||
Each `TenantControlPlane` can refer to a specific `Datastore` thanks to the `/spec/dataStore` field.
|
||||
This allows you to implement your preferred sharding or pooling strategy.
|
||||
|
||||
When the said key is omitted, Kamaji will use the default datastore configured with its CLI argument `--datastore`.
|
||||
|
||||
## NATS considerations
|
||||
|
||||
The NATS support is still experimental, mostly because multi-tenancy is **NOT** supported.
|
||||
|
||||
> A `NATS` based DataStore can host one and only one Tenant Control Plane.
|
||||
> When a `TenantControlPlane` is referring to a NATS `DataStore` already used by another instance,
|
||||
> reconciliation will fail and blocked.
|
||||
|
||||
@@ -99,7 +99,7 @@ The rotation will occur the day before their expiration.
|
||||
> Nota Bene:
|
||||
>
|
||||
> Kamaji is responsible for creating the `etcd` client certificate, and the generation of a new one will occur.
|
||||
> For other Datastore drivers, such as MySQL or PostgreSQL, the referenced Secret will always be deleted by the Controller to trigger the rotation:
|
||||
> For other Datastore drivers, such as MySQL, PostgreSQL, or NATS, the referenced Secret will always be deleted by the Controller to trigger the rotation:
|
||||
> the PKI management, since it's offloaded externally, must provide the renewed certificates.
|
||||
|
||||
## Certificate Authority rotation
|
||||
|
||||
@@ -69,7 +69,9 @@ From the main view, clicking on a Tenant Control Plane row will bring you to the
|
||||

|
||||
|
||||
### Working with Datastore
|
||||
From the menu bar on the left, clicking on the Datastores item, you can access the list of provisioned Datastores. It shows a summary about datastores, including name and the used driver, i.e. etcd, mysql, and postgresql.
|
||||
|
||||
From the menu bar on the left, clicking on the Datastores item, you can access the list of provisioned Datastores.
|
||||
It shows a summary about datastores, including name and the used driver, i.e. `etcd`, `MySQL`, `PostgreSQL`, and `NATS`.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Datastore Migration
|
||||
|
||||
On the Management Cluster, you can deploy one or more multi-tenant datastores as `etcd`, `PostgreSQL`, and `MySQL` to save the state of the Tenant Clusters. A Tenant Control Plane can be migrated from a datastore to another one without service disruption or without complex and error prone backup & restore procedures.
|
||||
On the Management Cluster, you can deploy one or more multi-tenant datastores as `etcd`, `PostgreSQL`, `MySQL`, and `NATS` to save the state of the Tenant Clusters.
|
||||
A Tenant Control Plane can be migrated from a datastore to another one without service disruption or without complex and error-prone backup & restore procedures.
|
||||
|
||||
This guide will assist you to live migrate Tenant's data from a datastore to another one having the same `etcd` driver.
|
||||
|
||||
@@ -80,7 +81,7 @@ helm install dedicated clastix/kamaji-etcd -n dedicated --create-namespace --set
|
||||
You should end up with a new datastore `dedicated` provided by an `etcd` cluster:
|
||||
|
||||
```yaml
|
||||
kubectl get datastore dedicated -o yaml
|
||||
# kubectl get datastore dedicated -o yaml
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: DataStore
|
||||
metadata:
|
||||
|
||||
@@ -125,7 +125,7 @@ helm install kamaji clastix/kamaji -n kamaji-system --create-namespace
|
||||
```
|
||||
|
||||
!!! note "A managed datastore is highly recommended in production"
|
||||
The [kamaji-etcd](https://github.com/clastix/kamaji-etcd) project provides the code to setup a multi-tenant `etcd` running as StatefulSet made of three replicas. Optionally, Kamaji offers support for a more robust storage system, as `MySQL` or `PostgreSQL` compatible database, thanks to the native [kine](https://github.com/k3s-io/kine) integration.
|
||||
The [kamaji-etcd](https://github.com/clastix/kamaji-etcd) project provides the code to setup a multi-tenant `etcd` running as StatefulSet made of three replicas. Optionally, Kamaji offers support for a more robust storage system, as `MySQL`, `PostgreSQL`, or `NATS` compatible database, thanks to the native [kine](https://github.com/k3s-io/kine) integration.
|
||||
|
||||
## Create Tenant Cluster
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ DataStoreSpec defines the desired state of DataStore.
|
||||
<td>
|
||||
The driver to use to connect to the shared datastore.<br/>
|
||||
<br/>
|
||||
<i>Enum</i>: etcd, MySQL, PostgreSQL<br/>
|
||||
<i>Enum</i>: etcd, MySQL, PostgreSQL, NATS<br/>
|
||||
</td>
|
||||
<td>true</td>
|
||||
</tr><tr>
|
||||
@@ -100,13 +100,6 @@ DataStoreSpec defines the desired state of DataStore.
|
||||
No need for protocol, just bare IP/FQDN and port.<br/>
|
||||
</td>
|
||||
<td>true</td>
|
||||
</tr><tr>
|
||||
<td><b><a href="#datastorespectlsconfig">tlsConfig</a></b></td>
|
||||
<td>object</td>
|
||||
<td>
|
||||
Defines the TLS/SSL configuration required to connect to the data store in a secure way.<br/>
|
||||
</td>
|
||||
<td>true</td>
|
||||
</tr><tr>
|
||||
<td><b><a href="#datastorespecbasicauth">basicAuth</a></b></td>
|
||||
<td>object</td>
|
||||
@@ -115,6 +108,202 @@ No need for protocol, just bare IP/FQDN and port.<br/>
|
||||
This value is optional.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b><a href="#datastorespectlsconfig">tlsConfig</a></b></td>
|
||||
<td>object</td>
|
||||
<td>
|
||||
Defines the TLS/SSL configuration required to connect to the data store in a secure way.
|
||||
This value is optional.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
### DataStore.spec.basicAuth
|
||||
|
||||
|
||||
|
||||
In case of authentication enabled for the given data store, specifies the username and password pair.
|
||||
This value is optional.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td><b><a href="#datastorespecbasicauthpassword">password</a></b></td>
|
||||
<td>object</td>
|
||||
<td>
|
||||
<br/>
|
||||
</td>
|
||||
<td>true</td>
|
||||
</tr><tr>
|
||||
<td><b><a href="#datastorespecbasicauthusername">username</a></b></td>
|
||||
<td>object</td>
|
||||
<td>
|
||||
<br/>
|
||||
</td>
|
||||
<td>true</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
### DataStore.spec.basicAuth.password
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td><b>content</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Bare content of the file, base64 encoded.
|
||||
It has precedence over the SecretReference value.<br/>
|
||||
<br/>
|
||||
<i>Format</i>: byte<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b><a href="#datastorespecbasicauthpasswordsecretreference">secretReference</a></b></td>
|
||||
<td>object</td>
|
||||
<td>
|
||||
<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
### DataStore.spec.basicAuth.password.secretReference
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td><b>keyPath</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the key for the given Secret reference where the content is stored.
|
||||
This value is mandatory.<br/>
|
||||
</td>
|
||||
<td>true</td>
|
||||
</tr><tr>
|
||||
<td><b>name</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
name is unique within a namespace to reference a secret resource.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b>namespace</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
namespace defines the space within which the secret name must be unique.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
### DataStore.spec.basicAuth.username
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td><b>content</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Bare content of the file, base64 encoded.
|
||||
It has precedence over the SecretReference value.<br/>
|
||||
<br/>
|
||||
<i>Format</i>: byte<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b><a href="#datastorespecbasicauthusernamesecretreference">secretReference</a></b></td>
|
||||
<td>object</td>
|
||||
<td>
|
||||
<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
### DataStore.spec.basicAuth.username.secretReference
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td><b>keyPath</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the key for the given Secret reference where the content is stored.
|
||||
This value is mandatory.<br/>
|
||||
</td>
|
||||
<td>true</td>
|
||||
</tr><tr>
|
||||
<td><b>name</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
name is unique within a namespace to reference a secret resource.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b>namespace</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
namespace defines the space within which the secret name must be unique.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
@@ -124,6 +313,7 @@ This value is optional.<br/>
|
||||
|
||||
|
||||
Defines the TLS/SSL configuration required to connect to the data store in a secure way.
|
||||
This value is optional.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
@@ -148,7 +338,7 @@ The key reference is required since etcd authentication is based on certificates
|
||||
<td>
|
||||
Specifies the SSL/TLS key and private key pair used to connect to the data store.<br/>
|
||||
</td>
|
||||
<td>true</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
@@ -493,194 +683,6 @@ It has precedence over the SecretReference value.<br/>
|
||||
|
||||
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td><b>keyPath</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the key for the given Secret reference where the content is stored.
|
||||
This value is mandatory.<br/>
|
||||
</td>
|
||||
<td>true</td>
|
||||
</tr><tr>
|
||||
<td><b>name</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
name is unique within a namespace to reference a secret resource.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b>namespace</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
namespace defines the space within which the secret name must be unique.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
### DataStore.spec.basicAuth
|
||||
|
||||
|
||||
|
||||
In case of authentication enabled for the given data store, specifies the username and password pair.
|
||||
This value is optional.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td><b><a href="#datastorespecbasicauthpassword">password</a></b></td>
|
||||
<td>object</td>
|
||||
<td>
|
||||
<br/>
|
||||
</td>
|
||||
<td>true</td>
|
||||
</tr><tr>
|
||||
<td><b><a href="#datastorespecbasicauthusername">username</a></b></td>
|
||||
<td>object</td>
|
||||
<td>
|
||||
<br/>
|
||||
</td>
|
||||
<td>true</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
### DataStore.spec.basicAuth.password
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td><b>content</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Bare content of the file, base64 encoded.
|
||||
It has precedence over the SecretReference value.<br/>
|
||||
<br/>
|
||||
<i>Format</i>: byte<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b><a href="#datastorespecbasicauthpasswordsecretreference">secretReference</a></b></td>
|
||||
<td>object</td>
|
||||
<td>
|
||||
<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
### DataStore.spec.basicAuth.password.secretReference
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td><b>keyPath</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the key for the given Secret reference where the content is stored.
|
||||
This value is mandatory.<br/>
|
||||
</td>
|
||||
<td>true</td>
|
||||
</tr><tr>
|
||||
<td><b>name</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
name is unique within a namespace to reference a secret resource.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b>namespace</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
namespace defines the space within which the secret name must be unique.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
### DataStore.spec.basicAuth.username
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td><b>content</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Bare content of the file, base64 encoded.
|
||||
It has precedence over the SecretReference value.<br/>
|
||||
<br/>
|
||||
<i>Format</i>: byte<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b><a href="#datastorespecbasicauthusernamesecretreference">secretReference</a></b></td>
|
||||
<td>object</td>
|
||||
<td>
|
||||
<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
### DataStore.spec.basicAuth.username.secretReference
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -1038,6 +1040,13 @@ Selector which must match a node's labels for the pod to be scheduled on that no
|
||||
More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b><a href="#tenantcontrolplanespeccontrolplanedeploymentpodadditionalmetadata">podAdditionalMetadata</a></b></td>
|
||||
<td>object</td>
|
||||
<td>
|
||||
AdditionalMetadata defines which additional metadata, such as labels and annotations, must be attached to the created resource.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b><a href="#tenantcontrolplanespeccontrolplanedeploymentregistrysettings">registrySettings</a></b></td>
|
||||
<td>object</td>
|
||||
@@ -1077,6 +1086,15 @@ empty definition that uses the default runtime handler.
|
||||
More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b>serviceAccountName</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
ServiceAccountName allows to specify the service account to be mounted to the pods of the Control plane deployment<br/>
|
||||
<br/>
|
||||
<i>Default</i>: default<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b><a href="#tenantcontrolplanespeccontrolplanedeploymentstrategy">strategy</a></b></td>
|
||||
<td>object</td>
|
||||
@@ -1511,8 +1529,14 @@ Selects a key of a ConfigMap.
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
@@ -1628,8 +1652,14 @@ Selects a key of a secret in the pod's namespace
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
@@ -1703,8 +1733,14 @@ The ConfigMap to select from
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
@@ -1738,8 +1774,14 @@ The Secret to select from
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
@@ -4328,8 +4370,14 @@ Selects a key of a ConfigMap.
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
@@ -4445,8 +4493,14 @@ Selects a key of a secret in the pod's namespace
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
@@ -4520,8 +4574,14 @@ The ConfigMap to select from
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
@@ -4555,8 +4615,14 @@ The Secret to select from
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
@@ -7647,8 +7713,14 @@ More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
@@ -7731,8 +7803,14 @@ to OpenStack.
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
@@ -7787,8 +7865,14 @@ relative and may not contain the '..' path or start with '..'.<br/>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
@@ -7939,8 +8023,14 @@ secret object contains more than one secret, all secret references are passed.
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
@@ -8819,8 +8909,14 @@ scripts.
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
@@ -9188,8 +9284,14 @@ secretRef is the CHAP Secret for iSCSI target and initiator authentication
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
@@ -9660,8 +9762,14 @@ relative and may not contain the '..' path or start with '..'.<br/>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
@@ -9913,8 +10021,14 @@ relative and may not contain the '..' path or start with '..'.<br/>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
@@ -10212,8 +10326,14 @@ More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
@@ -10337,8 +10457,14 @@ sensitive information. If this is not provided, Login operation will fail.
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
@@ -10543,8 +10669,14 @@ credentials. If not specified, default values will be attempted.
|
||||
<td>string</td>
|
||||
<td>
|
||||
Name of the referent.
|
||||
This field is effectively required, but due to backwards compatibility is
|
||||
allowed to be empty. Instances of this type with an empty value here are
|
||||
almost certainly wrong.
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?
|
||||
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?<br/>
|
||||
TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: <br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
@@ -12246,6 +12378,39 @@ Only modify if you know what you are doing.
|
||||
</table>
|
||||
|
||||
|
||||
### TenantControlPlane.spec.controlPlane.deployment.podAdditionalMetadata
|
||||
|
||||
|
||||
|
||||
AdditionalMetadata defines which additional metadata, such as labels and annotations, must be attached to the created resource.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td><b>annotations</b></td>
|
||||
<td>map[string]string</td>
|
||||
<td>
|
||||
<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b>labels</b></td>
|
||||
<td>map[string]string</td>
|
||||
<td>
|
||||
<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
### TenantControlPlane.spec.controlPlane.deployment.registrySettings
|
||||
|
||||
|
||||
@@ -13394,6 +13559,16 @@ unxpected ways. Only modify if you know what you are doing.<br/>
|
||||
<i>Default</i>: registry.k8s.io/kas-network-proxy/proxy-agent<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b><a href="#tenantcontrolplanespecaddonskonnectivityagenttolerationsindex">tolerations</a></b></td>
|
||||
<td>[]object</td>
|
||||
<td>
|
||||
Tolerations for the deployed agent.
|
||||
Can be customized to start the konnectivity-agent even if the nodes are not ready or tainted.<br/>
|
||||
<br/>
|
||||
<i>Default</i>: [map[key:CriticalAddonsOnly operator:Exists]]<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b>version</b></td>
|
||||
<td>string</td>
|
||||
@@ -13407,6 +13582,72 @@ unxpected ways. Only modify if you know what you are doing.<br/>
|
||||
</table>
|
||||
|
||||
|
||||
### TenantControlPlane.spec.addons.konnectivity.agent.tolerations[index]
|
||||
|
||||
|
||||
|
||||
The pod this Toleration is attached to tolerates any taint that matches
|
||||
the triple <key,value,effect> using the matching operator <operator>.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td><b>effect</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Effect indicates the taint effect to match. Empty means match all taint effects.
|
||||
When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b>key</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Key is the taint key that the toleration applies to. Empty means match all taint keys.
|
||||
If the key is empty, operator must be Exists; this combination means to match all values and all keys.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b>operator</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Operator represents a key's relationship to the value.
|
||||
Valid operators are Exists and Equal. Defaults to Equal.
|
||||
Exists is equivalent to wildcard for value, so that a pod can
|
||||
tolerate all taints of a particular category.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b>tolerationSeconds</b></td>
|
||||
<td>integer</td>
|
||||
<td>
|
||||
TolerationSeconds represents the period of time the toleration (which must be
|
||||
of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default,
|
||||
it is not set, which means tolerate the taint forever (do not evict). Zero and
|
||||
negative values will be treated as 0 (evict immediately) by the system.<br/>
|
||||
<br/>
|
||||
<i>Format</i>: int64<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b>value</b></td>
|
||||
<td>string</td>
|
||||
<td>
|
||||
Value is the taint value the toleration matches to.
|
||||
If the operator is Exists, the value should be empty, otherwise just a regular string.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
### TenantControlPlane.spec.addons.konnectivity.server
|
||||
|
||||
|
||||
|
||||
@@ -18,3 +18,4 @@ In Kamaji, there are different components that might require independent version
|
||||
| v0.4.1 | v1.22+ | [v1.21.0 .. v1.29.1] |
|
||||
| v0.4.2 | v1.22+ | [v1.21.0 .. v1.29.1] |
|
||||
| v0.5.0 | v1.22+ | [v1.21.0 .. v1.30.0] |
|
||||
| v0.6.0 | v1.22+ | [v1.21.0 .. v1.30.1] |
|
||||
|
||||
74
e2e/tcp_custom_sa_test.go
Normal file
74
e2e/tcp_custom_sa_test.go
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
|
||||
var _ = Describe("Deploy a TenantControlPlane with resource with custom service account", func() {
|
||||
// service account object
|
||||
sa := &corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test",
|
||||
Namespace: "default",
|
||||
},
|
||||
}
|
||||
// Fill TenantControlPlane object
|
||||
tcp := &kamajiv1alpha1.TenantControlPlane{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "tcp-clusterip-customsa",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: kamajiv1alpha1.TenantControlPlaneSpec{
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.To(int32(1)),
|
||||
ServiceAccountName: sa.GetName(),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "ClusterIP",
|
||||
},
|
||||
},
|
||||
NetworkProfile: kamajiv1alpha1.NetworkProfileSpec{
|
||||
Address: "172.18.0.2",
|
||||
},
|
||||
Kubernetes: kamajiv1alpha1.KubernetesSpec{
|
||||
Version: "v1.23.6",
|
||||
Kubelet: kamajiv1alpha1.KubeletSpec{
|
||||
CGroupFS: "cgroupfs",
|
||||
},
|
||||
AdmissionControllers: kamajiv1alpha1.AdmissionControllers{
|
||||
"LimitRanger",
|
||||
"ResourceQuota",
|
||||
},
|
||||
},
|
||||
Addons: kamajiv1alpha1.AddonsSpec{},
|
||||
},
|
||||
}
|
||||
|
||||
// Create service account and TenantControlPlane resources into the cluster
|
||||
JustBeforeEach(func() {
|
||||
Expect(k8sClient.Create(context.Background(), sa)).NotTo(HaveOccurred())
|
||||
Expect(k8sClient.Create(context.Background(), tcp)).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
// Delete the service account and TenantControlPlane resources after test is finished
|
||||
JustAfterEach(func() {
|
||||
Expect(k8sClient.Delete(context.Background(), tcp)).Should(Succeed())
|
||||
})
|
||||
// Check if TenantControlPlane resource has been created and if its pods have the right service account
|
||||
It("Should be Ready and have correct sa", func() {
|
||||
StatusMustEqualTo(tcp, kamajiv1alpha1.VersionReady)
|
||||
PodsServiceAccountMustEqualTo(tcp, sa)
|
||||
})
|
||||
})
|
||||
54
e2e/tcp_nats_ready_no_tls_test.go
Normal file
54
e2e/tcp_nats_ready_no_tls_test.go
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
|
||||
var _ = Describe("Deploy a TenantControlPlane resource with the NATS driver without TLS", func() {
|
||||
// Fill TenantControlPlane object
|
||||
tcp := &kamajiv1alpha1.TenantControlPlane{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "nats-notls",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: kamajiv1alpha1.TenantControlPlaneSpec{
|
||||
DataStore: "nats-notls",
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.To(int32(1)),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "ClusterIP",
|
||||
},
|
||||
},
|
||||
Kubernetes: kamajiv1alpha1.KubernetesSpec{
|
||||
Version: "v1.23.6",
|
||||
Kubelet: kamajiv1alpha1.KubeletSpec{
|
||||
CGroupFS: "cgroupfs",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
// Create a TenantControlPlane resource into the cluster
|
||||
JustBeforeEach(func() {
|
||||
Expect(k8sClient.Create(context.Background(), tcp)).NotTo(HaveOccurred())
|
||||
})
|
||||
// Delete the TenantControlPlane resource after test is finished
|
||||
JustAfterEach(func() {
|
||||
Expect(k8sClient.Delete(context.Background(), tcp)).Should(Succeed())
|
||||
})
|
||||
// Check if TenantControlPlane resource has been created
|
||||
It("Should be Ready", func() {
|
||||
StatusMustEqualTo(tcp, kamajiv1alpha1.VersionReady)
|
||||
})
|
||||
})
|
||||
54
e2e/tcp_nats_ready_test.go
Normal file
54
e2e/tcp_nats_ready_test.go
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
|
||||
var _ = Describe("Deploy a TenantControlPlane resource with the NATS driver", func() {
|
||||
// Fill TenantControlPlane object
|
||||
tcp := &kamajiv1alpha1.TenantControlPlane{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "nats",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: kamajiv1alpha1.TenantControlPlaneSpec{
|
||||
DataStore: "nats-bronze",
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.To(int32(1)),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "ClusterIP",
|
||||
},
|
||||
},
|
||||
Kubernetes: kamajiv1alpha1.KubernetesSpec{
|
||||
Version: "v1.23.6",
|
||||
Kubelet: kamajiv1alpha1.KubeletSpec{
|
||||
CGroupFS: "cgroupfs",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
// Create a TenantControlPlane resource into the cluster
|
||||
JustBeforeEach(func() {
|
||||
Expect(k8sClient.Create(context.Background(), tcp)).NotTo(HaveOccurred())
|
||||
})
|
||||
// Delete the TenantControlPlane resource after test is finished
|
||||
JustAfterEach(func() {
|
||||
Expect(k8sClient.Delete(context.Background(), tcp)).Should(Succeed())
|
||||
})
|
||||
// Check if TenantControlPlane resource has been created
|
||||
It("Should be Ready", func() {
|
||||
StatusMustEqualTo(tcp, kamajiv1alpha1.VersionReady)
|
||||
})
|
||||
})
|
||||
78
e2e/tcp_pod_additional_metadata_test.go
Normal file
78
e2e/tcp_pod_additional_metadata_test.go
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
|
||||
var _ = Describe("Deploy a TenantControlPlane resource with additional pod metadata", func() {
|
||||
// Fill TenantControlPlane object
|
||||
tcp := &kamajiv1alpha1.TenantControlPlane{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "tcp-clusterip-additional-metadata",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: kamajiv1alpha1.TenantControlPlaneSpec{
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.To(int32(1)),
|
||||
PodAdditionalMetadata: kamajiv1alpha1.AdditionalMetadata{
|
||||
Labels: map[string]string{
|
||||
"hello-label": "world",
|
||||
"foo-label": "bar",
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
"hello-ann": "world",
|
||||
"foo-ann": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "ClusterIP",
|
||||
},
|
||||
},
|
||||
NetworkProfile: kamajiv1alpha1.NetworkProfileSpec{
|
||||
Address: "172.18.0.2",
|
||||
},
|
||||
Kubernetes: kamajiv1alpha1.KubernetesSpec{
|
||||
Version: "v1.23.6",
|
||||
Kubelet: kamajiv1alpha1.KubeletSpec{
|
||||
CGroupFS: "cgroupfs",
|
||||
},
|
||||
AdmissionControllers: kamajiv1alpha1.AdmissionControllers{
|
||||
"LimitRanger",
|
||||
"ResourceQuota",
|
||||
},
|
||||
},
|
||||
Addons: kamajiv1alpha1.AddonsSpec{},
|
||||
},
|
||||
}
|
||||
|
||||
// Create a TenantControlPlane resource into the cluster
|
||||
JustBeforeEach(func() {
|
||||
Expect(k8sClient.Create(context.Background(), tcp)).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
// Delete the TenantControlPlane resource after test is finished
|
||||
JustAfterEach(func() {
|
||||
Expect(k8sClient.Delete(context.Background(), tcp)).Should(Succeed())
|
||||
})
|
||||
|
||||
// Check if TenantControlPlane resource has been created
|
||||
It("Should be Ready with expected additional metadata", func() {
|
||||
StatusMustEqualTo(tcp, kamajiv1alpha1.VersionReady)
|
||||
AllPodsLabelMustEqualTo(tcp, "hello-label", "world")
|
||||
AllPodsLabelMustEqualTo(tcp, "foo-label", "bar")
|
||||
AllPodsAnnotationMustEqualTo(tcp, "hello-ann", "world")
|
||||
AllPodsAnnotationMustEqualTo(tcp, "foo-ann", "bar")
|
||||
})
|
||||
})
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
@@ -136,3 +137,61 @@ func StatusMustEqualTo(tcp *kamajiv1alpha1.TenantControlPlane, status kamajiv1al
|
||||
return *tcp.Status.Kubernetes.Version.Status
|
||||
}, 5*time.Minute, time.Second).Should(Equal(status))
|
||||
}
|
||||
|
||||
func AllPodsLabelMustEqualTo(tcp *kamajiv1alpha1.TenantControlPlane, label string, value string) {
|
||||
Eventually(func() bool {
|
||||
tcpPods := &corev1.PodList{}
|
||||
err := k8sClient.List(context.Background(), tcpPods, client.MatchingLabels{
|
||||
"kamaji.clastix.io/name": tcp.GetName(),
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for _, pod := range tcpPods.Items {
|
||||
if pod.Labels[label] != value {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}, 5*time.Minute, time.Second).Should(BeTrue())
|
||||
}
|
||||
|
||||
func AllPodsAnnotationMustEqualTo(tcp *kamajiv1alpha1.TenantControlPlane, annotation string, value string) {
|
||||
Eventually(func() bool {
|
||||
tcpPods := &corev1.PodList{}
|
||||
err := k8sClient.List(context.Background(), tcpPods, client.MatchingLabels{
|
||||
"kamaji.clastix.io/name": tcp.GetName(),
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for _, pod := range tcpPods.Items {
|
||||
if pod.Annotations[annotation] != value {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}, 5*time.Minute, time.Second).Should(BeTrue())
|
||||
}
|
||||
|
||||
func PodsServiceAccountMustEqualTo(tcp *kamajiv1alpha1.TenantControlPlane, sa *corev1.ServiceAccount) {
|
||||
saName := sa.GetName()
|
||||
Eventually(func() bool {
|
||||
tcpPods := &corev1.PodList{}
|
||||
err := k8sClient.List(context.Background(), tcpPods, client.MatchingLabels{
|
||||
"kamaji.clastix.io/name": tcp.GetName(),
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for _, pod := range tcpPods.Items {
|
||||
if pod.Spec.ServiceAccountName != saName {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}, 5*time.Minute, time.Second).Should(BeTrue())
|
||||
}
|
||||
|
||||
80
go.mod
80
go.mod
@@ -14,6 +14,7 @@ require (
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/juju/mutex/v2 v2.0.0
|
||||
github.com/nats-io/nats.go v1.34.1
|
||||
github.com/onsi/ginkgo/v2 v2.17.1
|
||||
github.com/onsi/gomega v1.32.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
@@ -25,14 +26,14 @@ require (
|
||||
go.etcd.io/etcd/client/v3 v3.5.10
|
||||
go.uber.org/automaxprocs v1.5.1
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0
|
||||
k8s.io/api v0.30.0
|
||||
k8s.io/apimachinery v0.30.0
|
||||
k8s.io/apiserver v0.30.0
|
||||
k8s.io/client-go v0.30.0
|
||||
k8s.io/api v0.30.2
|
||||
k8s.io/apimachinery v0.30.2
|
||||
k8s.io/apiserver v0.30.2
|
||||
k8s.io/client-go v0.30.2
|
||||
k8s.io/cluster-bootstrap v0.0.0
|
||||
k8s.io/klog/v2 v2.120.1
|
||||
k8s.io/kubelet v0.0.0
|
||||
k8s.io/kubernetes v1.30.0
|
||||
k8s.io/kubernetes v1.30.2
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
|
||||
sigs.k8s.io/controller-runtime v0.17.1-0.20240416095710-67b27f27e514
|
||||
)
|
||||
@@ -84,6 +85,7 @@ require (
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/juju/errors v0.0.0-20220203013757-bd733f3c86b9 // indirect
|
||||
github.com/klauspost/compress v1.17.8 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/lithammer/dedent v1.1.0 // indirect
|
||||
github.com/magiconair/properties v1.8.5 // indirect
|
||||
@@ -98,6 +100,8 @@ require (
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nats-io/nkeys v0.4.7 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||
github.com/opencontainers/runc v1.1.12 // indirect
|
||||
@@ -124,14 +128,14 @@ require (
|
||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.26.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 // indirect
|
||||
golang.org/x/mod v0.15.0 // indirect
|
||||
golang.org/x/net v0.23.0 // indirect
|
||||
golang.org/x/oauth2 v0.12.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
golang.org/x/term v0.18.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
golang.org/x/term v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.18.0 // indirect
|
||||
@@ -146,9 +150,9 @@ require (
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.30.0 // indirect
|
||||
k8s.io/cli-runtime v0.30.0 // indirect
|
||||
k8s.io/component-base v0.30.0 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.30.1 // indirect
|
||||
k8s.io/cli-runtime v0.30.1 // indirect
|
||||
k8s.io/component-base v0.30.2 // indirect
|
||||
k8s.io/component-helpers v0.0.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
|
||||
k8s.io/kube-proxy v0.0.0 // indirect
|
||||
@@ -162,33 +166,33 @@ require (
|
||||
)
|
||||
|
||||
replace (
|
||||
k8s.io/api => k8s.io/api v0.30.0
|
||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.30.0
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.30.0
|
||||
k8s.io/apiserver => k8s.io/apiserver v0.30.0
|
||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.30.0
|
||||
k8s.io/client-go => k8s.io/client-go v0.30.0
|
||||
k8s.io/cloud-provider => k8s.io/cloud-provider v0.30.0
|
||||
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.30.0
|
||||
k8s.io/code-generator => k8s.io/code-generator v0.30.0
|
||||
k8s.io/component-base => k8s.io/component-base v0.30.0
|
||||
k8s.io/component-helpers => k8s.io/component-helpers v0.30.0
|
||||
k8s.io/controller-manager => k8s.io/controller-manager v0.30.0
|
||||
k8s.io/cri-api => k8s.io/cri-api v0.30.0
|
||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.30.0
|
||||
k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.30.0
|
||||
k8s.io/endpointslice => k8s.io/endpointslice v0.30.0
|
||||
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.30.0
|
||||
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.30.0
|
||||
k8s.io/kube-proxy => k8s.io/kube-proxy v0.30.0
|
||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.30.0
|
||||
k8s.io/kubectl => k8s.io/kubectl v0.30.0
|
||||
k8s.io/kubelet => k8s.io/kubelet v0.30.0
|
||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.0
|
||||
k8s.io/metrics => k8s.io/metrics v0.30.0
|
||||
k8s.io/mount-utils => k8s.io/mount-utils v0.30.0
|
||||
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.30.0
|
||||
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.30.0
|
||||
k8s.io/api => k8s.io/api v0.30.2
|
||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.30.2
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.30.2
|
||||
k8s.io/apiserver => k8s.io/apiserver v0.30.2
|
||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.30.2
|
||||
k8s.io/client-go => k8s.io/client-go v0.30.2
|
||||
k8s.io/cloud-provider => k8s.io/cloud-provider v0.30.2
|
||||
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.30.2
|
||||
k8s.io/code-generator => k8s.io/code-generator v0.30.2
|
||||
k8s.io/component-base => k8s.io/component-base v0.30.2
|
||||
k8s.io/component-helpers => k8s.io/component-helpers v0.30.2
|
||||
k8s.io/controller-manager => k8s.io/controller-manager v0.30.2
|
||||
k8s.io/cri-api => k8s.io/cri-api v0.30.2
|
||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.30.2
|
||||
k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.30.2
|
||||
k8s.io/endpointslice => k8s.io/endpointslice v0.30.2
|
||||
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.30.2
|
||||
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.30.2
|
||||
k8s.io/kube-proxy => k8s.io/kube-proxy v0.30.2
|
||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.30.2
|
||||
k8s.io/kubectl => k8s.io/kubectl v0.30.2
|
||||
k8s.io/kubelet => k8s.io/kubelet v0.30.2
|
||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.2
|
||||
k8s.io/metrics => k8s.io/metrics v0.30.2
|
||||
k8s.io/mount-utils => k8s.io/mount-utils v0.30.2
|
||||
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.30.2
|
||||
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.30.2
|
||||
)
|
||||
|
||||
replace github.com/JamesStewy/go-mysqldump => github.com/vtoma/go-mysqldump v1.0.0
|
||||
|
||||
69
go.sum
69
go.sum
@@ -1378,6 +1378,8 @@ github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j
|
||||
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
|
||||
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@@ -1469,6 +1471,12 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/nats-io/nats.go v1.34.1 h1:syWey5xaNHZgicYBemv0nohUPPmaLteiBEUT6Q5+F/4=
|
||||
github.com/nats-io/nats.go v1.34.1/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
|
||||
github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
|
||||
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
@@ -1873,8 +1881,9 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -2222,8 +2231,9 @@ golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -2243,8 +2253,9 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -2740,25 +2751,25 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
|
||||
k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA=
|
||||
k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE=
|
||||
k8s.io/apiextensions-apiserver v0.30.0 h1:jcZFKMqnICJfRxTgnC4E+Hpcq8UEhT8B2lhBcQ+6uAs=
|
||||
k8s.io/apiextensions-apiserver v0.30.0/go.mod h1:N9ogQFGcrbWqAY9p2mUAL5mGxsLqwgtUce127VtRX5Y=
|
||||
k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA=
|
||||
k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
|
||||
k8s.io/apiserver v0.30.0 h1:QCec+U72tMQ+9tR6A0sMBB5Vh6ImCEkoKkTDRABWq6M=
|
||||
k8s.io/apiserver v0.30.0/go.mod h1:smOIBq8t0MbKZi7O7SyIpjPsiKJ8qa+llcFCluKyqiY=
|
||||
k8s.io/cli-runtime v0.30.0 h1:0vn6/XhOvn1RJ2KJOC6IRR2CGqrpT6QQF4+8pYpWQ48=
|
||||
k8s.io/cli-runtime v0.30.0/go.mod h1:vATpDMATVTMA79sZ0YUCzlMelf6rUjoBzlp+RnoM+cg=
|
||||
k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ=
|
||||
k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY=
|
||||
k8s.io/cluster-bootstrap v0.30.0 h1:vaIjA1eMFpcLYz+p6NMj75aqiauDahFx9EkuTxc0GMI=
|
||||
k8s.io/cluster-bootstrap v0.30.0/go.mod h1:/ceTq+EC/aOrQk27mfmFW/iOeQDqzKg6vYWIBFNHSAE=
|
||||
k8s.io/component-base v0.30.0 h1:cj6bp38g0ainlfYtaOQuRELh5KSYjhKxM+io7AUIk4o=
|
||||
k8s.io/component-base v0.30.0/go.mod h1:V9x/0ePFNaKeKYA3bOvIbrNoluTSG+fSJKjLdjOoeXQ=
|
||||
k8s.io/component-helpers v0.30.0 h1:xbJtNCfSM4SB/Tz5JqCKDZv4eT5LVi/AWQ1VOxhmStU=
|
||||
k8s.io/component-helpers v0.30.0/go.mod h1:68HlSwXIumMKmCx8cZe1PoafQEYh581/sEpxMrkhmX4=
|
||||
k8s.io/cri-api v0.30.0/go.mod h1://4/umPJSW1ISNSNng4OwjpkvswJOQwU8rnkvO8P+xg=
|
||||
k8s.io/api v0.30.2 h1:+ZhRj+28QT4UOH+BKznu4CBgPWgkXO7XAvMcMl0qKvI=
|
||||
k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI=
|
||||
k8s.io/apiextensions-apiserver v0.30.2 h1:l7Eue2t6QiLHErfn2vwK4KgF4NeDgjQkCXtEbOocKIE=
|
||||
k8s.io/apiextensions-apiserver v0.30.2/go.mod h1:lsJFLYyK40iguuinsb3nt+Sj6CmodSI4ACDLep1rgjw=
|
||||
k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg=
|
||||
k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
|
||||
k8s.io/apiserver v0.30.2 h1:ACouHiYl1yFI2VFI3YGM+lvxgy6ir4yK2oLOsLI1/tw=
|
||||
k8s.io/apiserver v0.30.2/go.mod h1:BOTdFBIch9Sv0ypSEcUR6ew/NUFGocRFNl72Ra7wTm8=
|
||||
k8s.io/cli-runtime v0.30.2 h1:ooM40eEJusbgHNEqnHziN9ZpLN5U4WcQGsdLKVxpkKE=
|
||||
k8s.io/cli-runtime v0.30.2/go.mod h1:Y4g/2XezFyTATQUbvV5WaChoUGhojv/jZAtdp5Zkm0A=
|
||||
k8s.io/client-go v0.30.2 h1:sBIVJdojUNPDU/jObC+18tXWcTJVcwyqS9diGdWHk50=
|
||||
k8s.io/client-go v0.30.2/go.mod h1:JglKSWULm9xlJLx4KCkfLLQ7XwtlbflV6uFFSHTMgVs=
|
||||
k8s.io/cluster-bootstrap v0.30.2 h1:9PQ5phjWTxmPFKPEzTG6QJzPaUIfuW2RqcHDME5gqPg=
|
||||
k8s.io/cluster-bootstrap v0.30.2/go.mod h1:dvzAgNVmwRfZ0BzHI/WTvzqlzmNH7w21mdnahEq61KY=
|
||||
k8s.io/component-base v0.30.2 h1:pqGBczYoW1sno8q9ObExUqrYSKhtE5rW3y6gX88GZII=
|
||||
k8s.io/component-base v0.30.2/go.mod h1:yQLkQDrkK8J6NtP+MGJOws+/PPeEXNpwFixsUI7h/OE=
|
||||
k8s.io/component-helpers v0.30.2 h1:kDMYLiWEYeWU7H6jBI+Ua1i2hqNh0DzqDHNIppFC3po=
|
||||
k8s.io/component-helpers v0.30.2/go.mod h1:tI0anfS6AbRqooaICkGg7UVAQLedOauVSQW9srDBnJw=
|
||||
k8s.io/cri-api v0.30.2/go.mod h1://4/umPJSW1ISNSNng4OwjpkvswJOQwU8rnkvO8P+xg=
|
||||
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
@@ -2766,16 +2777,16 @@ k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
|
||||
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kms v0.30.0/go.mod h1:GrMurD0qk3G4yNgGcsCEmepqf9KyyIrTXYR2lyUOJC4=
|
||||
k8s.io/kms v0.30.2/go.mod h1:GrMurD0qk3G4yNgGcsCEmepqf9KyyIrTXYR2lyUOJC4=
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
|
||||
k8s.io/kube-proxy v0.30.0 h1:j+09l13SKeGIHEdU+kiOvUjKpqI82S9sGcBFiqC7EJw=
|
||||
k8s.io/kube-proxy v0.30.0/go.mod h1:0Dx6+2DKq73P7RaJaElqwZQ3L02TnCVvU+EaWicnI/s=
|
||||
k8s.io/kubelet v0.30.0 h1:/pqHVR2Rn8ExCpn211wL3pMtqRFpcBcJPl4+1INbIMk=
|
||||
k8s.io/kubelet v0.30.0/go.mod h1:WukdKqbQxnj+csn3K8XOKeX7Sh60J/da25IILjvvB5s=
|
||||
k8s.io/kube-proxy v0.30.2 h1:rBLnKQzXO5u2KO7t3rqYkHf5/oG46ZjqcqfEUw4yOEs=
|
||||
k8s.io/kube-proxy v0.30.2/go.mod h1:7qE0iyUFIi0FJZNO6fe/Eif17RKckTntEl2gjxsta+0=
|
||||
k8s.io/kubelet v0.30.2 h1:Ck4E/pHndI20IzDXxS57dElhDGASPO5pzXF7BcKfmCY=
|
||||
k8s.io/kubelet v0.30.2/go.mod h1:DSwwTbLQmdNkebAU7ypIALR4P9aXZNFwgRmedojUE94=
|
||||
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
|
||||
k8s.io/kubernetes v1.30.0 h1:u3Yw8rNlo2NDSGaDpoxoHXLPQnEu1tfqHATKOJe94HY=
|
||||
k8s.io/kubernetes v1.30.0/go.mod h1:yPbIk3MhmhGigX62FLJm+CphNtjxqCvAIFQXup6RKS0=
|
||||
k8s.io/kubernetes v1.30.2 h1:11WhS78OYX/lnSy6TXxPO6Hk+E5K9ZNrEsk9JgMSX8I=
|
||||
k8s.io/kubernetes v1.30.2/go.mod h1:yPbIk3MhmhGigX62FLJm+CphNtjxqCvAIFQXup6RKS0=
|
||||
k8s.io/system-validators v1.8.0 h1:tq05tdO9zdJZnNF3SXrq6LE7Knc/KfJm5wk68467JDg=
|
||||
k8s.io/system-validators v1.8.0/go.mod h1:gP1Ky+R9wtrSiFbrpEPwWMeYz9yqyy1S/KOh0Vci7WI=
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
|
||||
@@ -61,7 +61,8 @@ func (d Deployment) Build(ctx context.Context, deployment *appsv1.Deployment, te
|
||||
|
||||
d.setLabels(deployment, utilities.MergeMaps(utilities.KamajiLabels(tenantControlPlane.GetName(), "deployment"), tenantControlPlane.Spec.ControlPlane.Deployment.AdditionalMetadata.Labels))
|
||||
d.setAnnotations(deployment, utilities.MergeMaps(deployment.Annotations, tenantControlPlane.Spec.ControlPlane.Deployment.AdditionalMetadata.Annotations))
|
||||
d.setTemplateLabels(&deployment.Spec.Template, d.templateLabels(ctx, &tenantControlPlane))
|
||||
d.setTemplateLabels(&deployment.Spec.Template, utilities.MergeMaps(d.templateLabels(ctx, &tenantControlPlane), tenantControlPlane.Spec.ControlPlane.Deployment.PodAdditionalMetadata.Labels))
|
||||
d.setTemplateAnnotations(&deployment.Spec.Template, tenantControlPlane.Spec.ControlPlane.Deployment.PodAdditionalMetadata.Annotations)
|
||||
d.setNodeSelector(&deployment.Spec.Template.Spec, tenantControlPlane)
|
||||
d.setToleration(&deployment.Spec.Template.Spec, tenantControlPlane)
|
||||
d.setAffinity(&deployment.Spec.Template.Spec, tenantControlPlane)
|
||||
@@ -76,6 +77,7 @@ func (d Deployment) Build(ctx context.Context, deployment *appsv1.Deployment, te
|
||||
d.setContainers(&deployment.Spec.Template.Spec, tenantControlPlane, address)
|
||||
d.setAdditionalVolumes(&deployment.Spec.Template.Spec, tenantControlPlane)
|
||||
d.setVolumes(&deployment.Spec.Template.Spec, tenantControlPlane)
|
||||
d.setServiceAccount(&deployment.Spec.Template.Spec, tenantControlPlane)
|
||||
d.Client.Scheme().Default(deployment)
|
||||
}
|
||||
|
||||
@@ -708,7 +710,7 @@ func (d Deployment) buildKubeAPIServerCommand(tenantControlPlane kamajiv1alpha1.
|
||||
}
|
||||
|
||||
switch d.DataStore.Spec.Driver {
|
||||
case kamajiv1alpha1.KineMySQLDriver, kamajiv1alpha1.KinePostgreSQLDriver:
|
||||
case kamajiv1alpha1.KineMySQLDriver, kamajiv1alpha1.KinePostgreSQLDriver, kamajiv1alpha1.KineNatsDriver:
|
||||
desiredArgs["--etcd-servers"] = "http://127.0.0.1:2379"
|
||||
case kamajiv1alpha1.EtcdDriver:
|
||||
httpsEndpoints := make([]string, 0, len(d.DataStore.Spec.Endpoints))
|
||||
@@ -803,7 +805,10 @@ func (d Deployment) removeKineContainers(podSpec *corev1.PodSpec) {
|
||||
|
||||
podSpec.Containers = containers
|
||||
}
|
||||
// Removing the kine init-container, if present
|
||||
d.removeKineInitContainers(podSpec)
|
||||
}
|
||||
|
||||
func (d Deployment) removeKineInitContainers(podSpec *corev1.PodSpec) {
|
||||
if found, index := utilities.HasNamedContainer(podSpec.InitContainers, kineInitContainerName); found {
|
||||
var initContainers []corev1.Container
|
||||
|
||||
@@ -821,45 +826,67 @@ func (d Deployment) buildKine(podSpec *corev1.PodSpec, tcp kamajiv1alpha1.Tenant
|
||||
|
||||
return
|
||||
}
|
||||
// Ensuring the init container required for kine is present:
|
||||
// a chmod is required for kine in order to read the certificates to connect to the secured datastore.
|
||||
found, index := utilities.HasNamedContainer(podSpec.InitContainers, kineInitContainerName)
|
||||
if !found {
|
||||
index = len(podSpec.InitContainers)
|
||||
podSpec.InitContainers = append(podSpec.InitContainers, corev1.Container{})
|
||||
|
||||
// Building kine arguments, taking in consideration the user-space ones if provided.
|
||||
args := map[string]string{}
|
||||
|
||||
if d.DataStore.Spec.TLSConfig != nil {
|
||||
// Ensuring the init container required for kine is present:
|
||||
// a chmod is required for kine in order to read the certificates to connect to the secured datastore.
|
||||
found, index := utilities.HasNamedContainer(podSpec.InitContainers, kineInitContainerName)
|
||||
if !found {
|
||||
index = len(podSpec.InitContainers)
|
||||
podSpec.InitContainers = append(podSpec.InitContainers, corev1.Container{})
|
||||
}
|
||||
|
||||
podSpec.InitContainers[index].Name = kineInitContainerName
|
||||
podSpec.InitContainers[index].Image = d.KineContainerImage
|
||||
podSpec.InitContainers[index].Command = []string{"sh"}
|
||||
|
||||
podSpec.InitContainers[index].Args = []string{
|
||||
"-c",
|
||||
"cp /kine/*.* /certs && chmod -R 600 /certs/*.*",
|
||||
}
|
||||
|
||||
podSpec.InitContainers[index].VolumeMounts = []corev1.VolumeMount{
|
||||
{
|
||||
Name: dataStoreCertsVolumeName,
|
||||
ReadOnly: true,
|
||||
MountPath: "/kine",
|
||||
},
|
||||
{
|
||||
Name: kineVolumeCertName,
|
||||
MountPath: "/certs",
|
||||
ReadOnly: false,
|
||||
},
|
||||
}
|
||||
|
||||
args["--ca-file"] = "/certs/ca.crt"
|
||||
|
||||
if d.DataStore.Spec.TLSConfig.ClientCertificate != nil {
|
||||
args["--cert-file"] = "/certs/server.crt"
|
||||
args["--key-file"] = "/certs/server.key"
|
||||
}
|
||||
} else {
|
||||
// if no TLS configuration is provided, the kine initContainer must be removed.
|
||||
d.removeKineInitContainers(podSpec)
|
||||
}
|
||||
|
||||
podSpec.InitContainers[index].Name = kineInitContainerName
|
||||
podSpec.InitContainers[index].Image = d.KineContainerImage
|
||||
podSpec.InitContainers[index].Command = []string{"sh"}
|
||||
podSpec.InitContainers[index].Args = []string{
|
||||
"-c",
|
||||
"cp /kine/*.* /certs && chmod -R 600 /certs/*.*",
|
||||
}
|
||||
podSpec.InitContainers[index].VolumeMounts = []corev1.VolumeMount{
|
||||
{
|
||||
Name: dataStoreCertsVolumeName,
|
||||
ReadOnly: true,
|
||||
MountPath: "/kine",
|
||||
},
|
||||
{
|
||||
Name: kineVolumeCertName,
|
||||
MountPath: "/certs",
|
||||
ReadOnly: false,
|
||||
},
|
||||
}
|
||||
// Kine is expecting an additional container, and it must be removed before proceeding with the additional one
|
||||
// in order to make this function idempotent.
|
||||
found, index = utilities.HasNamedContainer(podSpec.Containers, kineContainerName)
|
||||
found, index := utilities.HasNamedContainer(podSpec.Containers, kineContainerName)
|
||||
if !found {
|
||||
index = len(podSpec.Containers)
|
||||
podSpec.Containers = append(podSpec.Containers, corev1.Container{})
|
||||
}
|
||||
// Building kine arguments, taking in consideration the user-space ones if provided.
|
||||
args := map[string]string{}
|
||||
|
||||
if tcp.Spec.ControlPlane.Deployment.ExtraArgs != nil {
|
||||
args = utilities.ArgsFromSliceToMap(tcp.Spec.ControlPlane.Deployment.ExtraArgs.Kine)
|
||||
utilArgs := utilities.ArgsFromSliceToMap(tcp.Spec.ControlPlane.Deployment.ExtraArgs.Kine)
|
||||
|
||||
// Merging the user-space arguments with the Kamaji ones.
|
||||
for k, v := range utilArgs {
|
||||
args[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
switch d.DataStore.Spec.Driver {
|
||||
@@ -867,12 +894,10 @@ func (d Deployment) buildKine(podSpec *corev1.PodSpec, tcp kamajiv1alpha1.Tenant
|
||||
args["--endpoint"] = "mysql://$(DB_USER):$(DB_PASSWORD)@tcp($(DB_CONNECTION_STRING))/$(DB_SCHEMA)"
|
||||
case kamajiv1alpha1.KinePostgreSQLDriver:
|
||||
args["--endpoint"] = "postgres://$(DB_USER):$(DB_PASSWORD)@$(DB_CONNECTION_STRING)/$(DB_SCHEMA)"
|
||||
case kamajiv1alpha1.KineNatsDriver:
|
||||
args["--endpoint"] = "nats://$(DB_USER):$(DB_PASSWORD)@$(DB_CONNECTION_STRING)?bucket=$(DB_SCHEMA)&noEmbed"
|
||||
}
|
||||
|
||||
args["--ca-file"] = "/certs/ca.crt"
|
||||
args["--cert-file"] = "/certs/server.crt"
|
||||
args["--key-file"] = "/certs/server.key"
|
||||
|
||||
podSpec.Containers[index].Name = kineContainerName
|
||||
podSpec.Containers[index].Image = d.KineContainerImage
|
||||
podSpec.Containers[index].Command = []string{"/bin/kine"}
|
||||
@@ -999,6 +1024,10 @@ func (d Deployment) setTemplateLabels(template *corev1.PodTemplateSpec, labels m
|
||||
template.SetLabels(labels)
|
||||
}
|
||||
|
||||
func (d Deployment) setTemplateAnnotations(template *corev1.PodTemplateSpec, annotations map[string]string) {
|
||||
template.SetAnnotations(annotations)
|
||||
}
|
||||
|
||||
func (d Deployment) setLabels(resource *appsv1.Deployment, labels map[string]string) {
|
||||
resource.SetLabels(labels)
|
||||
}
|
||||
@@ -1064,3 +1093,13 @@ func (d Deployment) setToleration(spec *corev1.PodSpec, tcp kamajiv1alpha1.Tenan
|
||||
func (d Deployment) setAffinity(spec *corev1.PodSpec, tcp kamajiv1alpha1.TenantControlPlane) {
|
||||
spec.Affinity = tcp.Spec.ControlPlane.Deployment.Affinity
|
||||
}
|
||||
|
||||
func (d Deployment) setServiceAccount(spec *corev1.PodSpec, tcp kamajiv1alpha1.TenantControlPlane) {
|
||||
if len(tcp.Spec.ControlPlane.Deployment.ServiceAccountName) > 0 {
|
||||
spec.ServiceAccountName = tcp.Spec.ControlPlane.Deployment.ServiceAccountName
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
spec.ServiceAccountName = "default"
|
||||
}
|
||||
|
||||
@@ -21,18 +21,26 @@ func NewStorageConnection(ctx context.Context, client client.Client, ds kamajiv1
|
||||
|
||||
switch ds.Spec.Driver {
|
||||
case kamajiv1alpha1.KineMySQLDriver:
|
||||
cc.TLSConfig.ServerName = cc.Endpoints[0].Host
|
||||
|
||||
if ds.Spec.TLSConfig != nil {
|
||||
cc.TLSConfig.ServerName = cc.Endpoints[0].Host
|
||||
}
|
||||
|
||||
cc.Parameters = map[string][]string{
|
||||
"multiStatements": {"true"},
|
||||
}
|
||||
|
||||
return NewMySQLConnection(*cc)
|
||||
case kamajiv1alpha1.KinePostgreSQLDriver:
|
||||
cc.TLSConfig.ServerName = cc.Endpoints[0].Host
|
||||
if ds.Spec.TLSConfig != nil {
|
||||
cc.TLSConfig.ServerName = cc.Endpoints[0].Host
|
||||
}
|
||||
|
||||
return NewPostgreSQLConnection(*cc)
|
||||
case kamajiv1alpha1.EtcdDriver:
|
||||
return NewETCDConnection(*cc)
|
||||
case kamajiv1alpha1.KineNatsDriver:
|
||||
return NewNATSConnection(*cc)
|
||||
default:
|
||||
return nil, fmt.Errorf("%s is not a valid driver", ds.Spec.Driver)
|
||||
}
|
||||
|
||||
@@ -36,29 +36,41 @@ type ConnectionConfig struct {
|
||||
}
|
||||
|
||||
func NewConnectionConfig(ctx context.Context, client client.Client, ds kamajiv1alpha1.DataStore) (*ConnectionConfig, error) {
|
||||
ca, err := ds.Spec.TLSConfig.CertificateAuthority.Certificate.GetContent(ctx, client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var tlsConfig *tls.Config
|
||||
|
||||
if ds.Spec.TLSConfig != nil {
|
||||
ca, err := ds.Spec.TLSConfig.CertificateAuthority.Certificate.GetContent(ctx, client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rootCAs := x509.NewCertPool()
|
||||
if ok := rootCAs.AppendCertsFromPEM(ca); !ok {
|
||||
return nil, fmt.Errorf("error create root CA for the DB connector")
|
||||
}
|
||||
|
||||
tlsConfig = &tls.Config{
|
||||
RootCAs: rootCAs,
|
||||
}
|
||||
}
|
||||
|
||||
crt, err := ds.Spec.TLSConfig.ClientCertificate.Certificate.GetContent(ctx, client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ds.Spec.TLSConfig != nil && ds.Spec.TLSConfig.ClientCertificate != nil {
|
||||
crt, err := ds.Spec.TLSConfig.ClientCertificate.Certificate.GetContent(ctx, client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key, err := ds.Spec.TLSConfig.ClientCertificate.PrivateKey.GetContent(ctx, client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key, err := ds.Spec.TLSConfig.ClientCertificate.PrivateKey.GetContent(ctx, client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rootCAs := x509.NewCertPool()
|
||||
if ok := rootCAs.AppendCertsFromPEM(ca); !ok {
|
||||
return nil, fmt.Errorf("error create root CA for the DB connector")
|
||||
}
|
||||
certificate, err := tls.X509KeyPair(crt, key)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot retrieve x.509 key pair from the Kine Secret")
|
||||
}
|
||||
|
||||
certificate, err := tls.X509KeyPair(crt, key)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot retrieve x.509 key pair from the Kine Secret")
|
||||
tlsConfig.Certificates = []tls.Certificate{certificate}
|
||||
}
|
||||
|
||||
var user, password string
|
||||
@@ -99,10 +111,7 @@ func NewConnectionConfig(ctx context.Context, client client.Client, ds kamajiv1a
|
||||
User: user,
|
||||
Password: password,
|
||||
Endpoints: eps,
|
||||
TLSConfig: &tls.Config{
|
||||
RootCAs: rootCAs,
|
||||
Certificates: []tls.Certificate{certificate},
|
||||
},
|
||||
TLSConfig: tlsConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -112,12 +112,14 @@ func NewMySQLConnection(config ConnectionConfig) (Connection, error) {
|
||||
|
||||
tlsKey := "mysql"
|
||||
|
||||
if err = mysql.RegisterTLSConfig(tlsKey, config.TLSConfig); err != nil {
|
||||
return nil, err
|
||||
if config.TLSConfig != nil {
|
||||
if err = mysql.RegisterTLSConfig(tlsKey, config.TLSConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mysqlConfig.TLSConfig = tlsKey
|
||||
}
|
||||
|
||||
mysqlConfig.DBName = config.DBName
|
||||
mysqlConfig.TLSConfig = tlsKey
|
||||
parsedDSN := mysqlConfig.FormatDSN()
|
||||
|
||||
db, err := sql.Open("mysql", parsedDSN)
|
||||
|
||||
184
internal/datastore/nats.go
Normal file
184
internal/datastore/nats.go
Normal file
@@ -0,0 +1,184 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package datastore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
|
||||
// NATSConnection represents a connection to a NATS KV store.
|
||||
type NATSConnection struct {
|
||||
js nats.JetStreamContext
|
||||
conn *nats.Conn
|
||||
config ConnectionConfig
|
||||
}
|
||||
|
||||
// NewNATSConnection initializes a connection to NATS and sets up the KV store.
|
||||
func NewNATSConnection(config ConnectionConfig) (*NATSConnection, error) {
|
||||
var endpoints string
|
||||
|
||||
if len(config.Endpoints) > 1 {
|
||||
// comma separated list of endpoints
|
||||
var ep []string
|
||||
for _, e := range config.Endpoints {
|
||||
ep = append(ep, fmt.Sprintf("nats://%s", e.String()))
|
||||
}
|
||||
|
||||
endpoints = strings.Join(ep, ",")
|
||||
} else {
|
||||
endpoints = fmt.Sprintf("nats://%s", config.Endpoints[0].String())
|
||||
}
|
||||
|
||||
var conn *nats.Conn
|
||||
var err error
|
||||
var natsOpts []nats.Option
|
||||
|
||||
if config.TLSConfig != nil {
|
||||
natsOpts = append(natsOpts, nats.Secure(config.TLSConfig))
|
||||
}
|
||||
|
||||
if config.User != "" && config.Password != "" {
|
||||
natsOpts = append(natsOpts, nats.UserInfo(config.User, config.Password))
|
||||
}
|
||||
|
||||
conn, err = nats.Connect(endpoints, natsOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
js, err := conn.JetStream()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &NATSConnection{
|
||||
js: js,
|
||||
conn: conn,
|
||||
config: config,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) CreateUser(_ context.Context, _, _ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) CreateDB(_ context.Context, dbName string) error {
|
||||
_, err := nc.js.CreateKeyValue(&nats.KeyValueConfig{Bucket: dbName})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to create the datastore")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) GrantPrivileges(_ context.Context, _, _ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) UserExists(_ context.Context, _ string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) DBExists(_ context.Context, dbName string) (bool, error) {
|
||||
_, err := nc.js.KeyValue(dbName)
|
||||
if err != nil {
|
||||
if errors.Is(err, nats.ErrBucketNotFound) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) GrantPrivilegesExists(_ context.Context, _, _ string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) DeleteUser(_ context.Context, _ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) DeleteDB(_ context.Context, dbName string) error {
|
||||
err := nc.js.DeleteKeyValue(dbName)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) RevokePrivileges(_ context.Context, _, _ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) GetConnectionString() string {
|
||||
return nc.config.Endpoints[0].String()
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) Close() error {
|
||||
return nc.conn.Drain()
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) Check(_ context.Context) error {
|
||||
status := nc.conn.Status()
|
||||
|
||||
if status != nats.CONNECTED {
|
||||
return errors.New("connection to NATS is not established")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) Driver() string {
|
||||
return string(kamajiv1alpha1.KineNatsDriver)
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) GetConfig() ConnectionConfig {
|
||||
return nc.config
|
||||
}
|
||||
|
||||
func (nc *NATSConnection) Migrate(ctx context.Context, tcp kamajiv1alpha1.TenantControlPlane, target Connection) error {
|
||||
targetClient := target.(*NATSConnection) //nolint:forcetypeassert
|
||||
dbName := tcp.Status.Storage.Setup.Schema
|
||||
|
||||
targetKv, err := targetClient.js.KeyValue(dbName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sourceKv, err := nc.js.KeyValue(dbName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := target.Check(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// copy all keys from source to target
|
||||
keys, err := sourceKv.Keys()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
entry, err := sourceKv.Get(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = targetKv.Put(key, entry.Value())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
goerrors "github.com/pkg/errors"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/datastore/errors"
|
||||
@@ -34,6 +35,7 @@ const (
|
||||
type PostgreSQLConnection struct {
|
||||
db *pg.DB
|
||||
connection ConnectionEndpoint
|
||||
rootUser string
|
||||
switchDatabaseFn func(dbName string) *pg.DB
|
||||
}
|
||||
|
||||
@@ -114,6 +116,7 @@ func NewPostgreSQLConnection(config ConnectionConfig) (Connection, error) {
|
||||
return &PostgreSQLConnection{
|
||||
db: pg.Connect(opt),
|
||||
switchDatabaseFn: fn,
|
||||
rootUser: config.User,
|
||||
connection: config.Endpoints[0],
|
||||
}, nil
|
||||
}
|
||||
@@ -232,6 +235,10 @@ func (r *PostgreSQLConnection) DeleteUser(ctx context.Context, user string) erro
|
||||
}
|
||||
|
||||
func (r *PostgreSQLConnection) DeleteDB(ctx context.Context, dbName string) error {
|
||||
if err := r.GrantPrivileges(ctx, r.rootUser, dbName); err != nil {
|
||||
return errors.NewCannotDeleteDatabaseError(goerrors.Wrap(err, "cannot grant privileges to root user"))
|
||||
}
|
||||
|
||||
if _, err := r.db.ExecContext(ctx, fmt.Sprintf(postgresqlDropDBStatement, dbName)); err != nil {
|
||||
return errors.NewCannotDeleteDatabaseError(err)
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ func (r *Certificate) Define(_ context.Context, tenantControlPlane *kamajiv1alph
|
||||
Name: r.getPrefixedName(tenantControlPlane),
|
||||
Namespace: tenantControlPlane.GetNamespace(),
|
||||
},
|
||||
Data: map[string][]byte{},
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -80,79 +79,93 @@ func (r *Certificate) mutate(ctx context.Context, tenantControlPlane *kamajiv1al
|
||||
return func() error {
|
||||
logger := log.FromContext(ctx, "resource", r.GetName())
|
||||
|
||||
ca, err := r.DataStore.Spec.TLSConfig.CertificateAuthority.Certificate.GetContent(ctx, r.Client)
|
||||
if err != nil {
|
||||
logger.Error(err, "cannot retrieve CA certificate content")
|
||||
if r.DataStore.Spec.TLSConfig != nil {
|
||||
ca, err := r.DataStore.Spec.TLSConfig.CertificateAuthority.Certificate.GetContent(ctx, r.Client)
|
||||
if err != nil {
|
||||
logger.Error(err, "cannot retrieve CA certificate content")
|
||||
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
r.resource.Data["ca.crt"] = ca
|
||||
if r.resource.Data == nil {
|
||||
r.resource.Data = map[string][]byte{}
|
||||
}
|
||||
|
||||
r.resource.SetLabels(utilities.MergeMaps(
|
||||
utilities.KamajiLabels(tenantControlPlane.GetName(), r.GetName()),
|
||||
map[string]string{
|
||||
constants.ControllerLabelResource: "x509",
|
||||
},
|
||||
))
|
||||
r.resource.Data["ca.crt"] = ca
|
||||
|
||||
if err = ctrl.SetControllerReference(tenantControlPlane, r.resource, r.Client.Scheme()); err != nil {
|
||||
logger.Error(err, "cannot set controller reference", "resource", r.GetName())
|
||||
r.resource.SetLabels(utilities.MergeMaps(
|
||||
utilities.KamajiLabels(tenantControlPlane.GetName(), r.GetName()),
|
||||
map[string]string{
|
||||
constants.ControllerLabelResource: "x509",
|
||||
},
|
||||
))
|
||||
|
||||
return err
|
||||
}
|
||||
if err = ctrl.SetControllerReference(tenantControlPlane, r.resource, r.Client.Scheme()); err != nil {
|
||||
logger.Error(err, "cannot set controller reference", "resource", r.GetName())
|
||||
|
||||
if utilities.GetObjectChecksum(r.resource) == utilities.CalculateMapChecksum(r.resource.Data) {
|
||||
if r.DataStore.Spec.Driver == kamajiv1alpha1.EtcdDriver {
|
||||
if isValid, _ := crypto.IsValidCertificateKeyPairBytes(r.resource.Data["server.crt"], r.resource.Data["server.key"]); isValid {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if utilities.GetObjectChecksum(r.resource) == utilities.CalculateMapChecksum(r.resource.Data) {
|
||||
if r.DataStore.Spec.Driver == kamajiv1alpha1.EtcdDriver {
|
||||
if isValid, _ := crypto.IsValidCertificateKeyPairBytes(r.resource.Data["server.crt"], r.resource.Data["server.key"]); isValid {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var crt, key *bytes.Buffer
|
||||
|
||||
switch r.DataStore.Spec.Driver {
|
||||
case kamajiv1alpha1.EtcdDriver:
|
||||
var privateKey []byte
|
||||
// When dealing with the etcd storage we cannot use the basic authentication, thus the generation of a
|
||||
// certificate used for authentication is mandatory, along with the CA private key.
|
||||
if privateKey, err = r.DataStore.Spec.TLSConfig.CertificateAuthority.PrivateKey.GetContent(ctx, r.Client); err != nil {
|
||||
logger.Error(err, "unable to retrieve CA private key content")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if crt, key, err = crypto.GenerateCertificatePrivateKeyPair(crypto.NewCertificateTemplate(tenantControlPlane.Status.Storage.Setup.User), ca, privateKey); err != nil {
|
||||
logger.Error(err, "unable to generate certificate and private key")
|
||||
|
||||
return err
|
||||
}
|
||||
case kamajiv1alpha1.KineMySQLDriver, kamajiv1alpha1.KinePostgreSQLDriver, kamajiv1alpha1.KineNatsDriver:
|
||||
var crtBytes, keyBytes []byte
|
||||
// For the SQL drivers we just need to copy the certificate, since the basic authentication is used
|
||||
// to connect to the desired schema and database.
|
||||
|
||||
if r.DataStore.Spec.TLSConfig.ClientCertificate != nil {
|
||||
if crtBytes, err = r.DataStore.Spec.TLSConfig.ClientCertificate.Certificate.GetContent(ctx, r.Client); err != nil {
|
||||
logger.Error(err, "unable to retrieve certificate content")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
crt = bytes.NewBuffer(crtBytes)
|
||||
|
||||
if keyBytes, err = r.DataStore.Spec.TLSConfig.ClientCertificate.PrivateKey.GetContent(ctx, r.Client); err != nil {
|
||||
logger.Error(err, "unable to retrieve private key content")
|
||||
|
||||
return err
|
||||
}
|
||||
key = bytes.NewBuffer(keyBytes)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unrecognized driver for Certificate generation")
|
||||
}
|
||||
|
||||
if r.DataStore.Spec.TLSConfig.ClientCertificate != nil {
|
||||
r.resource.Data["server.crt"] = crt.Bytes()
|
||||
r.resource.Data["server.key"] = key.Bytes()
|
||||
}
|
||||
} else {
|
||||
// set r.resource.Data to empty to allow switching from TLS to non-tls
|
||||
r.resource.Data = map[string][]byte{}
|
||||
}
|
||||
|
||||
var crt, key *bytes.Buffer
|
||||
|
||||
switch r.DataStore.Spec.Driver {
|
||||
case kamajiv1alpha1.EtcdDriver:
|
||||
var privateKey []byte
|
||||
// When dealing with the etcd storage we cannot use the basic authentication, thus the generation of a
|
||||
// certificate used for authentication is mandatory, along with the CA private key.
|
||||
if privateKey, err = r.DataStore.Spec.TLSConfig.CertificateAuthority.PrivateKey.GetContent(ctx, r.Client); err != nil {
|
||||
logger.Error(err, "unable to retrieve CA private key content")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if crt, key, err = crypto.GenerateCertificatePrivateKeyPair(crypto.NewCertificateTemplate(tenantControlPlane.Status.Storage.Setup.User), ca, privateKey); err != nil {
|
||||
logger.Error(err, "unable to generate certificate and private key")
|
||||
|
||||
return err
|
||||
}
|
||||
case kamajiv1alpha1.KineMySQLDriver, kamajiv1alpha1.KinePostgreSQLDriver:
|
||||
var crtBytes, keyBytes []byte
|
||||
// For the SQL drivers we just need to copy the certificate, since the basic authentication is used
|
||||
// to connect to the desired schema and database.
|
||||
if crtBytes, err = r.DataStore.Spec.TLSConfig.ClientCertificate.Certificate.GetContent(ctx, r.Client); err != nil {
|
||||
logger.Error(err, "unable to retrieve certificate content")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
crt = bytes.NewBuffer(crtBytes)
|
||||
|
||||
if keyBytes, err = r.DataStore.Spec.TLSConfig.ClientCertificate.PrivateKey.GetContent(ctx, r.Client); err != nil {
|
||||
logger.Error(err, "unable to retrieve private key content")
|
||||
|
||||
return err
|
||||
}
|
||||
key = bytes.NewBuffer(keyBytes)
|
||||
default:
|
||||
return fmt.Errorf("unrecognized driver for Certificate generation")
|
||||
}
|
||||
|
||||
r.resource.Data["server.crt"] = crt.Bytes()
|
||||
r.resource.Data["server.key"] = key.Bytes()
|
||||
|
||||
utilities.SetObjectChecksum(r.resource, r.resource.Data)
|
||||
|
||||
return nil
|
||||
|
||||
62
internal/resources/datastore/datastore_multitenancy.go
Normal file
62
internal/resources/datastore/datastore_multitenancy.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package datastore
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
|
||||
type MultiTenancy struct {
|
||||
DataStore kamajiv1alpha1.DataStore
|
||||
}
|
||||
|
||||
func (m MultiTenancy) Define(context.Context, *kamajiv1alpha1.TenantControlPlane) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m MultiTenancy) ShouldCleanup(*kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (m MultiTenancy) CleanUp(context.Context, *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (m MultiTenancy) CreateOrUpdate(_ context.Context, tcp *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
// If the NATS Datastore is already used by a Tenant Control Plane
|
||||
// and a new one is reclaiming it, we need to stop it, since it's not allowed.
|
||||
// TODO(prometherion): remove this after multi-tenancy is implemented for NATS.
|
||||
if m.DataStore.Spec.Driver != kamajiv1alpha1.KineNatsDriver {
|
||||
return controllerutil.OperationResultNone, nil
|
||||
}
|
||||
|
||||
usedBy := sets.New[string](m.DataStore.Status.UsedBy...)
|
||||
|
||||
switch {
|
||||
case usedBy.Has(tcp.Namespace + "/" + tcp.Name):
|
||||
return controllerutil.OperationResultNone, nil
|
||||
case usedBy.Len() == 0:
|
||||
return controllerutil.OperationResultNone, nil
|
||||
default:
|
||||
return controllerutil.OperationResultNone, errors.New("NATS doesn't support multi-tenancy, the current datastore is already in use")
|
||||
}
|
||||
}
|
||||
|
||||
func (m MultiTenancy) GetName() string {
|
||||
return "ds.multitenancy"
|
||||
}
|
||||
|
||||
func (m MultiTenancy) ShouldStatusBeUpdated(context.Context, *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (m MultiTenancy) UpdateTenantControlPlaneStatus(context.Context, *kamajiv1alpha1.TenantControlPlane) error {
|
||||
return nil
|
||||
}
|
||||
@@ -104,9 +104,10 @@ func (r *Config) UpdateTenantControlPlaneStatus(_ context.Context, tenantControl
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Config) mutate(_ context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) controllerutil.MutateFn {
|
||||
func (r *Config) mutate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) controllerutil.MutateFn {
|
||||
return func() error {
|
||||
var password []byte
|
||||
var username []byte
|
||||
|
||||
hash := utilities.GetObjectChecksum(r.resource)
|
||||
switch {
|
||||
@@ -133,10 +134,31 @@ func (r *Config) mutate(_ context.Context, tenantControlPlane *kamajiv1alpha1.Te
|
||||
finalizersList.Insert(finalizers.DatastoreSecretFinalizer)
|
||||
r.resource.SetFinalizers(finalizersList.UnsortedList())
|
||||
|
||||
// TODO(thecodeassassin): remove this after multi-tenancy is implemented for NATS.
|
||||
// Due to NATS is missing a programmatic approach to create users and password,
|
||||
// we're using the Datastore root password.
|
||||
if r.DataStore.Spec.Driver == kamajiv1alpha1.KineNatsDriver {
|
||||
// set username and password to the basicAuth values of the NATS datastore
|
||||
u, err := r.DataStore.Spec.BasicAuth.Username.GetContent(ctx, r.Client)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to retrieve the username for the NATS datastore")
|
||||
}
|
||||
|
||||
p, err := r.DataStore.Spec.BasicAuth.Password.GetContent(ctx, r.Client)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to retrieve the password for the NATS datastore")
|
||||
}
|
||||
|
||||
username = u
|
||||
password = p
|
||||
} else {
|
||||
username = coalesceFn(tenantControlPlane.Status.Storage.Setup.User)
|
||||
}
|
||||
|
||||
r.resource.Data = map[string][]byte{
|
||||
"DB_CONNECTION_STRING": []byte(r.ConnString),
|
||||
"DB_SCHEMA": coalesceFn(tenantControlPlane.Status.Storage.Setup.Schema),
|
||||
"DB_USER": coalesceFn(tenantControlPlane.Status.Storage.Setup.User),
|
||||
"DB_USER": username,
|
||||
"DB_PASSWORD": password,
|
||||
}
|
||||
|
||||
|
||||
@@ -126,12 +126,7 @@ func (r *Agent) mutate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.T
|
||||
))
|
||||
|
||||
r.resource.Spec.Template.Spec.PriorityClassName = "system-cluster-critical"
|
||||
r.resource.Spec.Template.Spec.Tolerations = []corev1.Toleration{
|
||||
{
|
||||
Key: "CriticalAddonsOnly",
|
||||
Operator: "Exists",
|
||||
},
|
||||
}
|
||||
r.resource.Spec.Template.Spec.Tolerations = tenantControlPlane.Spec.Addons.Konnectivity.KonnectivityAgentSpec.Tolerations
|
||||
r.resource.Spec.Template.Spec.NodeSelector = map[string]string{
|
||||
"kubernetes.io/os": "linux",
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ func (k *KubernetesUpgrade) CreateOrUpdate(ctx context.Context, tenantControlPla
|
||||
return controllerutil.OperationResultNone, errors.Wrap(err, "cannot create REST client required for Kubernetes upgrade plan")
|
||||
}
|
||||
|
||||
versionGetter := kamajiupgrade.NewKamajiKubeVersionGetter(clientSet)
|
||||
versionGetter := kamajiupgrade.NewKamajiKubeVersionGetter(clientSet, tenantControlPlane.Status.Kubernetes.Version.Version)
|
||||
|
||||
if _, err = upgrade.GetAvailableUpgrades(versionGetter, false, false, clientSet, &printers.Discard{}); err != nil {
|
||||
return controllerutil.OperationResultNone, errors.Wrap(err, "cannot retrieve available Upgrades for Kubernetes upgrade plan")
|
||||
|
||||
@@ -16,12 +16,13 @@ import (
|
||||
|
||||
type kamajiKubeVersionGetter struct {
|
||||
upgrade.VersionGetter
|
||||
Version string
|
||||
}
|
||||
|
||||
func NewKamajiKubeVersionGetter(restClient kubernetes.Interface) upgrade.VersionGetter {
|
||||
func NewKamajiKubeVersionGetter(restClient kubernetes.Interface, version string) upgrade.VersionGetter {
|
||||
kubeVersionGetter := upgrade.NewOfflineVersionGetter(upgrade.NewKubeVersionGetter(restClient), KubeadmVersion)
|
||||
|
||||
return &kamajiKubeVersionGetter{VersionGetter: kubeVersionGetter}
|
||||
return &kamajiKubeVersionGetter{VersionGetter: kubeVersionGetter, Version: version}
|
||||
}
|
||||
|
||||
func (k kamajiKubeVersionGetter) ClusterVersion() (string, *versionutil.Version, error) {
|
||||
@@ -51,3 +52,9 @@ func (k kamajiKubeVersionGetter) VersionFromCILabel(ciVersionLabel, description
|
||||
func (k kamajiKubeVersionGetter) KubeletVersions() (map[string][]string, error) {
|
||||
return k.VersionGetter.KubeletVersions()
|
||||
}
|
||||
|
||||
func (k kamajiKubeVersionGetter) ComponentVersions(string) (map[string][]string, error) {
|
||||
return map[string][]string{
|
||||
k.Version: {"kamaji"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
package upgrade
|
||||
|
||||
const (
|
||||
KubeadmVersion = "v1.30.0"
|
||||
KubeadmVersion = "v1.30.2"
|
||||
)
|
||||
|
||||
@@ -14,13 +14,7 @@ func ArgsFromSliceToMap(args []string) (m map[string]string) {
|
||||
m = make(map[string]string)
|
||||
|
||||
for _, arg := range args {
|
||||
parts := strings.SplitN(arg, "=", 2)
|
||||
|
||||
flag, value := parts[0], ""
|
||||
|
||||
if len(parts) > 1 {
|
||||
value = parts[1]
|
||||
}
|
||||
flag, value, _ := strings.Cut(arg, "=")
|
||||
|
||||
m[flag] = value
|
||||
}
|
||||
|
||||
30
internal/utilities/args_test.go
Normal file
30
internal/utilities/args_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package utilities
|
||||
|
||||
import (
|
||||
"maps"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestArgsFromSliceToMap(t *testing.T) {
|
||||
tests := map[string]map[string]string{
|
||||
"--a": {"--a": ""},
|
||||
"--a=": {"--a": ""},
|
||||
"--a=b": {"--a": "b"},
|
||||
"--a=b=c": {"--a": "b=c"},
|
||||
}
|
||||
|
||||
got := ArgsFromSliceToMap([]string{})
|
||||
if len(got) != 0 {
|
||||
t.Errorf("expected empty input to result in empty map, but got %+v", got)
|
||||
}
|
||||
|
||||
for arg, expect := range tests {
|
||||
got := ArgsFromSliceToMap([]string{arg})
|
||||
if !maps.Equal(expect, got) {
|
||||
t.Errorf("expected input %q to result in %+v, but got %+v", arg, expect, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,7 +60,7 @@ func GetRESTClientConfig(ctx context.Context, client client.Client, tenantContro
|
||||
}
|
||||
|
||||
config := &restclient.Config{
|
||||
Host: fmt.Sprintf("https://%s.%s.svc.cluster.local:%d", tenantControlPlane.GetName(), tenantControlPlane.GetNamespace(), tenantControlPlane.Spec.NetworkProfile.Port),
|
||||
Host: fmt.Sprintf("https://%s.%s.svc:%d", tenantControlPlane.GetName(), tenantControlPlane.GetNamespace(), tenantControlPlane.Spec.NetworkProfile.Port),
|
||||
TLSClientConfig: restclient.TLSClientConfig{
|
||||
CAData: kubeconfig.Clusters[0].Cluster.CertificateAuthorityData,
|
||||
CertData: kubeconfig.AuthInfos[0].AuthInfo.ClientCertificateData,
|
||||
|
||||
@@ -84,6 +84,10 @@ func (d DataStoreValidation) validateBasicAuth(ctx context.Context, ds kamajiv1a
|
||||
}
|
||||
|
||||
func (d DataStoreValidation) validateTLSConfig(ctx context.Context, ds kamajiv1alpha1.DataStore) error {
|
||||
if ds.Spec.TLSConfig == nil && ds.Spec.Driver != kamajiv1alpha1.EtcdDriver {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := d.validateContentReference(ctx, ds.Spec.TLSConfig.CertificateAuthority.Certificate); err != nil {
|
||||
return fmt.Errorf("CA certificate is not valid, %w", err)
|
||||
}
|
||||
|
||||
71
internal/webhook/handlers/tcp_service_cidr.go
Normal file
71
internal/webhook/handlers/tcp_service_cidr.go
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"gomodules.xyz/jsonpatch/v2"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/webhook/utils"
|
||||
)
|
||||
|
||||
type TenantControlPlaneServiceCIDR struct{}
|
||||
|
||||
func (t TenantControlPlaneServiceCIDR) handle(tcp *kamajiv1alpha1.TenantControlPlane) error {
|
||||
if tcp.Spec.Addons.CoreDNS == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, cidr, err := net.ParseCIDR(tcp.Spec.NetworkProfile.ServiceCIDR)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse Service CIDR, %s", err.Error())
|
||||
}
|
||||
|
||||
for _, serviceIP := range tcp.Spec.NetworkProfile.DNSServiceIPs {
|
||||
ip := net.ParseIP(serviceIP)
|
||||
if ip == nil {
|
||||
return fmt.Errorf("unable to parse IP address %s", serviceIP)
|
||||
}
|
||||
|
||||
if !cidr.Contains(ip) {
|
||||
return fmt.Errorf("the Service CIDR does not contain the DNS Service IP %s", serviceIP)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t TenantControlPlaneServiceCIDR) OnCreate(object runtime.Object) AdmissionResponse {
|
||||
return func(context.Context, admission.Request) ([]jsonpatch.JsonPatchOperation, error) {
|
||||
tcp := object.(*kamajiv1alpha1.TenantControlPlane) //nolint:forcetypeassert
|
||||
|
||||
if err := t.handle(tcp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (t TenantControlPlaneServiceCIDR) OnDelete(runtime.Object) AdmissionResponse {
|
||||
return utils.NilOp()
|
||||
}
|
||||
|
||||
func (t TenantControlPlaneServiceCIDR) OnUpdate(object runtime.Object, _ runtime.Object) AdmissionResponse {
|
||||
return func(ctx context.Context, req admission.Request) ([]jsonpatch.JsonPatchOperation, error) {
|
||||
tcp := object.(*kamajiv1alpha1.TenantControlPlane) //nolint:forcetypeassert
|
||||
|
||||
if err := t.handle(tcp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user