Skip to content

Commit 8e4673e

Browse files
committed
address comments
Signed-off-by: Britania Rodriguez Reyes <britaniar@microsoft.com>
1 parent 3567909 commit 8e4673e

File tree

3 files changed

+204
-3
lines changed

3 files changed

+204
-3
lines changed

pkg/controllers/updaterun/initialization.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,12 +495,11 @@ func (r *Reconciler) recordOverrideSnapshots(ctx context.Context, placementKey t
495495
return fmt.Errorf("%w: %s", errInitializedFailed, err.Error())
496496
}
497497

498-
klog.InfoS("Found master resourceSnapshot", "placement", placementKey, "masterResourceSnapshot", masterResourceSnapshot.GetName(), "updateRun", updateRunRef)
498+
klog.V(2).InfoS("Found master resourceSnapshot", "placement", placementKey, "masterResourceSnapshot", masterResourceSnapshot.GetName(), "updateRun", updateRunRef)
499499

500500
// Update the resource snapshot name in the UpdateRun status.
501501
updateRunStatus := updateRun.GetUpdateRunStatus()
502502
updateRunStatus.ResourceSnapshotName = masterResourceSnapshot.GetName()
503-
updateRun.SetUpdateRunStatus(*updateRunStatus)
504503
if updateErr := r.Client.Status().Update(ctx, updateRun); updateErr != nil {
505504
klog.ErrorS(updateErr, "Failed to update the UpdateRun status with resource snapshot name", "updateRun", klog.KObj(updateRun), "resourceSnapshot", klog.KObj(masterResourceSnapshot))
506505
// updateErr can be retried.

pkg/controllers/updaterun/initialization_integration_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,16 @@ var _ = Describe("Updaterun initialization tests", func() {
930930
Expect(k8sClient.Create(ctx, updateStrategy)).To(Succeed())
931931
})
932932

933+
AfterEach(func() {
934+
By("Deleting the second clusterResourceSnapshot")
935+
Expect(k8sClient.Delete(ctx, resourceSnapshot2)).To(Succeed())
936+
937+
By("Deleting the third clusterResourceSnapshot")
938+
Expect(k8sClient.Delete(ctx, resourceSnapshot3)).To(Succeed())
939+
940+
// Everything else should be deleted by the outer AfterEach
941+
})
942+
933943
It("Should pick latest master resource snapshot", func() {
934944
By("Creating a new cluster resource override")
935945
Expect(k8sClient.Create(ctx, clusterResourceOverride)).To(Succeed())

pkg/controllers/updaterun/initialization_test.go

Lines changed: 193 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
package updaterun
22

33
import (
4+
"context"
5+
"fmt"
6+
"strings"
47
"testing"
58
"time"
69

710
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11+
"k8s.io/apimachinery/pkg/runtime"
12+
"k8s.io/apimachinery/pkg/types"
13+
"k8s.io/client-go/kubernetes/scheme"
14+
"k8s.io/klog/v2"
815
"k8s.io/utils/ptr"
16+
"sigs.k8s.io/controller-runtime/pkg/client"
17+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
918

10-
"github.com/kubefleet-dev/kubefleet/apis/placement/v1beta1"
19+
v1beta1 "github.com/kubefleet-dev/kubefleet/apis/placement/v1beta1"
1120
)
1221

1322
func TestValidateAfterStageTask(t *testing.T) {
@@ -85,3 +94,186 @@ func TestValidateAfterStageTask(t *testing.T) {
8594
})
8695
}
8796
}
97+
98+
func TestGetResourceSnapshotObjs(t *testing.T) {
99+
ctx := context.Background()
100+
placementName := "test-placement"
101+
placementKey := types.NamespacedName{Name: placementName, Namespace: "test-namespace"}
102+
updateRunRef := klog.ObjectRef{
103+
Name: "test-updaterun",
104+
Namespace: "test-namespace",
105+
}
106+
107+
// Create test resource snapshots
108+
masterResourceSnapshot := &v1beta1.ClusterResourceSnapshot{
109+
ObjectMeta: metav1.ObjectMeta{
110+
Name: placementName + "-1-snapshot",
111+
Namespace: placementKey.Namespace,
112+
Labels: map[string]string{
113+
v1beta1.PlacementTrackingLabel: placementName,
114+
v1beta1.ResourceIndexLabel: "1",
115+
v1beta1.IsLatestSnapshotLabel: "false",
116+
v1beta1.ResourceGroupHashAnnotation: "hash123",
117+
},
118+
Annotations: map[string]string{
119+
v1beta1.ResourceGroupHashAnnotation: "hash123",
120+
},
121+
},
122+
}
123+
124+
tests := []struct {
125+
name string
126+
updateRunSpec *v1beta1.UpdateRunSpec
127+
resourceSnapshots []runtime.Object
128+
wantSnapshotCount int
129+
wantErr bool
130+
wantErrMsg string
131+
}{
132+
// negative cases only
133+
{
134+
name: "invalid resource snapshot index - non-numeric",
135+
updateRunSpec: &v1beta1.UpdateRunSpec{
136+
ResourceSnapshotIndex: "invalid",
137+
},
138+
resourceSnapshots: []runtime.Object{},
139+
wantSnapshotCount: 0,
140+
wantErr: true,
141+
wantErrMsg: "invalid resource snapshot index `invalid` provided, expected an integer >= 0",
142+
},
143+
{
144+
name: "invalid resource snapshot index - negative",
145+
updateRunSpec: &v1beta1.UpdateRunSpec{
146+
ResourceSnapshotIndex: "-1",
147+
},
148+
resourceSnapshots: []runtime.Object{},
149+
wantSnapshotCount: 0,
150+
wantErr: true,
151+
wantErrMsg: "invalid resource snapshot index `-1` provided, expected an integer >= 0",
152+
},
153+
{
154+
name: "no resource snapshots found for specific index",
155+
updateRunSpec: &v1beta1.UpdateRunSpec{
156+
ResourceSnapshotIndex: "999",
157+
},
158+
resourceSnapshots: []runtime.Object{
159+
masterResourceSnapshot, // has index "1", not "999"
160+
},
161+
wantSnapshotCount: 0,
162+
wantErr: true,
163+
wantErrMsg: fmt.Sprintf("no resourceSnapshots with index `999` found for placement `%s`", placementKey),
164+
},
165+
{
166+
name: "no latest resource snapshots found",
167+
updateRunSpec: &v1beta1.UpdateRunSpec{
168+
ResourceSnapshotIndex: "",
169+
},
170+
resourceSnapshots: []runtime.Object{}, // no snapshots
171+
wantSnapshotCount: 0,
172+
wantErr: true,
173+
wantErrMsg: fmt.Sprintf("no resourceSnapshots found for placement `%s`", placementKey),
174+
},
175+
}
176+
177+
for _, tt := range tests {
178+
t.Run(tt.name, func(t *testing.T) {
179+
// Create a fake client with the test objects
180+
s := runtime.NewScheme()
181+
_ = v1beta1.AddToScheme(s)
182+
_ = scheme.AddToScheme(s)
183+
184+
fakeClient := fake.NewClientBuilder().
185+
WithScheme(s).
186+
WithRuntimeObjects(tt.resourceSnapshots...).
187+
Build()
188+
189+
// Create reconciler with fake client
190+
r := &Reconciler{
191+
Client: fakeClient,
192+
}
193+
194+
// Call the function
195+
result, err := r.getResourceSnapshotObjs(ctx, tt.updateRunSpec, placementName, placementKey, updateRunRef)
196+
197+
// Verify error expectations
198+
if tt.wantErr {
199+
if err == nil {
200+
t.Errorf("getResourceSnapshotObjs() error = nil, wantErr %v", tt.wantErr)
201+
return
202+
}
203+
// Check if the error message contains the expected substring
204+
if !strings.Contains(err.Error(), tt.wantErrMsg) {
205+
t.Errorf("getResourceSnapshotObjs() error = %v, want error containing %v", err, tt.wantErrMsg)
206+
}
207+
return
208+
}
209+
210+
// Verify no error when not expected
211+
if err != nil {
212+
t.Errorf("getResourceSnapshotObjs() unexpected error = %v", err)
213+
return
214+
}
215+
216+
// Verify result count
217+
if len(result) != tt.wantSnapshotCount {
218+
t.Errorf("getResourceSnapshotObjs() returned %d snapshots, want %d", len(result), tt.wantSnapshotCount)
219+
return
220+
}
221+
})
222+
}
223+
}
224+
225+
// fakeListErrorClient wraps a client and always returns an error on List.
226+
type fakeListErrorClient struct {
227+
client.Client
228+
}
229+
230+
func (f *fakeListErrorClient) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error {
231+
return fmt.Errorf("simulated list error")
232+
}
233+
234+
func TestGetResourceSnapshotObjs_ListError(t *testing.T) {
235+
tests := []struct {
236+
name string
237+
spec *v1beta1.UpdateRunSpec
238+
wantErrMsg string
239+
}{
240+
{
241+
name: "list error simulation with resource index",
242+
spec: &v1beta1.UpdateRunSpec{
243+
ResourceSnapshotIndex: "1",
244+
},
245+
wantErrMsg: "Failed to list the resourceSnapshots associated with the placement for the given index",
246+
},
247+
{
248+
name: "list error simulation without resource index",
249+
spec: &v1beta1.UpdateRunSpec{
250+
ResourceSnapshotIndex: "",
251+
},
252+
wantErrMsg: "Failed to list the resourceSnapshots associated with the placement",
253+
},
254+
}
255+
256+
for _, tt := range tests {
257+
t.Run(tt.name, func(t *testing.T) {
258+
ctx := context.Background()
259+
placementName := "test-placement"
260+
placementKey := types.NamespacedName{Name: placementName, Namespace: "test-namespace"}
261+
updateRunRef := klog.ObjectRef{
262+
Name: "test-updaterun",
263+
Namespace: "test-namespace",
264+
}
265+
266+
s := runtime.NewScheme()
267+
_ = v1beta1.AddToScheme(s)
268+
_ = scheme.AddToScheme(s)
269+
270+
fakeClient := &fakeListErrorClient{Client: fake.NewClientBuilder().WithScheme(s).Build()}
271+
r := &Reconciler{Client: fakeClient}
272+
273+
_, err := r.getResourceSnapshotObjs(ctx, tt.spec, placementName, placementKey, updateRunRef)
274+
if err == nil || !strings.Contains(err.Error(), "simulated list error") {
275+
t.Errorf("expected simulated list error, got: %v", err)
276+
}
277+
})
278+
}
279+
}

0 commit comments

Comments
 (0)