Skip to content

Commit a242d8d

Browse files
authored
fix: Revert "fix: fix race condition in envelope work object creation via deterministic naming" (kubefleet-dev#454)
1 parent fa19935 commit a242d8d

3 files changed

Lines changed: 4 additions & 43 deletions

File tree

pkg/controllers/workgenerator/envelope.go

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,13 @@ package workgenerator
1818

1919
import (
2020
"context"
21-
"crypto/sha256"
22-
"encoding/hex"
2321
"fmt"
2422
"sort"
2523
"strings"
2624

2725
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2826
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
27+
"k8s.io/apimachinery/pkg/util/uuid"
2928
"k8s.io/klog/v2"
3029
"sigs.k8s.io/controller-runtime/pkg/client"
3130

@@ -82,19 +81,12 @@ func (r *Reconciler) createOrUpdateEnvelopeCRWorkObj(
8281
var work *fleetv1beta1.Work
8382
switch {
8483
case len(workList.Items) > 1:
85-
// Multiple matching work objects found; this should never occur under normal conditions
86-
// with deterministic naming. Log details for investigation.
84+
// Multiple matching work objects found; this should never occur under normal conditions.
8785
wrappedErr := fmt.Errorf("%d work objects found for the same envelope %v, only one expected", len(workList.Items), envelopeReader.GetEnvelopeObjRef())
8886
klog.ErrorS(wrappedErr, "Failed to create or update work object for envelope",
8987
"resourceBinding", klog.KObj(binding),
9088
"resourceSnapshot", klog.KObj(resourceSnapshot),
9189
"envelope", envelopeReader.GetEnvelopeObjRef())
92-
// Log the work object names to help debug
93-
for i := range workList.Items {
94-
klog.ErrorS(wrappedErr, "Duplicate work object found",
95-
"work", klog.KObj(&workList.Items[i]),
96-
"creationTimestamp", workList.Items[i].CreationTimestamp)
97-
}
9890
return nil, controller.NewUnexpectedBehaviorError(wrappedErr)
9991
case len(workList.Items) == 1:
10092
klog.V(2).InfoS("Found existing work object for the envelope; updating it",
@@ -204,11 +196,7 @@ func buildNewWorkForEnvelopeCR(
204196
manifests []fleetv1beta1.Manifest,
205197
resourceOverrideSnapshotHash, clusterResourceOverrideSnapshotHash string,
206198
) *fleetv1beta1.Work {
207-
// Generate a deterministic work name based on the envelope identity to prevent duplicate work objects
208-
// from being created by concurrent reconciliations. The name is stable across reconciliations for
209-
// the same envelope, allowing Kubernetes' built-in duplicate prevention to work correctly.
210-
envelopeIdentifier := generateEnvelopeIdentifier(envelopeReader)
211-
workName := fmt.Sprintf(fleetv1beta1.WorkNameWithEnvelopeCRFmt, workNamePrefix, envelopeIdentifier)
199+
workName := fmt.Sprintf(fleetv1beta1.WorkNameWithEnvelopeCRFmt, workNamePrefix, uuid.NewUUID())
212200
workNamespace := fmt.Sprintf(utils.NamespaceNameFormat, resourceBinding.GetBindingSpec().TargetCluster)
213201

214202
// Create the labels map
@@ -246,18 +234,3 @@ func buildNewWorkForEnvelopeCR(
246234
},
247235
}
248236
}
249-
250-
// generateEnvelopeIdentifier generates a stable, deterministic identifier for an envelope.
251-
// This identifier is used in the work name to ensure that the same envelope always produces
252-
// the same work name, enabling Kubernetes' atomic create operations to prevent duplicates.
253-
func generateEnvelopeIdentifier(envelopeReader fleetv1beta1.EnvelopeReader) string {
254-
// Create a stable identifier based on envelope type, name, and namespace.
255-
// For cluster-scoped envelopes, namespace is empty, so we include the type to ensure uniqueness.
256-
identifier := fmt.Sprintf("%s.%s.%s", envelopeReader.GetEnvelopeType(), envelopeReader.GetNamespace(), envelopeReader.GetName())
257-
258-
// Use SHA256 hash to create a deterministic identifier
259-
hash := sha256.Sum256([]byte(identifier))
260-
// Take first 8 characters of the hex-encoded hash to keep work names reasonably short
261-
// while maintaining uniqueness (8 hex chars = 4 bytes = 2^32 combinations, sufficient for envelope uniqueness)
262-
return hex.EncodeToString(hash[:])[:8]
263-
}

pkg/controllers/workgenerator/envelope_test.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -483,18 +483,6 @@ func TestCreateOrUpdateEnvelopeCRWorkObj(t *testing.T) {
483483
want: nil,
484484
wantErr: true,
485485
},
486-
{
487-
name: "two existing works should result in error",
488-
envelopeReader: resourceEnvelope,
489-
resourceOverrideSnapshotHash: "new-resource-hash",
490-
clusterResourceOverrideSnapshotHash: "new-cluster-resource-hash",
491-
existingObjects: func() []client.Object {
492-
existingWork1 := existingWork.DeepCopy()
493-
existingWork1.Name = "test-work-1"
494-
return []client.Object{existingWork, existingWork1}
495-
}(),
496-
wantErr: true,
497-
},
498486
}
499487

500488
for _, tt := range tests {

test/e2e/enveloped_object_placement_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ var _ = Describe("placing wrapped resources using a CRP", func() {
140140
for idx := range allMemberClusters {
141141
memberCluster := allMemberClusters[idx]
142142
workResourcesPlacedActual := checkAllResourcesPlacement(memberCluster)
143-
Eventually(workResourcesPlacedActual, workloadEventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to place work resources on member cluster %s", memberCluster.ClusterName)
143+
Eventually(workResourcesPlacedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to place work resources on member cluster %s", memberCluster.ClusterName)
144144
}
145145
})
146146

0 commit comments

Comments
 (0)