• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

openshift-kni / cluster-group-upgrades-operator / 6e522fdb177f6d512bdef6390d8450964150d583

24 Nov 2025 07:10PM UTC coverage: 5.68% (-23.1%) from 28.767%
6e522fdb177f6d512bdef6390d8450964150d583

push

web-flow
Replace oc wait with sleep (#5164)

Signed-off-by: Saeid Askari <saskari@redhat.com>

372 of 6549 relevant lines covered (5.68%)

0.06 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

12.84
/controllers/managedclusterForCGU_controller.go
1
/*
2
Copyright 2021.
3

4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7

8
    http://www.apache.org/licenses/LICENSE-2.0
9

10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
*/
16

17
package controllers
18

19
import (
20
        "context"
21
        "encoding/json"
22
        "fmt"
23
        "os"
24
        "sort"
25
        "strconv"
26
        "strings"
27

28
        "github.com/go-logr/logr"
29
        corev1 "k8s.io/api/core/v1"
30
        "k8s.io/apimachinery/pkg/api/errors"
31
        "k8s.io/apimachinery/pkg/api/meta"
32
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
33
        "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
34
        "k8s.io/apimachinery/pkg/runtime"
35
        "k8s.io/apimachinery/pkg/types"
36
        ctrl "sigs.k8s.io/controller-runtime"
37
        "sigs.k8s.io/controller-runtime/pkg/builder"
38
        "sigs.k8s.io/controller-runtime/pkg/client"
39
        "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
40
        "sigs.k8s.io/controller-runtime/pkg/event"
41
        "sigs.k8s.io/controller-runtime/pkg/predicate"
42
        "sigs.k8s.io/controller-runtime/pkg/reconcile"
43
        yaml "sigs.k8s.io/yaml"
44

45
        "github.com/openshift-kni/cluster-group-upgrades-operator/controllers/templates"
46
        utils "github.com/openshift-kni/cluster-group-upgrades-operator/controllers/utils"
47
        ranv1alpha1 "github.com/openshift-kni/cluster-group-upgrades-operator/pkg/api/clustergroupupgrades/v1alpha1"
48
        clusterv1 "open-cluster-management.io/api/cluster/v1"
49
        policyv1 "open-cluster-management.io/config-policy-controller/api/v1"
50
        policiesv1 "open-cluster-management.io/governance-policy-propagator/api/v1"
51
)
52

53
const (
54
        ztpInstallNS             = "ztp-install"
55
        ztpDeployWaveAnnotation  = "ran.openshift.io/ztp-deploy-wave"
56
        ztpRunningLabel          = "ztp-running"
57
        ztpDoneLabel             = "ztp-done"
58
        aztpRequiredLabel        = "accelerated-ztp"
59
        aztpDeployServiceVariant = "full"
60
)
61

62
// ManagedClusterForCguReconciler reconciles a ManagedCluster object to auto create the ClusterGroupUpgrade
63
type ManagedClusterForCguReconciler struct {
64
        client.Client
65
        Log    logr.Logger
66
        Scheme *runtime.Scheme
67
}
68

69
//+kubebuilder:rbac:groups=cluster.open-cluster-management.io,resources=managedclusters,verbs=get;list;watch
70
//+kubebuilder:rbac:groups=cluster.open-cluster-management.io,resources=managedclusters/finalizers,verbs=update
71
//+kubebuilder:rbac:groups=ran.openshift.io,resources=clustergroupupgrades,verbs=get;list;watch;create;update;patch;delete
72
//+kubebuilder:rbac:groups=ran.openshift.io,resources=precachingconfigs,verbs=get;list;watch;create;update;patch;delete
73
//+kubebuilder:rbac:groups="",resources=namespaces,verbs=get;list;watch;create;update;patch;delete
74
//+kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;create;delete
75

76
// Reconcile the managed cluster auto create ClusterGroupUpgrade
77
//   - Controller watches for create event of managed cluster object. Reconciliation
78
//     is triggered when a new managed cluster is created
79
//   - When a new managed cluster is created, create ClusterGroupUpgrade CR for the
80
//     cluster only when it's ready and its child policies are available
81
//   - As created ClusterGroupUpgrade has ownReference set to its managed cluster,
82
//     when the managed cluster is deleted, the ClusterGroupUpgrade will be auto-deleted
83
//
84
// Note: The Controller will requeue the Request to be processed again if the returned error is non-nil or
85
// Result.Requeue is true, otherwise upon completion it will remove the work from the queue.
86
func (r *ManagedClusterForCguReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
1✔
87

1✔
88
        managedCluster := &clusterv1.ManagedCluster{}
1✔
89
        if err := r.Get(ctx, types.NamespacedName{Name: req.Name}, managedCluster); err != nil {
1✔
90
                if errors.IsNotFound(err) {
×
91
                        // managed cluster could have been deleted
×
92
                        return ctrl.Result{}, nil
×
93
                }
×
94
                // Error reading managed cluster, requeue the request
95
                return ctrl.Result{}, err
×
96
        }
97

98
        // Stop creating UOCR or AZTP if ztp of this cluster is done already
99
        if _, found := managedCluster.Labels[ztpDoneLabel]; found {
2✔
100
                r.Log.Info("ZTP for the cluster has completed. "+ztpDoneLabel+" label found.", "Name", managedCluster.Name)
1✔
101
                return doNotRequeue(), nil
1✔
102
        }
1✔
103

104
        clusterGroupUpgrade := &ranv1alpha1.ClusterGroupUpgrade{}
1✔
105
        if err := r.Get(ctx, types.NamespacedName{Name: req.Name, Namespace: ztpInstallNS}, clusterGroupUpgrade); err != nil {
2✔
106
                if !errors.IsNotFound(err) {
1✔
107
                        // Error reading clusterGroupUpgrade, requeue the request
×
108
                        return ctrl.Result{}, err
×
109
                }
×
110
        } else {
×
111
                // clusterGroupUpgrade for this cluster already exists, stop reconcile
×
112
                r.Log.Info("clusterGroupUpgrade found", "Name", clusterGroupUpgrade.Name, "Namespace", clusterGroupUpgrade.Namespace)
×
113
                return doNotRequeue(), nil
×
114
        }
×
115

116
        // clusterGroupUpgrade CR doesn't exist
117
        availableCondition := meta.FindStatusCondition(managedCluster.Status.Conditions, clusterv1.ManagedClusterConditionAvailable)
1✔
118
        if availableCondition != nil && availableCondition.Status == metav1.ConditionTrue {
1✔
119
                // cluster is ready
×
120
                r.Log.Info("cluster is ready", "Name", managedCluster.Name)
×
121

×
122
                // Child policies get created as soon as the placementrule/placementbinding
×
123
                // gets created and matches the parent policies to the managedcluster.
×
124
                // It takes ~45 minutes for cluster to be installed and ready.
×
125
                // At this stage, all child policies should be created.
×
126
                policies, err := utils.GetChildPolicies(ctx, r.Client, []string{managedCluster.Name})
×
127
                if err != nil {
×
128
                        return ctrl.Result{}, err
×
129
                }
×
130
                if len(policies) == 0 {
×
131
                        // likely no policies were created, so no child policies found
×
132
                        r.Log.Info("WARN: No child policies found for cluster", "Name", managedCluster.Name)
×
133
                }
×
134

135
                // create clusterGroupUpgrade
136
                if err := r.newClusterGroupUpgrade(ctx, managedCluster, policies); err != nil {
×
137
                        return ctrl.Result{}, err
×
138
                }
×
139
        } else {
1✔
140
                // availableCondition is false or unknown, cluster is not ready
1✔
141
                return r.handleNotReadyCluster(ctx, managedCluster)
1✔
142
        }
1✔
143

144
        return doNotRequeue(), nil
×
145
}
146

147
func (r *ManagedClusterForCguReconciler) handleNotReadyCluster(
148
        ctx context.Context, managedCluster *clusterv1.ManagedCluster) (reconcile.Result, error) {
1✔
149
        if err := r.extractAztpPolicies(ctx, managedCluster); err != nil {
1✔
150
                return ctrl.Result{}, err
×
151
        }
×
152
        r.Log.Info("cluster is not ready", "Name", managedCluster.Name)
1✔
153
        return doNotRequeue(), nil
1✔
154
}
155

156
// sort map[string]int by value in ascending order, return sorted keys
157
func sortMapByValue(sortMap map[string]int) []string {
×
158
        var keys []string
×
159
        for key := range sortMap {
×
160
                keys = append(keys, key)
×
161
        }
×
162

163
        sort.Slice(keys, func(i, j int) bool {
×
164
                // for equal elements, sort string alphabetically
×
165
                if sortMap[keys[i]] == sortMap[keys[j]] {
×
166
                        return keys[i] < keys[j]
×
167
                }
×
168
                return sortMap[keys[i]] < sortMap[keys[j]]
×
169
        })
170
        return keys
×
171
}
172

173
// Create a clusterGroupUpgrade
174
func (r *ManagedClusterForCguReconciler) newClusterGroupUpgrade(
175
        ctx context.Context, cluster *clusterv1.ManagedCluster, childPolicies []policiesv1.Policy) (err error) {
×
176

×
177
        var policyWaveMap = make(map[string]int)
×
178

×
179
        // Generate a list of ordered managed policies based on the deploy wave.
×
180
        // Deploywave is a way to order deployment of policies, it's defined
×
181
        // as a annotation in policy.
×
182
        // For example,
×
183
        //   metadata:
×
184
        //     annotations:
×
185
        //       "ran.openshift.io/ztp-deploy-wave": "1"
×
186
        // The list of policies is ordered from the lowest value to the highest.
×
187
        // Policy without a wave is not managed.
×
188
        for _, cPolicy := range childPolicies {
×
189
                // Ignore policies with remediationAction enforce
×
190
                if strings.EqualFold(string(cPolicy.Spec.RemediationAction), "enforce") {
×
191
                        r.Log.Info("Ignoring policy with remediationAction enforce", "policy", cPolicy.Name)
×
192
                        continue
×
193
                }
194

195
                deployWave, found := cPolicy.GetAnnotations()[ztpDeployWaveAnnotation]
×
196
                if found {
×
197
                        deployWaveInt, err := strconv.Atoi(deployWave)
×
198
                        if err != nil {
×
199
                                // err convert from string to int
×
200
                                return fmt.Errorf("%s in policy %s is not an interger: %s", ztpDeployWaveAnnotation, cPolicy.GetName(), err)
×
201
                        }
×
202
                        policyName, err := utils.GetParentPolicyNameAndNamespace(cPolicy.GetName())
×
203
                        if err != nil {
×
204
                                r.Log.Info("Ignoring policy with invalid name", "policy", cPolicy.Name)
×
205
                                continue
×
206
                        }
207
                        policyWaveMap[policyName[1]] = deployWaveInt
×
208
                }
209
        }
210

211
        sortedManagedPolicies := sortMapByValue(policyWaveMap)
×
212
        cguMeta := metav1.ObjectMeta{
×
213
                Name:      cluster.Name,
×
214
                Namespace: ztpInstallNS,
×
215
        }
×
216
        enable := true // default
×
217
        cguSpec := ranv1alpha1.ClusterGroupUpgradeSpec{
×
218
                Enable:          &enable,
×
219
                Clusters:        []string{cluster.Name},
×
220
                ManagedPolicies: sortedManagedPolicies,
×
221
                RemediationStrategy: &ranv1alpha1.RemediationStrategySpec{
×
222
                        MaxConcurrency: 1,
×
223
                },
×
224
                Actions: ranv1alpha1.Actions{
×
225
                        BeforeEnable: &ranv1alpha1.BeforeEnable{
×
226
                                AddClusterLabels: map[string]string{
×
227
                                        ztpRunningLabel: "",
×
228
                                },
×
229
                        },
×
230
                        AfterCompletion: &ranv1alpha1.AfterCompletion{
×
231
                                AddClusterLabels: map[string]string{
×
232
                                        ztpDoneLabel: "",
×
233
                                },
×
234
                                RemoveClusterLabels: []string{
×
235
                                        ztpRunningLabel,
×
236
                                },
×
237
                        },
×
238
                },
×
239
        }
×
240
        clusterGroupUpgrade := &ranv1alpha1.ClusterGroupUpgrade{
×
241
                ObjectMeta: cguMeta,
×
242
                Spec:       cguSpec,
×
243
        }
×
244

×
245
        // set managedcluster as the owner of its created ClusterGroupUpgrade CR, so when a cluster
×
246
        // is deleted, its dependent ClusterGroupUpgrade CR will be automatically cleaned up
×
247
        if err := controllerutil.SetControllerReference(cluster, clusterGroupUpgrade, r.Scheme); err != nil {
×
248
                return err
×
249
        }
×
250

251
        if err := r.Create(ctx, clusterGroupUpgrade); err != nil {
×
252
                if errors.IsNotFound(err) && strings.Contains(err.Error(), "namespace") {
×
253
                        namespace := &corev1.Namespace{
×
254
                                ObjectMeta: metav1.ObjectMeta{
×
255
                                        Name: ztpInstallNS,
×
256
                                },
×
257
                        }
×
258
                        if err := r.Create(ctx, namespace); err != nil {
×
259
                                r.Log.Error(err, "Fail to create namespace", "name", ztpInstallNS)
×
260
                                return err
×
261
                        }
×
262
                        // retry
263
                        if err := r.Create(ctx, clusterGroupUpgrade); err != nil {
×
264
                                r.Log.Error(err, "Fail to create clusterGroupUpgrade", "name", cluster.Name, "namespace", ztpInstallNS)
×
265
                                return err
×
266
                        }
×
267
                }
268

269
                r.Log.Error(err, "Fail to create clusterGroupUpgrade", "name", cluster.Name, "namespace", ztpInstallNS)
×
270
                return err
×
271
        }
272

273
        r.Log.Info("Found ManagedCluster "+cluster.Name+" without "+ztpDoneLabel+" label. Created clusterGroupUpgrade.",
×
274
                "name", cluster.Name, "namespace", ztpInstallNS)
×
275
        return nil
×
276
}
277

278
func (r *ManagedClusterForCguReconciler) newConfigmap(name, namespace string) *corev1.ConfigMap {
×
279
        return &corev1.ConfigMap{
×
280
                TypeMeta:   metav1.TypeMeta{APIVersion: "v1", Kind: "ConfigMap"},
×
281
                ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace},
×
282
                Data:       map[string]string{},
×
283
        }
×
284
}
×
285

286
// Extract policies for AZTP
287
func (r *ManagedClusterForCguReconciler) extractAztpPolicies(ctx context.Context, managedCluster *clusterv1.ManagedCluster) (err error) {
1✔
288
        aztpVariant, aztpRequired := managedCluster.GetLabels()[aztpRequiredLabel]
1✔
289
        if !aztpRequired {
2✔
290
                return nil
1✔
291
        }
1✔
292
        namespace := managedCluster.GetName()
×
293
        if namespace == "local-cluster" {
×
294
                return nil
×
295
        }
×
296
        configMapName := fmt.Sprintf("%s-aztp", namespace)
×
297
        innerCmNs := os.Getenv("AZTP_INNER_CONFIGMAP_NAMESPACE")
×
298
        if innerCmNs == "" {
×
299
                innerCmNs = "ztp-profile"
×
300
        }
×
301
        innerCmName := os.Getenv("AZTP_INNER_CONFIGMAP_NAME")
×
302
        if innerCmName == "" {
×
303
                innerCmName = "ztp-post-provision"
×
304
        }
×
305
        cm := r.newConfigmap(configMapName, namespace)
×
306
        if err := r.Delete(ctx, cm, &client.DeleteOptions{}); err != nil {
×
307
                if !errors.IsNotFound(err) {
×
308
                        return err
×
309
                }
×
310
        }
311

312
        policies, err := utils.GetChildPolicies(ctx, r.Client, []string{namespace})
×
313
        if err != nil {
×
314
                return err
×
315
        }
×
316
        if len(policies) == 0 {
×
317
                r.Log.Info("no child policies found for cluster", "Name", namespace)
×
318
                return nil
×
319
        }
×
320

321
        objects, err := r.GetConfigurationObjects(policies)
×
322
        if err != nil {
×
323
                return err
×
324
        }
×
325
        r.Log.Info(fmt.Sprintf("found %d policies and %d objects for %s", len(policies), len(objects), namespace))
×
326
        var directlyAppliedObjects []unstructured.Unstructured
×
327
        var wrappedObjects []unstructured.Unstructured
×
328

×
329
        for _, ob := range objects {
×
330
                ob.Object["status"] = map[string]interface{}{} // remove status, we can't apply it
×
331
                groupKind := ob.GroupVersionKind().GroupKind().String()
×
332
                r.Log.Info("adding object", "groupKind", groupKind, "name", ob.GetName())
×
333
                switch groupKind {
×
334
                case "PerformanceProfile.performance.openshift.io",
335
                        "Tuned.tuned.openshift.io",
336
                        "Namespace",
337
                        "CatalogSource.operators.coreos.com",
338
                        "ContainerRuntimeConfig.machineconfiguration.openshift.io":
×
339
                        directlyAppliedObjects = append(directlyAppliedObjects, ob)
×
340
                case "Subscription.operators.coreos.com":
×
341
                        ob.Object["spec"].(map[string]interface{})["installPlanApproval"] = "Automatic"
×
342
                        wrappedObjects = append(wrappedObjects, ob)
×
343
                default:
×
344
                        wrappedObjects = append(wrappedObjects, ob)
×
345
                }
346
        }
347
        if len(wrappedObjects) > 0 {
×
348
                innerCm, err := r.wrapObjects(wrappedObjects, innerCmName, innerCmNs)
×
349
                if err != nil {
×
350
                        return err
×
351
                }
×
352

353
                innerCmObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(innerCm)
×
354
                if err != nil {
×
355
                        return err
×
356
                }
×
357
                var innerCmUns unstructured.Unstructured
×
358
                innerCmUns.SetUnstructuredContent(innerCmObj)
×
359
                directlyAppliedObjects = append(directlyAppliedObjects, innerCmUns)
×
360
        }
361

362
        var data templates.AztpTemplateData
×
363

×
364
        data.AztpImage = os.Getenv("AZTP_IMG")
×
365
        if strings.Compare(data.AztpImage, "") == 0 {
×
366
                return fmt.Errorf("aztp failure: can't retrieve aztp image pull spec")
×
367
        }
×
368

369
        objects, err = templates.RenderAztpService(data, aztpVariant)
×
370
        if err != nil {
×
371
                return fmt.Errorf("failed to create aztp service manifests: %v", err)
×
372
        }
×
373
        directlyAppliedObjects = append(directlyAppliedObjects, objects...)
×
374

×
375
        cmr, err := r.wrapObjects(directlyAppliedObjects, configMapName, namespace)
×
376
        if err != nil {
×
377
                return err
×
378
        }
×
379
        // make this managedcluster owner of the configmap
380
        if err := controllerutil.SetControllerReference(managedCluster, cmr, r.Scheme); err != nil {
×
381
                return err
×
382
        }
×
383
        if err := r.Create(ctx, cmr); err != nil {
×
384
                return err
×
385
        }
×
386
        return nil
×
387
}
388

389
func (r *ManagedClusterForCguReconciler) wrapObjects(objects []unstructured.Unstructured, name, namespace string) (*corev1.ConfigMap, error) {
×
390
        cm := r.newConfigmap(name, namespace)
×
391
        for _, item := range objects {
×
392
                key := strings.ToLower(fmt.Sprintf("%s-%s-%s.yaml", item.GetKind(), item.GetNamespace(), item.GetName()))
×
393
                out, err := yaml.Marshal(item.Object)
×
394
                if err != nil {
×
395
                        return cm, err
×
396
                }
×
397
                cm.Data[key] = string(out)
×
398
        }
399
        return cm, nil
×
400
}
401

402
// GetConfigurationObjects gets encapsulated objects from configuration policies
403
func (r *ManagedClusterForCguReconciler) GetConfigurationObjects(policies []policiesv1.Policy) ([]unstructured.Unstructured, error) {
×
404
        var uobjects []unstructured.Unstructured
×
405

×
406
        var objects []runtime.RawExtension
×
407
        for _, pol := range policies {
×
408
                if !pol.Spec.Disabled {
×
409
                        for _, template := range pol.Spec.PolicyTemplates {
×
410
                                o := *template.ObjectDefinition.DeepCopy()
×
411
                                objects = append(objects, o)
×
412
                        }
×
413
                }
414
        }
415

416
        for _, ob := range objects {
×
417
                var pol policyv1.ConfigurationPolicy
×
418
                err := json.Unmarshal(ob.DeepCopy().Raw, &pol)
×
419
                if err != nil {
×
420
                        r.Log.Info(err.Error())
×
421
                        return uobjects, err
×
422
                }
×
423
                for _, ot := range pol.Spec.ObjectTemplates {
×
424
                        var object unstructured.Unstructured
×
425
                        err = object.UnmarshalJSON(ot.ObjectDefinition.DeepCopy().Raw)
×
426
                        if err != nil {
×
427
                                return uobjects, err
×
428
                        }
×
429
                        object.Object["status"] = map[string]interface{}{}
×
430
                        _, specDefined := object.Object["spec"]
×
431
                        if specDefined || object.GetKind() == "Namespace" {
×
432
                                uobjects = append(uobjects, object)
×
433
                        }
×
434
                }
435
        }
436
        return uobjects, nil
×
437
}
438

439
// SetupWithManager sets up the controller with the Manager.
440
func (r *ManagedClusterForCguReconciler) SetupWithManager(mgr ctrl.Manager) error {
1✔
441
        namespace := &corev1.Namespace{
1✔
442
                ObjectMeta: metav1.ObjectMeta{
1✔
443
                        Name: ztpInstallNS,
1✔
444
                },
1✔
445
        }
1✔
446
        if err := r.Create(context.TODO(), namespace); err != nil {
2✔
447
                // fail to create namespace
1✔
448
                if !errors.IsAlreadyExists(err) {
1✔
449
                        return err
×
450
                }
×
451
        }
452

453
        return ctrl.NewControllerManagedBy(mgr).
1✔
454
                Named("managedclusterForCGU").
1✔
455
                For(&clusterv1.ManagedCluster{},
1✔
456
                        // watch for create event for managedcluster
1✔
457
                        builder.WithPredicates(predicate.Funcs{
1✔
458
                                GenericFunc: func(e event.GenericEvent) bool { return false },
1✔
459
                                CreateFunc:  func(e event.CreateEvent) bool { return true },
1✔
460
                                DeleteFunc:  func(e event.DeleteEvent) bool { return false },
×
461
                                UpdateFunc: func(e event.UpdateEvent) bool {
×
462
                                        // Check if the event was deleting the label "ztp-done"
×
463
                                        // We want to return true for that event only, and false for everything else
×
464
                                        _, doneLabelExistsInOld := e.ObjectOld.GetLabels()[ztpDoneLabel]
×
465
                                        _, doneLabelExistsInNew := e.ObjectNew.GetLabels()[ztpDoneLabel]
×
466
                                        _, aztpRequired := e.ObjectNew.GetLabels()[aztpRequiredLabel]
×
467

×
468
                                        doneLabelRemoved := doneLabelExistsInOld && !doneLabelExistsInNew
×
469

×
470
                                        var availableInNew, availableInOld bool
×
471
                                        availableCondition := meta.FindStatusCondition(e.ObjectOld.(*clusterv1.ManagedCluster).Status.Conditions, clusterv1.ManagedClusterConditionAvailable)
×
472
                                        if availableCondition != nil && availableCondition.Status == metav1.ConditionTrue {
×
473
                                                availableInOld = true
×
474
                                        }
×
475
                                        availableCondition = meta.FindStatusCondition(e.ObjectNew.(*clusterv1.ManagedCluster).Status.Conditions, clusterv1.ManagedClusterConditionAvailable)
×
476
                                        if availableCondition != nil && availableCondition.Status == metav1.ConditionTrue {
×
477
                                                availableInNew = true
×
478
                                        }
×
479

480
                                        var hubAccepted bool
×
481
                                        acceptedCondition := meta.FindStatusCondition(e.ObjectNew.(*clusterv1.ManagedCluster).Status.Conditions, clusterv1.ManagedClusterConditionHubAccepted)
×
482
                                        if acceptedCondition != nil && acceptedCondition.Status == metav1.ConditionTrue {
×
483
                                                hubAccepted = true
×
484
                                        }
×
485

486
                                        return (doneLabelRemoved && availableInNew) || (!availableInOld && availableInNew && !doneLabelExistsInNew) || (hubAccepted && aztpRequired)
×
487
                                },
488
                        })).
489
                Owns(&ranv1alpha1.ClusterGroupUpgrade{},
490
                        // watch for delete event for owned ClusterGroupUpgrade
491
                        builder.WithPredicates(predicate.Funcs{
492
                                GenericFunc: func(e event.GenericEvent) bool { return false },
×
493
                                CreateFunc:  func(e event.CreateEvent) bool { return false },
1✔
494
                                DeleteFunc:  func(e event.DeleteEvent) bool { return true },
×
495
                                UpdateFunc:  func(e event.UpdateEvent) bool { return false },
×
496
                        })).
497
                Complete(r)
498
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc