Skip to content
13 changes: 13 additions & 0 deletions hack/run-e2e-kind.sh
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,31 @@ function cleanup {
kubectl get crds -A -o yaml
kubectl describe crds -A

echo "---"
echo "AppWrappers..."
kubectl get appwrappers -A -o yaml
kubectl describe appwrappers -A

echo "---"
echo "'test' Pod list..."
kubectl get pods -n test

echo "---"
echo "'test' Pod yaml..."
kubectl get pods -n test -o yaml

echo "---"
echo "'test' Pod descriptions..."
kubectl describe pods -n test

echo "---"
echo "'all' Namespaces list..."
kubectl get namespaces

echo "---"
echo "'aw-namespace-1' Namespace list..."
kubectl get namespace aw-namespace-1 -o yaml

echo "===================================================================================="
echo "==========================>>>>> MCAD Controller Logs <<<<<=========================="
echo "===================================================================================="
Expand Down
21 changes: 21 additions & 0 deletions test/e2e/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,27 @@ var _ = Describe("Predicates E2E Test", func() {
Expect(err).NotTo(HaveOccurred())
})

It("Create AppWrapper - StatefulSet Only - 2 Pods", func() {
context := initTestContext()
defer cleanupTestContext(context)

aw := createStatefulSetAW(context,"aw-statefulset-2")

err := waitAWReady(context, aw)

Expect(err).NotTo(HaveOccurred())
})

It("Create AppWrapper - Namespace Only - 0 Pods", func() {
context := initTestContext()
defer cleanupTestContext(context)

aw := createNamespaceAW(context,"aw-namespace-0")

err := waitAWNonComputeResourceActive(context, aw)

Expect(err).NotTo(HaveOccurred())
})
/*
It("Gang scheduling", func() {
context := initTestContext()
Expand Down
148 changes: 148 additions & 0 deletions test/e2e/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,40 @@ func waitPodGroupUnschedulable(ctx *context, pg *arbv1.PodGroup) error {
}
*/

func waitAWNonComputeResourceActive(ctx *context, aw *arbv1.AppWrapper) error {
return waitAWNamespaceActive(ctx, aw)
}

func waitAWNamespaceActive(ctx *context, aw *arbv1.AppWrapper) error {
return wait.Poll(100*time.Millisecond, oneMinute, awNamespacePhase(ctx, aw,
[]v1.NamespacePhase{v1.NamespaceActive} ))
}

func awNamespacePhase(ctx *context, aw *arbv1.AppWrapper, phase []v1.NamespacePhase) wait.ConditionFunc {
return func() (bool, error) {
aw, err := ctx.karclient.ArbV1().AppWrappers(aw.Namespace).Get(aw.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())

namespaces, err := ctx.kubeclient.CoreV1().Namespaces().List(metav1.ListOptions{})
Expect(err).NotTo(HaveOccurred())

readyTaskNum := 0
for _, namespace := range namespaces.Items {
if awns, found := namespace.Labels["appwrapper.arbitrator.k8s.io"]; !found || awns != aw.Name {
continue
}

for _, p := range phase {
if namespace.Status.Phase == p {
readyTaskNum++
break
}
}
}

return 0 < readyTaskNum, nil
}
}
func waitAWReady(ctx *context, aw *arbv1.AppWrapper) error {
return waitAWReadyEx(ctx, aw, int(aw.Spec.SchedSpec.MinAvailable))
}
Expand All @@ -367,6 +401,7 @@ func waitAWPending(ctx *context, aw *arbv1.AppWrapper) error {
[]v1.PodPhase{v1.PodPending}, int(aw.Spec.SchedSpec.MinAvailable)))
}


func waitAWReadyEx(ctx *context, aw *arbv1.AppWrapper, taskNum int) error {
return wait.Poll(100*time.Millisecond, oneMinute, awPhase(ctx, aw,
[]v1.PodPhase{v1.PodRunning, v1.PodSucceeded}, taskNum))
Expand Down Expand Up @@ -508,6 +543,119 @@ func createDeploymentAW(context *context, name string) *arbv1.AppWrapper {
return appwrapper
}

func createNamespaceAW(context *context, name string) *arbv1.AppWrapper {
rb := []byte(`{"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"name": "aw-namespace-1",
"labels": {
"app": "aw-namespace-1"
}
}} `)
var schedSpecMin int = 0

aw := &arbv1.AppWrapper{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: arbv1.AppWrapperSpec{
SchedSpec: arbv1.SchedulingSpecTemplate{
MinAvailable: schedSpecMin,
},
AggrResources: arbv1.AppWrapperResourceList{
Items: []arbv1.AppWrapperResource{
{
// ObjectMeta: metav1.ObjectMeta{
// Name: fmt.Sprintf("%s-%s", name, "item1"),
// },
Replicas: 1,
Type: arbv1.ResourceTypeNamespace,
Template: runtime.RawExtension{
Raw: rb,
},
},
},
},
},
}

appwrapper, err := context.karclient.ArbV1().AppWrappers(context.namespace).Create(aw)
Expect(err).NotTo(HaveOccurred())

return appwrapper
}
func createStatefulSetAW(context *context, name string) *arbv1.AppWrapper {
rb := []byte(`{"apiVersion": "apps/v1",
"kind": "StatefulSet",
"metadata": {
"name": "aw-statefulset-1",
"namespace": "test",
"labels": {
"app": "nginx"
}
},
"spec": {
"replicas": 2,
"selector": {
"matchLabels": {
"app": "nginx"
}
},
"template": {
"metadata": {
"labels": {
"app": "nginx"
}
},
"spec": {
"containers": [
{
"name": "nginx",
"image": "nginx",
"ports": [
{
"containerPort": 80
}
]
}
]
}
}
}} `)
var schedSpecMin int = 2

aw := &arbv1.AppWrapper{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: context.namespace,
},
Spec: arbv1.AppWrapperSpec{
SchedSpec: arbv1.SchedulingSpecTemplate{
MinAvailable: schedSpecMin,
},
AggrResources: arbv1.AppWrapperResourceList{
Items: []arbv1.AppWrapperResource{
{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%s", name, "item1"),
Namespace: context.namespace,
},
Replicas: 1,
Type: arbv1.ResourceTypeStatefulSet,
Template: runtime.RawExtension{
Raw: rb,
},
},
},
},
},
}

appwrapper, err := context.karclient.ArbV1().AppWrappers(context.namespace).Create(aw)
Expect(err).NotTo(HaveOccurred())

return appwrapper
}
//NOTE: Recommend this test not to be the last test in the test suite it may pass
// may pass the local test but may cause controller to fail which is not
// part of this test's validation.
Expand Down