mirror of
https://github.com/gitpod-io/gitpod.git
synced 2025-12-08 17:36:30 +00:00
224 lines
6.0 KiB
Go
224 lines
6.0 KiB
Go
// Copyright (c) 2021 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 integration
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"math/rand"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/util/wait"
|
|
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
|
"k8s.io/client-go/tools/clientcmd"
|
|
"k8s.io/klog/v2"
|
|
"sigs.k8s.io/e2e-framework/klient"
|
|
"sigs.k8s.io/e2e-framework/pkg/env"
|
|
"sigs.k8s.io/e2e-framework/pkg/envconf"
|
|
"sigs.k8s.io/e2e-framework/pkg/flags"
|
|
)
|
|
|
|
func SkipWithoutUsername(t *testing.T, username string) {
|
|
if username == "" {
|
|
t.Skip("Skipping because requires a username")
|
|
}
|
|
}
|
|
|
|
func SkipWithoutUserToken(t *testing.T, userToken string) {
|
|
if userToken == "" {
|
|
t.Skip("Skipping because requires a user token")
|
|
}
|
|
}
|
|
|
|
func SkipWithoutEnterpriseLicense(t *testing.T, enterpise bool) {
|
|
if !enterpise {
|
|
t.Skip("Skipping because requires enterprise license")
|
|
}
|
|
}
|
|
|
|
func EnsureUserExists(t *testing.T, username string, api *ComponentAPI) string {
|
|
if username == "" {
|
|
t.Logf("no username provided, creating temporary one")
|
|
rand.Seed(time.Now().UnixNano())
|
|
randN := rand.Intn(1000)
|
|
newUser := fmt.Sprintf("johndoe%d", randN)
|
|
userId, err := CreateUser(newUser, false, api)
|
|
if err != nil {
|
|
t.Fatalf("cannot create user: %q", err)
|
|
}
|
|
t.Cleanup(func() {
|
|
err := DeleteUser(userId, api)
|
|
if err != nil {
|
|
t.Fatalf("error deleting user %q", err)
|
|
}
|
|
})
|
|
t.Logf("user '%s' with ID %s created", newUser, userId)
|
|
return newUser
|
|
}
|
|
return username
|
|
}
|
|
|
|
func Setup(ctx context.Context) (string, string, env.Environment, bool, string, bool) {
|
|
var (
|
|
username string
|
|
enterprise bool
|
|
gitlab bool
|
|
waitGitpodReady time.Duration
|
|
|
|
namespace string
|
|
kubeconfig string
|
|
feature string
|
|
assess string
|
|
parallel bool
|
|
|
|
labels = make(flags.LabelsMap)
|
|
)
|
|
|
|
flagset := flag.CommandLine
|
|
klog.InitFlags(flagset)
|
|
|
|
flagset.StringVar(&username, "username", "", "username to execute the tests with. Chooses one automatically if left blank.")
|
|
flagset.BoolVar(&enterprise, "enterprise", false, "whether to test enterprise features. requires enterprise lisence installed.")
|
|
flagset.BoolVar(&gitlab, "gitlab", false, "whether to test gitlab integration.")
|
|
flagset.BoolVar(¶llel, "parallel", false, "Run test features in parallel")
|
|
flagset.DurationVar(&waitGitpodReady, "wait-gitpod-timeout", 5*time.Minute, `wait time for Gitpod components before starting integration test`)
|
|
flagset.StringVar(&namespace, "namespace", "", "Kubernetes cluster namespaces to use")
|
|
flagset.StringVar(&kubeconfig, "kubeconfig", "", "The path to the kubeconfig file")
|
|
flagset.StringVar(&feature, "feature", "", "Regular expression that targets features to test")
|
|
flagset.StringVar(&assess, "assess", "", "Regular expression that targets assertive steps to run")
|
|
flagset.Var(&labels, "labels", "Comma-separated key/value pairs to filter tests by labels")
|
|
if err := flagset.Parse(os.Args[1:]); err != nil {
|
|
klog.Fatalf("cannot parse flags: %v", err)
|
|
}
|
|
|
|
e := envconf.New()
|
|
if assess != "" {
|
|
e.WithAssessmentRegex(assess)
|
|
}
|
|
if feature != "" {
|
|
e.WithFeatureRegex(feature)
|
|
}
|
|
if parallel {
|
|
e.WithParallelTestEnabled()
|
|
}
|
|
|
|
client, err := klient.NewWithKubeConfigFile(kubeconfig)
|
|
if err != nil {
|
|
klog.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
e.WithClient(client)
|
|
e.WithLabels(labels)
|
|
e.WithNamespace(namespace)
|
|
|
|
// use the namespace from the CurrentContext
|
|
if namespace == "" {
|
|
ns, err := getNamespace(kubeconfig)
|
|
if err != nil {
|
|
klog.Fatalf("unexpected error obtaining context namespace: %v", err)
|
|
}
|
|
e.WithNamespace(ns)
|
|
}
|
|
|
|
testenv, err := env.NewWithContext(ctx, e)
|
|
if err != nil {
|
|
klog.Fatalf("unexpected error: %v", err)
|
|
}
|
|
testenv.Setup(
|
|
waitOnGitpodRunning(e.Namespace(), waitGitpodReady),
|
|
)
|
|
|
|
return username, e.Namespace(), testenv, enterprise, kubeconfig, gitlab
|
|
}
|
|
|
|
func waitOnGitpodRunning(namespace string, waitTimeout time.Duration) env.Func {
|
|
klog.V(2).Info("Checking status of Gitpod components...")
|
|
|
|
return func(ctx context.Context, cfg *envconf.Config) (context.Context, error) {
|
|
components := []string{
|
|
"agent-smith",
|
|
"blobserve",
|
|
"content-service",
|
|
"dashboard",
|
|
"image-builder-mk3",
|
|
"proxy",
|
|
"registry-facade",
|
|
"server",
|
|
"ws-daemon",
|
|
"ws-manager",
|
|
"ws-manager-bridge",
|
|
"ws-proxy",
|
|
}
|
|
|
|
client := cfg.Client()
|
|
err := wait.PollImmediate(5*time.Second, waitTimeout, func() (bool, error) {
|
|
for _, component := range components {
|
|
var pods corev1.PodList
|
|
err := client.Resources(namespace).List(context.Background(), &pods, func(opts *metav1.ListOptions) {
|
|
opts.LabelSelector = fmt.Sprintf("component=%v", component)
|
|
})
|
|
if err != nil {
|
|
klog.Errorf("unexpected error searching Gitpod components: %v", err)
|
|
return false, nil
|
|
}
|
|
|
|
if len(pods.Items) == 0 {
|
|
klog.Warningf("no pod ready for component %v", component)
|
|
return false, nil
|
|
}
|
|
|
|
for _, p := range pods.Items {
|
|
var isReady bool
|
|
for _, cond := range p.Status.Conditions {
|
|
if cond.Type == corev1.PodReady {
|
|
isReady = cond.Status == corev1.ConditionTrue
|
|
break
|
|
}
|
|
}
|
|
if !isReady {
|
|
klog.Warningf("no pod ready for component %v", component)
|
|
return false, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
klog.V(2).Info("All Gitpod components are running...")
|
|
return true, nil
|
|
})
|
|
if err != nil {
|
|
return ctx, nil
|
|
}
|
|
|
|
return ctx, nil
|
|
}
|
|
}
|
|
|
|
func getNamespace(path string) (string, error) {
|
|
var cfg clientcmd.ClientConfig
|
|
|
|
switch path {
|
|
case "":
|
|
loadingrules := clientcmd.NewDefaultClientConfigLoadingRules()
|
|
cfg = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingrules,
|
|
&clientcmd.ConfigOverrides{})
|
|
default:
|
|
cfg = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
|
|
&clientcmd.ClientConfigLoadingRules{ExplicitPath: path},
|
|
&clientcmd.ConfigOverrides{})
|
|
}
|
|
|
|
namespace, _, err := cfg.Namespace()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return namespace, nil
|
|
}
|