diff --git a/e2e/e2e_suite_test.go b/e2e/e2e_suite_test.go index ca786b518..dc0a9c4b5 100644 --- a/e2e/e2e_suite_test.go +++ b/e2e/e2e_suite_test.go @@ -33,8 +33,14 @@ func TestRunE2ETests(t *testing.T) { if runtime.GOOS != "linux" { go framework.ServeAgent() - // wait for http server to be up and running + // wait for http server to be up and running (max 30s) + deadline := time.After(30 * time.Second) for { + select { + case <-deadline: + t.Fatal("timeout waiting for DEVPOD_AGENT_URL to be set after 30s") + default: + } time.Sleep(time.Second) if os.Getenv("DEVPOD_AGENT_URL") != "" { break diff --git a/e2e/framework/command.go b/e2e/framework/command.go index 2c5a2d18b..5e4105803 100644 --- a/e2e/framework/command.go +++ b/e2e/framework/command.go @@ -286,22 +286,22 @@ func (f *Framework) DevPodProviderUpdate(ctx context.Context, args ...string) er return nil } -func (f *Framework) DevPodMachineCreate(args []string) error { +func (f *Framework) DevPodMachineCreate(ctx context.Context, args []string) error { baseArgs := []string{"machine", "create"} baseArgs = append(baseArgs, args...) - err := f.ExecCommand(context.Background(), false, false, "", baseArgs) + err := f.ExecCommand(ctx, false, false, "", baseArgs) if err != nil { - return fmt.Errorf("devpod nachine create failed: %s", err.Error()) + return fmt.Errorf("devpod machine create failed: %s", err.Error()) } return nil } -func (f *Framework) DevPodMachineDelete(args []string) error { +func (f *Framework) DevPodMachineDelete(ctx context.Context, args []string) error { baseArgs := []string{"machine", "delete"} baseArgs = append(baseArgs, args...) - err := f.ExecCommand(context.Background(), false, false, "", baseArgs) + err := f.ExecCommand(ctx, false, false, "", baseArgs) if err != nil { - return fmt.Errorf("devpod nachine delete failed: %s", err.Error()) + return fmt.Errorf("devpod machine delete failed: %s", err.Error()) } return nil } @@ -325,31 +325,31 @@ func (f *Framework) DevPodWorkspaceDelete( func (f *Framework) SetupGPG(tmpDir string) error { if _, err := exec.LookPath("gpg"); err != nil { - err := exec.Command("sudo", "apt-get", " install", "gnupg2", "-y").Run() - if err != nil { - return nil + if installErr := exec.Command("sudo", "apt-get", "install", "gnupg2", "-y"). + Run(); installErr != nil { + return fmt.Errorf("gpg not found and failed to install gnupg2: %w", installErr) } } - err := exec.Command("gpg", "--import", filepath.Join(tmpDir, "gpg-public.key")).Run() - if err != nil { - return nil + // #nosec G204 -- gpg with fixed arguments for test GPG key setup + if err := exec.Command("gpg", "--import", filepath.Join(tmpDir, "gpg-public.key")). + Run(); err != nil { + return fmt.Errorf("failed to import gpg public key: %w", err) } - err = exec.Command("gpg", "--import", filepath.Join(tmpDir, "gpg-private.key")).Run() - if err != nil { - return nil + // #nosec G204 -- gpg with fixed arguments for test GPG key setup + if err := exec.Command("gpg", "--import", filepath.Join(tmpDir, "gpg-private.key")). + Run(); err != nil { + return fmt.Errorf("failed to import gpg private key: %w", err) } - err = exec.Command("gpgconf", "--kill", "gpg-agent").Run() - if err != nil { - return nil + if err := exec.Command("gpgconf", "--kill", "gpg-agent").Run(); err != nil { + return fmt.Errorf("failed to kill gpg-agent: %w", err) } - err = exec.Command("gpg-agent", "--homedir", "$HOME/.gnupg", "--use-standard-socket", "--daemon"). - Run() - if err != nil { - return nil + if err := exec.Command("gpg-agent", "--homedir", "$HOME/.gnupg", "--use-standard-socket", "--daemon"). + Run(); err != nil { + return fmt.Errorf("failed to start gpg-agent: %w", err) } return exec.Command("gpg", "-k").Run() @@ -456,3 +456,19 @@ func (f *Framework) DevPodIDEList(ctx context.Context, extraArgs ...string) (str baseArgs := []string{"ide", "list"} return f.ExecCommandOutput(ctx, append(baseArgs, extraArgs...)) } + +// SetupDockerProvider creates a new framework, removes any existing docker provider, +// adds a fresh one with the given docker path, and sets it as the active provider. +func SetupDockerProvider(binDir, dockerPath string) (*Framework, error) { + f := NewDefaultFramework(binDir) + _ = f.DevPodProviderDelete(context.Background(), "docker") + if err := f.DevPodProviderAdd( + context.Background(), + "docker", + "-o", + "DOCKER_PATH="+dockerPath, + ); err != nil { + return nil, fmt.Errorf("failed to add docker provider: %w", err) + } + return f, f.DevPodProviderUse(context.Background(), "docker") +} diff --git a/e2e/framework/server_utils.go b/e2e/framework/server_utils.go index 99fb9dd82..61a836b8e 100644 --- a/e2e/framework/server_utils.go +++ b/e2e/framework/server_utils.go @@ -24,8 +24,9 @@ func ServeAgent() { // Create a file server handler for the specified directory fileServer := http.FileServer(http.Dir(dir)) - // Register the file server handler to serve files under the /files route - http.Handle("/files/", http.StripPrefix("/files", fileServer)) + // Use a dedicated ServeMux to avoid conflicts with http.DefaultServeMux + mux := http.NewServeMux() + mux.Handle("/files/", http.StripPrefix("/files", fileServer)) ip := getIP() @@ -40,10 +41,10 @@ func ServeAgent() { log.Fatal(err) } - // Start the HTTP server on port 8080 log.Printf("Server started on %s", addr) - err = http.Serve(listener, nil) + // #nosec G114 -- test-only agent file server, no timeout needed + err = http.Serve(listener, mux) if err != nil { log.Fatal(err) } diff --git a/e2e/tests/build/build.go b/e2e/tests/build/build.go index f1ff23cde..b1237d134 100644 --- a/e2e/tests/build/build.go +++ b/e2e/tests/build/build.go @@ -70,81 +70,84 @@ var _ = ginkgo.Describe("devpod build test suite", ginkgo.Label("build"), ginkgo dockerHelper = &docker.DockerHelper{DockerCommand: "docker", Log: log.Default} }) - ginkgo.It("build docker buildx", func(ctx context.Context) { - f := framework.NewDefaultFramework(initialDir + "/bin") - tempDir, err := framework.CopyToTempDir("tests/build/testdata/docker") - framework.ExpectNoError(err) - ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) + ginkgo.It("build docker buildx", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + f := framework.NewDefaultFramework(initialDir + "/bin") + tempDir, err := framework.CopyToTempDir("tests/build/testdata/docker") + framework.ExpectNoError(err) + ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) - _ = f.DevPodProviderDelete(ctx, "docker") - err = f.DevPodProviderAdd(ctx, "docker") - framework.ExpectNoError(err) - err = f.DevPodProviderUse(ctx, "docker") - framework.ExpectNoError(err) + _ = f.DevPodProviderDelete(ctx, "docker") + err = f.DevPodProviderAdd(ctx, "docker") + framework.ExpectNoError(err) + err = f.DevPodProviderUse(ctx, "docker") + framework.ExpectNoError(err) - cfg := getDevcontainerConfig(tempDir) + cfg := getDevcontainerConfig(tempDir) - dockerfilePath := tempDir + "/.devcontainer/Dockerfile" - contentToParse, err := prepareDockerfileContent(dockerfilePath) - framework.ExpectNoError(err) + dockerfilePath := tempDir + "/.devcontainer/Dockerfile" + contentToParse, err := prepareDockerfileContent(dockerfilePath) + framework.ExpectNoError(err) - // do the build - platforms := "linux/amd64,linux/arm64" - err = f.DevPodBuild( - ctx, - tempDir, - "--force-build", - "--platform", - platforms, - "--repository", - prebuildRepoName, - "--skip-push", - ) - framework.ExpectNoError(err) + // do the build + platforms := "linux/amd64,linux/arm64" + err = f.DevPodBuild( + ctx, + tempDir, + "--force-build", + "--platform", + platforms, + "--repository", + prebuildRepoName, + "--skip-push", + ) + framework.ExpectNoError(err) - // parse the dockerfile - file, err := dockerfile.Parse(contentToParse) - framework.ExpectNoError(err) - info := &config.ImageBuildInfo{Dockerfile: file} - - // make sure images are there - prebuildHash, err := config.CalculatePrebuildHash(config.PrebuildHashParams{ - Config: cfg, - Platform: "linux/amd64", - Architecture: "amd64", - ContextPath: filepath.Dir(cfg.Origin), - DockerfilePath: dockerfilePath, - DockerfileContent: contentToParse, - BuildInfo: info, - Log: log.Default, - }) - framework.ExpectNoError(err) - _, err = dockerHelper.InspectImage(ctx, prebuildRepoName+":"+prebuildHash, false) - framework.ExpectNoError(err) + // parse the dockerfile + file, err := dockerfile.Parse(contentToParse) + framework.ExpectNoError(err) + info := &config.ImageBuildInfo{Dockerfile: file} - prebuildHash, err = config.CalculatePrebuildHash(config.PrebuildHashParams{ - Config: cfg, - Platform: "linux/arm64", - Architecture: "arm64", - ContextPath: filepath.Dir(cfg.Origin), - DockerfilePath: dockerfilePath, - DockerfileContent: contentToParse, - BuildInfo: info, - Log: log.Default, - }) - framework.ExpectNoError(err) + // make sure images are there + prebuildHash, err := config.CalculatePrebuildHash(config.PrebuildHashParams{ + Config: cfg, + Platform: "linux/amd64", + Architecture: "amd64", + ContextPath: filepath.Dir(cfg.Origin), + DockerfilePath: dockerfilePath, + DockerfileContent: contentToParse, + BuildInfo: info, + Log: log.Default, + }) + framework.ExpectNoError(err) + _, err = dockerHelper.InspectImage(ctx, prebuildRepoName+":"+prebuildHash, false) + framework.ExpectNoError(err) - details, err := dockerHelper.InspectImage(ctx, prebuildRepoName+":"+prebuildHash, false) - framework.ExpectNoError(err) - framework.ExpectEqual( - details.Config.Labels["test"], - "VALUE", - "should contain test label", - ) - }) + prebuildHash, err = config.CalculatePrebuildHash(config.PrebuildHashParams{ + Config: cfg, + Platform: "linux/arm64", + Architecture: "arm64", + ContextPath: filepath.Dir(cfg.Origin), + DockerfilePath: dockerfilePath, + DockerfileContent: contentToParse, + BuildInfo: info, + Log: log.Default, + }) + framework.ExpectNoError(err) + + details, err := dockerHelper.InspectImage(ctx, prebuildRepoName+":"+prebuildHash, false) + framework.ExpectNoError(err) + framework.ExpectEqual( + details.Config.Labels["test"], + "VALUE", + "should contain test label", + ) + }) ginkgo.It( "should build image without repository specified if skip-push flag is set", + ginkgo.SpecTimeout(framework.GetTimeout()), func(ctx context.Context) { f := framework.NewDefaultFramework(initialDir + "/bin") tempDir, err := framework.CopyToTempDir("tests/build/testdata/docker") @@ -156,7 +159,7 @@ var _ = ginkgo.Describe("devpod build test suite", ginkgo.Label("build"), ginkgo framework.ExpectNoError(err) err = f.DevPodProviderUse(ctx, "docker") framework.ExpectNoError(err) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), tempDir) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, tempDir) cfg := getDevcontainerConfig(tempDir) @@ -196,6 +199,7 @@ var _ = ginkgo.Describe("devpod build test suite", ginkgo.Label("build"), ginkgo ginkgo.It( "should build the image of the referenced service from the docker compose file", + ginkgo.SpecTimeout(framework.GetTimeout()), func(ctx context.Context) { f := framework.NewDefaultFramework(initialDir + "/bin") tempDir, err := framework.CopyToTempDir("tests/build/testdata/docker-compose") @@ -208,7 +212,7 @@ var _ = ginkgo.Describe("devpod build test suite", ginkgo.Label("build"), ginkgo err = f.DevPodProviderUse(ctx, "docker") framework.ExpectNoError(err) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), tempDir) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, tempDir) prebuildRepo := prebuildRepoName @@ -220,6 +224,7 @@ var _ = ginkgo.Describe("devpod build test suite", ginkgo.Label("build"), ginkgo ginkgo.It( "should build docker-compose with features when build context differs from devcontainer location", + ginkgo.SpecTimeout(framework.GetTimeout()), func(ctx context.Context) { f := framework.NewDefaultFramework(initialDir + "/bin") tempDir, err := framework.CopyToTempDir( @@ -234,121 +239,129 @@ var _ = ginkgo.Describe("devpod build test suite", ginkgo.Label("build"), ginkgo err = f.DevPodProviderUse(ctx, "docker") framework.ExpectNoError(err) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), tempDir) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, tempDir) err = f.DevPodBuild(ctx, tempDir, "--skip-push") framework.ExpectNoError(err) }, ) - ginkgo.It("build docker internal buildkit", func(ctx context.Context) { - f := framework.NewDefaultFramework(initialDir + "/bin") - tempDir, err := framework.CopyToTempDir("tests/build/testdata/docker") - framework.ExpectNoError(err) - ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) + ginkgo.It("build docker internal buildkit", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + f := framework.NewDefaultFramework(initialDir + "/bin") + tempDir, err := framework.CopyToTempDir("tests/build/testdata/docker") + framework.ExpectNoError(err) + ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) - _ = f.DevPodProviderDelete(ctx, "docker") - err = f.DevPodProviderAdd(ctx, "docker") - framework.ExpectNoError(err) - err = f.DevPodProviderUse(ctx, "docker") - framework.ExpectNoError(err) + _ = f.DevPodProviderDelete(ctx, "docker") + err = f.DevPodProviderAdd(ctx, "docker") + framework.ExpectNoError(err) + err = f.DevPodProviderUse(ctx, "docker") + framework.ExpectNoError(err) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), tempDir) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, tempDir) - cfg := getDevcontainerConfig(tempDir) + cfg := getDevcontainerConfig(tempDir) - dockerfilePath := tempDir + "/.devcontainer/Dockerfile" - contentToParse, err := prepareDockerfileContent(dockerfilePath) - framework.ExpectNoError(err) + dockerfilePath := tempDir + "/.devcontainer/Dockerfile" + contentToParse, err := prepareDockerfileContent(dockerfilePath) + framework.ExpectNoError(err) - prebuildRepo := prebuildRepoName - - // do the build - err = f.DevPodBuild( - ctx, - tempDir, - "--force-build", - "--force-internal-buildkit", - "--repository", - prebuildRepo, - "--skip-push", - ) - framework.ExpectNoError(err) + prebuildRepo := prebuildRepoName - // parse the dockerfile - file, err := dockerfile.Parse(contentToParse) - framework.ExpectNoError(err) - info := &config.ImageBuildInfo{Dockerfile: file} - - // make sure images are there - prebuildHash, err := config.CalculatePrebuildHash(config.PrebuildHashParams{ - Config: cfg, - Platform: "linux/" + runtime.GOARCH, - Architecture: runtime.GOARCH, - ContextPath: filepath.Dir(cfg.Origin), - DockerfilePath: dockerfilePath, - DockerfileContent: contentToParse, - BuildInfo: info, - Log: log.Default, - }) - framework.ExpectNoError(err) + // do the build + err = f.DevPodBuild( + ctx, + tempDir, + "--force-build", + "--force-internal-buildkit", + "--repository", + prebuildRepo, + "--skip-push", + ) + framework.ExpectNoError(err) - _, err = dockerHelper.InspectImage(ctx, prebuildRepo+":"+prebuildHash, false) - framework.ExpectNoError(err) - }) + // parse the dockerfile + file, err := dockerfile.Parse(contentToParse) + framework.ExpectNoError(err) + info := &config.ImageBuildInfo{Dockerfile: file} + + // make sure images are there + prebuildHash, err := config.CalculatePrebuildHash(config.PrebuildHashParams{ + Config: cfg, + Platform: "linux/" + runtime.GOARCH, + Architecture: runtime.GOARCH, + ContextPath: filepath.Dir(cfg.Origin), + DockerfilePath: dockerfilePath, + DockerfileContent: contentToParse, + BuildInfo: info, + Log: log.Default, + }) + framework.ExpectNoError(err) - ginkgo.It("build kubernetes dockerless", func(ctx context.Context) { - if runtime.GOOS == osWindows { - ginkgo.Skip("skipping on windows") - } + _, err = dockerHelper.InspectImage(ctx, prebuildRepo+":"+prebuildHash, false) + framework.ExpectNoError(err) + }) - f := framework.NewDefaultFramework(initialDir + "/bin") - tempDir, err := framework.CopyToTempDir("tests/build/testdata/kubernetes") - framework.ExpectNoError(err) - ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) + ginkgo.It("build kubernetes dockerless", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + if runtime.GOOS == osWindows { + ginkgo.Skip("skipping on windows") + } - _ = f.DevPodProviderDelete(ctx, "kubernetes") - err = f.DevPodProviderAdd(ctx, "kubernetes") - framework.ExpectNoError(err) - err = f.DevPodProviderUse( - ctx, - "kubernetes", - "-o", - "KUBERNETES_NAMESPACE=devpod", - ) - framework.ExpectNoError(err) + f := framework.NewDefaultFramework(initialDir + "/bin") + tempDir, err := framework.CopyToTempDir("tests/build/testdata/kubernetes") + framework.ExpectNoError(err) + ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), tempDir) + _ = f.DevPodProviderDelete(ctx, "kubernetes") + err = f.DevPodProviderAdd(ctx, "kubernetes") + framework.ExpectNoError(err) + err = f.DevPodProviderUse( + ctx, + "kubernetes", + "-o", + "KUBERNETES_NAMESPACE=devpod", + ) + framework.ExpectNoError(err) - // do the up - err = f.DevPodUp(ctx, tempDir) - framework.ExpectNoError(err) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, tempDir) - // check if ssh works - out, err := f.DevPodSSH(ctx, tempDir, "echo -n $MY_TEST") - framework.ExpectNoError(err) - framework.ExpectEqual(out, "test456", "should contain my-test") - }) + // do the up + err = f.DevPodUp(ctx, tempDir) + framework.ExpectNoError(err) - ginkgo.It("rebuild kubernetes dockerless", func(ctx context.Context) { - validateKubernetesDeploymentWithoutDocker( - ctx, - initialDir, - func(ctx context.Context, f *framework.Framework, tempDir string) error { - return f.DevPodUpRecreate(ctx, tempDir) - }, - ) - }) + // check if ssh works + out, err := f.DevPodSSH(ctx, tempDir, "echo -n $MY_TEST") + framework.ExpectNoError(err) + framework.ExpectEqual(out, "test456", "should contain my-test") + }) - ginkgo.It("reset kubernetes dockerless", func(ctx context.Context) { - validateKubernetesDeploymentWithoutDocker( - ctx, - initialDir, - func(ctx context.Context, f *framework.Framework, tempDir string) error { - return f.DevPodUpReset(ctx, tempDir) - }, - ) - }) + ginkgo.It("rebuild kubernetes dockerless", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + validateKubernetesDeploymentWithoutDocker( + ctx, + initialDir, + func(ctx context.Context, f *framework.Framework, tempDir string) error { + return f.DevPodUpRecreate(ctx, tempDir) + }, + ) + }) + + ginkgo.It("reset kubernetes dockerless", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + validateKubernetesDeploymentWithoutDocker( + ctx, + initialDir, + func(ctx context.Context, f *framework.Framework, tempDir string) error { + return f.DevPodUpReset(ctx, tempDir) + }, + ) + }) }) func validateKubernetesDeploymentWithoutDocker( @@ -376,7 +389,7 @@ func validateKubernetesDeploymentWithoutDocker( ) framework.ExpectNoError(err) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), tempDir) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, tempDir) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) diff --git a/e2e/tests/context/context.go b/e2e/tests/context/context.go index 7e6b206a6..20b186ebf 100644 --- a/e2e/tests/context/context.go +++ b/e2e/tests/context/context.go @@ -6,9 +6,12 @@ import ( "os" "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" "github.com/skevetter/devpod/e2e/framework" ) +const ideIntelliJ = "intellij" + var _ = ginkgo.Describe( "devpod context test suite", ginkgo.Label("context"), @@ -24,6 +27,7 @@ var _ = ginkgo.Describe( ginkgo.It( "create a new context, switch to it and delete afterwards", + ginkgo.SpecTimeout(framework.GetTimeout()), func(ctx context.Context) { f := framework.NewDefaultFramework(initialDir + "/bin") @@ -41,88 +45,98 @@ var _ = ginkgo.Describe( }, ) - ginkgo.It("should use shared context in IDE commands", func(ctx context.Context) { - f := framework.NewDefaultFramework(initialDir + "/bin") + ginkgo.It( + "should use shared context in IDE commands", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + f := framework.NewDefaultFramework(initialDir + "/bin") - contextA := "test-ctx-a-ide" - contextB := "test-ctx-b-ide" + contextA := "test-ctx-a-ide" + contextB := "test-ctx-b-ide" - var err error - err = f.DevPodContextCreate(ctx, contextA) - framework.ExpectNoError(err) - ginkgo.DeferCleanup(func(cleanupCtx context.Context) { - _ = f.DevPodContextDelete(cleanupCtx, contextA) - }) + var err error + err = f.DevPodContextCreate(ctx, contextA) + framework.ExpectNoError(err) + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + _ = f.DevPodContextDelete(cleanupCtx, contextA) + }) - err = f.DevPodContextCreate(ctx, contextB) - framework.ExpectNoError(err) - ginkgo.DeferCleanup(func(cleanupCtx context.Context) { - err = f.DevPodContextDelete(cleanupCtx, contextB) + err = f.DevPodContextCreate(ctx, contextB) framework.ExpectNoError(err) - }) + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + err = f.DevPodContextDelete(cleanupCtx, contextB) + framework.ExpectNoError(err) + }) - err = f.DevPodContextUse(ctx, contextA) - framework.ExpectNoError(err) + err = f.DevPodContextUse(ctx, contextA) + framework.ExpectNoError(err) - err = f.DevPodIDEUse(ctx, "intellij", "--context", contextB) - framework.ExpectNoError(err) + err = f.DevPodIDEUse(ctx, ideIntelliJ, "--context", contextB) + framework.ExpectNoError(err) - output, err := f.DevPodIDEList(ctx, "--output", "json") - framework.ExpectNoError(err) + output, err := f.DevPodIDEList(ctx, "--output", "json") + framework.ExpectNoError(err) - var ides []map[string]any - err = json.Unmarshal([]byte(output), &ides) - framework.ExpectNoError(err) + var ides []map[string]any + err = json.Unmarshal([]byte(output), &ides) + framework.ExpectNoError(err) + gomega.Expect(ides).NotTo(gomega.BeEmpty(), "IDE list should not be empty") - for _, ide := range ides { - if ide["name"] == "intellij" { - if defaultVal, exists := ide["default"]; exists && defaultVal == true { - ginkgo.Fail("IDE was incorrectly set in context-a instead of context-b") + for _, ide := range ides { + if ide["name"] == ideIntelliJ { + if defaultVal, exists := ide["default"]; exists && defaultVal == true { + ginkgo.Fail("IDE was incorrectly set in context-a instead of context-b") + } } } - } - - output, err = f.DevPodIDEList(ctx, "--context", contextB, "--output", "json") - framework.ExpectNoError(err) - err = json.Unmarshal([]byte(output), &ides) - framework.ExpectNoError(err) + output, err = f.DevPodIDEList(ctx, "--context", contextB, "--output", "json") + framework.ExpectNoError(err) - intellijFound := false - for _, ide := range ides { - if ide["name"] == "intellij" { - if defaultVal, exists := ide["default"]; exists && defaultVal == true { - intellijFound = true - break + err = json.Unmarshal([]byte(output), &ides) + framework.ExpectNoError(err) + gomega.Expect(ides). + NotTo(gomega.BeEmpty(), "IDE list for context-b should not be empty") + + intellijFound := false + for _, ide := range ides { + if ide["name"] == ideIntelliJ { + if defaultVal, exists := ide["default"]; exists && defaultVal == true { + intellijFound = true + break + } } } - } - if !intellijFound { - ginkgo.Fail("IDE was not set in context-b as expected") - } + gomega.Expect(intellijFound).To( + gomega.BeTrue(), "IDE should be set as default in context-b", + ) - ginkgo.GinkgoT().Setenv("DEVPOD_CONTEXT", contextB) + ginkgo.GinkgoT().Setenv("DEVPOD_CONTEXT", contextB) - output, err = f.DevPodIDEList(ctx, "--output", "json") - framework.ExpectNoError(err) + output, err = f.DevPodIDEList(ctx, "--output", "json") + framework.ExpectNoError(err) - err = json.Unmarshal([]byte(output), &ides) - framework.ExpectNoError(err) + err = json.Unmarshal([]byte(output), &ides) + framework.ExpectNoError(err) + gomega.Expect(ides).NotTo( + gomega.BeEmpty(), + "IDE list via DEVPOD_CONTEXT should not be empty", + ) - intellijFound = false - for _, ide := range ides { - if ide["name"] == "intellij" { - if defaultVal, exists := ide["default"]; exists && defaultVal == true { - intellijFound = true - break + intellijFound = false + for _, ide := range ides { + if ide["name"] == ideIntelliJ { + if defaultVal, exists := ide["default"]; exists && defaultVal == true { + intellijFound = true + break + } } } - } - if !intellijFound { - ginkgo.Fail( - "Selecting context-b using environment variable DEVPOD_CONTEXT does not work as expected", + gomega.Expect(intellijFound).To( + gomega.BeTrue(), + "DEVPOD_CONTEXT env var should select context-b with intellij as default IDE", ) - } - }) + }, + ) }, ) diff --git a/e2e/tests/dockerinstall/dockerinstall.go b/e2e/tests/dockerinstall/dockerinstall.go index 121f054e4..338683454 100644 --- a/e2e/tests/dockerinstall/dockerinstall.go +++ b/e2e/tests/dockerinstall/dockerinstall.go @@ -34,7 +34,7 @@ var _ = ginkgo.Describe( err = f.DevPodProviderUse(ctx, "docker") framework.ExpectNoError(err) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), tempDir) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, tempDir) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) diff --git a/e2e/tests/ide/ide.go b/e2e/tests/ide/ide.go index ecad77599..b7ae3961c 100644 --- a/e2e/tests/ide/ide.go +++ b/e2e/tests/ide/ide.go @@ -17,10 +17,11 @@ var _ = ginkgo.Describe("devpod ide test suite", ginkgo.Label("ide"), ginkgo.Ord framework.ExpectNoError(err) }) - ginkgo.It("start ides", func(ctx context.Context) { + ginkgo.It("start ides", ginkgo.SpecTimeout(framework.GetTimeout()), func(ctx context.Context) { f := framework.NewDefaultFramework(initialDir + "/bin") tempDir, err := framework.CopyToTempDir("tests/ide/testdata") framework.ExpectNoError(err) + ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) err = f.DevPodProviderAdd(ctx, "docker") framework.ExpectNoError(err) diff --git a/e2e/tests/integration/integration.go b/e2e/tests/integration/integration.go index 3d7a7791e..a03c3e98c 100644 --- a/e2e/tests/integration/integration.go +++ b/e2e/tests/integration/integration.go @@ -24,6 +24,7 @@ var _ = ginkgo.Describe( ginkgo.It( "should setup ssh, add provider, run workspace, test ssh, and cleanup", + ginkgo.SpecTimeout(framework.GetTimeout()), func(ctx context.Context) { sshDir := os.Getenv("HOME") + "/.ssh" if _, err := os.Stat(sshDir); os.IsNotExist(err) { diff --git a/e2e/tests/machine/machine.go b/e2e/tests/machine/machine.go index b4fc5bf15..9f5012575 100644 --- a/e2e/tests/machine/machine.go +++ b/e2e/tests/machine/machine.go @@ -18,76 +18,88 @@ var _ = ginkgo.Describe("devpod testing machine", ginkgo.Label("machine"), ginkg framework.ExpectNoError(err) }) - ginkgo.It("should add simple machine and then delete it", func(ctx context.Context) { - tempDir, err := framework.CopyToTempDir("tests/machine/testdata") - framework.ExpectNoError(err) - ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) + ginkgo.It( + "should add simple machine and then delete it", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + tempDir, err := framework.CopyToTempDir("tests/machine/testdata") + framework.ExpectNoError(err) + ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) - f := framework.NewDefaultFramework(initialDir + "/bin") + f := framework.NewDefaultFramework(initialDir + "/bin") - // Ensure that mock-provider is deleted - _ = f.DevPodProviderDelete(ctx, "mock-provider") + // Ensure that mock-provider is deleted + _ = f.DevPodProviderDelete(ctx, "mock-provider") - ginkgo.By("Add mock provider") - err = f.DevPodProviderAdd(ctx, tempDir+"/mock-provider.yaml") - framework.ExpectNoError(err) - ginkgo.DeferCleanup(func(cleanupCtx context.Context) { - err = f.DevPodProviderDelete(cleanupCtx, "mock-provider") + ginkgo.By("Add mock provider") + err = f.DevPodProviderAdd(ctx, tempDir+"/mock-provider.yaml") framework.ExpectNoError(err) - }) + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + err = f.DevPodProviderDelete(cleanupCtx, "mock-provider") + framework.ExpectNoError(err) + }) - ginkgo.By("Use mock provider") - err = f.DevPodProviderUse(ctx, "mock-provider") - framework.ExpectNoError(err) - - machineUUID, _ := uuid.NewRandom() - machineName := machineUUID.String() + ginkgo.By("Use mock provider") + err = f.DevPodProviderUse(ctx, "mock-provider") + framework.ExpectNoError(err) - ginkgo.By("Create test machine with mock provider") - err = f.DevPodMachineCreate([]string{machineName}) - framework.ExpectNoError(err) + machineUUID, _ := uuid.NewRandom() + machineName := machineUUID.String() - ginkgo.By("Remove test machine") - err = f.DevPodMachineDelete([]string{machineName}) - framework.ExpectNoError(err) - }) + ginkgo.By("Create test machine with mock provider") + err = f.DevPodMachineCreate(ctx, []string{machineName}) + framework.ExpectNoError(err) - ginkgo.It("should delete a non-existing machine and get an error", func(ctx context.Context) { - tempDir, err := framework.CopyToTempDir("tests/machine/testdata") - framework.ExpectNoError(err) - ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) + ginkgo.By("Remove test machine") + err = f.DevPodMachineDelete(ctx, []string{machineName}) + framework.ExpectNoError(err) + }, + ) + + ginkgo.It( + "should delete a non-existing machine and get an error", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + tempDir, err := framework.CopyToTempDir("tests/machine/testdata") + framework.ExpectNoError(err) + ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) - f := framework.NewDefaultFramework(initialDir + "/bin") + f := framework.NewDefaultFramework(initialDir + "/bin") - // Ensure that mock-provider is deleted - _ = f.DevPodProviderDelete(ctx, "mock-provider") + // Ensure that mock-provider is deleted + _ = f.DevPodProviderDelete(ctx, "mock-provider") - ginkgo.By("Add mock provider") - err = f.DevPodProviderAdd(ctx, tempDir+"/mock-provider.yaml") - framework.ExpectNoError(err) + ginkgo.By("Add mock provider") + err = f.DevPodProviderAdd(ctx, tempDir+"/mock-provider.yaml") + framework.ExpectNoError(err) + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + err = f.DevPodProviderDelete(cleanupCtx, "mock-provider") + framework.ExpectNoError(err) + }) - ginkgo.By("Use mock provider") - err = f.DevPodProviderUse(ctx, "mock-provider") - framework.ExpectNoError(err) + ginkgo.By("Use mock provider") + err = f.DevPodProviderUse(ctx, "mock-provider") + framework.ExpectNoError(err) - machineUUID1, err := uuid.NewRandom() - framework.ExpectNoError(err) - machineName1 := machineUUID1.String() + machineUUID1, err := uuid.NewRandom() + framework.ExpectNoError(err) + machineName1 := machineUUID1.String() - machineUUID2, err := uuid.NewRandom() - framework.ExpectNoError(err) - machineName2 := machineUUID2.String() + machineUUID2, err := uuid.NewRandom() + framework.ExpectNoError(err) + machineName2 := machineUUID2.String() - ginkgo.By("Create test machine with mock provider") - err = f.DevPodMachineCreate([]string{machineName1}) - framework.ExpectNoError(err) + ginkgo.By("Create test machine with mock provider") + err = f.DevPodMachineCreate(ctx, []string{machineName1}) + framework.ExpectNoError(err) - ginkgo.By("Remove existing test machine") - err = f.DevPodMachineDelete([]string{machineName1}) - framework.ExpectNoError(err) + ginkgo.By("Remove existing test machine") + err = f.DevPodMachineDelete(ctx, []string{machineName1}) + framework.ExpectNoError(err) - ginkgo.By("Remove not existing test machine (should get an error)") - err = f.DevPodMachineDelete([]string{machineName2}) - framework.ExpectError(err) - }) + ginkgo.By("Remove not existing test machine (should get an error)") + err = f.DevPodMachineDelete(ctx, []string{machineName2}) + framework.ExpectError(err) + }, + ) }) diff --git a/e2e/tests/machineprovider/machineprovider.go b/e2e/tests/machineprovider/machineprovider.go index 1611bd111..e0238e8f3 100644 --- a/e2e/tests/machineprovider/machineprovider.go +++ b/e2e/tests/machineprovider/machineprovider.go @@ -26,148 +26,148 @@ var _ = ginkgo.Describe( framework.ExpectNoError(err) }) - ginkgo.It("test start / stop / status", func(ctx context.Context) { - f := framework.NewDefaultFramework(initialDir + "/bin") + ginkgo.It("test start / stop / status", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + f := framework.NewDefaultFramework(initialDir + "/bin") + + // copy test dir + tempDir, err := framework.CopyToTempDirWithoutChdir( + initialDir + "/tests/machineprovider/testdata/machineprovider", + ) + framework.ExpectNoError(err) + ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) - // copy test dir - tempDir, err := framework.CopyToTempDirWithoutChdir( - initialDir + "/tests/machineprovider/testdata/machineprovider", - ) - framework.ExpectNoError(err) - ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) + // create docker provider + err = f.DevPodProviderAdd( + ctx, + filepath.Join(tempDir, "provider.yaml"), + ) + framework.ExpectNoError(err) + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + err = f.DevPodWorkspaceDelete(cleanupCtx, tempDir) + framework.ExpectNoError(err) + }) - // create docker provider - err = f.DevPodProviderAdd( - ctx, - filepath.Join(tempDir, "provider.yaml"), - ) - framework.ExpectNoError(err) - ginkgo.DeferCleanup(func(cleanupCtx context.Context) { - err = f.DevPodWorkspaceDelete(cleanupCtx, tempDir) + // wait for devpod workspace to come online (deadline: 30s) + err = f.DevPodUp(ctx, tempDir, "--debug") framework.ExpectNoError(err) - }) - ginkgo.DeferCleanup(func(cleanupCtx context.Context) { - err = f.DevPodWorkspaceDelete(cleanupCtx, tempDir) + + // expect workspace + workspace, err := f.FindWorkspace(ctx, tempDir) framework.ExpectNoError(err) - }) - // wait for devpod workspace to come online (deadline: 30s) - err = f.DevPodUp(ctx, tempDir, "--debug") - framework.ExpectNoError(err) + // check status + status, err := f.DevPodStatus(ctx, tempDir) + framework.ExpectNoError(err) + framework.ExpectEqual( + strings.ToUpper(status.State), + "RUNNING", + "workspace status did not match", + ) + + // stop container + err = f.DevPodStop(ctx, tempDir) + framework.ExpectNoError(err) - // expect workspace - workspace, err := f.FindWorkspace(ctx, tempDir) - framework.ExpectNoError(err) + // check status + status, err = f.DevPodStatus(ctx, tempDir) + framework.ExpectNoError(err) + framework.ExpectEqual( + strings.ToUpper(status.State), + "STOPPED", + "workspace status did not match", + ) + + // wait for devpod workspace to come online (deadline: 30s) + err = f.DevPodUp(ctx, tempDir) + framework.ExpectNoError(err) - // check status - status, err := f.DevPodStatus(ctx, tempDir) - framework.ExpectNoError(err) - framework.ExpectEqual( - strings.ToUpper(status.State), - "RUNNING", - "workspace status did not match", - ) - - // stop container - err = f.DevPodStop(ctx, tempDir) - framework.ExpectNoError(err) + // check if ssh works as it should start the container + out, err := f.DevPodSSH( + ctx, + tempDir, + fmt.Sprintf("cat /workspaces/%s/test.txt", workspace.ID), + ) + framework.ExpectNoError(err) + framework.ExpectEqual( + strings.TrimSpace(out), + "Test123", + "workspace content does not match", + ) + }) - // check status - status, err = f.DevPodStatus(ctx, tempDir) - framework.ExpectNoError(err) - framework.ExpectEqual( - strings.ToUpper(status.State), - "STOPPED", - "workspace status did not match", - ) - - // wait for devpod workspace to come online (deadline: 30s) - err = f.DevPodUp(ctx, tempDir) - framework.ExpectNoError(err) + ginkgo.It("test devpod inactivity timeout", + ginkgo.SpecTimeout(framework.GetTimeout()*5), + func(ctx context.Context) { + f := framework.NewDefaultFramework(initialDir + "/bin") - // check if ssh works as it should start the container - out, err := f.DevPodSSH( - ctx, - tempDir, - fmt.Sprintf("cat /workspaces/%s/test.txt", workspace.ID), - ) - framework.ExpectNoError(err) - framework.ExpectEqual( - strings.TrimSpace(out), - "Test123", - "workspace content does not match", - ) - }, ginkgo.SpecTimeout(framework.GetTimeout())) - - ginkgo.It("test devpod inactivity timeout", func(ctx context.Context) { - f := framework.NewDefaultFramework(initialDir + "/bin") - - // copy test dir - tempDir, err := framework.CopyToTempDirWithoutChdir( - initialDir + "/tests/machineprovider/testdata/machineprovider2", - ) - framework.ExpectNoError(err) - ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) + // copy test dir + tempDir, err := framework.CopyToTempDirWithoutChdir( + initialDir + "/tests/machineprovider/testdata/machineprovider2", + ) + framework.ExpectNoError(err) + ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) - // create provider - _ = f.DevPodProviderDelete(ctx, "docker123") - err = f.DevPodProviderAdd(ctx, filepath.Join(tempDir, "provider.yaml")) - framework.ExpectNoError(err) - ginkgo.DeferCleanup(func(cleanupCtx context.Context) { - err = f.DevPodWorkspaceDelete(cleanupCtx, tempDir) + // create provider + _ = f.DevPodProviderDelete(ctx, "docker123") + err = f.DevPodProviderAdd(ctx, filepath.Join(tempDir, "provider.yaml")) framework.ExpectNoError(err) - err = f.DevPodProviderDelete(cleanupCtx, "docker123") + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + err = f.DevPodWorkspaceDelete(cleanupCtx, tempDir) + framework.ExpectNoError(err) + err = f.DevPodProviderDelete(cleanupCtx, "docker123") + framework.ExpectNoError(err) + }) + + // wait for devpod workspace to come online (deadline: 30s) + err = f.DevPodUp(ctx, tempDir, "--debug", "--daemon-interval=3s") framework.ExpectNoError(err) - }) - // wait for devpod workspace to come online (deadline: 30s) - err = f.DevPodUp(ctx, tempDir, "--debug", "--daemon-interval=3s") - framework.ExpectNoError(err) - - // check status - status, err := f.DevPodStatus(ctx, tempDir, "--container-status=false") - framework.ExpectNoError(err) - framework.ExpectEqual( - strings.ToUpper(status.State), - "RUNNING", - "workspace status did not match", - ) - - // stop container - err = f.DevPodStop(ctx, tempDir) - framework.ExpectNoError(err) + // check status + status, err := f.DevPodStatus(ctx, tempDir, "--container-status=false") + framework.ExpectNoError(err) + framework.ExpectEqual( + strings.ToUpper(status.State), + "RUNNING", + "workspace status did not match", + ) + + // stop container + err = f.DevPodStop(ctx, tempDir) + framework.ExpectNoError(err) - // check status - status, err = f.DevPodStatus(ctx, tempDir, "--container-status=false") - framework.ExpectNoError(err) - framework.ExpectEqual( - strings.ToUpper(status.State), - "STOPPED", - "workspace status did not match", - ) - - // wait for devpod workspace to come online (deadline: 30s) - err = f.DevPodUp(ctx, tempDir, "--daemon-interval=3s") - framework.ExpectNoError(err) + // check status + status, err = f.DevPodStatus(ctx, tempDir, "--container-status=false") + framework.ExpectNoError(err) + framework.ExpectEqual( + strings.ToUpper(status.State), + "STOPPED", + "workspace status did not match", + ) + + // wait for devpod workspace to come online (deadline: 30s) + err = f.DevPodUp(ctx, tempDir, "--daemon-interval=3s") + framework.ExpectNoError(err) - // check status - status, err = f.DevPodStatus(ctx, tempDir, "--container-status=false") - framework.ExpectNoError(err) - framework.ExpectEqual( - strings.ToUpper(status.State), - "RUNNING", - "workspace status did not match", - ) - - // wait until workspace is stopped again - gomega.Eventually(func() string { - status, err := f.DevPodStatus(ctx, tempDir, "--container-status=false") + // check status + status, err = f.DevPodStatus(ctx, tempDir, "--container-status=false") framework.ExpectNoError(err) - return strings.ToUpper(status.State) - }, time.Minute*2, time.Second*2).Should( - gomega.Equal("STOPPED"), - "machine did not shutdown in time", - ) - }, ginkgo.SpecTimeout(framework.GetTimeout()*5)) + framework.ExpectEqual( + strings.ToUpper(status.State), + "RUNNING", + "workspace status did not match", + ) + + // wait until workspace is stopped again + gomega.Eventually(func() string { + status, err := f.DevPodStatus(ctx, tempDir, "--container-status=false") + framework.ExpectNoError(err) + return strings.ToUpper(status.State) + }, time.Minute*2, time.Second*2).Should( + gomega.Equal("STOPPED"), + "machine did not shutdown in time", + ) + }) }, ) diff --git a/e2e/tests/provider/provider.go b/e2e/tests/provider/provider.go index 13895d421..05b48d1c1 100644 --- a/e2e/tests/provider/provider.go +++ b/e2e/tests/provider/provider.go @@ -34,132 +34,140 @@ var _ = ginkgo.Describe( framework.ExpectNoError(err) }) - ginkgo.It("should add simple provider and delete it", func(ctx context.Context) { - tempDir, err := framework.CopyToTempDir( - "tests/provider/testdata/simple-k8s-provider", - ) - framework.ExpectNoError(err) - ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) + ginkgo.It("should add simple provider and delete it", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + tempDir, err := framework.CopyToTempDir( + "tests/provider/testdata/simple-k8s-provider", + ) + framework.ExpectNoError(err) + ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) - f := framework.NewDefaultFramework(initialDir + "/bin") + f := framework.NewDefaultFramework(initialDir + "/bin") - err = f.DevPodProviderDelete(ctx, "provider1", "--ignore-not-found") - framework.ExpectNoError(err) + err = f.DevPodProviderDelete(ctx, "provider1", "--ignore-not-found") + framework.ExpectNoError(err) - err = f.DevPodProviderAdd(ctx, tempDir+"/provider1.yaml") - framework.ExpectNoError(err) + err = f.DevPodProviderAdd(ctx, tempDir+"/provider1.yaml") + framework.ExpectNoError(err) - err = f.DevPodProviderUse(ctx, "provider1") - framework.ExpectNoError(err) - err = f.DevPodProviderUse(ctx, "providerX") - framework.ExpectError(err) + err = f.DevPodProviderUse(ctx, "provider1") + framework.ExpectNoError(err) + err = f.DevPodProviderUse(ctx, "providerX") + framework.ExpectError(err) - err = f.DevPodProviderDelete(ctx, "provider1") - framework.ExpectNoError(err) + err = f.DevPodProviderDelete(ctx, "provider1") + framework.ExpectNoError(err) - err = f.DevPodProviderUse(ctx, "provider1") - framework.ExpectError(err) - }) + err = f.DevPodProviderUse(ctx, "provider1") + framework.ExpectError(err) + }) - ginkgo.It("should add simple provider and update it", func(ctx context.Context) { - tempDir, err := framework.CopyToTempDir( - "tests/provider/testdata/simple-k8s-provider", - ) - framework.ExpectNoError(err) - ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) + ginkgo.It("should add simple provider and update it", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + tempDir, err := framework.CopyToTempDir( + "tests/provider/testdata/simple-k8s-provider", + ) + framework.ExpectNoError(err) + ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) - f := framework.NewDefaultFramework(initialDir + "/bin") + f := framework.NewDefaultFramework(initialDir + "/bin") - err = f.DevPodProviderDelete(ctx, "provider2", "--ignore-not-found") - framework.ExpectNoError(err) + err = f.DevPodProviderDelete(ctx, "provider2", "--ignore-not-found") + framework.ExpectNoError(err) - err = f.DevPodProviderAdd(ctx, tempDir+"/provider2.yaml") - framework.ExpectNoError(err) - err = f.DevPodProviderUse(ctx, "provider2") - framework.ExpectNoError(err) + err = f.DevPodProviderAdd(ctx, tempDir+"/provider2.yaml") + framework.ExpectNoError(err) + err = f.DevPodProviderUse(ctx, "provider2") + framework.ExpectNoError(err) - checkCtx, cancel := context.WithDeadline( - ctx, - time.Now().Add(30*time.Second), - ) - err = f.DevPodProviderOptionsCheckNamespaceDescription( - checkCtx, - "provider2", - "The namespace to use", - ) - framework.ExpectNoError(err) - cancel() + checkCtx, cancel := context.WithDeadline( + ctx, + time.Now().Add(30*time.Second), + ) + err = f.DevPodProviderOptionsCheckNamespaceDescription( + checkCtx, + "provider2", + "The namespace to use", + ) + framework.ExpectNoError(err) + cancel() - err = f.DevPodProviderUpdate( - ctx, - "provider2", - tempDir+"/provider2-update.yaml", - ) - framework.ExpectNoError(err) + err = f.DevPodProviderUpdate( + ctx, + "provider2", + tempDir+"/provider2-update.yaml", + ) + framework.ExpectNoError(err) - checkCtx, cancel = context.WithDeadline( - ctx, - time.Now().Add(30*time.Second), - ) - err = f.DevPodProviderOptionsCheckNamespaceDescription( - checkCtx, - "provider2", - "Updated namespace parameter", - ) - framework.ExpectNoError(err) - cancel() + checkCtx, cancel = context.WithDeadline( + ctx, + time.Now().Add(30*time.Second), + ) + err = f.DevPodProviderOptionsCheckNamespaceDescription( + checkCtx, + "provider2", + "Updated namespace parameter", + ) + framework.ExpectNoError(err) + cancel() - err = f.DevPodProviderDelete(ctx, "provider2") - framework.ExpectNoError(err) + err = f.DevPodProviderDelete(ctx, "provider2") + framework.ExpectNoError(err) - err = f.DevPodProviderUse(ctx, "provider2") - framework.ExpectError(err) - }) + err = f.DevPodProviderUse(ctx, "provider2") + framework.ExpectError(err) + }) - ginkgo.It("should list all providers", func(ctx context.Context) { - tempDir, err := framework.CopyToTempDir( - "tests/provider/testdata/simple-k8s-provider", - ) - framework.ExpectNoError(err) - ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) + ginkgo.It("should list all providers", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + tempDir, err := framework.CopyToTempDir( + "tests/provider/testdata/simple-k8s-provider", + ) + framework.ExpectNoError(err) + ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) - f := framework.NewDefaultFramework(initialDir + "/bin") + f := framework.NewDefaultFramework(initialDir + "/bin") - err = f.DevPodProviderDelete(ctx, "provider1", "--ignore-not-found") - framework.ExpectNoError(err) + err = f.DevPodProviderDelete(ctx, "provider1", "--ignore-not-found") + framework.ExpectNoError(err) - err = f.DevPodProviderAdd(ctx, tempDir+"/provider1.yaml") - framework.ExpectNoError(err) + err = f.DevPodProviderAdd(ctx, tempDir+"/provider1.yaml") + framework.ExpectNoError(err) - err = f.DevPodProviderUse(ctx, "provider1") - framework.ExpectNoError(err) + err = f.DevPodProviderUse(ctx, "provider1") + framework.ExpectNoError(err) - err = os.WriteFile(tempDir+"/.DS_Store", []byte("test"), 0o644) // #nosec G306 - framework.ExpectNoError(err) + err = os.WriteFile(tempDir+"/.DS_Store", []byte("test"), 0o644) // #nosec G306 + framework.ExpectNoError(err) - err = f.DevPodProviderList(ctx) - framework.ExpectNoError(err) + err = f.DevPodProviderList(ctx) + framework.ExpectNoError(err) - err = f.DevPodProviderDelete(ctx, "provider1") - framework.ExpectNoError(err) + err = f.DevPodProviderDelete(ctx, "provider1") + framework.ExpectNoError(err) - err = f.DevPodProviderUse(ctx, "provider1") - framework.ExpectError(err) - }) + err = f.DevPodProviderUse(ctx, "provider1") + framework.ExpectError(err) + }) - ginkgo.It("should parse options", func(ctx context.Context) { - tempDir, err := framework.CopyToTempDir( - "tests/provider/testdata/simple-k8s-provider", - ) - framework.ExpectNoError(err) - ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) + ginkgo.It("should parse options", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + tempDir, err := framework.CopyToTempDir( + "tests/provider/testdata/simple-k8s-provider", + ) + framework.ExpectNoError(err) + ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) - f := framework.NewDefaultFramework(initialDir + "/bin") + f := framework.NewDefaultFramework(initialDir + "/bin") - err = f.DevPodProviderDelete(ctx, "provider3", "--ignore-not-found") - framework.ExpectNoError(err) + err = f.DevPodProviderDelete(ctx, "provider3", "--ignore-not-found") + framework.ExpectNoError(err) - podManifest := ` + podManifest := ` apiVersion: v1 kind: Pod metadata: @@ -168,65 +176,70 @@ spec: containers: - name: devpod ` - err = f.DevPodProviderAdd( - ctx, - tempDir+"/provider3.yaml", - "--option=TEMPLATE="+podManifest, - ) - framework.ExpectNoError(err) + err = f.DevPodProviderAdd( + ctx, + tempDir+"/provider3.yaml", + "--option=TEMPLATE="+podManifest, + ) + framework.ExpectNoError(err) - err = f.DevPodProviderUse(ctx, "provider3") - framework.ExpectNoError(err) + err = f.DevPodProviderUse(ctx, "provider3") + framework.ExpectNoError(err) - err = f.DevPodProviderFindOption(ctx, "provider3", podManifest) - framework.ExpectNoError(err) + err = f.DevPodProviderFindOption(ctx, "provider3", podManifest) + framework.ExpectNoError(err) - err = f.DevPodProviderDelete(ctx, "provider3") - framework.ExpectNoError(err) + err = f.DevPodProviderDelete(ctx, "provider3") + framework.ExpectNoError(err) - err = f.DevPodProviderUse(ctx, "provider3") - framework.ExpectError(err) - }) + err = f.DevPodProviderUse(ctx, "provider3") + framework.ExpectError(err) + }) // RENAME-1. - ginkgo.It("should rename a provider to a new, valid name", func(ctx context.Context) { - tempDir, err := framework.CopyToTempDir("tests/provider/testdata/simple-k8s-provider") - framework.ExpectNoError(err) - ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) + ginkgo.It("should rename a provider to a new, valid name", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + tempDir, err := framework.CopyToTempDir( + "tests/provider/testdata/simple-k8s-provider", + ) + framework.ExpectNoError(err) + ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) - f := framework.NewDefaultFramework(initialDir + "/bin") + f := framework.NewDefaultFramework(initialDir + "/bin") - providerName := "provider-rename1" - renamedProviderName := "provider-renamed" + providerName := "provider-rename1" + renamedProviderName := "provider-renamed" - // Ensure that provider is deleted. - err = f.DevPodProviderDelete(ctx, providerName, "--ignore-not-found") - framework.ExpectNoError(err) - err = f.DevPodProviderDelete(ctx, renamedProviderName, "--ignore-not-found") - framework.ExpectNoError(err) + // Ensure that provider is deleted. + err = f.DevPodProviderDelete(ctx, providerName, "--ignore-not-found") + framework.ExpectNoError(err) + err = f.DevPodProviderDelete(ctx, renamedProviderName, "--ignore-not-found") + framework.ExpectNoError(err) - // Add provider. - err = f.DevPodProviderAdd(ctx, tempDir+"/provider1.yaml", "--name", providerName) - framework.ExpectNoError(err) + // Add provider. + err = f.DevPodProviderAdd(ctx, tempDir+"/provider1.yaml", "--name", providerName) + framework.ExpectNoError(err) - err = f.DevPodProviderUse(ctx, providerName) - framework.ExpectNoError(err) + err = f.DevPodProviderUse(ctx, providerName) + framework.ExpectNoError(err) - err = f.DevPodProviderRename(ctx, providerName, renamedProviderName) - framework.ExpectNoError(err) + err = f.DevPodProviderRename(ctx, providerName, renamedProviderName) + framework.ExpectNoError(err) - err = f.DevPodProviderUse(ctx, providerName) - framework.ExpectError(err) - err = f.DevPodProviderUse(ctx, renamedProviderName) - framework.ExpectNoError(err) + err = f.DevPodProviderUse(ctx, providerName) + framework.ExpectError(err) + err = f.DevPodProviderUse(ctx, renamedProviderName) + framework.ExpectNoError(err) - err = f.DevPodProviderDelete(ctx, renamedProviderName) - framework.ExpectNoError(err) - }) + err = f.DevPodProviderDelete(ctx, renamedProviderName) + framework.ExpectNoError(err) + }) // RENAME-2. ginkgo.It( "should fail to rename a provider to a name that already exists", + ginkgo.SpecTimeout(framework.GetTimeout()), func(ctx context.Context) { tempDir, err := framework.CopyToTempDir( "tests/provider/testdata/simple-k8s-provider", @@ -278,22 +291,25 @@ spec: }, ) - ginkgo.It("should fail to rename a non-existent provider", func(ctx context.Context) { - f := framework.NewDefaultFramework(initialDir + "/bin") + ginkgo.It("should fail to rename a non-existent provider", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + f := framework.NewDefaultFramework(initialDir + "/bin") - nonExistentProvider := "non-existent-provider3" - newName := "new-name3" + nonExistentProvider := "non-existent-provider3" + newName := "new-name3" - err := f.DevPodProviderDelete(ctx, nonExistentProvider, "--ignore-not-found") - framework.ExpectNoError(err) + err := f.DevPodProviderDelete(ctx, nonExistentProvider, "--ignore-not-found") + framework.ExpectNoError(err) - // Attempt to rename non-existent provider. - err = f.DevPodProviderRename(ctx, nonExistentProvider, newName) - framework.ExpectError(err) - }) + // Attempt to rename non-existent provider. + err = f.DevPodProviderRename(ctx, nonExistentProvider, newName) + framework.ExpectError(err) + }) ginkgo.It( "should rename a provider with an associated running workspace", + ginkgo.SpecTimeout(framework.GetTimeout()), func(ctx context.Context) { f := framework.NewDefaultFramework(initialDir + "/bin") @@ -370,86 +386,92 @@ spec: }, ) - ginkgo.It("should fail to rename a provider to an invalid name", func(ctx context.Context) { - tempDir, err := framework.CopyToTempDir("tests/provider/testdata/simple-k8s-provider") - framework.ExpectNoError(err) - ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) + ginkgo.It("should fail to rename a provider to an invalid name", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + tempDir, err := framework.CopyToTempDir( + "tests/provider/testdata/simple-k8s-provider", + ) + framework.ExpectNoError(err) + ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) - f := framework.NewDefaultFramework(initialDir + "/bin") + f := framework.NewDefaultFramework(initialDir + "/bin") - providerName := "provider-to-rename-invalid6" + providerName := "provider-to-rename-invalid6" - err = f.DevPodProviderDelete(ctx, providerName, "--ignore-not-found") - framework.ExpectNoError(err) + err = f.DevPodProviderDelete(ctx, providerName, "--ignore-not-found") + framework.ExpectNoError(err) - err = f.DevPodProviderAdd(ctx, tempDir+"/provider1.yaml", "--name", providerName) - framework.ExpectNoError(err) + err = f.DevPodProviderAdd(ctx, tempDir+"/provider1.yaml", "--name", providerName) + framework.ExpectNoError(err) - err = f.DevPodProviderRename(ctx, providerName, "invalid/name6") - framework.ExpectError(err) + err = f.DevPodProviderRename(ctx, providerName, "invalid/name6") + framework.ExpectError(err) - err = f.DevPodProviderUse(ctx, providerName) - framework.ExpectNoError(err) + err = f.DevPodProviderUse(ctx, providerName) + framework.ExpectNoError(err) - err = f.DevPodProviderDelete(ctx, providerName) - framework.ExpectNoError(err) - }) + err = f.DevPodProviderDelete(ctx, providerName) + framework.ExpectNoError(err) + }) - ginkgo.It("should preserve provider options after rename", func(ctx context.Context) { - f := framework.NewDefaultFramework(initialDir + "/bin") + ginkgo.It("should preserve provider options after rename", + ginkgo.SpecTimeout(framework.GetTimeout()), + func(ctx context.Context) { + f := framework.NewDefaultFramework(initialDir + "/bin") - providerName := "provider-opts-rename7" - renamedName := "renamed-opts-rename7" + providerName := "provider-opts-rename7" + renamedName := "renamed-opts-rename7" - err := f.DevPodProviderDelete(ctx, providerName, "--ignore-not-found") - framework.ExpectNoError(err) - err = f.DevPodProviderDelete(ctx, renamedName, "--ignore-not-found") - framework.ExpectNoError(err) + err := f.DevPodProviderDelete(ctx, providerName, "--ignore-not-found") + framework.ExpectNoError(err) + err = f.DevPodProviderDelete(ctx, renamedName, "--ignore-not-found") + framework.ExpectNoError(err) - err = addDockerProvider(ctx, f, providerName) - framework.ExpectNoError(err) - err = f.DevPodProviderUse(ctx, providerName) - framework.ExpectNoError(err) + err = addDockerProvider(ctx, f, providerName) + framework.ExpectNoError(err) + err = f.DevPodProviderUse(ctx, providerName) + framework.ExpectNoError(err) - beforeJSON, err := f.DevPodProviderOptionsJSON(ctx, providerName) - framework.ExpectNoError(err) + beforeJSON, err := f.DevPodProviderOptionsJSON(ctx, providerName) + framework.ExpectNoError(err) - var beforeOpts map[string]any - err = json.Unmarshal([]byte(beforeJSON), &beforeOpts) - framework.ExpectNoError(err) + var beforeOpts map[string]any + err = json.Unmarshal([]byte(beforeJSON), &beforeOpts) + framework.ExpectNoError(err) - err = f.DevPodProviderRename(ctx, providerName, renamedName) - framework.ExpectNoError(err) + err = f.DevPodProviderRename(ctx, providerName, renamedName) + framework.ExpectNoError(err) - afterJSON, err := f.DevPodProviderOptionsJSON(ctx, renamedName) - framework.ExpectNoError(err) + afterJSON, err := f.DevPodProviderOptionsJSON(ctx, renamedName) + framework.ExpectNoError(err) - var afterOpts map[string]any - err = json.Unmarshal([]byte(afterJSON), &afterOpts) - framework.ExpectNoError(err) + var afterOpts map[string]any + err = json.Unmarshal([]byte(afterJSON), &afterOpts) + framework.ExpectNoError(err) - for key, beforeVal := range beforeOpts { - afterVal, exists := afterOpts[key] - gomega.Expect(exists). - To(gomega.BeTrue(), "option %s should exist after rename", key) - - beforeMap := beforeVal.(map[string]any) - afterMap := afterVal.(map[string]any) - - beforeV, hasBefore := beforeMap["value"] - afterV, hasAfter := afterMap["value"] - gomega.Expect(hasAfter).To(gomega.Equal(hasBefore), - "option %s value presence should be preserved", key) - if hasBefore { - gomega.Expect(afterV).To(gomega.Equal(beforeV), - "option %s value should be preserved", key) + for key, beforeVal := range beforeOpts { + afterVal, exists := afterOpts[key] + gomega.Expect(exists). + To(gomega.BeTrue(), "option %s should exist after rename", key) + + beforeMap := beforeVal.(map[string]any) + afterMap := afterVal.(map[string]any) + + beforeV, hasBefore := beforeMap["value"] + afterV, hasAfter := afterMap["value"] + gomega.Expect(hasAfter).To(gomega.Equal(hasBefore), + "option %s value presence should be preserved", key) + if hasBefore { + gomega.Expect(afterV).To(gomega.Equal(beforeV), + "option %s value should be preserved", key) + } } - } - err = f.DevPodProviderUse(ctx, providerName) - framework.ExpectError(err) + err = f.DevPodProviderUse(ctx, providerName) + framework.ExpectError(err) - err = f.DevPodProviderDelete(ctx, renamedName) - framework.ExpectNoError(err) - }) + err = f.DevPodProviderDelete(ctx, renamedName) + framework.ExpectNoError(err) + }) }) diff --git a/e2e/tests/ssh/ssh.go b/e2e/tests/ssh/ssh.go index 1356d2f09..7bc39200c 100644 --- a/e2e/tests/ssh/ssh.go +++ b/e2e/tests/ssh/ssh.go @@ -10,6 +10,7 @@ import ( "runtime" "strconv" "strings" + "sync" "time" "github.com/onsi/ginkgo/v2" @@ -30,6 +31,7 @@ var _ = ginkgo.Describe("devpod ssh test suite", ginkgo.Label("ssh"), ginkgo.Ord ginkgo.It( "should start a new workspace with a docker provider (default) and SSH into it", + ginkgo.SpecTimeout(framework.GetTimeout()), func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/ssh/testdata/local-test") framework.ExpectNoError(err) @@ -59,54 +61,6 @@ var _ = ginkgo.Describe("devpod ssh test suite", ginkgo.Label("ssh"), ginkgo.Ord }, ) - // ginkgo.It("should start a new workspace with a docker provider (default) and forward gpg agent into it", func() { - // // skip windows for now - // if runtime.GOOS == osWindows { - // return - // } - // - // tempDir, err := framework.CopyToTempDir("tests/ssh/testdata/gpg-forwarding") - // framework.ExpectNoError(err) - // defer framework.CleanupTempDir(initialDir, tempDir) - // - // f := framework.NewDefaultFramework(initialDir + "/bin") - // _ = f.DevPodProviderAdd(ctx, "docker") - // err = f.DevPodProviderUse(context.Background(), "docker") - // framework.ExpectNoError(err) - // - // ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), tempDir) - // - // out, err := exec.Command("gpg", "-k").Output() - // if err != nil || len(out) == 0 { - // err = f.SetupGPG(tempDir) - // framework.ExpectNoError(err) - // } - // - // // Start up devpod workspace - // devpodUpDeadline := time.Now().Add(5 * time.Minute) - // devpodUpCtx, cancel := context.WithDeadline(context.Background(), devpodUpDeadline) - // defer cancel() - // err = f.DevPodUp(devpodUpCtx, tempDir, "--gpg-agent-forwarding") - // framework.ExpectNoError(err) - // - // devpodSSHDeadline := time.Now().Add(20 * time.Second) - // devpodSSHCtx, cancelSSH := context.WithDeadline(context.Background(), devpodSSHDeadline) - // defer cancelSSH() - // - // // GPG agent might be not ready, let's try 10 times, 1 second each - // retries := 10 - // for retries > 0 { - // err = f.DevPodSSHGpgTestKey(devpodSSHCtx, tempDir) - // if err != nil { - // retries-- - // time.Sleep(time.Second) - // } else { - // break - // } - // } - // framework.ExpectNoError(err) - // }) - ginkgo.It( "should set up git SSH signature helper and sign a commit", ginkgo.SpecTimeout(7*time.Minute), @@ -131,7 +85,7 @@ var _ = ginkgo.Describe("devpod ssh test suite", ginkgo.Label("ssh"), ginkgo.Ord // Generate a temporary SSH key for signing sshKeyDir, err := os.MkdirTemp("", "devpod-ssh-signing-test") framework.ExpectNoError(err) - defer func() { _ = os.RemoveAll(sshKeyDir) }() + ginkgo.DeferCleanup(func() { _ = os.RemoveAll(sshKeyDir) }) keyPath := filepath.Join(sshKeyDir, "id_ed25519") // #nosec G204 -- test command with controlled arguments @@ -341,7 +295,7 @@ var _ = ginkgo.Describe("devpod ssh test suite", ginkgo.Label("ssh"), ginkgo.Ord // Generate a key but do NOT add it to the ssh-agent so signing will fail sshKeyDir, err := os.MkdirTemp("", "devpod-ssh-signing-err-test") framework.ExpectNoError(err) - defer func() { _ = os.RemoveAll(sshKeyDir) }() + ginkgo.DeferCleanup(func() { _ = os.RemoveAll(sshKeyDir) }) keyPath := filepath.Join(sshKeyDir, "id_ed25519") // #nosec G204 -- test command with controlled arguments @@ -394,6 +348,7 @@ var _ = ginkgo.Describe("devpod ssh test suite", ginkgo.Label("ssh"), ginkgo.Ord ginkgo.It( "should start a new workspace with a docker provider (default) and forward a port into it", + ginkgo.SpecTimeout(framework.GetTimeout()), func(ctx context.Context) { if runtime.GOOS == osWindows { ginkgo.Skip("skipping on windows") @@ -433,12 +388,10 @@ var _ = ginkgo.Describe("devpod ssh test suite", ginkgo.Label("ssh"), ginkgo.Ord ) err = serverCmd.Start() framework.ExpectNoError(err) - go func() { + var wg sync.WaitGroup + wg.Go(func() { _ = serverCmd.Wait() - }() - - ginkgo.GinkgoWriter.Println("Waiting for server to start") - time.Sleep(3 * time.Second) + }) portForwardCtx, cancelPort := context.WithTimeout( ctx, @@ -447,9 +400,14 @@ var _ = ginkgo.Describe("devpod ssh test suite", ginkgo.Label("ssh"), ginkgo.Ord defer cancelPort() ginkgo.GinkgoWriter.Println("Starting port forwarding for port", port) - go func() { + wg.Go(func() { _ = f.DevpodPortTest(portForwardCtx, strconv.Itoa(port), tempDir) - }() + }) + ginkgo.DeferCleanup(func() { + serverCancel() + cancelPort() + wg.Wait() + }) ginkgo.GinkgoWriter.Println("Polling for port", port, "to be accessible") address := net.JoinHostPort("localhost", strconv.Itoa(port)) diff --git a/e2e/tests/up-docker-compose/build.go b/e2e/tests/up-docker-compose/build.go index 3baf39e82..57cdeb791 100644 --- a/e2e/tests/up-docker-compose/build.go +++ b/e2e/tests/up-docker-compose/build.go @@ -8,6 +8,7 @@ import ( "io" "os" "path/filepath" + "time" "github.com/onsi/ginkgo/v2" "github.com/onsi/gomega" @@ -82,7 +83,10 @@ var _ = ginkgo.Describe( return 0 } return len(ids) - }).Should(gomega.Equal(1), "1 compose container to be created") + }). + WithTimeout(60*time.Second). + WithPolling(1*time.Second). + Should(gomega.Equal(1), "1 compose container to be created") ginkgo.By("Modifying .devcontainer.json with failing changes") origPath := filepath.Join(tempDir, ".devcontainer.json") @@ -152,7 +156,10 @@ var _ = ginkgo.Describe( return 0 } return len(ids) - }).Should(gomega.Equal(1), "1 compose container to be created") + }). + WithTimeout(60*time.Second). + WithPolling(1*time.Second). + Should(gomega.Equal(1), "1 compose container to be created") ginkgo.By("Starting DevPod again with --recreate") err = f.DevPodUp(ctx, tempDir, "--debug", "--recreate") diff --git a/e2e/tests/up-docker-compose/helper.go b/e2e/tests/up-docker-compose/helper.go index 6463cabe2..6a6e568ae 100644 --- a/e2e/tests/up-docker-compose/helper.go +++ b/e2e/tests/up-docker-compose/helper.go @@ -140,10 +140,7 @@ func setupWorkspace(testdataPath, initialDir string, f *framework.Framework) (st } func setupDockerProvider(binDir, dockerPath string) (*framework.Framework, error) { - f := framework.NewDefaultFramework(binDir) - _ = f.DevPodProviderDelete(context.Background(), "docker") - _ = f.DevPodProviderAdd(context.Background(), "docker", "-o", "DOCKER_PATH="+dockerPath) - return f, f.DevPodProviderUse(context.Background(), "docker") + return framework.SetupDockerProvider(binDir, dockerPath) } func findComposeContainer( diff --git a/e2e/tests/up-features/helper.go b/e2e/tests/up-features/helper.go index c9c9748ed..b7504a496 100644 --- a/e2e/tests/up-features/helper.go +++ b/e2e/tests/up-features/helper.go @@ -3,7 +3,6 @@ package up import ( "archive/tar" "compress/gzip" - "context" "io" "os" @@ -57,8 +56,5 @@ func addFileToTar(tarWriter *tar.Writer, filePath string) error { } func setupDockerProvider(binDir, dockerPath string) (*framework.Framework, error) { - f := framework.NewDefaultFramework(binDir) - _ = f.DevPodProviderDelete(context.Background(), "docker") - _ = f.DevPodProviderAdd(context.Background(), "docker", "-o", "DOCKER_PATH="+dockerPath) - return f, f.DevPodProviderUse(context.Background(), "docker") + return framework.SetupDockerProvider(binDir, dockerPath) } diff --git a/e2e/tests/up-features/up_features.go b/e2e/tests/up-features/up_features.go index 9b6b97398..0878bef83 100644 --- a/e2e/tests/up-features/up_features.go +++ b/e2e/tests/up-features/up_features.go @@ -34,7 +34,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) @@ -101,7 +101,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite framework.ExpectNoError(err) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) @@ -118,7 +118,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) @@ -138,7 +138,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) @@ -165,7 +165,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) @@ -192,7 +192,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) @@ -219,7 +219,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) // This should fail with circular dependency error err = f.DevPodUp(ctx, tempDir) @@ -243,7 +243,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) @@ -270,7 +270,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) @@ -297,7 +297,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) // Should fail with circular dependency error err = f.DevPodUp(ctx, tempDir) @@ -320,7 +320,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) // Should fail when dependency cannot be resolved err = f.DevPodUp(ctx, tempDir) @@ -343,7 +343,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) @@ -371,7 +371,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) // This should not fail with "Parent does not exist" error err = f.DevPodUp(ctx, tempDir) @@ -399,7 +399,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) @@ -426,7 +426,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) @@ -447,7 +447,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-features", "suite ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) wsName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), wsName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, wsName) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) diff --git a/e2e/tests/up-features/wsl.go b/e2e/tests/up-features/wsl.go index b9f46a27a..6ffd18d3d 100644 --- a/e2e/tests/up-features/wsl.go +++ b/e2e/tests/up-features/wsl.go @@ -29,6 +29,7 @@ var _ = ginkgo.Describe( ginkgo.It("should use http headers to download feature", func(ctx context.Context) { server := ghttp.NewServer() + ginkgo.DeferCleanup(server.Close) tempDir, err := framework.CopyToTempDir( "tests/up-features/testdata/docker-features-http-headers", @@ -51,7 +52,6 @@ var _ = ginkgo.Describe( framework.ExpectNoError(err) ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) - ginkgo.DeferCleanup(server.Close) respHeader := http.Header{} respHeader.Set( @@ -77,12 +77,11 @@ var _ = ginkgo.Describe( err = f.DevPodProviderUse(ctx, "docker") framework.ExpectNoError(err) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), tempDir) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, tempDir) // Wait for devpod workspace to come online (deadline: 30s) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) - server.Close() }, ginkgo.SpecTimeout(framework.GetTimeout())) ginkgo.It( @@ -98,7 +97,7 @@ var _ = ginkgo.Describe( ginkgo.DeferCleanup(framework.CleanupTempDir, initialDir, tempDir) workspaceName := filepath.Base(tempDir) - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), workspaceName) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, workspaceName) // Wait for devpod workspace to come online (deadline: 30s) err = f.DevPodUp(ctx, tempDir, "--debug") diff --git a/e2e/tests/up/git_repositories.go b/e2e/tests/up/git_repositories.go index 1bbcc2bd1..3152451cb 100644 --- a/e2e/tests/up/git_repositories.go +++ b/e2e/tests/up/git_repositories.go @@ -28,7 +28,7 @@ var _ = ginkgo.Describe( framework.ExpectNoError(err) name := "sha256-0c1547c" - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), name) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, name) // Wait for devpod workspace to come online (deadline: 30s) err = f.DevPodUp( @@ -47,7 +47,7 @@ var _ = ginkgo.Describe( framework.ExpectNoError(err) name := "devpod" - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), name) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, name) err = f.DevPodUp(ctx, "github.com/skevetter/devpod@pull/1/head") framework.ExpectNoError(err) @@ -65,8 +65,8 @@ var _ = ginkgo.Describe( framework.ExpectNoError(err) err = f.DevPodProviderUse(ctx, providerName) framework.ExpectNoError(err) - ginkgo.DeferCleanup(func() { - err = f.DevPodProviderDelete(context.Background(), providerName) + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + err := f.DevPodProviderDelete(cleanupCtx, providerName) framework.ExpectNoError(err) }) diff --git a/e2e/tests/up/handles_errors.go b/e2e/tests/up/handles_errors.go index 33ecb4a9e..c0bf7edce 100644 --- a/e2e/tests/up/handles_errors.go +++ b/e2e/tests/up/handles_errors.go @@ -32,8 +32,8 @@ var _ = ginkgo.Describe( err = f.DevPodProviderAdd(ctx, "docker", "--name", "test-docker") framework.ExpectNoError(err) - ginkgo.DeferCleanup(func() { - err = f.DevPodProviderDelete(context.Background(), "test-docker") + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + err := f.DevPodProviderDelete(cleanupCtx, "test-docker") framework.ExpectNoError(err) }) @@ -68,8 +68,8 @@ var _ = ginkgo.Describe( func(ctx context.Context) { f, err := setupDockerProvider(initialDir+"/bin", "docker") framework.ExpectNoError(err) - ginkgo.DeferCleanup(func() { - _ = f.DevPodProviderDelete(context.Background(), "docker") + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + _ = f.DevPodProviderDelete(cleanupCtx, "docker") }) initialList, err := f.DevPodList(ctx) @@ -90,8 +90,8 @@ var _ = ginkgo.Describe( func(ctx context.Context) { f, err := setupDockerProvider(initialDir+"/bin", "docker") framework.ExpectNoError(err) - ginkgo.DeferCleanup(func() { - _ = f.DevPodProviderDelete(context.Background(), "docker") + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + _ = f.DevPodProviderDelete(cleanupCtx, "docker") }) tempDir, err := framework.CopyToTempDir( diff --git a/e2e/tests/up/helper.go b/e2e/tests/up/helper.go index 34c6bce12..c4452be1b 100644 --- a/e2e/tests/up/helper.go +++ b/e2e/tests/up/helper.go @@ -101,10 +101,7 @@ func setupWorkspace(testdataPath, initialDir string, f *framework.Framework) (st } func setupDockerProvider(binDir, dockerPath string) (*framework.Framework, error) { - f := framework.NewDefaultFramework(binDir) - _ = f.DevPodProviderDelete(context.Background(), "docker") - _ = f.DevPodProviderAdd(context.Background(), "docker", "-o", "DOCKER_PATH="+dockerPath) - return f, f.DevPodProviderUse(context.Background(), "docker") + return framework.SetupDockerProvider(binDir, dockerPath) } func setupWorkspaceAndUp( diff --git a/e2e/tests/up/provider_docker.go b/e2e/tests/up/provider_docker.go index a9c1381ac..4903ae32c 100644 --- a/e2e/tests/up/provider_docker.go +++ b/e2e/tests/up/provider_docker.go @@ -8,6 +8,7 @@ import ( "path/filepath" "runtime" "strings" + "time" "github.com/docker/docker/api/types/container" "github.com/onsi/ginkgo/v2" @@ -76,7 +77,7 @@ var _ = ginkgo.Describe( var containerDetails []container.InspectResponse err = dtc.dockerHelper.Inspect(ctx, ids, "container", &containerDetails) return err == nil && containerDetails[0].State.Running - }).Should(gomega.BeTrue()) + }).WithTimeout(30 * time.Second).WithPolling(1 * time.Second).Should(gomega.BeTrue()) ginkgo.DeferCleanup(dtc.dockerHelper.Remove, ids[0]) ginkgo.DeferCleanup(dtc.dockerHelper.Stop, ids[0]) diff --git a/e2e/tests/up/provider_kubernetes.go b/e2e/tests/up/provider_kubernetes.go index 7bc818233..860ed4384 100644 --- a/e2e/tests/up/provider_kubernetes.go +++ b/e2e/tests/up/provider_kubernetes.go @@ -65,8 +65,8 @@ var _ = ginkgo.Describe( _ = f.DevPodProviderDelete(ctx, "kubernetes") err = f.DevPodProviderAdd(ctx, "kubernetes", "-o", "KUBERNETES_NAMESPACE=devpod") framework.ExpectNoError(err) - ginkgo.DeferCleanup(func() { - err = f.DevPodProviderDelete(context.Background(), "kubernetes") + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + err := f.DevPodProviderDelete(cleanupCtx, "kubernetes") framework.ExpectNoError(err) }) diff --git a/e2e/tests/up/provider_podman.go b/e2e/tests/up/provider_podman.go index 20dd38692..fa8e475c6 100644 --- a/e2e/tests/up/provider_podman.go +++ b/e2e/tests/up/provider_podman.go @@ -50,10 +50,11 @@ var _ = ginkgo.Describe( wrapper, err := os.Create(initialDir + "/bin/podman-rootful") framework.ExpectNoError(err) - defer func() { _ = wrapper.Close() }() - _, err = wrapper.WriteString("#!/bin/sh\nsudo podman \"$@\"\n") - framework.ExpectNoError(err) + if err != nil { + _ = wrapper.Close() + framework.ExpectNoError(err) + } err = wrapper.Close() framework.ExpectNoError(err) diff --git a/e2e/tests/up/up.go b/e2e/tests/up/up.go index 6da87d6ed..be5c77981 100644 --- a/e2e/tests/up/up.go +++ b/e2e/tests/up/up.go @@ -33,7 +33,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-workspaces"), fun framework.ExpectNoError(err) name := "vscode-remote-try-python" - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), name) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, name) // Wait for devpod workspace to come online (deadline: 30s) err = f.DevPodUp(ctx, "https://github.com/microsoft/vscode-remote-try-python.git") @@ -75,7 +75,7 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-workspaces"), fun // set env vars with file tmpDir, err := framework.CreateTempDir() framework.ExpectNoError(err) - defer func() { _ = os.RemoveAll(tmpDir) }() + ginkgo.DeferCleanup(func() { _ = os.RemoveAll(tmpDir) }) // create invalid env file invalidData := []byte("TEST VAR=" + value) @@ -156,8 +156,8 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-workspaces"), fun framework.ExpectNoError(err) err = f.DevPodProviderUse(ctx, providerName) framework.ExpectNoError(err) - ginkgo.DeferCleanup(func() { - err = f.DevPodProviderDelete(context.Background(), providerName) + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + err := f.DevPodProviderDelete(cleanupCtx, providerName) framework.ExpectNoError(err) }) @@ -203,8 +203,8 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-workspaces"), fun framework.ExpectNoError(err) err = f.DevPodProviderUse(ctx, providerName) framework.ExpectNoError(err) - ginkgo.DeferCleanup(func() { - err = f.DevPodProviderDelete(context.Background(), providerName) + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + err := f.DevPodProviderDelete(cleanupCtx, providerName) framework.ExpectNoError(err) }) @@ -229,8 +229,8 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-workspaces"), fun framework.ExpectNoError(err) err = f.DevPodProviderUse(ctx, providerName) framework.ExpectNoError(err) - ginkgo.DeferCleanup(func() { - err = f.DevPodProviderDelete(context.Background(), providerName) + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + err := f.DevPodProviderDelete(cleanupCtx, providerName) framework.ExpectNoError(err) }) @@ -268,8 +268,8 @@ var _ = ginkgo.Describe("testing up command", ginkgo.Label("up-workspaces"), fun framework.ExpectNoError(err) err = f.DevPodProviderUse(ctx, providerName) framework.ExpectNoError(err) - ginkgo.DeferCleanup(func() { - err = f.DevPodProviderDelete(context.Background(), providerName) + ginkgo.DeferCleanup(func(cleanupCtx context.Context) { + err := f.DevPodProviderDelete(cleanupCtx, providerName) framework.ExpectNoError(err) }) diff --git a/e2e/tests/up/up_private_token.go b/e2e/tests/up/up_private_token.go index 33cb8866b..b72524d2a 100644 --- a/e2e/tests/up/up_private_token.go +++ b/e2e/tests/up/up_private_token.go @@ -25,24 +25,28 @@ var _ = ginkgo.Describe( ginkgo.It("should allow checkout of a private GitRepo", func(ctx context.Context) { username := os.Getenv("GH_USERNAME") token := os.Getenv("GH_ACCESS_TOKEN") + if username == "" || token == "" { + ginkgo.Skip("GH_USERNAME and GH_ACCESS_TOKEN must be set") + } f, err := setupDockerProvider(initialDir+"/bin", "docker") framework.ExpectNoError(err) + // Register credential cleanup before writing to ensure cleanup on any failure + credentialPath := filepath.Join(os.Getenv("HOME"), ".git-credentials") + ginkgo.DeferCleanup(func() { _ = os.Remove(credentialPath) }) + // setup git credentials err = exec.Command("git", []string{"config", "--global", "credential.helper", "store"}...). Run() framework.ExpectNoError(err) gitCredentialString := []byte("https://" + username + ":" + token + "@github.com") - err = os.WriteFile( - filepath.Join(os.Getenv("HOME"), ".git-credentials"), - gitCredentialString, 0o600) + err = os.WriteFile(credentialPath, gitCredentialString, 0o600) framework.ExpectNoError(err) - defer func() { _ = os.Remove(filepath.Join(os.Getenv("HOME"), ".git-credentials")) }() name := "testprivaterepo" - ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), name) + ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, name) err = f.DevPodUp(ctx, "https://github.com/"+username+"/test_private_repo.git") framework.ExpectNoError(err) diff --git a/e2e/tests/upgrade/upgrade.go b/e2e/tests/upgrade/upgrade.go index b97b71138..afbf6845f 100644 --- a/e2e/tests/upgrade/upgrade.go +++ b/e2e/tests/upgrade/upgrade.go @@ -14,6 +14,7 @@ import ( var _ = ginkgo.Describe("testing upgrade command", ginkgo.Label("upgrade"), ginkgo.Ordered, func() { ginkgo.It( "should detect correct binary for current OS and architecture using dry-run", + ginkgo.SpecTimeout(framework.GetTimeout()), func(ctx context.Context) { initialDir, err := os.Getwd() framework.ExpectNoError(err, "getting current working directory should not error")