@@ -23,6 +23,7 @@ import (
23
23
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
24
24
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25
25
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
26
+ "k8s.io/apimachinery/pkg/util/errors"
26
27
"k8s.io/apimachinery/pkg/util/sets"
27
28
"k8s.io/klog/v2"
28
29
"k8s.io/utils/ptr"
@@ -45,19 +46,8 @@ func ensureWork(
45
46
ctx context.Context , c client.Client , resourceInterpreter resourceinterpreter.ResourceInterpreter , workload * unstructured.Unstructured ,
46
47
overrideManager overridemanager.OverrideManager , binding metav1.Object , scope apiextensionsv1.ResourceScope ,
47
48
) error {
48
- var targetClusters []workv1alpha2.TargetCluster
49
- var bindingSpec workv1alpha2.ResourceBindingSpec
50
- switch scope {
51
- case apiextensionsv1 .NamespaceScoped :
52
- bindingObj := binding .(* workv1alpha2.ResourceBinding )
53
- bindingSpec = bindingObj .Spec
54
- case apiextensionsv1 .ClusterScoped :
55
- bindingObj := binding .(* workv1alpha2.ClusterResourceBinding )
56
- bindingSpec = bindingObj .Spec
57
- }
58
-
59
- targetClusters = bindingSpec .Clusters
60
- targetClusters = mergeTargetClusters (targetClusters , bindingSpec .RequiredBy )
49
+ bindingSpec := getBindingSpec (binding , scope )
50
+ targetClusters := mergeTargetClusters (bindingSpec .Clusters , bindingSpec .RequiredBy )
61
51
62
52
var jobCompletions []workv1alpha2.TargetCluster
63
53
var err error
@@ -68,6 +58,7 @@ func ensureWork(
68
58
}
69
59
}
70
60
61
+ var errs []error
71
62
for i := range targetClusters {
72
63
targetCluster := targetClusters [i ]
73
64
clonedWorkload := workload .DeepCopy ()
@@ -82,7 +73,8 @@ func ensureWork(
82
73
if err != nil {
83
74
klog .Errorf ("Failed to revise replica for %s/%s/%s in cluster %s, err is: %v" ,
84
75
workload .GetKind (), workload .GetNamespace (), workload .GetName (), targetCluster .Name , err )
85
- return err
76
+ errs = append (errs , err )
77
+ continue
86
78
}
87
79
}
88
80
@@ -94,25 +86,29 @@ func ensureWork(
94
86
if err = helper .ApplyReplica (clonedWorkload , int64 (jobCompletions [i ].Replicas ), util .CompletionsField ); err != nil {
95
87
klog .Errorf ("Failed to apply Completions for %s/%s/%s in cluster %s, err is: %v" ,
96
88
clonedWorkload .GetKind (), clonedWorkload .GetNamespace (), clonedWorkload .GetName (), targetCluster .Name , err )
97
- return err
89
+ errs = append (errs , err )
90
+ continue
98
91
}
99
92
}
100
93
}
101
94
102
95
// We should call ApplyOverridePolicies last, as override rules have the highest priority
103
96
cops , ops , err := overrideManager .ApplyOverridePolicies (clonedWorkload , targetCluster .Name )
104
97
if err != nil {
105
- klog .Errorf ("Failed to apply overrides for %s/%s/%s, err is: %v" , clonedWorkload .GetKind (), clonedWorkload .GetNamespace (), clonedWorkload .GetName (), err )
106
- return err
98
+ klog .Errorf ("Failed to apply overrides for %s/%s/%s in cluster %s, err is: %v" ,
99
+ clonedWorkload .GetKind (), clonedWorkload .GetNamespace (), clonedWorkload .GetName (), targetCluster .Name , err )
100
+ errs = append (errs , err )
101
+ continue
107
102
}
108
103
workLabel := mergeLabel (clonedWorkload , binding , scope )
109
104
110
105
annotations := mergeAnnotations (clonedWorkload , binding , scope )
111
106
annotations = mergeConflictResolution (clonedWorkload , bindingSpec .ConflictResolution , annotations )
112
107
annotations , err = RecordAppliedOverrides (cops , ops , annotations )
113
108
if err != nil {
114
- klog .Errorf ("Failed to record appliedOverrides, Error: %v" , err )
115
- return err
109
+ klog .Errorf ("Failed to record appliedOverrides in cluster %s, Error: %v" , targetCluster .Name , err )
110
+ errs = append (errs , err )
111
+ continue
116
112
}
117
113
118
114
if features .FeatureGate .Enabled (features .StatefulFailoverInjection ) {
@@ -137,12 +133,29 @@ func ensureWork(
137
133
ctrlutil .WithSuspendDispatching (shouldSuspendDispatching (bindingSpec .Suspension , targetCluster )),
138
134
ctrlutil .WithPreserveResourcesOnDeletion (ptr .Deref (bindingSpec .PreserveResourcesOnDeletion , false )),
139
135
); err != nil {
140
- return err
136
+ errs = append (errs , err )
137
+ continue
141
138
}
142
139
}
140
+ if len (errs ) > 0 {
141
+ return errors .NewAggregate (errs )
142
+ }
143
143
return nil
144
144
}
145
145
146
+ func getBindingSpec (binding metav1.Object , scope apiextensionsv1.ResourceScope ) workv1alpha2.ResourceBindingSpec {
147
+ var bindingSpec workv1alpha2.ResourceBindingSpec
148
+ switch scope {
149
+ case apiextensionsv1 .NamespaceScoped :
150
+ bindingObj := binding .(* workv1alpha2.ResourceBinding )
151
+ bindingSpec = bindingObj .Spec
152
+ case apiextensionsv1 .ClusterScoped :
153
+ bindingObj := binding .(* workv1alpha2.ClusterResourceBinding )
154
+ bindingSpec = bindingObj .Spec
155
+ }
156
+ return bindingSpec
157
+ }
158
+
146
159
// injectReservedLabelState injects the reservedLabelState in to the failover to cluster.
147
160
// We have the following restrictions on whether to perform injection operations:
148
161
// 1. Only the scenario where an application is deployed in one cluster and migrated to
0 commit comments