diff --git a/api/v1alpha1/tenantcontrolplane_types.go b/api/v1alpha1/tenantcontrolplane_types.go
index bcb6bc4..2cc0a39 100644
--- a/api/v1alpha1/tenantcontrolplane_types.go
+++ b/api/v1alpha1/tenantcontrolplane_types.go
@@ -277,8 +277,10 @@ type AddonsSpec struct {
// +kubebuilder:validation:XValidation:rule="oldSelf.controlPlane.service.serviceType != self.controlPlane.service.serviceType || (!has(oldSelf.networkProfile.loadBalancerClass) && has(self.networkProfile.loadBalancerClass))",message="LoadBalancerClass can not be unset"
type TenantControlPlaneSpec struct {
- // DataStore allows to specify a DataStore that should be used to store the Kubernetes data for the given Tenant Control Plane.
- // This parameter is optional and acts as an override over the default one which is used by the Kamaji Operator.
+ // DataStore specifies the DataStore that should be used to store the Kubernetes data for the given Tenant Control Plane.
+ // When Kamaji runs with the default DataStore flag, all empty values will inherit the default value.
+ // By leaving it empty and running Kamaji with no default DataStore flag, it is possible to achieve automatic assignment to a specific DataStore object.
+ //
// Migration from one DataStore to another backed by the same Driver is possible. See: https://kamaji.clastix.io/guides/datastore-migration/
// Migration from one DataStore to another backed by a different Driver is not supported.
DataStore string `json:"dataStore,omitempty"`
diff --git a/charts/kamaji/README.md b/charts/kamaji/README.md
index 01d4634..7622135 100644
--- a/charts/kamaji/README.md
+++ b/charts/kamaji/README.md
@@ -70,7 +70,7 @@ Here the values you can override:
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| affinity | object | `{}` | Kubernetes affinity rules to apply to Kamaji controller pods |
-| defaultDatastoreName | string | `"default"` | Specify the default DataStore name for the Kamaji instance. |
+| defaultDatastoreName | string | `"default"` | If specified, all the Kamaji instances with an unassigned DataStore will inherit this default value. |
| extraArgs | list | `[]` | A list of extra arguments to add to the kamaji controller default ones |
| fullnameOverride | string | `""` | |
| healthProbeBindAddress | string | `":8081"` | The address the probe endpoint binds to. (default ":8081") |
diff --git a/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml b/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml
index 27c07ce..82bdfb3 100644
--- a/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml
+++ b/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml
@@ -6412,8 +6412,10 @@ spec:
type: object
dataStore:
description: |-
- DataStore allows to specify a DataStore that should be used to store the Kubernetes data for the given Tenant Control Plane.
- This parameter is optional and acts as an override over the default one which is used by the Kamaji Operator.
+ DataStore specifies the DataStore that should be used to store the Kubernetes data for the given Tenant Control Plane.
+ When Kamaji runs with the default DataStore flag, all empty values will inherit the default value.
+ By leaving it empty and running Kamaji with no default DataStore flag, it is possible to achieve automatic assignment to a specific DataStore object.
+
Migration from one DataStore to another backed by the same Driver is possible. See: https://kamaji.clastix.io/guides/datastore-migration/
Migration from one DataStore to another backed by a different Driver is not supported.
type: string
diff --git a/charts/kamaji/templates/controller.yaml b/charts/kamaji/templates/controller.yaml
index d4ca6dc..38d635d 100644
--- a/charts/kamaji/templates/controller.yaml
+++ b/charts/kamaji/templates/controller.yaml
@@ -33,8 +33,9 @@ spec:
- --leader-elect
- --metrics-bind-address={{ .Values.metricsBindAddress }}
- --tmp-directory={{ .Values.temporaryDirectoryPath }}
- {{- $datastoreName := .Values.defaultDatastoreName | required ".Values.defaultDatastoreName is required!" }}
- - --datastore={{ $datastoreName }}
+ {{- if not (eq .Values.defaultDatastoreName "") }}
+ - --datastore={{ .Values.defaultDatastoreName }}
+ {{- end }}
{{- if .Values.telemetry.disabled }}
- --disable-telemetry
{{- end }}
diff --git a/charts/kamaji/values.yaml b/charts/kamaji/values.yaml
index 21b529e..79dd254 100644
--- a/charts/kamaji/values.yaml
+++ b/charts/kamaji/values.yaml
@@ -95,7 +95,7 @@ loggingDevel:
# -- Development Mode defaults(encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn). Production Mode defaults(encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error) (default false)
enable: false
-# -- Specify the default DataStore name for the Kamaji instance.
+# -- If specified, all the Kamaji instances with an unassigned DataStore will inherit this default value.
defaultDatastoreName: default
kamaji-etcd:
diff --git a/cmd/manager/cmd.go b/cmd/manager/cmd.go
index 82df75e..be55973 100644
--- a/cmd/manager/cmd.go
+++ b/cmd/manager/cmd.go
@@ -73,7 +73,7 @@ func NewCmd(scheme *runtime.Scheme) *cobra.Command {
klog.SetOutput(io.Discard)
klog.LogToStderr(false)
- if err = cmdutils.CheckFlags(cmd.Flags(), []string{"kine-image", "datastore", "migrate-image", "tmp-directory", "pod-namespace", "webhook-service-name", "serviceaccount-name", "webhook-ca-path"}...); err != nil {
+ if err = cmdutils.CheckFlags(cmd.Flags(), []string{"kine-image", "migrate-image", "tmp-directory", "pod-namespace", "webhook-service-name", "serviceaccount-name", "webhook-ca-path"}...); err != nil {
return err
}
@@ -304,7 +304,7 @@ func NewCmd(scheme *runtime.Scheme) *cobra.Command {
cmd.Flags().BoolVar(&leaderElect, "leader-elect", true, "Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.")
cmd.Flags().StringVar(&tmpDirectory, "tmp-directory", "/tmp/kamaji", "Directory which will be used to work with temporary files.")
cmd.Flags().StringVar(&kineImage, "kine-image", "rancher/kine:v0.11.10-amd64", "Container image along with tag to use for the Kine sidecar container (used only if etcd-storage-type is set to one of kine strategies).")
- cmd.Flags().StringVar(&datastore, "datastore", "etcd", "The default DataStore that should be used by Kamaji to setup the required storage.")
+ cmd.Flags().StringVar(&datastore, "datastore", "", "Optional, the default DataStore that should be used by Kamaji to setup the required storage of Tenant Control Planes with undeclared DataStore.")
cmd.Flags().StringVar(&migrateJobImage, "migrate-image", fmt.Sprintf("clastix/kamaji:%s", internal.GitTag), "Specify the container image to launch when a TenantControlPlane is migrated to a new datastore.")
cmd.Flags().IntVar(&maxConcurrentReconciles, "max-concurrent-tcp-reconciles", 1, "Specify the number of workers for the Tenant Control Plane controller (beware of CPU consumption)")
cmd.Flags().StringVar(&managerNamespace, "pod-namespace", os.Getenv("POD_NAMESPACE"), "The Kubernetes Namespace on which the Operator is running in, required for the TenantControlPlane migration jobs.")
diff --git a/controllers/tenantcontrolplane_controller.go b/controllers/tenantcontrolplane_controller.go
index 72dd141..1d441e3 100644
--- a/controllers/tenantcontrolplane_controller.go
+++ b/controllers/tenantcontrolplane_controller.go
@@ -122,6 +122,12 @@ func (r *TenantControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R
// Retrieving the DataStore to use for the current reconciliation
ds, err := r.dataStore(ctx, tenantControlPlane)
if err != nil {
+ if errors.Is(err, ErrMissingDataStore) {
+ log.Info(err.Error())
+
+ return ctrl.Result{Requeue: true}, nil
+ }
+
log.Error(err, "cannot retrieve the DataStore for the given instance")
return ctrl.Result{}, err
@@ -300,18 +306,23 @@ func (r *TenantControlPlaneReconciler) RemoveFinalizer(ctx context.Context, tena
return r.Client.Update(ctx, tenantControlPlane)
}
+var ErrMissingDataStore = errors.New("the Tenant Control Plane doesn't have a DataStore assigned, and Kamaji is running with no default DataStore fallback")
+
// dataStore retrieves the override DataStore for the given Tenant Control Plane if specified,
// otherwise fallback to the default one specified in the Kamaji setup.
func (r *TenantControlPlaneReconciler) dataStore(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*kamajiv1alpha1.DataStore, error) {
- dataStoreName := tenantControlPlane.Spec.DataStore
- if len(dataStoreName) == 0 {
- dataStoreName = r.Config.DefaultDataStoreName
+ if tenantControlPlane.Spec.DataStore == "" && r.Config.DefaultDataStoreName == "" {
+ return nil, ErrMissingDataStore
}
- ds := &kamajiv1alpha1.DataStore{}
- if err := r.Client.Get(ctx, k8stypes.NamespacedName{Name: dataStoreName}, ds); err != nil {
+ if tenantControlPlane.Spec.DataStore == "" {
+ tenantControlPlane.Spec.DataStore = r.Config.DefaultDataStoreName
+ }
+
+ var ds kamajiv1alpha1.DataStore
+ if err := r.Client.Get(ctx, k8stypes.NamespacedName{Name: tenantControlPlane.Spec.DataStore}, &ds); err != nil {
return nil, errors.Wrap(err, "cannot retrieve *kamajiv1alpha.DataStore object")
}
- return ds, nil
+ return &ds, nil
}
diff --git a/docs/content/reference/api.md b/docs/content/reference/api.md
index 24f6a04..8fed87f 100644
--- a/docs/content/reference/api.md
+++ b/docs/content/reference/api.md
@@ -837,8 +837,10 @@ such as the number of Pod replicas, the Service resource, or the Ingress.