gitpod/components/ws-manager-mk2/controllers/workspace_controller_test.go
2023-01-23 14:14:30 +01:00

127 lines
3.8 KiB
Go

// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License-AGPL.txt in the project root for license information.
package controllers
import (
"context"
"fmt"
"time"
"github.com/aws/smithy-go/ptr"
workspacev1 "github.com/gitpod-io/gitpod/ws-manager/api/crd/v1"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
// . "github.com/onsi/ginkgo/extensions/table"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
var _ = Describe("WorkspaceController", func() {
Context("When starting workspaces", func() {
It("Should create Pods", func() {
const (
WorkspaceName = "test-workspace"
WorkspaceNamespace = "default"
timeout = time.Second * 10
duration = time.Second * 2
interval = time.Millisecond * 250
)
By("creating a status")
ctx := context.Background()
workspace := &workspacev1.Workspace{
TypeMeta: metav1.TypeMeta{
APIVersion: "workspace.gitpod.io/v1",
Kind: "Workspace",
},
ObjectMeta: metav1.ObjectMeta{
Name: WorkspaceName,
Namespace: WorkspaceNamespace,
},
Spec: workspacev1.WorkspaceSpec{
Ownership: workspacev1.Ownership{
Owner: "foobar",
WorkspaceID: "cool-workspace",
},
Type: workspacev1.WorkspaceTypeRegular,
Class: "default",
Image: workspacev1.WorkspaceImages{
Workspace: workspacev1.WorkspaceImage{
Ref: ptr.String("alpine:latest"),
},
IDE: workspacev1.IDEImages{
Refs: []string{},
},
},
Ports: []workspacev1.PortSpec{},
Initializer: []byte("abc"),
Admission: workspacev1.AdmissionSpec{
Level: workspacev1.AdmissionLevelEveryone,
},
},
}
Expect(k8sClient.Create(ctx, workspace)).Should(Succeed())
By("creating a pod")
podLookupKey := types.NamespacedName{Name: "ws-" + WorkspaceName, Namespace: WorkspaceNamespace}
createdPod := &corev1.Pod{}
// We'll need to retry getting this newly created CronJob, given that creation may not immediately happen.
Eventually(func() bool {
err := k8sClient.Get(ctx, podLookupKey, createdPod)
return err == nil
}, timeout, interval).Should(BeTrue())
By("updating the pod starts value")
createdWS := &workspacev1.Workspace{}
Eventually(func() (int, error) {
err := k8sClient.Get(ctx, types.NamespacedName{Name: WorkspaceName, Namespace: WorkspaceNamespace}, createdWS)
if err != nil {
return 0, err
}
return createdWS.Status.PodStarts, nil
}, timeout, interval).Should(Equal(1))
By("Creating the pod only once")
// TODO(cw): remove this hell of a hack once we're on PVC and no longer need to rely on concurrent init processes.
// Here we assume that the controller will have deleted the pod because it failed,
// and we removed the finalizer.
createdPod.Finalizers = []string{}
Expect(k8sClient.Update(ctx, createdPod)).To(Succeed())
Expect(k8sClient.Delete(ctx, createdPod)).To(Succeed())
Eventually(func() bool {
err := k8sClient.Get(ctx, podLookupKey, createdPod)
if err != nil {
// TODO(cw): check if this is a not found error
// We have an error and assume we did not find the pod. This is what we want.
return true
}
fmt.Println(createdPod.ResourceVersion)
return false
}, timeout, interval).Should(BeTrue(), "pod did not go away")
// Now we make sure the pod doesn't come back
Consistently(func() bool {
err := k8sClient.Get(ctx, podLookupKey, createdPod)
if err != nil {
// TODO(cw): check if this is a not found error
// We have an error and assume we did not find the pod. This is what we want.
return true
}
fmt.Println(createdPod.ResourceVersion)
return false
}, duration, interval).Should(BeTrue(), "pod came back")
})
})
})