Skip to content

Commit 0d5ea43

Browse files
author
Arvind Thirumurugan
committed
add tests
1 parent d246699 commit 0d5ea43

3 files changed

Lines changed: 447 additions & 0 deletions

File tree

test/e2e/drain_tool_test.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
Copyright (c) Microsoft Corporation.
3+
Licensed under the MIT license.
4+
*/
5+
6+
package e2e
7+
8+
import (
9+
"fmt"
10+
11+
. "github.com/onsi/ginkgo/v2"
12+
. "github.com/onsi/gomega"
13+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14+
15+
placementv1beta1 "go.goms.io/fleet/apis/placement/v1beta1"
16+
"go.goms.io/fleet/test/e2e/framework"
17+
"go.goms.io/fleet/tools/draincluster/drain"
18+
"go.goms.io/fleet/tools/uncordoncluster/uncordon"
19+
)
20+
21+
var _ = Describe("Drain cluster", Ordered, Serial, func() {
22+
crpName := fmt.Sprintf(crpNameTemplate, GinkgoParallelProcess())
23+
var d *drain.Helper
24+
var u *uncordon.Helper
25+
var noDrainClusterNames []string
26+
var drainClusters, noDrainClusters []*framework.Cluster
27+
28+
BeforeAll(func() {
29+
drainClusters = []*framework.Cluster{memberCluster1EastProd}
30+
31+
noDrainClusters = []*framework.Cluster{memberCluster2EastCanary, memberCluster3WestProd}
32+
noDrainClusterNames = []string{memberCluster2EastCanaryName, memberCluster3WestProdName}
33+
34+
By("creating work resources")
35+
createWorkResources()
36+
37+
// Create the CRP.
38+
crp := &placementv1beta1.ClusterResourcePlacement{
39+
ObjectMeta: metav1.ObjectMeta{
40+
Name: crpName,
41+
// Add a custom finalizer; this would allow us to better observe
42+
// the behavior of the controllers.
43+
Finalizers: []string{customDeletionBlockerFinalizer},
44+
},
45+
Spec: placementv1beta1.ClusterResourcePlacementSpec{
46+
Policy: &placementv1beta1.PlacementPolicy{
47+
PlacementType: placementv1beta1.PickAllPlacementType,
48+
},
49+
ResourceSelectors: workResourceSelector(),
50+
},
51+
}
52+
Expect(hubClient.Create(ctx, crp)).To(Succeed(), "Failed to create CRP %s", crpName)
53+
54+
d = &drain.Helper{
55+
HubClient: hubClient,
56+
ClusterName: memberCluster1EastProdName,
57+
ClusterResourcePlacementResourcesMap: make(map[string][]placementv1beta1.ResourceIdentifier),
58+
}
59+
60+
u = &uncordon.Helper{
61+
HubClient: hubClient,
62+
ClusterName: memberCluster1EastProdName,
63+
}
64+
})
65+
66+
AfterAll(func() {
67+
ensureCRPAndRelatedResourcesDeleted(crpName, allMemberClusters)
68+
})
69+
70+
It("should update cluster resource placement status as expected", func() {
71+
crpStatusUpdatedActual := crpStatusUpdatedActual(workResourceIdentifiers(), allMemberClusterNames, nil, "0")
72+
Eventually(crpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update cluster resource placement status as expected")
73+
})
74+
75+
It("should place resources on the all available member clusters", checkIfPlacedWorkResourcesOnAllMemberClusters)
76+
77+
It("drain cluster", func() {
78+
isDrainSuccessful, err := d.Drain(ctx)
79+
Expect(isDrainSuccessful).To(BeTrue(), "Failed to drain member cluster")
80+
Expect(err).To(Succeed(), "Failed to drain member cluster")
81+
})
82+
83+
It("should ensure no resources exist on drained clusters", func() {
84+
for _, cluster := range drainClusters {
85+
resourceRemovedActual := workNamespaceRemovedFromClusterActual(cluster)
86+
Eventually(resourceRemovedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to check if resources doesn't exist on member cluster")
87+
}
88+
})
89+
90+
It("should update cluster resource placement status as expected", func() {
91+
crpStatusUpdatedActual := crpStatusUpdatedActual(workResourceIdentifiers(), noDrainClusterNames, nil, "0")
92+
Eventually(crpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update cluster resource placement status as expected")
93+
})
94+
95+
It("should place resources on the selected clusters with no taint", func() {
96+
for _, cluster := range noDrainClusters {
97+
resourcePlacedActual := workNamespaceAndConfigMapPlacedOnClusterActual(cluster)
98+
Eventually(resourcePlacedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to place resources on the selected clusters")
99+
}
100+
})
101+
102+
It("uncordon cluster", func() {
103+
Expect(u.Uncordon(ctx)).To(Succeed(), "Failed to uncordon member cluster")
104+
})
105+
106+
It("should update cluster resource placement status as expected", func() {
107+
crpStatusUpdatedActual := crpStatusUpdatedActual(workResourceIdentifiers(), allMemberClusterNames, nil, "0")
108+
Eventually(crpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update cluster resource placement status as expected")
109+
})
110+
111+
It("should place resources on the all available member clusters", checkIfPlacedWorkResourcesOnAllMemberClusters)
112+
})
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/*
2+
Copyright (c) Microsoft Corporation.
3+
Licensed under the MIT license.
4+
*/
5+
6+
package drain
7+
8+
import (
9+
"context"
10+
"fmt"
11+
"testing"
12+
13+
"github.com/google/go-cmp/cmp"
14+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15+
"k8s.io/apimachinery/pkg/runtime"
16+
"sigs.k8s.io/controller-runtime/pkg/client"
17+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
18+
19+
placementv1beta1 "go.goms.io/fleet/apis/placement/v1beta1"
20+
"go.goms.io/fleet/pkg/utils"
21+
)
22+
23+
func TestFetchClusterResourcePlacementToEvict(t *testing.T) {
24+
tests := []struct {
25+
name string
26+
targetCluster string
27+
bindings []placementv1beta1.ClusterResourceBinding
28+
works []placementv1beta1.Work
29+
wantErr error
30+
wantMap map[string][]placementv1beta1.ResourceIdentifier
31+
}{
32+
{
33+
name: "successfully collected resources for CRP",
34+
targetCluster: "test-cluster1",
35+
bindings: []placementv1beta1.ClusterResourceBinding{
36+
{
37+
ObjectMeta: metav1.ObjectMeta{
38+
Name: "test-crb1",
39+
Labels: map[string]string{
40+
placementv1beta1.CRPTrackingLabel: "test-crp1",
41+
},
42+
},
43+
Spec: placementv1beta1.ResourceBindingSpec{
44+
TargetCluster: "test-cluster1",
45+
State: placementv1beta1.BindingStateBound,
46+
},
47+
},
48+
{
49+
ObjectMeta: metav1.ObjectMeta{
50+
Name: "test-crb2",
51+
Labels: map[string]string{
52+
placementv1beta1.CRPTrackingLabel: "test-crp1",
53+
},
54+
},
55+
Spec: placementv1beta1.ResourceBindingSpec{
56+
TargetCluster: "test-cluster2",
57+
State: placementv1beta1.BindingStateBound,
58+
},
59+
},
60+
},
61+
works: []placementv1beta1.Work{
62+
{
63+
ObjectMeta: metav1.ObjectMeta{
64+
Name: "test-work1",
65+
Namespace: fmt.Sprintf(utils.NamespaceNameFormat, "test-cluster1"),
66+
Labels: map[string]string{
67+
placementv1beta1.CRPTrackingLabel: "test-crp1",
68+
},
69+
},
70+
Status: placementv1beta1.WorkStatus{
71+
ManifestConditions: []placementv1beta1.ManifestCondition{
72+
{
73+
Identifier: placementv1beta1.WorkResourceIdentifier{
74+
Group: "test-group1",
75+
Version: "test-version1",
76+
Kind: "test-kind1",
77+
Name: "test-name1",
78+
},
79+
Conditions: []metav1.Condition{
80+
{
81+
Type: placementv1beta1.WorkConditionTypeApplied,
82+
Status: metav1.ConditionTrue,
83+
},
84+
},
85+
},
86+
},
87+
},
88+
},
89+
{
90+
ObjectMeta: metav1.ObjectMeta{
91+
Name: "test-work2",
92+
Namespace: fmt.Sprintf(utils.NamespaceNameFormat, "test-cluster1"),
93+
Labels: map[string]string{
94+
placementv1beta1.CRPTrackingLabel: "test-crp1",
95+
},
96+
},
97+
Status: placementv1beta1.WorkStatus{
98+
ManifestConditions: []placementv1beta1.ManifestCondition{
99+
{
100+
Identifier: placementv1beta1.WorkResourceIdentifier{
101+
Group: "test-group2",
102+
Version: "test-version2",
103+
Kind: "test-kind2",
104+
Name: "test-name2",
105+
},
106+
Conditions: []metav1.Condition{
107+
{
108+
Type: placementv1beta1.WorkConditionTypeApplied,
109+
Status: metav1.ConditionTrue,
110+
},
111+
},
112+
},
113+
},
114+
},
115+
},
116+
{
117+
ObjectMeta: metav1.ObjectMeta{
118+
Name: "test-work3",
119+
Namespace: fmt.Sprintf(utils.NamespaceNameFormat, "test-cluster2"),
120+
Labels: map[string]string{
121+
placementv1beta1.CRPTrackingLabel: "test-crp1",
122+
},
123+
},
124+
Status: placementv1beta1.WorkStatus{
125+
ManifestConditions: []placementv1beta1.ManifestCondition{
126+
{
127+
Identifier: placementv1beta1.WorkResourceIdentifier{
128+
Group: "test-group3",
129+
Version: "test-version3",
130+
Kind: "test-kind3",
131+
Name: "test-name3",
132+
},
133+
Conditions: []metav1.Condition{
134+
{
135+
Type: placementv1beta1.WorkConditionTypeApplied,
136+
Status: metav1.ConditionTrue,
137+
},
138+
},
139+
},
140+
},
141+
},
142+
},
143+
},
144+
wantErr: nil,
145+
wantMap: map[string][]placementv1beta1.ResourceIdentifier{
146+
"test-crp1": {
147+
{
148+
Group: "test-group1",
149+
Version: "test-version1",
150+
Kind: "test-kind1",
151+
Name: "test-name1",
152+
},
153+
{
154+
Group: "test-group2",
155+
Version: "test-version2",
156+
Kind: "test-kind2",
157+
Name: "test-name2",
158+
},
159+
},
160+
},
161+
},
162+
{
163+
name: "failed to wait for placement to be present",
164+
targetCluster: "test-cluster1",
165+
bindings: []placementv1beta1.ClusterResourceBinding{
166+
{
167+
ObjectMeta: metav1.ObjectMeta{
168+
Name: "test-crb1",
169+
Labels: map[string]string{
170+
placementv1beta1.CRPTrackingLabel: "test-crp1",
171+
},
172+
},
173+
Spec: placementv1beta1.ResourceBindingSpec{
174+
TargetCluster: "test-cluster1",
175+
State: placementv1beta1.BindingStateScheduled,
176+
},
177+
},
178+
},
179+
wantMap: map[string][]placementv1beta1.ResourceIdentifier{},
180+
wantErr: fmt.Errorf("failed to wait for placement to be present on member cluster: timed out waiting for the condition"),
181+
},
182+
}
183+
184+
for _, tc := range tests {
185+
t.Run(tc.name, func(t *testing.T) {
186+
var objects []client.Object
187+
scheme := serviceScheme(t)
188+
for i := range tc.bindings {
189+
objects = append(objects, &tc.bindings[i])
190+
}
191+
for i := range tc.works {
192+
objects = append(objects, &tc.works[i])
193+
}
194+
fakeClient := fake.NewClientBuilder().
195+
WithScheme(scheme).
196+
WithObjects(objects...).
197+
Build()
198+
d := &Helper{
199+
HubClient: fakeClient,
200+
ClusterName: tc.targetCluster,
201+
ClusterResourcePlacementResourcesMap: make(map[string][]placementv1beta1.ResourceIdentifier),
202+
}
203+
gotErr := d.fetchClusterResourcePlacementToEvict(context.Background())
204+
if tc.wantErr == nil {
205+
if gotErr != nil {
206+
t.Errorf("fetchClusterResourcePlacementToEvict() test %s failed, got error %v, want error %v", tc.name, gotErr, tc.wantErr)
207+
}
208+
} else if gotErr == nil || gotErr.Error() != tc.wantErr.Error() {
209+
t.Errorf("fetchClusterResourcePlacementToEvict() test %s failed, got error %v, want error %v", tc.name, gotErr, tc.wantErr)
210+
}
211+
if diff := cmp.Diff(d.ClusterResourcePlacementResourcesMap, tc.wantMap); diff != "" {
212+
t.Errorf("fetchClusterResourcePlacementToEvict() test %s failed, got %v, want %v", tc.name, d.ClusterResourcePlacementResourcesMap, tc.wantMap)
213+
}
214+
})
215+
}
216+
}
217+
218+
func serviceScheme(t *testing.T) *runtime.Scheme {
219+
scheme := runtime.NewScheme()
220+
if err := placementv1beta1.AddToScheme(scheme); err != nil {
221+
t.Fatalf("failed to add placement v1beta1 scheme: %v", err)
222+
}
223+
return scheme
224+
}

0 commit comments

Comments
 (0)