Skip to content
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
48 changes: 41 additions & 7 deletions internal/controller/designate_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ func (r *DesignateReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Man
}

for _, cr := range designates.Items {
if o.GetName() == cr.Spec.ExternalBindsSecret {
if o.GetName() == cr.Spec.ExternalBindsSecret || o.GetName() == cr.Name+"-backendbind9"+designate.TsigSecretSuffix {
name := client.ObjectKey{
Namespace: o.GetNamespace(),
Name: cr.Name,
Expand Down Expand Up @@ -1388,6 +1388,7 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
return ctrl.Result{}, err
}

tsigKeysPending := false
if len(nsRecords) > 0 && instance.Status.DesignateCentralReadyCount > 0 {
Log.Info("NS records data found")
poolsYamlConfigMap := &corev1.ConfigMap{
Expand All @@ -1399,25 +1400,55 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
Data: make(map[string]string),
}

// Read per-pool TSIG key ID mapping if AZ-aware mode is enabled
// Read per-pool TSIG key IDs in both shared and AZ-aware modes.
var tsigKeyIDs map[string]string
if instance.Spec.AZAwareMode == designatev1beta1.AZModeEnabled && multipoolConfig != nil {
if multipoolConfig != nil {
tsigSecretName := fmt.Sprintf("%s-backendbind9%s", instance.Name, designate.TsigSecretSuffix)
tsigSecret := &corev1.Secret{}
err := helper.GetClient().Get(ctx, types.NamespacedName{Name: tsigSecretName, Namespace: instance.GetNamespace()}, tsigSecret)
if err != nil && !k8s_errors.IsNotFound(err) {
return ctrl.Result{}, fmt.Errorf("failed to get TSIG secret %s: %w", tsigSecretName, err)
}
if err == nil {
if data, exists := tsigSecret.Data[designate.TSIGKeyIDsDataKey]; exists {
if tsigSecret.Annotations["tsig-keys-ready"] == "false" {
// Reuse the applied identities until BIND has loaded the keys.
// Continue reconciling service specs and registering new pools:
// either can be needed for the pending rollout to finish.
tsigKeysPending = true
appliedPools := &corev1.ConfigMap{}
if err := helper.GetClient().Get(ctx, types.NamespacedName{Name: designate.PoolsYamlConfigMap, Namespace: instance.Namespace}, appliedPools); err != nil {
if !k8s_errors.IsNotFound(err) {
return ctrl.Result{}, err
}
} else {
var pools []designate.Pool
if err := yaml.Unmarshal([]byte(appliedPools.Data[designate.PoolsYamlContent]), &pools); err != nil {
return ctrl.Result{}, fmt.Errorf("invalid applied pools.yaml: %w", err)
}
tsigKeyIDs = make(map[string]string)
for _, pool := range pools {
for _, target := range pool.Targets {
if target.TSIGKeyID != "" {
tsigKeyIDs[pool.Name] = target.TSIGKeyID
break
}
}
}
}
} else if data, exists := tsigSecret.Data[designate.TSIGKeyIDsDataKey]; exists {
if jsonErr := json.Unmarshal(data, &tsigKeyIDs); jsonErr != nil {
Log.Info(fmt.Sprintf("Failed to parse TSIG key ID mapping from secret, pools.yaml will be generated without tsigkey_ids: %v", jsonErr))
return ctrl.Result{}, fmt.Errorf("invalid TSIG key ID mapping: %w", jsonErr)
}
}
}
// If secret doesn't exist yet, tsigKeyIDs stays nil — pools.yaml is generated without tsigkey_ids (first pass)
}

if instance.Spec.AZAwareMode != designatev1beta1.AZModeEnabled {
// Also strip a stale default binding during migration from AZ mode.
delete(tsigKeyIDs, designate.DefaultPoolName)
}

poolsYaml, poolsYamlHash, err := designate.GeneratePoolsYamlDataAndHash(updatedBindMap, mdnsConfigMap.Data, nsRecords, multipoolConfig, externalBindData, externalMasterServiceIPs, tsigKeyIDs)
if err != nil {
return ctrl.Result{}, err
Expand Down Expand Up @@ -1656,7 +1687,7 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des

// We reached the end of the Reconcile, update the Ready condition based on
// the sub conditions
if instance.Status.Conditions.AllSubConditionIsTrue() {
if !tsigKeysPending && instance.Status.Conditions.AllSubConditionIsTrue() {
instance.Status.Conditions.MarkTrue(
condition.ReadyCondition, condition.ReadyMessage)
}
Expand All @@ -1667,7 +1698,7 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
// covers sub-CRs that don't participate in the input-hash correlation
// (unbound, backendbind9), so the finalizer is held until the whole
// deployment has stabilized on the new credentials.
guardReady := allServicesReady && instance.Status.Conditions.AllSubConditionIsTrue()
guardReady := !tsigKeysPending && allServicesReady && instance.Status.Conditions.AllSubConditionIsTrue()

// Finalize transport URL rotation
transportSecretName, err := object.FinalizeSecretRotation(
Expand Down Expand Up @@ -1728,6 +1759,9 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
return ctrl.Result{}, err
}

if tsigKeysPending {
return ctrl.Result{RequeueAfter: 5 * time.Second}, nil
}
Log.Info("Reconciled Service successfully")
return ctrl.Result{}, nil
}
Expand Down
11 changes: 6 additions & 5 deletions internal/controller/designatebackendbind9_multipool.go
Original file line number Diff line number Diff line change
Expand Up @@ -767,20 +767,21 @@ func (r *DesignateBackendbind9Reconciler) reconcileMultipoolResources(
return ctrlResult, err
}

ctrlResult, err = r.reconcileMultipoolStatefulSets(ctx, instance, helper, multipoolConfig, inputHash, serviceLabels, serviceAnnotations, topology)
if err != nil || (ctrlResult != ctrl.Result{}) {
return ctrlResult, err
statefulSetResult, err := r.reconcileMultipoolStatefulSets(ctx, instance, helper, multipoolConfig, inputHash, serviceLabels, serviceAnnotations, topology)
if err != nil {
return statefulSetResult, err
}

// Create/update TSIG secrets for non-default pools
// Reconcile keys even while StatefulSets are pending: new BIND pods can be
// waiting for these Secrets to exist before their init containers can run.
ctrlResult, err = r.reconcileTSIGSecrets(ctx, instance, helper, multipoolConfig)
if err != nil || (ctrlResult != ctrl.Result{}) {
return ctrlResult, err
}

// Note: Per-pool bind IP ConfigMaps are cleaned up by DesignateReconciler.reconcileBindConfigMaps()

return ctrl.Result{}, nil
return statefulSetResult, nil
}

// cleanupMultipoolServices deletes pool-specific services during migration to single-pool mode
Expand Down
Loading
Loading