@@ -18,6 +18,7 @@ import (
1818 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1919 "k8s.io/apimachinery/pkg/types"
2020 "k8s.io/client-go/kubernetes"
21+ "k8s.io/client-go/util/retry"
2122 workv1 "open-cluster-management.io/api/work/v1"
2223 "sigs.k8s.io/controller-runtime/pkg/client"
2324
@@ -321,12 +322,9 @@ func updateManifestWork(conn *sdk.Connection, kubeCli client.Client, clusterID,
321322 return fmt .Errorf ("failed to get cluster: %w" , err )
322323 }
323324
324- // Use domain prefix here instead of hostedcluster.Name, since the pull secret will follow the domain prefix
325325 secretNamePrefix := hostedCluster .DomainPrefix () + "-pull"
326326
327- // Generate a random new secret name based on the existing pull secret name
328327 randomSuffix := func (chars string , length int ) string {
329- rand .Seed (time .Now ().UnixNano ())
330328 result := make ([]byte , length )
331329 for i := range result {
332330 result [i ] = chars [rand .Intn (len (chars ))]
@@ -335,74 +333,84 @@ func updateManifestWork(conn *sdk.Connection, kubeCli client.Client, clusterID,
335333 }
336334 newSecretName := secretNamePrefix + "-" + randomSuffix ("0123456789abcdef" , 6 )
337335
338- manifestWork := & workv1.ManifestWork {}
339- err = kubeCli .Get (context .TODO (), types.NamespacedName {Name : manifestWorkName , Namespace : manifestWorkNamespace }, manifestWork )
336+ ctx , cancel := context .WithTimeout (context .Background (), 2 * time .Minute )
337+ defer cancel ()
338+
339+ err = retry .RetryOnConflict (retry .DefaultRetry , func () error {
340+ manifestWork := & workv1.ManifestWork {}
341+ if err := kubeCli .Get (ctx , types.NamespacedName {Name : manifestWorkName , Namespace : manifestWorkNamespace }, manifestWork ); err != nil {
342+ return fmt .Errorf ("failed to get the target manifestwork for given cluster %v: %w" , clusterID , err )
343+ }
344+
345+ if err := updateManifestWorkPayloads (manifestWork , secretNamePrefix , newSecretName , pullsecret ); err != nil {
346+ return err
347+ }
348+
349+ return kubeCli .Update (ctx , manifestWork , & client.UpdateOptions {})
350+ })
340351 if err != nil {
341- return fmt .Errorf ("failed to get the target manifestwork for given cluster %v : %w" , clusterID , err )
352+ return fmt .Errorf ("cannot update the pull-secret within manifestwork : %w" , err )
342353 }
343354
344- for i , manifest := range manifestWork .Spec .Workload .Manifests {
345- if manifest .Raw != nil {
346- var manifestData map [string ]interface {}
347- err := json .Unmarshal (manifest .Raw , & manifestData )
348- if err != nil {
349- return err
350- }
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+ }
351361
352- jsonData , err := json .Marshal (manifestData )
353- if err != nil {
362+ return nil
363+ }
364+
365+ func updateManifestWorkPayloads (mw * workv1.ManifestWork , secretNamePrefix , newSecretName string , pullsecret []byte ) error {
366+ for i , manifest := range mw .Spec .Workload .Manifests {
367+ if manifest .Raw == nil {
368+ continue
369+ }
370+
371+ var meta struct {
372+ Kind string `json:"kind"`
373+ }
374+ if err := json .Unmarshal (manifest .Raw , & meta ); err != nil {
375+ return err
376+ }
377+
378+ switch meta .Kind {
379+ case "Secret" :
380+ secret := & corev1.Secret {}
381+ if err := json .Unmarshal (manifest .Raw , secret ); err != nil {
354382 return err
355383 }
356-
357- if manifestData ["kind" ] == "Secret" {
358- secret := & corev1.Secret {}
359- err = json .Unmarshal (jsonData , secret )
360- if err != nil {
361- return err
384+ if strings .Contains (secret .Name , secretNamePrefix ) {
385+ if secret .Data == nil {
386+ secret .Data = map [string ][]byte {}
362387 }
363- if strings .Contains (secret .Name , secretNamePrefix ) {
364- // Firstly, get the ecr auth from the existing pull secret and append it to new pull secret
365- oldPullSecret := secret .Data [".dockerconfigjson" ]
366- newPullSecret , err := buildNewSecret (oldPullSecret , pullsecret )
367- if err != nil {
368- return fmt .Errorf ("cannot build the new pull secret: %w" , err )
369- }
370- // Then, update the secret with new name and new value
371- secret .Name = newSecretName
372- secret .Data [".dockerconfigjson" ] = newPullSecret
388+ oldPullSecret := secret .Data [".dockerconfigjson" ]
389+ newPullSecret , err := buildNewSecret (oldPullSecret , pullsecret )
390+ if err != nil {
391+ return fmt .Errorf ("cannot build the new pull secret: %w" , err )
373392 }
393+ secret .Name = newSecretName
394+ secret .Data [".dockerconfigjson" ] = newPullSecret
374395 secretJson , err := json .Marshal (secret )
375396 if err != nil {
376397 return err
377398 }
378- manifestWork .Spec .Workload .Manifests [i ].Raw = secretJson
399+ mw .Spec .Workload .Manifests [i ].Raw = secretJson
379400 }
380- if manifestData ["kind" ] == "HostedCluster" {
381- hc := & hypershiftv1beta1.HostedCluster {}
382- err = json .Unmarshal (jsonData , hc )
383- if err != nil {
384- return err
385- }
386- // Update the hosted cluster reference secret name to the new name
387- hc .Spec .PullSecret .Name = newSecretName
388- hcJson , err := json .Marshal (hc )
389- if err != nil {
390- return err
391- }
392- manifestWork .Spec .Workload .Manifests [i ].Raw = hcJson
401+ case "HostedCluster" :
402+ hc := & hypershiftv1beta1.HostedCluster {}
403+ if err := json .Unmarshal (manifest .Raw , hc ); err != nil {
404+ return err
393405 }
406+ hc .Spec .PullSecret .Name = newSecretName
407+ hcJson , err := json .Marshal (hc )
408+ if err != nil {
409+ return err
410+ }
411+ mw .Spec .Workload .Manifests [i ].Raw = hcJson
394412 }
395413 }
396-
397- err = kubeCli .Update (context .TODO (), manifestWork , & client.UpdateOptions {})
398- if err != nil {
399- return fmt .Errorf ("cannot update the pull-secret within manifestwork: %w" , err )
400- }
401-
402- // The secret will be synced to the management cluster and guest cluster in a few seconds, wait here
403- fmt .Println ("sleep 60 seconds here to make sure secret gets synced on guest cluster" )
404- time .Sleep (time .Second * 60 )
405-
406414 return nil
407415}
408416
0 commit comments