Skip to content

Commit bc011c0

Browse files
typeidclaude
authored andcommitted
Harden updateManifestWork: bounded context, nil guard, stricter tests
- Replace context.TODO() with context.WithTimeout(2m) for Get/Update calls inside the retry loop, bounding total wall time - Replace unconditional time.Sleep with a select on ctx.Done() so the post-update wait respects cancellation - Guard against nil secret.Data before assigning .dockerconfigjson - Replace ignored json.Marshal/Unmarshal errors in tests with require.NoError to fail fast on unexpected marshaling failures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent caf54f6 commit bc011c0

2 files changed

Lines changed: 30 additions & 14 deletions

File tree

cmd/cluster/transferowner.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -333,24 +333,31 @@ func updateManifestWork(conn *sdk.Connection, kubeCli client.Client, clusterID,
333333
}
334334
newSecretName := secretNamePrefix + "-" + randomSuffix("0123456789abcdef", 6)
335335

336+
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
337+
defer cancel()
338+
336339
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
337340
manifestWork := &workv1.ManifestWork{}
338-
if err := kubeCli.Get(context.TODO(), types.NamespacedName{Name: manifestWorkName, Namespace: manifestWorkNamespace}, manifestWork); err != nil {
341+
if err := kubeCli.Get(ctx, types.NamespacedName{Name: manifestWorkName, Namespace: manifestWorkNamespace}, manifestWork); err != nil {
339342
return fmt.Errorf("failed to get the target manifestwork for given cluster %v: %w", clusterID, err)
340343
}
341344

342345
if err := updateManifestWorkPayloads(manifestWork, secretNamePrefix, newSecretName, pullsecret); err != nil {
343346
return err
344347
}
345348

346-
return kubeCli.Update(context.TODO(), manifestWork, &client.UpdateOptions{})
349+
return kubeCli.Update(ctx, manifestWork, &client.UpdateOptions{})
347350
})
348351
if err != nil {
349352
return fmt.Errorf("cannot update the pull-secret within manifestwork: %w", err)
350353
}
351354

352-
fmt.Println("sleep 60 seconds here to make sure secret gets synced on guest cluster")
353-
time.Sleep(time.Second * 60)
355+
fmt.Println("waiting 60 seconds for secret to sync on guest cluster")
356+
select {
357+
case <-ctx.Done():
358+
return fmt.Errorf("context cancelled while waiting for secret sync: %w", ctx.Err())
359+
case <-time.After(60 * time.Second):
360+
}
354361

355362
return nil
356363
}
@@ -375,6 +382,9 @@ func updateManifestWorkPayloads(mw *workv1.ManifestWork, secretNamePrefix, newSe
375382
return err
376383
}
377384
if strings.Contains(secret.Name, secretNamePrefix) {
385+
if secret.Data == nil {
386+
secret.Data = map[string][]byte{}
387+
}
378388
oldPullSecret := secret.Data[".dockerconfigjson"]
379389
newPullSecret, err := buildNewSecret(oldPullSecret, pullsecret)
380390
if err != nil {

cmd/cluster/transferowner_test.go

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
hypershiftv1beta1 "github.com/openshift/hypershift/api/hypershift/v1beta1"
1616
"github.com/stretchr/testify/assert"
1717
"github.com/stretchr/testify/mock"
18+
"github.com/stretchr/testify/require"
1819
corev1 "k8s.io/api/core/v1"
1920
apierrors "k8s.io/apimachinery/pkg/api/errors"
2021
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -367,7 +368,8 @@ func TestBuildNewSecret(t *testing.T) {
367368
}
368369
}
369370

370-
func buildTestManifestWork(secretName string, pullSecretData []byte, hcPullSecretRef string) *workv1.ManifestWork {
371+
func buildTestManifestWork(t *testing.T, secretName string, pullSecretData []byte, hcPullSecretRef string) *workv1.ManifestWork {
372+
t.Helper()
371373
secret := &corev1.Secret{
372374
TypeMeta: metav1.TypeMeta{Kind: "Secret", APIVersion: "v1"},
373375
ObjectMeta: metav1.ObjectMeta{
@@ -378,7 +380,8 @@ func buildTestManifestWork(secretName string, pullSecretData []byte, hcPullSecre
378380
".dockerconfigjson": pullSecretData,
379381
},
380382
}
381-
secretJSON, _ := json.Marshal(secret)
383+
secretJSON, err := json.Marshal(secret)
384+
require.NoError(t, err)
382385

383386
hc := &hypershiftv1beta1.HostedCluster{
384387
TypeMeta: metav1.TypeMeta{Kind: "HostedCluster", APIVersion: "hypershift.openshift.io/v1beta1"},
@@ -390,15 +393,17 @@ func buildTestManifestWork(secretName string, pullSecretData []byte, hcPullSecre
390393
PullSecret: corev1.LocalObjectReference{Name: hcPullSecretRef},
391394
},
392395
}
393-
hcJSON, _ := json.Marshal(hc)
396+
hcJSON, err := json.Marshal(hc)
397+
require.NoError(t, err)
394398

395399
cm := map[string]interface{}{
396400
"kind": "ConfigMap",
397401
"apiVersion": "v1",
398402
"metadata": map[string]interface{}{"name": "unrelated-config", "namespace": "clusters"},
399403
"data": map[string]interface{}{"key": "value"},
400404
}
401-
cmJSON, _ := json.Marshal(cm)
405+
cmJSON, err := json.Marshal(cm)
406+
require.NoError(t, err)
402407

403408
return &workv1.ManifestWork{
404409
ObjectMeta: metav1.ObjectMeta{
@@ -427,7 +432,7 @@ func TestUpdateManifestWorkRetriesOnConflict(t *testing.T) {
427432
newSecretName := secretNamePrefix + "-def456"
428433

429434
originalCMRaw := func() []byte {
430-
mw := buildTestManifestWork(oldSecretName, oldPullSecret, oldSecretName)
435+
mw := buildTestManifestWork(t, oldSecretName, oldPullSecret, oldSecretName)
431436
raw := make([]byte, len(mw.Spec.Workload.Manifests[0].Raw))
432437
copy(raw, mw.Spec.Workload.Manifests[0].Raw)
433438
return raw
@@ -445,7 +450,7 @@ func TestUpdateManifestWorkRetriesOnConflict(t *testing.T) {
445450
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
446451
getCalls.Add(1)
447452

448-
freshMW := buildTestManifestWork(oldSecretName, oldPullSecret, oldSecretName)
453+
freshMW := buildTestManifestWork(t, oldSecretName, oldPullSecret, oldSecretName)
449454

450455
if err := updateManifestWorkPayloads(freshMW, secretNamePrefix, newSecretName, newPullSecret); err != nil {
451456
return err
@@ -489,7 +494,7 @@ func TestUpdateManifestWorkPreservesUnrelatedManifests(t *testing.T) {
489494
oldSecretName := secretNamePrefix + "-aaa111"
490495
newSecretName := secretNamePrefix + "-bbb222"
491496

492-
mw := buildTestManifestWork(oldSecretName, oldPullSecret, oldSecretName)
497+
mw := buildTestManifestWork(t, oldSecretName, oldPullSecret, oldSecretName)
493498

494499
originalRaws := make([][]byte, len(mw.Spec.Workload.Manifests))
495500
for i, m := range mw.Spec.Workload.Manifests {
@@ -527,15 +532,16 @@ func TestUpdateManifestWorkIndexShiftSafety(t *testing.T) {
527532
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
528533
call := updateCalls.Add(1)
529534

530-
mw := buildTestManifestWork(oldSecretName, oldPullSecret, oldSecretName)
535+
mw := buildTestManifestWork(t, oldSecretName, oldPullSecret, oldSecretName)
531536

532537
if call > 1 {
533538
// Another controller prepended a Namespace manifest, shifting all indices
534539
ns := map[string]interface{}{
535540
"kind": "Namespace", "apiVersion": "v1",
536541
"metadata": map[string]interface{}{"name": "new-namespace"},
537542
}
538-
nsJSON, _ := json.Marshal(ns)
543+
nsJSON, err := json.Marshal(ns)
544+
require.NoError(t, err)
539545
shifted := make([]workv1.Manifest, 0, len(mw.Spec.Workload.Manifests)+1)
540546
shifted = append(shifted, workv1.Manifest{RawExtension: runtime.RawExtension{Raw: nsJSON}})
541547
shifted = append(shifted, mw.Spec.Workload.Manifests...)
@@ -559,7 +565,7 @@ func TestUpdateManifestWorkIndexShiftSafety(t *testing.T) {
559565
var meta struct {
560566
Kind string `json:"kind"`
561567
}
562-
json.Unmarshal(manifest.Raw, &meta)
568+
require.NoError(t, json.Unmarshal(manifest.Raw, &meta))
563569

564570
switch meta.Kind {
565571
case "Secret":

0 commit comments

Comments
 (0)