Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow app.kubernetes.io/name to be set in the VerticaDB CR #394

Merged
merged 7 commits into from
May 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions api/v1beta1/verticadb_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"reflect"
"strings"

vmeta "github.com/vertica/vertica-kubernetes/pkg/meta"
"github.com/vertica/vertica-kubernetes/pkg/paths"
v1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
Expand Down Expand Up @@ -272,6 +273,7 @@ func (v *VerticaDB) validateVerticaDBSpec() field.ErrorList {
allErrs = v.validateCommunalPath(allErrs)
allErrs = v.validateS3ServerSideEncryption(allErrs)
allErrs = v.validateAdditionalConfigParms(allErrs)
allErrs = v.validateCustomLabels(allErrs)
allErrs = v.validateEndpoint(allErrs)
allErrs = v.hasValidDomainName(allErrs)
allErrs = v.hasValidNodePort(allErrs)
Expand Down Expand Up @@ -388,6 +390,19 @@ func (v *VerticaDB) validateAdditionalConfigParms(allErrs field.ErrorList) field
return allErrs
}

func (v *VerticaDB) validateCustomLabels(allErrs field.ErrorList) field.ErrorList {
for _, invalidLabel := range vmeta.ProtectedLabels {
_, ok := v.Spec.Labels[invalidLabel]
if ok {
err := field.Invalid(field.NewPath("spec").Child("labels"),
v.Spec.Labels,
fmt.Sprintf("'%s' is a restricted label.", invalidLabel))
allErrs = append(allErrs, err)
}
}
return allErrs
}

func (v *VerticaDB) validateEndpoint(allErrs field.ErrorList) field.ErrorList {
if v.Spec.InitPolicy == CommunalInitPolicyScheduleOnly {
return allErrs
Expand Down
21 changes: 21 additions & 0 deletions api/v1beta1/verticadb_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
vmeta "github.com/vertica/vertica-kubernetes/pkg/meta"
"github.com/vertica/vertica-kubernetes/pkg/paths"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
Expand Down Expand Up @@ -657,6 +658,26 @@ var _ = Describe("verticadb_webhook", func() {
validateSpecValuesHaveErr(vdb, true)
})

It("should prevent internally generated labels to be overridden", func() {
vdb := MakeVDB()
vdb.Spec.Labels = map[string]string{
vmeta.SubclusterNameLabel: "sc-name",
}
validateSpecValuesHaveErr(vdb, true)
vdb.Spec.Labels = map[string]string{
vmeta.VDBInstanceLabel: "v",
}
validateSpecValuesHaveErr(vdb, true)
vdb.Spec.Labels = map[string]string{
vmeta.ClientRoutingLabel: vmeta.ClientRoutingVal,
}
validateSpecValuesHaveErr(vdb, true)
vdb.Spec.Labels = map[string]string{
"vertica.com/good-label": "val",
}
validateSpecValuesHaveErr(vdb, false)
})

It("should verify httpServerMode is valid", func() {
vdb := MakeVDB()
vdb.Spec.HTTPServerMode = "bad-server-mode"
Expand Down
5 changes: 5 additions & 0 deletions changes/unreleased/Fixed-20230511-141746.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: Fixed
body: Allow app.kubernetes.io/name to be overridden
time: 2023-05-11T14:17:46.053871313-03:00
custom:
Issue: "394"
5 changes: 3 additions & 2 deletions cmd/operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"github.com/vertica/vertica-kubernetes/pkg/controllers/et"
"github.com/vertica/vertica-kubernetes/pkg/controllers/vas"
"github.com/vertica/vertica-kubernetes/pkg/controllers/vdb"
vmeta "github.com/vertica/vertica-kubernetes/pkg/meta"
"github.com/vertica/vertica-kubernetes/pkg/opcfg"
"github.com/vertica/vertica-kubernetes/pkg/security"
//+kubebuilder:scaffold:imports
Expand Down Expand Up @@ -105,7 +106,7 @@ func addReconcilersToManager(mgr manager.Manager, restCfg *rest.Config, oc *opcf
Log: ctrl.Log.WithName("controllers").WithName("VerticaDB"),
Scheme: mgr.GetScheme(),
Cfg: restCfg,
EVRec: mgr.GetEventRecorderFor(builder.OperatorName),
EVRec: mgr.GetEventRecorderFor(vmeta.OperatorName),
OpCfg: *oc,
DeploymentNames: builder.DeploymentNames{
ServiceAccountName: oc.ServiceAccountName,
Expand All @@ -119,7 +120,7 @@ func addReconcilersToManager(mgr manager.Manager, restCfg *rest.Config, oc *opcf
if err := (&vas.VerticaAutoscalerReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
EVRec: mgr.GetEventRecorderFor(builder.OperatorName),
EVRec: mgr.GetEventRecorderFor(vmeta.OperatorName),
Log: ctrl.Log.WithName("controllers").WithName("VerticaAutoscaler"),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "VerticaAutoscaler")
Expand Down
13 changes: 7 additions & 6 deletions pkg/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

vapi "github.com/vertica/vertica-kubernetes/api/v1beta1"
"github.com/vertica/vertica-kubernetes/pkg/cloud"
vmeta "github.com/vertica/vertica-kubernetes/pkg/meta"
"github.com/vertica/vertica-kubernetes/pkg/names"
"github.com/vertica/vertica-kubernetes/pkg/paths"
appsv1 "k8s.io/api/apps/v1"
Expand Down Expand Up @@ -331,19 +332,19 @@ func buildDownwardAPIProjection() *corev1.DownwardAPIProjection {
{
Path: "k8s-version",
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: fmt.Sprintf("metadata.annotations['%s']", KubernetesVersionAnnotation),
FieldPath: fmt.Sprintf("metadata.annotations['%s']", vmeta.KubernetesVersionAnnotation),
},
},
{
Path: "k8s-git-commit",
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: fmt.Sprintf("metadata.annotations['%s']", KubernetesGitCommitAnnotation),
FieldPath: fmt.Sprintf("metadata.annotations['%s']", vmeta.KubernetesGitCommitAnnotation),
},
},
{
Path: "k8s-build-date",
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: fmt.Sprintf("metadata.annotations['%s']", KubernetesBuildDateAnnotation),
FieldPath: fmt.Sprintf("metadata.annotations['%s']", vmeta.KubernetesBuildDateAnnotation),
},
},
},
Expand Down Expand Up @@ -774,9 +775,9 @@ func BuildPod(vdb *vapi.VerticaDB, sc *vapi.Subcluster, podIndex int32) *corev1.
// added by the AnnotationAndLabelPodReconciler. However, this function is for test
// purposes, and we have a few dependencies on these annotations. Rather
// than having many tests run the reconciler, we will add in sample values.
pod.Annotations[KubernetesBuildDateAnnotation] = "2022-03-16T15:58:47Z"
pod.Annotations[KubernetesGitCommitAnnotation] = "c285e781331a3785a7f436042c65c5641ce8a9e9"
pod.Annotations[KubernetesVersionAnnotation] = "v1.23.5"
pod.Annotations[vmeta.KubernetesBuildDateAnnotation] = "2022-03-16T15:58:47Z"
pod.Annotations[vmeta.KubernetesGitCommitAnnotation] = "c285e781331a3785a7f436042c65c5641ce8a9e9"
pod.Annotations[vmeta.KubernetesVersionAnnotation] = "v1.23.5"
// Set a few things in the spec that are normally done by the statefulset
// controller. Again, this is for testing purposes only as the statefulset
// controller handles adding of the PVC to the volume list.
Expand Down
77 changes: 19 additions & 58 deletions pkg/builder/labels_annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,85 +19,46 @@ import (
"strconv"

vapi "github.com/vertica/vertica-kubernetes/api/v1beta1"
)

const (
SvcTypeLabel = "vertica.com/svc-type"
SubclusterNameLabel = "vertica.com/subcluster-name"
SubclusterLegacyNameLabel = "vertica.com/subcluster"
SubclusterTypeLabel = "vertica.com/subcluster-type"
SubclusterSvcNameLabel = "vertica.com/subcluster-svc"
SubclusterTransientLabel = "vertica.com/subcluster-transient"

// ClientRoutingLabel is a label that must exist on the pod in
// order for Service objects to route to the pod. This label isn't part of
// the template in the StatefulSet. This label is added after the pod is
// scheduled. There are a couple of uses for it:
// - after an add node, we only add the labels once the node has at least
// one shard subscription. This saves routing to a pod that cannot fulfill
// a query request.
// - before we remove a node. It allows us to drain out pods that are going
// to be removed by a pending node removal.
ClientRoutingLabel = "vertica.com/client-routing"
ClientRoutingVal = "true"

VDBInstanceLabel = "app.kubernetes.io/instance"
OperatorVersionLabel = "app.kubernetes.io/version"
ManagedByLabel = "app.kubernetes.io/managed-by"
OperatorName = "verticadb-operator" // The name of the operator

CurOperatorVersion = "1.11.0" // The version number of the operator
spilchen marked this conversation as resolved.
Show resolved Hide resolved
// If any of the operator versions are used in the code, add a const here.
// But it isn't necessary to create a const for each version.
OperatorVersion100 = "1.0.0"
OperatorVersion110 = "1.1.0"
OperatorVersion120 = "1.2.0"
OperatorVersion130 = "1.3.0"

// Annotations that we set in each of the pod. These are set by the
// AnnotateAndLabelPodReconciler. They are available in the pod with the
// downwardAPI so they can be picked up by the Vertica data collector (DC).
KubernetesVersionAnnotation = "kubernetes.io/version" // Version of the k8s server
KubernetesGitCommitAnnotation = "kubernetes.io/gitcommit" // Git commit of the k8s server
KubernetesBuildDateAnnotation = "kubernetes.io/buildDate" // Build date of the k8s server
vmeta "github.com/vertica/vertica-kubernetes/pkg/meta"
)

// MakeSubclusterLabels returns the labels added for the subcluster
func MakeSubclusterLabels(sc *vapi.Subcluster) map[string]string {
m := map[string]string{
SubclusterNameLabel: sc.Name,
SubclusterTypeLabel: sc.GetType(),
SubclusterTransientLabel: strconv.FormatBool(sc.IsTransient),
vmeta.SubclusterNameLabel: sc.Name,
vmeta.SubclusterTypeLabel: sc.GetType(),
vmeta.SubclusterTransientLabel: strconv.FormatBool(sc.IsTransient),
}
// Transient subclusters never have the service name label set. At various
// parts of the upgrade, it will accept traffic from all of the subclusters.
if !sc.IsTransient {
m[SubclusterSvcNameLabel] = sc.GetServiceName()
m[vmeta.SubclusterSvcNameLabel] = sc.GetServiceName()
}
return m
}

// MakeOperatorLabels returns the labels that all objects created by this operator will have
func MakeOperatorLabels(vdb *vapi.VerticaDB) map[string]string {
return map[string]string{
ManagedByLabel: OperatorName,
"app.kubernetes.io/name": "vertica",
VDBInstanceLabel: vdb.Name,
"app.kubernetes.io/component": "database",
"vertica.com/database": vdb.Spec.DBName,
vmeta.ManagedByLabel: vmeta.OperatorName,
vmeta.VDBInstanceLabel: vdb.Name,
vmeta.ComponentLabel: "database",
vmeta.DataBaseLabel: vdb.Spec.DBName,
}
}

// MakeCommonLabels returns the labels that are common to all objects.
func MakeCommonLabels(vdb *vapi.VerticaDB, sc *vapi.Subcluster, forPod bool) map[string]string {
labels := MakeOperatorLabels(vdb)
// This can be overridden through 'labels' in the CR.
labels[vmeta.NameLabel] = "vertica"
if !forPod {
// Apply a label to indicate a version of the operator that created the
// object. This is separate from MakeOperatorLabels as we don't want to
// set this for pods in the template. We set the operator version in
// the pods as part of a reconciler so that we don't have to reschedule
// the pods.
labels[OperatorVersionLabel] = CurOperatorVersion
labels[vmeta.OperatorVersionLabel] = vmeta.CurOperatorVersion
}

// Remaining labels are for objects that are subcluster specific
Expand Down Expand Up @@ -137,7 +98,7 @@ func MakeLabelsForStsObject(vdb *vapi.VerticaDB, sc *vapi.Subcluster) map[string
// MakeLabelsForSvcObject will create the set of labels for use with service objects
func MakeLabelsForSvcObject(vdb *vapi.VerticaDB, sc *vapi.Subcluster, svcType string) map[string]string {
labels := makeLabelsForObject(vdb, sc, false)
labels[SvcTypeLabel] = svcType
labels[vmeta.SvcTypeLabel] = svcType
return labels
}

Expand All @@ -158,7 +119,7 @@ func MakeBaseSvcSelectorLabels(vdb *vapi.VerticaDB) map[string]string {
// pods created from an older operator, we need to be more selective in the
// labels we choose.
return map[string]string{
VDBInstanceLabel: vdb.Name,
vmeta.VDBInstanceLabel: vdb.Name,
}
}

Expand All @@ -167,10 +128,10 @@ func MakeBaseSvcSelectorLabels(vdb *vapi.VerticaDB) map[string]string {
// allows us to combine multiple subcluster under a single service object.
func MakeSvcSelectorLabelsForServiceNameRouting(vdb *vapi.VerticaDB, sc *vapi.Subcluster) map[string]string {
m := MakeBaseSvcSelectorLabels(vdb)
m[SubclusterSvcNameLabel] = sc.GetServiceName()
m[vmeta.SubclusterSvcNameLabel] = sc.GetServiceName()
// Only route to nodes that have verified they own at least one shard and
// aren't pending delete
m[ClientRoutingLabel] = ClientRoutingVal
m[vmeta.ClientRoutingLabel] = vmeta.ClientRoutingVal
return m
}

Expand All @@ -179,16 +140,16 @@ func MakeSvcSelectorLabelsForServiceNameRouting(vdb *vapi.VerticaDB, sc *vapi.Su
func MakeSvcSelectorLabelsForSubclusterNameRouting(vdb *vapi.VerticaDB, sc *vapi.Subcluster) map[string]string {
m := MakeBaseSvcSelectorLabels(vdb)
// Routing is done using the subcluster name rather than the service name.
m[SubclusterNameLabel] = sc.Name
m[ClientRoutingLabel] = ClientRoutingVal
m[vmeta.SubclusterNameLabel] = sc.Name
m[vmeta.ClientRoutingLabel] = vmeta.ClientRoutingVal

return m
}

// MakeStsSelectorLabels will create the selector labels for use within a StatefulSet
func MakeStsSelectorLabels(vdb *vapi.VerticaDB, sc *vapi.Subcluster) map[string]string {
m := MakeBaseSvcSelectorLabels(vdb)
m[SubclusterNameLabel] = sc.Name
m[vmeta.SubclusterNameLabel] = sc.Name
return m
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/controllers/vas/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
vapi "github.com/vertica/vertica-kubernetes/api/v1beta1"
"github.com/vertica/vertica-kubernetes/pkg/builder"
vmeta "github.com/vertica/vertica-kubernetes/pkg/meta"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -70,7 +70,7 @@ var _ = BeforeSuite(func() {
Client: k8sClient,
Log: logger,
Scheme: scheme.Scheme,
EVRec: mgr.GetEventRecorderFor(builder.OperatorName),
EVRec: mgr.GetEventRecorderFor(vmeta.OperatorName),
}
})

Expand Down
10 changes: 5 additions & 5 deletions pkg/controllers/vdb/annotateandlabelpod_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import (
"context"

vapi "github.com/vertica/vertica-kubernetes/api/v1beta1"
"github.com/vertica/vertica-kubernetes/pkg/builder"
"github.com/vertica/vertica-kubernetes/pkg/controllers"
vmeta "github.com/vertica/vertica-kubernetes/pkg/meta"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -91,16 +91,16 @@ func (s *AnnotateAndLabelPodReconciler) generateAnnotations() (map[string]string
s.VRec.Log.Info("Kubernetes server version", "version", ver.GitVersion, "gitCommit", ver.GitCommit, "buildDate", ver.BuildDate)

return map[string]string{
builder.KubernetesVersionAnnotation: ver.GitVersion,
builder.KubernetesGitCommitAnnotation: ver.GitCommit,
builder.KubernetesBuildDateAnnotation: ver.BuildDate,
vmeta.KubernetesVersionAnnotation: ver.GitVersion,
vmeta.KubernetesGitCommitAnnotation: ver.GitCommit,
vmeta.KubernetesBuildDateAnnotation: ver.BuildDate,
}, nil
}

// generateLabels will generate static labels that will be applied to each running pod
func (s *AnnotateAndLabelPodReconciler) generateLabels() map[string]string {
return map[string]string{
builder.OperatorVersionLabel: builder.CurOperatorVersion,
vmeta.OperatorVersionLabel: vmeta.CurOperatorVersion,
}
}

Expand Down
12 changes: 6 additions & 6 deletions pkg/controllers/vdb/clientroutinglabel_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import (
"fmt"

vapi "github.com/vertica/vertica-kubernetes/api/v1beta1"
"github.com/vertica/vertica-kubernetes/pkg/builder"
"github.com/vertica/vertica-kubernetes/pkg/controllers"
verrors "github.com/vertica/vertica-kubernetes/pkg/errors"
vmeta "github.com/vertica/vertica-kubernetes/pkg/meta"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -118,7 +118,7 @@ func (c *ClientRoutingLabelReconciler) reconcilePod(ctx context.Context, pn type
}

func (c *ClientRoutingLabelReconciler) manipulateRoutingLabelInPod(pod *corev1.Pod, pf *PodFact) {
_, labelExists := pod.Labels[builder.ClientRoutingLabel]
_, labelExists := pod.Labels[vmeta.ClientRoutingLabel]

// There are 4 cases this reconciler is used:
// 1) Called after add node
Expand All @@ -139,15 +139,15 @@ func (c *ClientRoutingLabelReconciler) manipulateRoutingLabelInPod(pod *corev1.P
switch c.ApplyMethod {
case AddNodeApplyMethod, PodRescheduleApplyMethod:
if !labelExists && pf.upNode && (pf.shardSubscriptions > 0 || !c.Vdb.IsEON()) && !pf.pendingDelete {
pod.Labels[builder.ClientRoutingLabel] = builder.ClientRoutingVal
pod.Labels[vmeta.ClientRoutingLabel] = vmeta.ClientRoutingVal
c.VRec.Log.Info("Adding client routing label", "pod",
pod.Name, "label", fmt.Sprintf("%s=%s", builder.ClientRoutingLabel, builder.ClientRoutingVal))
pod.Name, "label", fmt.Sprintf("%s=%s", vmeta.ClientRoutingLabel, vmeta.ClientRoutingVal))
}
case DelNodeApplyMethod:
if labelExists && pf.pendingDelete {
delete(pod.Labels, builder.ClientRoutingLabel)
delete(pod.Labels, vmeta.ClientRoutingLabel)
c.VRec.Log.Info("Removing client routing label", "pod",
pod.Name, "label", fmt.Sprintf("%s=%s", builder.ClientRoutingLabel, builder.ClientRoutingVal))
pod.Name, "label", fmt.Sprintf("%s=%s", vmeta.ClientRoutingLabel, vmeta.ClientRoutingVal))
}
}
}
Loading