From 54a9f26436c5dce41aab6d06fadfcc23eb2681eb Mon Sep 17 00:00:00 2001 From: Ramon de Klein Date: Thu, 17 Oct 2024 20:45:30 +0200 Subject: [PATCH] Allow custom (non-propagating) stateful set metadata (#2337) * allow custom (non-propagating) sts metadata --- docs/tenant_crd.adoc | 47 +++++++++++++ .../tenant-certmanager/tenant.yaml | 4 ++ .../templates/minio.min.io_tenants.yaml | 19 ++++++ helm/tenant/templates/tenant.yaml | 6 ++ helm/tenant/values.yaml | 10 +++ pkg/apis/minio.min.io/v2/helper.go | 14 ---- pkg/apis/minio.min.io/v2/types.go | 29 ++++++++ .../minio.min.io/v2/zz_generated.deepcopy.go | 49 ++++++++++++++ .../minio.min.io/v2/poolsmetadata.go | 60 +++++++++++++++++ .../minio.min.io/v2/servicemetadata.go | 30 +++++++++ .../minio.min.io/v2/tenantspec.go | 9 +++ pkg/client/applyconfiguration/utils.go | 2 + pkg/resources/services/service.go | 47 +++++-------- .../statefulsets/minio-statefulset.go | 67 ++++++------------- pkg/utils/utils.go | 11 +++ resources/base/crds/minio.min.io_tenants.yaml | 19 ++++++ testing/common.sh | 1 + 17 files changed, 331 insertions(+), 93 deletions(-) create mode 100644 pkg/client/applyconfiguration/minio.min.io/v2/poolsmetadata.go diff --git a/docs/tenant_crd.adoc b/docs/tenant_crd.adoc index 1359765e8cf..e01e63ed310 100644 --- a/docs/tenant_crd.adoc +++ b/docs/tenant_crd.adoc @@ -689,6 +689,35 @@ Security Context |=== +[id="{anchor_prefix}-github-com-minio-operator-pkg-apis-minio-min-io-v2-poolsmetadata"] +==== PoolsMetadata + +PoolsMetadata (`poolsMetadata`) defines custom labels and annotations for the MinIO pool stateful sets / pods. + + +.Appears In: +**** +- xref:{anchor_prefix}-github-com-minio-operator-pkg-apis-minio-min-io-v2-tenantspec[$$TenantSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description + +|*`labels`* __object (keys:string, values:string)__ +|*Optional* + + + +If provided, append these labels to the MinIO statefulset / pods + +|*`annotations`* __object (keys:string, values:string)__ +|*Optional* + + + +If provided, append these annotations to the MinIO statefulset / pods + +|=== + + [id="{anchor_prefix}-github-com-minio-operator-pkg-apis-minio-min-io-v2-servicemetadata"] ==== ServiceMetadata @@ -727,6 +756,18 @@ If provided, append these labels to the Console service If provided, append these annotations to the Console service +|*`kesServiceLabels`* __object (keys:string, values:string)__ +|*Optional* + + + +If provided, append these labels to the KES service + +|*`kesServiceAnnotations`* __object (keys:string, values:string)__ +|*Optional* + + + +If provided, append these annotations to the KES service + |=== @@ -1154,6 +1195,12 @@ Directs the Operator to expose the MinIO and/or Console services. + Specify custom labels and annotations to append to the MinIO service and/or Console service. +|*`poolsMetadata`* __xref:{anchor_prefix}-github-com-minio-operator-pkg-apis-minio-min-io-v2-poolsmetadata[$$PoolsMetadata$$]__ +|*Optional* + + + +Specify custom labels and annotations to append to all pool statefulsets and pods. + |*`users`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#localobjectreference-v1-core[$$LocalObjectReference$$] array__ |*Optional* + diff --git a/examples/kustomization/tenant-certmanager/tenant.yaml b/examples/kustomization/tenant-certmanager/tenant.yaml index 0ec92d16841..409a4f32a8f 100644 --- a/examples/kustomization/tenant-certmanager/tenant.yaml +++ b/examples/kustomization/tenant-certmanager/tenant.yaml @@ -4,6 +4,10 @@ metadata: name: myminio namespace: minio-tenant spec: + ## Assign labels to the pool + poolsMetadata: + labels: + app: minio ## Disable default tls certificates. requestAutoCert: false ## Use certificates generated by cert-manager. diff --git a/helm/operator/templates/minio.min.io_tenants.yaml b/helm/operator/templates/minio.min.io_tenants.yaml index d4a1f9fc5e4..e295126ce51 100644 --- a/helm/operator/templates/minio.min.io_tenants.yaml +++ b/helm/operator/templates/minio.min.io_tenants.yaml @@ -3638,6 +3638,17 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map + poolsMetadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object priorityClassName: type: string prometheusOperator: @@ -3736,6 +3747,14 @@ spec: additionalProperties: type: string type: object + kesServiceAnnotations: + additionalProperties: + type: string + type: object + kesServiceLabels: + additionalProperties: + type: string + type: object minioServiceAnnotations: additionalProperties: type: string diff --git a/helm/tenant/templates/tenant.yaml b/helm/tenant/templates/tenant.yaml index f55a26150f0..15c8f79136a 100644 --- a/helm/tenant/templates/tenant.yaml +++ b/helm/tenant/templates/tenant.yaml @@ -28,6 +28,12 @@ spec: ## Secret with default environment variable configurations configuration: name: {{ .configuration.name }} + {{- if hasKey . "poolsMetadata" }} + poolsMetadata: {{- if eq (len .poolsMetadata) 0 }} {} {{- end }} + {{- with (dig "poolsMetadata" (dict) .) }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} pools: {{- range (dig "pools" (list) .) }} - servers: {{ dig "servers" 4 . }} diff --git a/helm/tenant/values.yaml b/helm/tenant/values.yaml index 1572081c615..52d8ca8dd62 100644 --- a/helm/tenant/values.yaml +++ b/helm/tenant/values.yaml @@ -70,6 +70,16 @@ tenant: secretKey: minio123 #existingSecret: true + ### + # Metadata that will be added to the statefulset and pods of all pools + poolsMetadata: + ### + # Specify `annotations `__ to associate to Tenant pods. + annotations: { } + ### + # Specify `labels `__ to associate to Tenant pods. + labels: { } + ### # If this variable is set to true, then enable the usage of an existing Kubernetes secret to set environment variables for the Tenant. # The existing Kubernetes secret name must be placed under .tenant.configuration.name e.g. existing-minio-env-configuration diff --git a/pkg/apis/minio.min.io/v2/helper.go b/pkg/apis/minio.min.io/v2/helper.go index 22927919d58..c86a66552ac 100644 --- a/pkg/apis/minio.min.io/v2/helper.go +++ b/pkg/apis/minio.min.io/v2/helper.go @@ -878,20 +878,6 @@ func GetClusterDomain() string { return k8sClusterDomain } -// MergeMaps merges two maps and returns the union -func MergeMaps(a, b map[string]string) map[string]string { - if a == nil { - a = map[string]string{} - } - if b == nil { - b = map[string]string{} - } - for k, v := range b { - a[k] = v - } - return a -} - // ToMap converts a slice of env vars to a map of Name and value func ToMap(envs []corev1.EnvVar) map[string]string { newMap := make(map[string]string) diff --git a/pkg/apis/minio.min.io/v2/types.go b/pkg/apis/minio.min.io/v2/types.go index 9aade94a34f..4644f72a58a 100644 --- a/pkg/apis/minio.min.io/v2/types.go +++ b/pkg/apis/minio.min.io/v2/types.go @@ -318,6 +318,11 @@ type TenantSpec struct { ServiceMetadata *ServiceMetadata `json:"serviceMetadata,omitempty"` // *Optional* + // + // Specify custom labels and annotations to append to all pool statefulsets and pods. + // +optional + PoolsMetadata *PoolsMetadata `json:"poolsMetadata,omitempty"` + // *Optional* + + // // An array of https://kubernetes.io/docs/concepts/configuration/secret/[Kubernetes opaque secrets] to use for generating MinIO users during tenant provisioning. + // // Each element in the array is an object consisting of a key-value pair `name: `, where the `` references an opaque Kubernetes secret. + @@ -395,6 +400,30 @@ type ServiceMetadata struct { // If provided, append these annotations to the Console service // +optional ConsoleServiceAnnotations map[string]string `json:"consoleServiceAnnotations,omitempty"` + // *Optional* + + // + // If provided, append these labels to the KES service + // +optional + KESServiceLabels map[string]string `json:"kesServiceLabels,omitempty"` + // *Optional* + + // + // If provided, append these annotations to the KES service + // +optional + KESServiceAnnotations map[string]string `json:"kesServiceAnnotations,omitempty"` +} + +// PoolsMetadata (`poolsMetadata`) defines custom labels and annotations for the MinIO pool stateful sets / pods. + +type PoolsMetadata struct { + // *Optional* + + // + // If provided, append these labels to the MinIO statefulset / pods + // +optional + Labels map[string]string `json:"labels,omitempty"` + // *Optional* + + // + // If provided, append these annotations to the MinIO statefulset / pods + // +optional + Annotations map[string]string `json:"annotations,omitempty"` } // LocalCertificateReference (`externalCertSecret`, `externalCaCertSecret`,`clientCertSecret`) contains a Kubernetes secret containing TLS certificates or Certificate Authority files for use with enabling TLS in the MinIO Tenant. + diff --git a/pkg/apis/minio.min.io/v2/zz_generated.deepcopy.go b/pkg/apis/minio.min.io/v2/zz_generated.deepcopy.go index f126817ac5a..cec7292ab06 100644 --- a/pkg/apis/minio.min.io/v2/zz_generated.deepcopy.go +++ b/pkg/apis/minio.min.io/v2/zz_generated.deepcopy.go @@ -441,6 +441,36 @@ func (in *PoolStatus) DeepCopy() *PoolStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PoolsMetadata) DeepCopyInto(out *PoolsMetadata) { + *out = *in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PoolsMetadata. +func (in *PoolsMetadata) DeepCopy() *PoolsMetadata { + if in == nil { + return nil + } + out := new(PoolsMetadata) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceMetadata) DeepCopyInto(out *ServiceMetadata) { *out = *in @@ -472,6 +502,20 @@ func (in *ServiceMetadata) DeepCopyInto(out *ServiceMetadata) { (*out)[key] = val } } + if in.KESServiceLabels != nil { + in, out := &in.KESServiceLabels, &out.KESServiceLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.KESServiceAnnotations != nil { + in, out := &in.KESServiceAnnotations, &out.KESServiceAnnotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } return } @@ -742,6 +786,11 @@ func (in *TenantSpec) DeepCopyInto(out *TenantSpec) { *out = new(ServiceMetadata) (*in).DeepCopyInto(*out) } + if in.PoolsMetadata != nil { + in, out := &in.PoolsMetadata, &out.PoolsMetadata + *out = new(PoolsMetadata) + (*in).DeepCopyInto(*out) + } if in.Users != nil { in, out := &in.Users, &out.Users *out = make([]v1.LocalObjectReference, len(*in)) diff --git a/pkg/client/applyconfiguration/minio.min.io/v2/poolsmetadata.go b/pkg/client/applyconfiguration/minio.min.io/v2/poolsmetadata.go new file mode 100644 index 00000000000..613013e8ce5 --- /dev/null +++ b/pkg/client/applyconfiguration/minio.min.io/v2/poolsmetadata.go @@ -0,0 +1,60 @@ +// This file is part of MinIO Operator +// Copyright (c) 2024 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v2 + +// PoolsMetadataApplyConfiguration represents an declarative configuration of the PoolsMetadata type for use +// with apply. +type PoolsMetadataApplyConfiguration struct { + Labels map[string]string `json:"labels,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` +} + +// PoolsMetadataApplyConfiguration constructs an declarative configuration of the PoolsMetadata type for use with +// apply. +func PoolsMetadata() *PoolsMetadataApplyConfiguration { + return &PoolsMetadataApplyConfiguration{} +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *PoolsMetadataApplyConfiguration) WithLabels(entries map[string]string) *PoolsMetadataApplyConfiguration { + if b.Labels == nil && len(entries) > 0 { + b.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *PoolsMetadataApplyConfiguration) WithAnnotations(entries map[string]string) *PoolsMetadataApplyConfiguration { + if b.Annotations == nil && len(entries) > 0 { + b.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Annotations[k] = v + } + return b +} diff --git a/pkg/client/applyconfiguration/minio.min.io/v2/servicemetadata.go b/pkg/client/applyconfiguration/minio.min.io/v2/servicemetadata.go index d04cadf13c7..6fb7a296678 100644 --- a/pkg/client/applyconfiguration/minio.min.io/v2/servicemetadata.go +++ b/pkg/client/applyconfiguration/minio.min.io/v2/servicemetadata.go @@ -25,6 +25,8 @@ type ServiceMetadataApplyConfiguration struct { MinIOServiceAnnotations map[string]string `json:"minioServiceAnnotations,omitempty"` ConsoleServiceLabels map[string]string `json:"consoleServiceLabels,omitempty"` ConsoleServiceAnnotations map[string]string `json:"consoleServiceAnnotations,omitempty"` + KESServiceLabels map[string]string `json:"kesServiceLabels,omitempty"` + KESServiceAnnotations map[string]string `json:"kesServiceAnnotations,omitempty"` } // ServiceMetadataApplyConfiguration constructs a declarative configuration of the ServiceMetadata type for use with @@ -88,3 +90,31 @@ func (b *ServiceMetadataApplyConfiguration) WithConsoleServiceAnnotations(entrie } return b } + +// WithKESServiceLabels puts the entries into the KESServiceLabels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the KESServiceLabels field, +// overwriting an existing map entries in KESServiceLabels field with the same key. +func (b *ServiceMetadataApplyConfiguration) WithKESServiceLabels(entries map[string]string) *ServiceMetadataApplyConfiguration { + if b.KESServiceLabels == nil && len(entries) > 0 { + b.KESServiceLabels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.KESServiceLabels[k] = v + } + return b +} + +// WithKESServiceAnnotations puts the entries into the KESServiceAnnotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the KESServiceAnnotations field, +// overwriting an existing map entries in KESServiceAnnotations field with the same key. +func (b *ServiceMetadataApplyConfiguration) WithKESServiceAnnotations(entries map[string]string) *ServiceMetadataApplyConfiguration { + if b.KESServiceAnnotations == nil && len(entries) > 0 { + b.KESServiceAnnotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.KESServiceAnnotations[k] = v + } + return b +} diff --git a/pkg/client/applyconfiguration/minio.min.io/v2/tenantspec.go b/pkg/client/applyconfiguration/minio.min.io/v2/tenantspec.go index a4f9f955875..74acd245bd0 100644 --- a/pkg/client/applyconfiguration/minio.min.io/v2/tenantspec.go +++ b/pkg/client/applyconfiguration/minio.min.io/v2/tenantspec.go @@ -54,6 +54,7 @@ type TenantSpecApplyConfiguration struct { SideCars *SideCarsApplyConfiguration `json:"sideCars,omitempty"` ExposeServices *ExposeServicesApplyConfiguration `json:"exposeServices,omitempty"` ServiceMetadata *ServiceMetadataApplyConfiguration `json:"serviceMetadata,omitempty"` + PoolsMetadata *PoolsMetadataApplyConfiguration `json:"poolsMetadata,omitempty"` Users []v1.LocalObjectReference `json:"users,omitempty"` Buckets []BucketApplyConfiguration `json:"buckets,omitempty"` Logging *LoggingApplyConfiguration `json:"logging,omitempty"` @@ -307,6 +308,14 @@ func (b *TenantSpecApplyConfiguration) WithServiceMetadata(value *ServiceMetadat return b } +// WithPoolsMetadata sets the PoolsMetadata field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the PoolsMetadata field is set to the value of the last call. +func (b *TenantSpecApplyConfiguration) WithPoolsMetadata(value *PoolsMetadataApplyConfiguration) *TenantSpecApplyConfiguration { + b.PoolsMetadata = value + return b +} + // WithUsers adds the given value to the Users field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the Users field. diff --git a/pkg/client/applyconfiguration/utils.go b/pkg/client/applyconfiguration/utils.go index 98f3d786e06..2a1101983a5 100644 --- a/pkg/client/applyconfiguration/utils.go +++ b/pkg/client/applyconfiguration/utils.go @@ -58,6 +58,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &miniominiov2.LoggingApplyConfiguration{} case v2.SchemeGroupVersion.WithKind("Pool"): return &miniominiov2.PoolApplyConfiguration{} + case v2.SchemeGroupVersion.WithKind("PoolsMetadata"): + return &miniominiov2.PoolsMetadataApplyConfiguration{} case v2.SchemeGroupVersion.WithKind("PoolStatus"): return &miniominiov2.PoolStatusApplyConfiguration{} case v2.SchemeGroupVersion.WithKind("ServiceMetadata"): diff --git a/pkg/resources/services/service.go b/pkg/resources/services/service.go index 2a7a6021e7c..b5960f628ac 100644 --- a/pkg/resources/services/service.go +++ b/pkg/resources/services/service.go @@ -30,18 +30,6 @@ func NewClusterIPForMinIO(t *miniov2.Tenant) *corev1.Service { port = miniov2.MinIOTLSPortLoadBalancerSVC name = miniov2.MinIOServiceHTTPSPortName } - var internalLabels, labels, annotations map[string]string - - internalLabels = t.MinIOPodLabels() - if t.Spec.ServiceMetadata != nil && t.Spec.ServiceMetadata.MinIOServiceLabels != nil { - labels = miniov2.MergeMaps(internalLabels, t.Spec.ServiceMetadata.MinIOServiceLabels) - } else { - labels = internalLabels - } - - if t.Spec.ServiceMetadata != nil && t.Spec.ServiceMetadata.MinIOServiceAnnotations != nil { - annotations = t.Spec.ServiceMetadata.MinIOServiceAnnotations - } minioPort := corev1.ServicePort{ Port: port, @@ -51,11 +39,9 @@ func NewClusterIPForMinIO(t *miniov2.Tenant) *corev1.Service { svc := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ - Labels: labels, Name: t.MinIOCIServiceName(), Namespace: t.Namespace, OwnerReferences: t.OwnerRef(), - Annotations: annotations, }, Spec: corev1.ServiceSpec{ Ports: []corev1.ServicePort{minioPort}, @@ -64,6 +50,12 @@ func NewClusterIPForMinIO(t *miniov2.Tenant) *corev1.Service { PublishNotReadyAddresses: false, }, } + + if t.Spec.ServiceMetadata != nil { + svc.Labels = t.Spec.ServiceMetadata.MinIOServiceLabels + svc.Annotations = t.Spec.ServiceMetadata.MinIOServiceAnnotations + } + // check if the service is meant to be exposed if t.Spec.ExposeServices != nil && t.Spec.ExposeServices.MinIO { svc.Spec.Type = corev1.ServiceTypeLoadBalancer @@ -73,9 +65,6 @@ func NewClusterIPForMinIO(t *miniov2.Tenant) *corev1.Service { // NewClusterIPForConsole will return a new cluster IP service for Console Deployment func NewClusterIPForConsole(t *miniov2.Tenant) *corev1.Service { - var internalLabels, labels, annotations map[string]string - internalLabels = t.ConsolePodLabels() - consolePort := corev1.ServicePort{ Port: miniov2.ConsolePort, TargetPort: intstr.FromInt(miniov2.ConsolePort), @@ -88,23 +77,12 @@ func NewClusterIPForConsole(t *miniov2.Tenant) *corev1.Service { Name: miniov2.ConsoleServiceTLSPortName, } } - if t.Spec.ServiceMetadata != nil && t.Spec.ServiceMetadata.ConsoleServiceLabels != nil { - labels = miniov2.MergeMaps(internalLabels, t.Spec.ServiceMetadata.ConsoleServiceLabels) - } else { - labels = internalLabels - } - - if t.Spec.ServiceMetadata != nil && t.Spec.ServiceMetadata.ConsoleServiceAnnotations != nil { - annotations = t.Spec.ServiceMetadata.ConsoleServiceAnnotations - } svc := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ - Labels: labels, Name: t.ConsoleCIServiceName(), Namespace: t.Namespace, OwnerReferences: t.OwnerRef(), - Annotations: annotations, }, Spec: corev1.ServiceSpec{ Ports: []corev1.ServicePort{ @@ -114,6 +92,12 @@ func NewClusterIPForConsole(t *miniov2.Tenant) *corev1.Service { Type: corev1.ServiceTypeClusterIP, }, } + + if t.Spec.ServiceMetadata != nil { + svc.Labels = t.Spec.ServiceMetadata.ConsoleServiceLabels + svc.Annotations = t.Spec.ServiceMetadata.ConsoleServiceAnnotations + } + // check if the service is meant to be exposed if t.Spec.ExposeServices != nil && t.Spec.ExposeServices.Console { svc.Spec.Type = corev1.ServiceTypeLoadBalancer @@ -166,7 +150,6 @@ func NewHeadlessForMinIO(t *miniov2.Tenant) *corev1.Service { svc := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ - Labels: t.MinIOPodLabels(), Name: t.MinIOHLServiceName(), Namespace: t.Namespace, OwnerReferences: t.OwnerRef(), @@ -188,7 +171,6 @@ func NewHeadlessForKES(t *miniov2.Tenant) *corev1.Service { kesPort := corev1.ServicePort{Port: miniov2.KESPort, Name: miniov2.KESServicePortName} svc := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ - Labels: t.KESPodLabels(), Name: t.KESHLServiceName(), Namespace: t.Namespace, OwnerReferences: t.OwnerRef(), @@ -200,6 +182,9 @@ func NewHeadlessForKES(t *miniov2.Tenant) *corev1.Service { ClusterIP: corev1.ClusterIPNone, }, } - + if t.Spec.ServiceMetadata != nil { + svc.Labels = t.Spec.ServiceMetadata.KESServiceLabels + svc.Annotations = t.Spec.ServiceMetadata.KESServiceAnnotations + } return svc } diff --git a/pkg/resources/statefulsets/minio-statefulset.go b/pkg/resources/statefulsets/minio-statefulset.go index 7124e351a9a..c9e416fe193 100644 --- a/pkg/resources/statefulsets/minio-statefulset.go +++ b/pkg/resources/statefulsets/minio-statefulset.go @@ -24,6 +24,7 @@ import ( miniov2 "github.com/minio/operator/pkg/apis/minio.min.io/v2" "github.com/minio/operator/pkg/certs" + "github.com/minio/operator/pkg/utils" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -61,48 +62,23 @@ func minioEnvironmentVars(t *miniov2.Tenant, skipEnvVars map[string][]byte) []co // If a user specifies metadata in the spec we return that metadata. func PodMetadata(t *miniov2.Tenant, pool *miniov2.Pool) metav1.ObjectMeta { meta := metav1.ObjectMeta{} - // Copy Labels and Annotations from Tenant - labels := t.ObjectMeta.Labels - annotations := t.ObjectMeta.Annotations - - if annotations == nil { - annotations = make(map[string]string) - } - - annotations[miniov2.Revision] = fmt.Sprintf("%d", t.Status.Revision) - - if labels == nil { - labels = make(map[string]string) - } - // Add the additional label used by StatefulSet spec selector - for k, v := range t.MinIOPodLabels() { - labels[k] = v - } - // Add information labels, such as which pool we are building this pod about - labels[miniov2.PoolLabel] = pool.Name - // Add the additional label used by Console spec selector - for k, v := range t.ConsolePodLabels() { - labels[k] = v - } - - // Add user specific annotations - if pool.Annotations != nil { - annotations = miniov2.MergeMaps(annotations, pool.Annotations) - } - - if pool.Labels != nil { - labels = miniov2.MergeMaps(labels, pool.Labels) + if t.Spec.PoolsMetadata != nil { + meta.Labels = t.Spec.PoolsMetadata.Labels + meta.Annotations = t.Spec.PoolsMetadata.Annotations } + meta.Labels = utils.MergeMaps(meta.Labels, pool.Labels, t.MinIOPodLabels(), t.ConsolePodLabels()) + meta.Annotations = utils.MergeMaps(meta.Annotations, pool.Annotations) - meta.Labels = labels - meta.Annotations = annotations + // Set specific information + meta.Labels[miniov2.PoolLabel] = pool.Name + meta.Annotations[miniov2.Revision] = fmt.Sprintf("%d", t.Status.Revision) return meta } // ContainerMatchLabels Returns the labels that match the Pods in the statefulset func ContainerMatchLabels(t *miniov2.Tenant, pool *miniov2.Pool) *metav1.LabelSelector { - labels := miniov2.MergeMaps(t.MinIOPodLabels(), t.ConsolePodLabels()) + labels := utils.MergeMaps(t.MinIOPodLabels(), t.ConsolePodLabels()) // Add pool information so it's passed down to the underlying PVCs labels[miniov2.PoolLabel] = pool.Name return &metav1.LabelSelector{ @@ -628,26 +604,21 @@ func NewPool(args *NewPoolArgs) *appsv1.StatefulSet { }, } // Copy labels and annotations from the Tenant.Spec.Metadata - ssMeta.Labels = t.ObjectMeta.Labels - ssMeta.Annotations = t.ObjectMeta.Annotations - - if ssMeta.Labels == nil { - ssMeta.Labels = make(map[string]string) + // unless `StatefulSetMetadata` is defined, then we'll copy it + // from there. + if t.Spec.PoolsMetadata != nil { + ssMeta.Labels = t.Spec.PoolsMetadata.Labels + ssMeta.Annotations = t.Spec.PoolsMetadata.Annotations } + // Add pool specific annotations + ssMeta.Annotations = utils.MergeMaps(ssMeta.Annotations, pool.Annotations) + ssMeta.Labels = utils.MergeMaps(ssMeta.Labels, pool.Labels) + // Add information labels, such as which pool we are building this pod about ssMeta.Labels[miniov2.PoolLabel] = pool.Name ssMeta.Labels[miniov2.TenantLabel] = t.Name - // Add user specific annotations - if pool.Annotations != nil { - ssMeta.Annotations = miniov2.MergeMaps(ssMeta.Annotations, pool.Annotations) - } - - if pool.Labels != nil { - ssMeta.Labels = miniov2.MergeMaps(ssMeta.Labels, pool.Labels) - } - containers := []corev1.Container{ poolMinioServerContainer(t, skipEnvVars, pool, certVolumeSources), getSideCarContainer(t, pool), diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index f9e86bc64c1..b2e724bd19b 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -70,3 +70,14 @@ func CastObjectToMetaV1(obj interface{}) (metav1.Object, error) { } return object, nil } + +// MergeMaps merges maps and returns the union +func MergeMaps(maps ...map[string]string) map[string]string { + dest := map[string]string{} + for _, m := range maps { + for k, v := range m { + dest[k] = v + } + } + return dest +} diff --git a/resources/base/crds/minio.min.io_tenants.yaml b/resources/base/crds/minio.min.io_tenants.yaml index d4a1f9fc5e4..e295126ce51 100644 --- a/resources/base/crds/minio.min.io_tenants.yaml +++ b/resources/base/crds/minio.min.io_tenants.yaml @@ -3638,6 +3638,17 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map + poolsMetadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object priorityClassName: type: string prometheusOperator: @@ -3736,6 +3747,14 @@ spec: additionalProperties: type: string type: object + kesServiceAnnotations: + additionalProperties: + type: string + type: object + kesServiceLabels: + additionalProperties: + type: string + type: object minioServiceAnnotations: additionalProperties: type: string diff --git a/testing/common.sh b/testing/common.sh index 712e066fa8b..54e7ab61f98 100644 --- a/testing/common.sh +++ b/testing/common.sh @@ -798,6 +798,7 @@ function install_tenant() { value=myminio create_restricted_namespace $namespace try helm install --namespace $namespace \ + --set tenant.poolsMetadata.labels.app=minio \ tenant ./helm/tenant elif [ "$1" = "logs" ]; then namespace="tenant-lite"