Skip to content

Commit a946354

Browse files
authored
initial batch of end-to-end tests (#35)
1 parent 4845e93 commit a946354

File tree

11 files changed

+487
-118
lines changed

11 files changed

+487
-118
lines changed

hack/e2e-util.sh

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,16 @@ function configure_cluster {
159159
done
160160
}
161161

162+
function wait_for_appwrapper_controller {
163+
# Sleep until the appwrapper controller is running
164+
echo "Waiting for pods in the appwrapper-system namespace to become ready"
165+
while [[ $(kubectl get pods -n appwrapper-system -o 'jsonpath={..status.conditions[?(@.type=="Ready")].status}' | tr ' ' '\n' | sort -u) != "True" ]]
166+
do
167+
echo -n "." && sleep 1;
168+
done
169+
echo ""
170+
}
171+
162172
# clean up
163173
function cleanup {
164174
echo "==========================>>>>> Cleaning up... <<<<<=========================="
@@ -200,25 +210,14 @@ function cleanup {
200210
echo "'all' Namespaces list..."
201211
kubectl get namespaces
202212

203-
# TODO: Need to update this for appwrapper system/controller
204-
205-
local mcad_dispatcher_pod=$(kubectl get pods -n mcad-system | grep mcad-controller | grep -v mcad-controller-runner | awk '{print $1}')
206-
local mcad_runner_pod=$(kubectl get pods -n mcad-system | grep mcad-controller-runner | awk '{print $1}')
207-
if [[ "$mcad_dispatcher_pod" != "" ]]
208-
then
209-
echo "===================================================================================="
210-
echo "==========================>>>>> MCAD Controller Logs <<<<<=========================="
211-
echo "===================================================================================="
212-
echo "kubectl logs ${mcad_dispatcher_pod} -n mcad-system"
213-
kubectl logs ${mcad_dispatcher_pod} -n mcad-system
214-
fi
215-
if [[ "$mcad_runner_pod" != "" ]]
213+
local appwrapper_controller_pod=$(kubectl get pods -n appwrapper-system | grep appwrapper-controller | awk '{print $1}')
214+
if [[ "$appwrapper_controller_pod" != "" ]]
216215
then
217216
echo "===================================================================================="
218-
echo "==========================>>>>> MCAD Runner Logs <<<<<=============================="
217+
echo "==========================>>>>> AppWrapper Controller Logs <<<<<=========================="
219218
echo "===================================================================================="
220-
echo "kubectl logs ${mcad_runner_pod} -n mcad-system"
221-
kubectl logs ${mcad_runner_pod} -n mcad-system
219+
echo "kubectl logs ${appwrapper_controller_pod} -n appwrapper-system"
220+
kubectl logs ${appwrapper_controller_pod} -n appwrapper-system
222221
fi
223222
fi
224223

hack/run-tests-on-cluster.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
# Run the e2e tests on an existing cluster with mcad already installed
15+
# Run the e2e tests on an existing cluster with kueue and AppWrapper already installed
1616

1717
export ROOT_DIR="$(dirname "$(dirname "$(readlink -fn "$0")")")"
1818
export GORACE=1
@@ -24,6 +24,8 @@ source ${ROOT_DIR}/hack/e2e-util.sh
2424

2525
trap cleanup EXIT
2626

27+
wait_for_appwrapper_controller
28+
2729
run_kuttl_test_suite
2830
go run github.com/onsi/ginkgo/v2/ginkgo -v -fail-fast --procs 1 -timeout 130m ./test/e2e
2931

internal/controller/appwrapper_controller.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import (
3939
)
4040

4141
const (
42-
appWrapperLabel = "workload.codeflare.dev/appwrapper"
42+
AppWrapperLabel = "workload.codeflare.dev/appwrapper"
4343
appWrapperFinalizer = "workload.codeflare.dev/finalizer"
4444
)
4545

@@ -275,7 +275,7 @@ func (r *AppWrapperReconciler) SetupWithManager(mgr ctrl.Manager) error {
275275
// podMapFunc maps pods to appwrappers
276276
func (r *AppWrapperReconciler) podMapFunc(ctx context.Context, obj client.Object) []reconcile.Request {
277277
pod := obj.(*v1.Pod)
278-
if name, ok := pod.Labels[appWrapperLabel]; ok {
278+
if name, ok := pod.Labels[AppWrapperLabel]; ok {
279279
if pod.Status.Phase == v1.PodSucceeded {
280280
return []reconcile.Request{{NamespacedName: types.NamespacedName{Namespace: pod.Namespace, Name: name}}}
281281
}
@@ -363,10 +363,10 @@ func (r *AppWrapperReconciler) workloadStatus(ctx context.Context, aw *workloadv
363363
pods := &v1.PodList{}
364364
if err := r.List(ctx, pods,
365365
client.InNamespace(aw.Namespace),
366-
client.MatchingLabels{appWrapperLabel: aw.Name}); err != nil {
366+
client.MatchingLabels{AppWrapperLabel: aw.Name}); err != nil {
367367
return nil, err
368368
}
369-
summary := &podStatusSummary{expected: expectedPodCount(aw)}
369+
summary := &podStatusSummary{expected: ExpectedPodCount(aw)}
370370

371371
for _, pod := range pods.Items {
372372
switch pod.Status.Phase {
@@ -392,7 +392,7 @@ func replicas(ps workloadv1beta2.AppWrapperPodSet) int32 {
392392
}
393393
}
394394

395-
func expectedPodCount(aw *workloadv1beta2.AppWrapper) int32 {
395+
func ExpectedPodCount(aw *workloadv1beta2.AppWrapper) int32 {
396396
var expected int32
397397
for _, c := range aw.Spec.Components {
398398
for _, s := range c.PodSets {

internal/controller/appwrapper_controller_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@ var _ = Describe("AppWrapper Controller", func() {
7878
Expect((*AppWrapper)(aw).IsSuspended()).Should(BeFalse())
7979
podStatus, err := awReconciler.workloadStatus(ctx, aw)
8080
Expect(err).NotTo(HaveOccurred())
81-
Expect(podStatus.pending).Should(Equal(expectedPodCount(aw)))
81+
Expect(podStatus.pending).Should(Equal(ExpectedPodCount(aw)))
8282

8383
By("Simulating all Pods Running")
84-
Expect(setPodStatus(aw, v1.PodRunning, expectedPodCount(aw))).To(Succeed())
84+
Expect(setPodStatus(aw, v1.PodRunning, ExpectedPodCount(aw))).To(Succeed())
8585
By("Reconciling: Running -> Running")
8686
_, err = awReconciler.Reconcile(ctx, reconcile.Request{NamespacedName: awName})
8787
Expect(err).NotTo(HaveOccurred())
@@ -96,7 +96,7 @@ var _ = Describe("AppWrapper Controller", func() {
9696
Expect((*AppWrapper)(aw).PodsReady()).Should(BeTrue())
9797
podStatus, err = awReconciler.workloadStatus(ctx, aw)
9898
Expect(err).NotTo(HaveOccurred())
99-
Expect(podStatus.running).Should(Equal(expectedPodCount(aw)))
99+
Expect(podStatus.running).Should(Equal(ExpectedPodCount(aw)))
100100
_, finished := (*AppWrapper)(aw).Finished()
101101
Expect(finished).Should(BeFalse())
102102
}
@@ -152,11 +152,11 @@ var _ = Describe("AppWrapper Controller", func() {
152152
Expect((*AppWrapper)(aw).IsSuspended()).Should(BeFalse())
153153
podStatus, err := awReconciler.workloadStatus(ctx, aw)
154154
Expect(err).NotTo(HaveOccurred())
155-
Expect(podStatus.running).Should(Equal(expectedPodCount(aw) - 1))
155+
Expect(podStatus.running).Should(Equal(ExpectedPodCount(aw) - 1))
156156
Expect(podStatus.succeeded).Should(Equal(int32(1)))
157157

158158
By("Simulating all Pods Completing")
159-
Expect(setPodStatus(aw, v1.PodSucceeded, expectedPodCount(aw))).To(Succeed())
159+
Expect(setPodStatus(aw, v1.PodSucceeded, ExpectedPodCount(aw))).To(Succeed())
160160
By("Reconciling: Running -> Succeeded")
161161
_, err = awReconciler.Reconcile(ctx, reconcile.Request{NamespacedName: awName})
162162
Expect(err).NotTo(HaveOccurred())

internal/controller/appwrapper_fixtures_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func setPodStatus(aw *workloadv1beta2.AppWrapper, phase v1.PodPhase, numToChange
6969
if numToChange <= 0 {
7070
return nil
7171
}
72-
if awn, found := pod.Labels[appWrapperLabel]; found && awn == aw.Name {
72+
if awn, found := pod.Labels[AppWrapperLabel]; found && awn == aw.Name {
7373
pod.Status.Phase = phase
7474
err = k8sClient.Status().Update(ctx, &pod)
7575
if err != nil {

internal/controller/workload_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ func (aw *AppWrapper) RunWithPodSetsInfo(podSetsInfo []podset.PodSetInfo) error
120120
}
121121
}
122122
}
123-
awLabels := map[string]string{appWrapperLabel: aw.Name}
123+
awLabels := map[string]string{AppWrapperLabel: aw.Name}
124124

125125
podSetsInfoIndex := 0
126126
for componentIndex := range aw.Spec.Components {

test/e2e/appwrapper_test.go

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,85 @@ limitations under the License.
1717
package e2e
1818

1919
import (
20+
"time"
21+
2022
. "github.com/onsi/ginkgo/v2"
21-
// . "github.com/onsi/gomega"
23+
. "github.com/onsi/gomega"
2224

23-
awv1b2 "github.com/project-codeflare/appwrapper/api/v1beta2"
25+
workloadv1beta2 "github.com/project-codeflare/appwrapper/api/v1beta2"
2426
)
2527

2628
var _ = Describe("AppWrapper E2E Test", func() {
27-
var appwrappers []*awv1b2.AppWrapper
29+
var appwrappers []*workloadv1beta2.AppWrapper
2830

2931
BeforeEach(func() {
30-
appwrappers = []*awv1b2.AppWrapper{}
32+
appwrappers = []*workloadv1beta2.AppWrapper{}
3133
})
3234

3335
AfterEach(func() {
3436
By("Cleaning up test objects")
3537
cleanupTestObjects(ctx, appwrappers)
3638
})
3739

38-
It("Dummy Test", func() {
39-
By("Testing nothing of interest...")
40+
Describe("Creation of Fundamental GVKs", func() {
41+
It("Pods", func() {
42+
aw := createAppWrapper(ctx, pod(250), pod(250))
43+
appwrappers = append(appwrappers, aw)
44+
Expect(waitAWPodsReady(ctx, aw)).Should(Succeed())
45+
})
46+
It("Deployments", func() {
47+
aw := createAppWrapper(ctx, deployment(2, 200))
48+
appwrappers = append(appwrappers, aw)
49+
Expect(waitAWPodsReady(ctx, aw)).Should(Succeed())
50+
})
51+
It("StatefulSets", func() {
52+
aw := createAppWrapper(ctx, statefulset(2, 200))
53+
appwrappers = append(appwrappers, aw)
54+
Expect(waitAWPodsReady(ctx, aw)).Should(Succeed())
55+
})
56+
// TODO: Batch v1.Jobs
57+
It("Mixed Basic Resources", func() {
58+
aw := createAppWrapper(ctx, pod(100), deployment(2, 100), statefulset(2, 100), service())
59+
appwrappers = append(appwrappers, aw)
60+
Expect(waitAWPodsReady(ctx, aw)).Should(Succeed())
61+
})
62+
})
63+
64+
Describe("Error Handling for Invalid Resources", func() {
65+
// TODO: Replicate scenarios from the AdmissionController unit tests
66+
67+
})
68+
69+
Describe("Queueing and Preemption", func() {
70+
It("Basic Queuing", Label("slow"), func() {
71+
By("Jobs should be admitted when there is available quota")
72+
aw := createAppWrapper(ctx, deployment(2, 500))
73+
appwrappers = append(appwrappers, aw)
74+
Expect(waitAWPodsReady(ctx, aw)).Should(Succeed())
75+
aw2 := createAppWrapper(ctx, deployment(2, 500))
76+
appwrappers = append(appwrappers, aw2)
77+
Expect(waitAWPodsReady(ctx, aw2)).Should(Succeed())
78+
79+
By("Jobs should be queued when quota is exhausted")
80+
aw3 := createAppWrapper(ctx, deployment(2, 250))
81+
appwrappers = append(appwrappers, aw3)
82+
Eventually(AppWrapperPhase(ctx, aw3), 10*time.Second).Should(Equal(workloadv1beta2.AppWrapperSuspended))
83+
Consistently(AppWrapperPhase(ctx, aw3), 20*time.Second).Should(Equal(workloadv1beta2.AppWrapperSuspended))
84+
85+
By("Queued job is admitted when quota becomes available")
86+
Expect(deleteAppWrapper(ctx, aw.Name, aw.Namespace)).Should(Succeed())
87+
appwrappers = []*workloadv1beta2.AppWrapper{aw2, aw3}
88+
Expect(waitAWPodsReady(ctx, aw3)).Should(Succeed())
89+
})
90+
91+
})
92+
93+
Describe("Detection of Completion Status", func() {
94+
95+
})
96+
97+
Describe("Load Testing", Label("slow"), func() {
98+
4099
})
100+
41101
})

test/e2e/e2e_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ var _ = BeforeSuite(func() {
3333
log.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))
3434
ctx = extendContextWithClient(context.Background())
3535
ensureNamespaceExists(ctx)
36+
ensureTestQueuesExist(ctx)
3637
})
3738

3839
func TestE2E(t *testing.T) {

0 commit comments

Comments
 (0)