Skip to content

Commit

Permalink
Change default labels to use Kubernetes resource datacenter name and …
Browse files Browse the repository at this point in the history
…not datacenter override name. Create new Status field for MetadataVersion and if we keep running old ones (or old CRD), we simply fetch also with the older possible name
  • Loading branch information
burmanm committed Sep 4, 2024
1 parent 9559155 commit 0573b8b
Show file tree
Hide file tree
Showing 15 changed files with 89 additions and 45 deletions.
27 changes: 19 additions & 8 deletions apis/cassandra/v1beta1/cassandradatacenter_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,9 @@ type CassandraDatacenterStatus struct {
// This field is used to perform validation checks preventing a user from changing the override
// +optional
DatacenterName *string `json:"datacenterName,omitempty"`

// +optional
MetadataVersion int64 `json:"metadataVersion,omitempty"`
}

// CassandraDatacenter is the Schema for the cassandradatacenters API
Expand Down Expand Up @@ -596,7 +599,7 @@ func (dc *CassandraDatacenter) SetCondition(condition DatacenterCondition) {
// GetDatacenterLabels ...
func (dc *CassandraDatacenter) GetDatacenterLabels() map[string]string {
labels := dc.GetClusterLabels()
labels[DatacenterLabel] = CleanLabelValue(dc.DatacenterName())
labels[DatacenterLabel] = CleanLabelValue(dc.Name)
return labels
}

Expand Down Expand Up @@ -661,19 +664,19 @@ func (dc *CassandraDatacenter) GetSeedServiceName() string {
}

func (dc *CassandraDatacenter) GetAdditionalSeedsServiceName() string {
return CleanupForKubernetes(dc.Spec.ClusterName) + "-" + dc.SanitizedName() + "-additional-seed-service"
return CleanupForKubernetes(dc.Spec.ClusterName) + "-" + dc.LabelResourceName() + "-additional-seed-service"
}

func (dc *CassandraDatacenter) GetAllPodsServiceName() string {
return CleanupForKubernetes(dc.Spec.ClusterName) + "-" + dc.SanitizedName() + "-all-pods-service"
return CleanupForKubernetes(dc.Spec.ClusterName) + "-" + dc.LabelResourceName() + "-all-pods-service"
}

func (dc *CassandraDatacenter) GetDatacenterServiceName() string {
return CleanupForKubernetes(dc.Spec.ClusterName) + "-" + dc.SanitizedName() + "-service"
return CleanupForKubernetes(dc.Spec.ClusterName) + "-" + dc.LabelResourceName() + "-service"
}

func (dc *CassandraDatacenter) GetNodePortServiceName() string {
return CleanupForKubernetes(dc.Spec.ClusterName) + "-" + dc.SanitizedName() + "-node-port-service"
return CleanupForKubernetes(dc.Spec.ClusterName) + "-" + dc.LabelResourceName() + "-node-port-service"
}

func (dc *CassandraDatacenter) ShouldGenerateSuperuserSecret() bool {
Expand Down Expand Up @@ -970,9 +973,17 @@ func SplitRacks(nodeCount, rackCount int) []int {
return topology
}

// SanitizedName returns a sanitized version of the name returned by DatacenterName()
func (dc *CassandraDatacenter) SanitizedName() string {
return CleanupForKubernetes(dc.DatacenterName())
func (dc *CassandraDatacenter) DatacenterNameStatus() bool {
return dc.Status.DatacenterName != nil
}

// LabelResourceName returns a sanitized version of the name returned by DatacenterName()
func (dc *CassandraDatacenter) LabelResourceName() string {
// If existing cluster, return dc.DatacenterName() else return dc.Name
if dc.DatacenterNameStatus() {
return CleanupForKubernetes(*dc.Status.DatacenterName)
}
return CleanupForKubernetes(dc.Name)
}

// DatacenterName returns the Cassandra DC name override if it exists,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11221,6 +11221,9 @@ spec:
with the management API
format: date-time
type: string
metadataVersion:
format: int64
type: integer
nodeReplacements:
items:
type: string
Expand Down
2 changes: 1 addition & 1 deletion internal/controllers/control/cassandratask_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ func (r *CassandraTaskReconciler) Reconcile(ctx context.Context, req ctrl.Reques
return ctrl.Result{}, errors.Wrapf(err, "unable to fetch target CassandraDatacenter: %s", cassTask.Spec.Datacenter)
}

logger = log.FromContext(ctx, "datacenterName", dc.SanitizedName(), "clusterName", dc.Spec.ClusterName)
logger = log.FromContext(ctx, "datacenterName", dc.LabelResourceName(), "clusterName", dc.Spec.ClusterName)
log.IntoContext(ctx, logger)

// If we're active, we can proceed - otherwise verify if we're allowed to run
Expand Down
4 changes: 2 additions & 2 deletions pkg/reconciliation/construct_podtemplatespec.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ func addVolumes(dc *api.CassandraDatacenter, baseTemplate *corev1.PodTemplateSpe
Name: "encryption-cred-storage",
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: fmt.Sprintf("%s-keystore", dc.SanitizedName()),
SecretName: fmt.Sprintf("%s-keystore", dc.LabelResourceName()),
},
},
}
Expand Down Expand Up @@ -558,7 +558,7 @@ func getConfigDataEnVars(dc *api.CassandraDatacenter) ([]corev1.EnvVar, error) {
return envVars, nil
}

return nil, fmt.Errorf("datacenter %s is missing %s annotation", dc.SanitizedName(), api.ConfigHashAnnotation)
return nil, fmt.Errorf("datacenter %s is missing %s annotation", dc.LabelResourceName(), api.ConfigHashAnnotation)
}

configData, err := dc.GetConfigAsJSON(dc.Spec.Config)
Expand Down
2 changes: 1 addition & 1 deletion pkg/reconciliation/construct_statefulset.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func newNamespacedNameForStatefulSet(
dc *api.CassandraDatacenter,
rackName string) types.NamespacedName {

name := api.CleanupForKubernetes(dc.Spec.ClusterName) + "-" + dc.SanitizedName() + "-" + api.CleanupSubdomain(rackName) + "-sts"
name := api.CleanupForKubernetes(dc.Spec.ClusterName) + "-" + dc.LabelResourceName() + "-" + api.CleanupSubdomain(rackName) + "-sts"
ns := dc.Namespace

return types.NamespacedName{
Expand Down
4 changes: 2 additions & 2 deletions pkg/reconciliation/construct_statefulset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ func Test_newStatefulSetForCassandraDatacenter_dcNameOverride(t *testing.T) {
oplabels.NameLabel: oplabels.NameLabelValue,
oplabels.CreatedByLabel: oplabels.CreatedByLabelValue,
oplabels.VersionLabel: "4.0.1",
api.DatacenterLabel: "MySuperDC",
api.DatacenterLabel: "dc1",
api.ClusterLabel: "piclem",
api.RackLabel: dc.Spec.Racks[0].Name,
}
Expand All @@ -652,7 +652,7 @@ func Test_newStatefulSetForCassandraDatacenter_dcNameOverride(t *testing.T) {
oplabels.NameLabel: oplabels.NameLabelValue,
oplabels.CreatedByLabel: oplabels.CreatedByLabelValue,
oplabels.VersionLabel: "4.0.1",
api.DatacenterLabel: "MySuperDC",
api.DatacenterLabel: "dc1",
api.ClusterLabel: "piclem",
api.RackLabel: dc.Spec.Racks[0].Name,
api.CassNodeState: stateReadyToStart,
Expand Down
7 changes: 5 additions & 2 deletions pkg/reconciliation/constructor.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func newPodDisruptionBudgetForDatacenter(dc *api.CassandraDatacenter) *policyv1.

pdb := &policyv1.PodDisruptionBudget{
ObjectMeta: metav1.ObjectMeta{
Name: dc.SanitizedName() + "-pdb",
Name: dc.LabelResourceName() + "-pdb",
Namespace: dc.Namespace,
Labels: labels,
Annotations: anns,
Expand Down Expand Up @@ -62,8 +62,11 @@ func setOperatorProgressStatus(rc *ReconciliationContext, newState api.ProgressS
rc.Datacenter.Status.CassandraOperatorProgress = newState

if newState == api.ProgressReady {
if rc.Datacenter.Status.MetadataVersion < 1 {
rc.Datacenter.Status.MetadataVersion = 1
}
if rc.Datacenter.Status.DatacenterName == nil {
rc.Datacenter.Status.DatacenterName = &rc.Datacenter.Spec.DatacenterName
rc.Datacenter.Status.DatacenterName = &rc.Datacenter.Name
}
}
if err := rc.Client.Status().Patch(rc.Ctx, rc.Datacenter, patch); err != nil {
Expand Down
8 changes: 4 additions & 4 deletions pkg/reconciliation/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func CreateReconciliationContext(
}

rc.ReqLogger = rc.ReqLogger.
WithValues("datacenterName", dc.SanitizedName()).
WithValues("datacenterName", dc.LabelResourceName()).
WithValues("clusterName", dc.Spec.ClusterName)

log.IntoContext(ctx, rc.ReqLogger)
Expand Down Expand Up @@ -146,8 +146,8 @@ func (rc *ReconciliationContext) validateDatacenterNameConflicts() []error {
errs = append(errs, fmt.Errorf("failed to list CassandraDatacenters in namespace %s: %w", dc.Namespace, err))
} else {
for _, existingDc := range cassandraDatacenters.Items {
if existingDc.SanitizedName() == dc.SanitizedName() && existingDc.Name != dc.Name {
errs = append(errs, fmt.Errorf("datacenter name/override %s/%s is already in use by CassandraDatacenter %s/%s", dc.Name, dc.SanitizedName(), existingDc.Name, existingDc.SanitizedName()))
if existingDc.LabelResourceName() == dc.LabelResourceName() && existingDc.Name != dc.Name {
errs = append(errs, fmt.Errorf("datacenter name/override %s/%s is already in use by CassandraDatacenter %s/%s", dc.Name, dc.LabelResourceName(), existingDc.Name, existingDc.LabelResourceName()))
}
}
}
Expand All @@ -164,7 +164,7 @@ func (rc *ReconciliationContext) validateDatacenterNameOverride() []error {
return errs
} else {
if *dc.Status.DatacenterName != dc.Spec.DatacenterName {
errs = append(errs, fmt.Errorf("datacenter %s name override '%s' cannot be changed after creation to '%s'.", dc.Name, dc.Spec.DatacenterName, *dc.Status.DatacenterName))
errs = append(errs, fmt.Errorf("datacenter %s name override '%s' cannot be changed after creation to '%s'", dc.Name, dc.Spec.DatacenterName, *dc.Status.DatacenterName))
}
}

Expand Down
8 changes: 5 additions & 3 deletions pkg/reconciliation/handler_reconcile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)

func TestReconcile(t *testing.T) {
var (
name = "cluster-example-cluster"
name = "dc1-example"
namespace = "default"
size int32 = 2
)
Expand Down Expand Up @@ -74,6 +75,7 @@ func TestReconcile(t *testing.T) {
Client: fakeClient,
Scheme: s,
Recorder: record.NewFakeRecorder(100),
Log: ctrl.Log.WithName("controllers").WithName("CassandraDatacenter"),
}

request := reconcile.Request{
Expand All @@ -88,8 +90,8 @@ func TestReconcile(t *testing.T) {
t.Fatalf("Reconciliation Failure: (%v)", err)
}

if result != (reconcile.Result{Requeue: true, RequeueAfter: 2 * time.Second}) {
t.Error("Reconcile did not return a correct result.")
if result != (reconcile.Result{Requeue: true, RequeueAfter: 10 * time.Second}) {
t.Errorf("Reconcile did not return a correct result. (%v)", result)
}
}

Expand Down
6 changes: 5 additions & 1 deletion pkg/reconciliation/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,11 @@ func TestConflictingDcNameOverride(t *testing.T) {
Spec: api.CassandraDatacenterSpec{
ClusterName: "cluster1",
DatacenterName: "CassandraDatacenter_example",
}}}
},
Status: api.CassandraDatacenterStatus{
DatacenterName: ptr.To[string]("CassandraDatacenter_example"),
},
}}
})

errs := rc.validateDatacenterNameConflicts()
Expand Down
2 changes: 1 addition & 1 deletion pkg/reconciliation/reconcile_configsecret.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func getConfigFromConfigSecret(dc *api.CassandraDatacenter, secret *corev1.Secre

// getDatacenterConfigSecretName The format is clusterName-dcName-config
func getDatacenterConfigSecretName(dc *api.CassandraDatacenter) string {
return api.CleanupForKubernetes(dc.Spec.ClusterName) + "-" + dc.SanitizedName() + "-config"
return api.CleanupForKubernetes(dc.Spec.ClusterName) + "-" + dc.LabelResourceName() + "-config"
}

// getDatacenterConfigSecret Fetches the secret from the api server or creates a new secret
Expand Down
5 changes: 2 additions & 3 deletions pkg/reconciliation/reconcile_datacenter.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,12 @@ func (rc *ReconciliationContext) ProcessDeletion() result.ReconcileResult {
}

if _, found := rc.Datacenter.Annotations[api.DecommissionOnDeleteAnnotation]; found {
podList, err := rc.listPods(rc.Datacenter.GetDatacenterLabels())
dcPods, err := rc.listPods(rc.Datacenter.GetDatacenterLabels())
if err != nil {
rc.ReqLogger.Error(err, "Failed to list pods, unable to proceed with deletion")
return result.Error(err)
}
dcPods := PodPtrsFromPodList(podList)
if len(podList.Items) > 0 {
if len(dcPods) > 0 {
rc.ReqLogger.V(1).Info("Deletion is being processed by the decommission check")
dcs, err := rc.getClusterDatacenters(dcPods)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/reconciliation/reconcile_fql.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func (rc *ReconciliationContext) CheckFullQueryLogging() result.ReconcileResult
rc.ReqLogger.Error(err, "error listing all pods in the cluster to progress full query logging reconciliation")
return result.RequeueSoon(2)
}
for _, podPtr := range PodPtrsFromPodList(podList) {
for _, podPtr := range podList {
features, err := rc.NodeMgmtClient.FeatureSet(podPtr)
if err != nil {
rc.ReqLogger.Error(err, "failed to verify featureset for FQL support")
Expand Down
52 changes: 37 additions & 15 deletions pkg/reconciliation/reconcile_racks.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@ import (
)

var (
ResultShouldNotRequeue reconcile.Result = reconcile.Result{Requeue: false}
ResultShouldRequeueNow reconcile.Result = reconcile.Result{Requeue: true}
ResultShouldRequeueSoon reconcile.Result = reconcile.Result{Requeue: true, RequeueAfter: 2 * time.Second}
ResultShouldRequeueTenSecs reconcile.Result = reconcile.Result{Requeue: true, RequeueAfter: 10 * time.Second}
ResultShouldNotRequeue reconcile.Result = reconcile.Result{Requeue: false}
ResultShouldRequeueNow reconcile.Result = reconcile.Result{Requeue: true}
ResultShouldRequeueSoon reconcile.Result = reconcile.Result{Requeue: true, RequeueAfter: 2 * time.Second}

QuietDurationFunc func(int) time.Duration = func(secs int) time.Duration { return time.Duration(secs) * time.Second }
)
Expand Down Expand Up @@ -618,7 +617,7 @@ func (rc *ReconciliationContext) CheckRackStoppedState() result.ReconcileResult
emittedStoppingEvent = true
}

rackPods := FilterPodListByLabels(rc.dcPods, rc.Datacenter.GetRackLabels(rackInfo.RackName))
rackPods := rc.rackPods(rackInfo.RackName)

nodesDrained := 0
nodeDrainErrors := 0
Expand Down Expand Up @@ -751,7 +750,7 @@ func (rc *ReconciliationContext) CheckPodsReady(endpointData httphelper.CassMeta
return result.Error(err)
}
if atLeastOneFirstNodeNotReady {
return result.RequeueSoon(2)
return result.RequeueSoon(10)
}

// step 3 - if the cluster isn't healthy, that's ok, but go back to step 1
Expand Down Expand Up @@ -1432,8 +1431,8 @@ func (rc *ReconciliationContext) isClusterHealthy() bool {
func (rc *ReconciliationContext) labelSeedPods(rackInfo *RackInformation) (int, error) {
logger := rc.ReqLogger.WithName("labelSeedPods")

rackLabels := rc.Datacenter.GetRackLabels(rackInfo.RackName)
rackPods := FilterPodListByLabels(rc.dcPods, rackLabels)
rackPods := rc.rackPods(rackInfo.RackName)

sort.SliceStable(rackPods, func(i, j int) bool {
return rackPods[i].Name < rackPods[j].Name
})
Expand Down Expand Up @@ -2150,7 +2149,7 @@ func (rc *ReconciliationContext) refreshSeeds() error {
return nil
}

func (rc *ReconciliationContext) listPods(selector map[string]string) (*corev1.PodList, error) {
func (rc *ReconciliationContext) listPods(selector map[string]string) ([]*corev1.Pod, error) {
rc.ReqLogger.Info("reconcile_racks::listPods")

listOptions := &client.ListOptions{
Expand All @@ -2165,7 +2164,11 @@ func (rc *ReconciliationContext) listPods(selector map[string]string) (*corev1.P
},
}

return podList, rc.Client.List(rc.Ctx, podList, listOptions)
if err := rc.Client.List(rc.Ctx, podList, listOptions); err != nil {
return nil, err
}

return PodPtrsFromPodList(podList), nil
}

func (rc *ReconciliationContext) CheckRollingRestart() result.ReconcileResult {
Expand Down Expand Up @@ -2425,21 +2428,40 @@ func (rc *ReconciliationContext) fixMissingPVC() (bool, error) {
return false, nil
}

func (rc *ReconciliationContext) datacenterPods() []*corev1.Pod {
if rc.dcPods != nil {
return rc.dcPods
}

dcSelector := rc.Datacenter.GetDatacenterLabels()
dcPods := FilterPodListByLabels(rc.clusterPods, dcSelector)

if rc.Datacenter.Status.MetadataVersion < 1 && rc.Datacenter.Status.DatacenterName != nil && *rc.Datacenter.Status.DatacenterName == rc.Datacenter.Spec.DatacenterName {
rc.ReqLogger.Info("Fetching with the old metadata version also")
dcSelector[api.DatacenterLabel] = api.CleanLabelValue(rc.Datacenter.Spec.DatacenterName)
rc.dcPods = append(rc.dcPods, FilterPodListByLabels(rc.clusterPods, dcSelector)...)
}

return dcPods
}

func (rc *ReconciliationContext) rackPods(rackName string) []*corev1.Pod {
return FilterPodListByLabels(rc.datacenterPods(), map[string]string{api.RackLabel: rackName})
}

// ReconcileAllRacks determines if a rack needs to be reconciled.
func (rc *ReconciliationContext) ReconcileAllRacks() (reconcile.Result, error) {
rc.ReqLogger.Info("reconciliationContext::reconcileAllRacks")

logger := rc.ReqLogger

podList, err := rc.listPods(rc.Datacenter.GetClusterLabels())
pods, err := rc.listPods(rc.Datacenter.GetClusterLabels())
if err != nil {
logger.Error(err, "error listing all pods in the cluster")
}

rc.clusterPods = PodPtrsFromPodList(podList)

dcSelector := rc.Datacenter.GetDatacenterLabels()
rc.dcPods = FilterPodListByLabels(rc.clusterPods, dcSelector)
rc.clusterPods = pods
rc.dcPods = rc.datacenterPods()

endpointData := rc.getCassMetadataEndpoints()

Expand Down
2 changes: 1 addition & 1 deletion scripts/release-helm-chart.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ if [[ ! $0 == scripts/* ]]; then
fi

# This script assumes k8ssandra is checked out at ../k8ssandra and is checked out at main
if [ "$#" -le 1 ]; then
if [ "$#" -lt 1 ]; then
echo "Usage: scripts/release-helm-chart.sh version legacy"
echo "Script assumes you are in the correct branch / tag and that k8ssandra repository"
echo "has been checked out to ../k8ssandra/. If legacy is set, the script will generate"
Expand Down

0 comments on commit 0573b8b

Please sign in to comment.