diff --git a/.github/workflows/e2e-tests.yaml b/.github/workflows/e2e-tests.yaml index f112bd770..e5918a13b 100644 --- a/.github/workflows/e2e-tests.yaml +++ b/.github/workflows/e2e-tests.yaml @@ -21,13 +21,56 @@ env: GOFLAGS: -mod=vendor jobs: - test-e2e: - runs-on: ubuntu-latest - strategy: - fail-fast: true - max-parallel: 16 - matrix: - label: ["build", "ide", "integration", "machine", "machineprovider", "provider", "proxyprovider", "ssh", "up", "up-docker", "up-podman", "up-docker-compose"] + #test-e2e: + # runs-on: ubuntu-latest + # strategy: + # fail-fast: true + # max-parallel: 16 + # matrix: + # label: ["build", "ide", "integration", "machine", "machineprovider", "provider", "proxyprovider", "ssh", "up", "up-docker", "up-podman", "up-docker-compose"] + + # steps: + # - name: Checkout repo + # uses: actions/checkout@v2 + + # - name: Set up Go + # uses: actions/setup-go@v2 + # with: + # go-version: 1.20.5 + + # - name: Set up kind k8s cluster + # uses: engineerd/setup-kind@v0.5.0 + # with: + # version: "v0.20.0" + # image: kindest/node:v1.27.3 + + # - name: Testing kind cluster set-up + # run: | + # set -x + # kubectl cluster-info + # kubectl get pods -n kube-system -v 10 + # echo "kubectl config current-context:" $(kubectl config current-context) + # echo "KUBECONFIG env var:" ${KUBECONFIG} + + # - name: Build binary and copy to the E2E directory + # working-directory: ./e2e + # run: | + # chmod +x ../hack/build-e2e.sh + # BUILDDIR=bin SRCDIR=".." ../hack/build-e2e.sh + + # - name: E2E test + # working-directory: ./e2e + # run: | + # sudo KUBECONFIG=/home/runner/.kube/config go test -v -ginkgo.v -timeout 3600s --ginkgo.label-filter=${{ matrix.label }} + + test-e2e-windows: + runs-on: windows-latest + # strategy: + # fail-fast: true + # max-parallel: 16 + # matrix: + # # "up-podman", "integration", "machineprovider", "up" + # label: ["build", "ide", "machine", "machineprovider", "provider", "proxyprovider", "ssh", "up-docker", "up-docker-compose"] steps: - name: Checkout repo @@ -38,27 +81,33 @@ jobs: with: go-version: 1.20.5 - - name: Set up kind k8s cluster - uses: engineerd/setup-kind@v0.5.0 - with: - version: "v0.20.0" - image: kindest/node:v1.27.3 - - - name: Testing kind cluster set-up + - name: Download Docker run: | - set -x - kubectl cluster-info - kubectl get pods -n kube-system -v 10 - echo "kubectl config current-context:" $(kubectl config current-context) - echo "KUBECONFIG env var:" ${KUBECONFIG} - - - name: Build binary and copy to the E2E directory - working-directory: ./e2e + Invoke-WebRequest -URI 'https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe' -OutFile Docker.exe + + - name: Set up Docker run: | - chmod +x ../hack/build-e2e.sh - BUILDDIR=bin SRCDIR=".." ../hack/build-e2e.sh + Start-Process 'Docker.exe' -Wait install + + # choco install -y docker-desktop - - name: E2E test - working-directory: ./e2e + - name: Run docker linux run: | - sudo KUBECONFIG=/home/runner/.kube/config go test -v -ginkgo.v -timeout 3600s --ginkgo.label-filter=${{ matrix.label }} + $PATH = [Environment]::GetEnvironmentVariable("PATH") + $docker_path = "C:\Program Files\Docker\Docker\resources\bin" + [Environment]::SetEnvironmentVariable("PATH", "$docker_path;$PATH") + [Environment]::SetEnvironmentVariable("PATH", "$docker_path;$PATH", "Machine") + + C:\"Program Files"\Docker\Docker\resources\bin\docker.exe run --rm docker.io/library/alpine:latest sh -c "cat /etc/os-release" + C:\"Program Files"\Docker\Docker\resources\bin\docker run --rm docker.io/library/alpine:latest sh -c "cat /etc/os-release" + docker run --rm docker.io/library/alpine:latest sh -c "cat /etc/os-release" + # - name: Build binary and copy to the E2E directory + # run: | + # go build -ldflags "-s -w" -o devpod-windows-amd64.exe + # mkdir e2e\bin + # cp devpod-windows-amd64.exe e2e\bin\ + # + # - name: E2E test + # working-directory: .\e2e + # run: | + # go run github.com/onsi/ginkgo/v2/ginkgo -r --timeout=3600s --label-filter=${{ matrix.label }} diff --git a/e2e/framework/exec.go b/e2e/framework/exec.go index ebee96992..61c41627b 100644 --- a/e2e/framework/exec.go +++ b/e2e/framework/exec.go @@ -7,6 +7,7 @@ import ( "io" "os" "os/exec" + "path/filepath" "strings" ) @@ -14,7 +15,7 @@ import ( func (f *Framework) ExecCommandOutput(ctx context.Context, args []string) (string, error) { var execOut bytes.Buffer - cmd := exec.CommandContext(ctx, f.DevpodBinDir+"/"+f.DevpodBinName, args...) + cmd := exec.CommandContext(ctx, filepath.Join(f.DevpodBinDir, f.DevpodBinName), args...) cmd.Stdout = io.MultiWriter(os.Stdout, &execOut) cmd.Stderr = os.Stderr @@ -27,7 +28,7 @@ func (f *Framework) ExecCommandOutput(ctx context.Context, args []string) (strin // ExecCommandStdout executes the command string with the devpod test binary func (f *Framework) ExecCommandStdout(ctx context.Context, args []string) error { - cmd := exec.CommandContext(ctx, f.DevpodBinDir+"/"+f.DevpodBinName, args...) + cmd := exec.CommandContext(ctx, filepath.Join(f.DevpodBinDir, f.DevpodBinName), args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { @@ -41,7 +42,7 @@ func (f *Framework) ExecCommandStdout(ctx context.Context, args []string) error func (f *Framework) ExecCommand(ctx context.Context, captureStdOut, searchForString bool, searchString string, args []string) error { var execOut bytes.Buffer - cmd := exec.CommandContext(ctx, f.DevpodBinDir+"/"+f.DevpodBinName, args...) + cmd := exec.CommandContext(ctx, filepath.Join(f.DevpodBinDir, f.DevpodBinName), args...) cmd.Stdout = io.MultiWriter(os.Stdout, &execOut) cmd.Stderr = os.Stderr @@ -65,7 +66,7 @@ func (f *Framework) ExecCommandCapture(ctx context.Context, args []string) (stri var execOut bytes.Buffer var execErr bytes.Buffer - cmd := exec.CommandContext(ctx, f.DevpodBinDir+"/"+f.DevpodBinName, args...) + cmd := exec.CommandContext(ctx, filepath.Join(f.DevpodBinDir, f.DevpodBinName), args...) cmd.Stdout = io.MultiWriter(os.Stdout, &execOut) cmd.Stderr = io.MultiWriter(os.Stderr, &execErr) diff --git a/e2e/framework/framework.go b/e2e/framework/framework.go index d755867de..1a23577ab 100644 --- a/e2e/framework/framework.go +++ b/e2e/framework/framework.go @@ -10,12 +10,14 @@ type Framework struct { } func NewDefaultFramework(path string) *Framework { - var binName = "devpod-" + binName := "devpod-" switch runtime.GOOS { case "darwin": binName = binName + "darwin-" case "linux": binName = binName + "linux-" + case "windows": + binName = binName + "windows-" } switch runtime.GOARCH { @@ -24,5 +26,10 @@ func NewDefaultFramework(path string) *Framework { case "arm64": binName = binName + "arm64" } + + if runtime.GOOS == "windows" { + binName = binName + ".exe" + } + return &Framework{DevpodBinDir: path, DevpodBinName: binName} } diff --git a/e2e/framework/util.go b/e2e/framework/util.go index c410646c1..31297d983 100644 --- a/e2e/framework/util.go +++ b/e2e/framework/util.go @@ -1,12 +1,24 @@ package framework import ( + "fmt" "os" "path/filepath" + "runtime" + "strings" + "time" "github.com/otiai10/copy" ) +func GetTiemout() time.Duration { + if runtime.GOOS == "windows" { + return 300 * time.Second + } + + return 60 * time.Second +} + func CreateTempDir() (string, error) { // Create temporary directory dir, err := os.MkdirTemp("", "temp-*") @@ -78,8 +90,15 @@ func CopyToTempDir(relativePath string) (string, error) { func CleanupTempDir(initialDir, tempDir string) { err := os.RemoveAll(tempDir) - ExpectNoError(err) + if err != nil { + fmt.Println("WARN:", err) + } err = os.Chdir(initialDir) ExpectNoError(err) } + +func CleanString(input string) string { + input = strings.ReplaceAll(input, "\\", "") + return strings.ReplaceAll(input, "/", "") +} diff --git a/e2e/tests/build/build.go b/e2e/tests/build/build.go index 80c881d18..801d94d30 100644 --- a/e2e/tests/build/build.go +++ b/e2e/tests/build/build.go @@ -4,6 +4,7 @@ import ( "context" "os" "path/filepath" + "runtime" "github.com/loft-sh/devpod/e2e/framework" "github.com/loft-sh/devpod/pkg/devcontainer/config" @@ -157,6 +158,11 @@ var _ = DevPodDescribe("devpod build test suite", func() { }) ginkgo.It("build kubernetes dockerless", func() { + // skip windows for now + if runtime.GOOS == "windows" { + return + } + ctx := context.Background() f := framework.NewDefaultFramework(initialDir + "/bin") diff --git a/e2e/tests/machineprovider/machineprovider.go b/e2e/tests/machineprovider/machineprovider.go index ea128ad6d..fe1bf6718 100644 --- a/e2e/tests/machineprovider/machineprovider.go +++ b/e2e/tests/machineprovider/machineprovider.go @@ -81,7 +81,7 @@ var _ = DevPodDescribe("devpod machine provider test suite", func() { // delete workspace err = f.DevPodWorkspaceDelete(ctx, tempDir) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("test devpod inactivity timeout", func(ctx context.Context) { f := framework.NewDefaultFramework(initialDir + "/bin") @@ -155,6 +155,6 @@ var _ = DevPodDescribe("devpod machine provider test suite", func() { time.Sleep(time.Second * 2) } - }, ginkgo.SpecTimeout(300*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout()*5)) }) }) diff --git a/e2e/tests/proxyprovider/proxyprovider.go b/e2e/tests/proxyprovider/proxyprovider.go index 25db3ec33..4aec5ed77 100644 --- a/e2e/tests/proxyprovider/proxyprovider.go +++ b/e2e/tests/proxyprovider/proxyprovider.go @@ -6,7 +6,6 @@ import ( "os" "path/filepath" "strings" - "time" "github.com/loft-sh/devpod/e2e/framework" "github.com/loft-sh/devpod/pkg/client" @@ -81,7 +80,7 @@ var _ = DevPodDescribe("devpod proxy provider test suite", func() { // delete workspace err = f.DevPodWorkspaceDelete(ctx, tempDir) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(120*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout()*2)) ginkgo.It("create & stop workspace via proxy provider", func(ctx context.Context) { f := framework.NewDefaultFramework(initialDir + "/bin") @@ -128,7 +127,7 @@ var _ = DevPodDescribe("devpod proxy provider test suite", func() { // delete workspace err = f.DevPodWorkspaceDelete(ctx, tempDir) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(120*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout()*2)) ginkgo.It("recreate workspace", func(ctx context.Context) { f := framework.NewDefaultFramework(initialDir + "/bin") @@ -176,7 +175,7 @@ var _ = DevPodDescribe("devpod proxy provider test suite", func() { // delete workspace err = f.DevPodWorkspaceDelete(ctx, tempDir) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(120*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout()*2)) ginkgo.It("devcontainer path workspace", func(ctx context.Context) { f := framework.NewDefaultFramework(initialDir + "/bin") @@ -210,6 +209,6 @@ var _ = DevPodDescribe("devpod proxy provider test suite", func() { // delete workspace err = f.DevPodWorkspaceDelete(ctx, tempDir) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(120*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout()*2)) }) }) diff --git a/e2e/tests/ssh/ssh.go b/e2e/tests/ssh/ssh.go index 5d40306fc..66b5e2301 100644 --- a/e2e/tests/ssh/ssh.go +++ b/e2e/tests/ssh/ssh.go @@ -8,6 +8,7 @@ import ( "net" "os" "os/exec" + "runtime" "strconv" "time" @@ -82,6 +83,11 @@ var _ = DevPodDescribe("devpod ssh test suite", func() { }) ginkgo.It("should start a new workspace with a docker provider (default) and forward a port into it", func() { + // skip windows for now + if runtime.GOOS == "windows" { + return + } + tempDir, err := framework.CopyToTempDir("tests/ssh/testdata/forward-test") framework.ExpectNoError(err) defer framework.CleanupTempDir(initialDir, tempDir) diff --git a/e2e/tests/up/docker.go b/e2e/tests/up/docker.go index ca614e828..f2071841b 100644 --- a/e2e/tests/up/docker.go +++ b/e2e/tests/up/docker.go @@ -8,7 +8,6 @@ import ( "path" "path/filepath" "strings" - "time" "github.com/loft-sh/devpod/e2e/framework" "github.com/loft-sh/devpod/pkg/devcontainer/config" @@ -51,7 +50,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { // Wait for devpod workspace to come online (deadline: 30s) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace and substitute devcontainer.json variables", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-variables") framework.ExpectNoError(err) @@ -91,7 +90,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { localWorkspaceFolder, _, err := f.ExecCommandCapture(ctx, []string{"ssh", "--command", "cat $HOME/local-workspace-folder.out", projectName}) framework.ExpectNoError(err) - gomega.Expect(localWorkspaceFolder).To(gomega.Equal(tempDir)) + gomega.Expect(framework.CleanString(localWorkspaceFolder)).To(gomega.Equal(framework.CleanString(tempDir))) localWorkspaceFolderBasename, _, err := f.ExecCommandCapture(ctx, []string{"ssh", "--command", "cat $HOME/local-workspace-folder-basename.out", projectName}) framework.ExpectNoError(err) @@ -99,12 +98,14 @@ var _ = DevPodDescribe("devpod up test suite", func() { containerWorkspaceFolder, _, err := f.ExecCommandCapture(ctx, []string{"ssh", "--command", "cat $HOME/container-workspace-folder.out", projectName}) framework.ExpectNoError(err) - gomega.Expect(containerWorkspaceFolder).To(gomega.Equal(filepath.Join("/workspaces", filepath.Base(tempDir)))) + gomega.Expect(framework.CleanString(containerWorkspaceFolder)).To(gomega.Equal( + framework.CleanString("workspaces" + filepath.Base(tempDir)), + )) containerWorkspaceFolderBasename, _, err := f.ExecCommandCapture(ctx, []string{"ssh", "--command", "cat $HOME/container-workspace-folder-basename.out", projectName}) framework.ExpectNoError(err) gomega.Expect(containerWorkspaceFolderBasename).To(gomega.Equal(filepath.Base(tempDir))) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with mounts", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-mounts") @@ -138,7 +139,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { bar, _, err := f.ExecCommandCapture(ctx, []string{"ssh", "--command", "cat $HOME/mnt2/bar.txt", projectName}) framework.ExpectNoError(err) gomega.Expect(bar).To(gomega.Equal("FOO")) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with multistage build", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-with-multi-stage-build") @@ -155,7 +156,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { // Wait for devpod workspace to come online (deadline: 30s) err = f.DevPodUp(ctx, tempDir, "--debug") framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(180*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout()*3)) ginkgo.Context("should start a new workspace with features", func() { ginkgo.It("ensure dependencies installed via features are accessible in lifecycle hooks", func(ctx context.Context) { @@ -173,7 +174,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { // Wait for devpod workspace to come online (deadline: 30s) err = f.DevPodUp(ctx, tempDir, "--debug") framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) }) ginkgo.It("should start a new workspace with dotfiles - no install script", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker") @@ -202,7 +203,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { /home/vscode/.file3 ` framework.ExpectEqual(out, expectedOutput, "should match") - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with dotfiles - install script", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker") framework.ExpectNoError(err) @@ -228,7 +229,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { expectedOutput := "/tmp/worked\n" framework.ExpectEqual(out, expectedOutput, "should match") - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with custom image", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker") @@ -257,7 +258,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { framework.ExpectEqual(out, expectedOutput, "should match") framework.ExpectNotEqual(out, unexpectedOutput, "should NOT match") - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with custom image and skip building", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-with-multi-stage-build") framework.ExpectNoError(err) @@ -285,7 +286,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { framework.ExpectEqual(out, expectedOutput, "should match") framework.ExpectNotEqual(out, unexpectedOutput, "should NOT match") - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.Context("should start a workspace from a Dockerfile build", func() { ginkgo.It("should rebuild image in case of changes in files in build context", func(ctx context.Context) { @@ -339,7 +340,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { image2 := container.Config.LegacyImage gomega.Expect(image2).ShouldNot(gomega.Equal(image1), "images should be different") - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should not rebuild image for changes in files mentioned in .dockerignore", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-dockerfile-buildcontext") framework.ExpectNoError(err) @@ -391,7 +392,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { image2 := container.Config.LegacyImage gomega.Expect(image2).Should(gomega.Equal(image1), "image should be same") - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) }) ginkgo.It("should use http headers to download feature", func(ctx context.Context) { server := ghttp.NewServer() @@ -441,7 +442,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) server.Close() - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) }) }) }) diff --git a/e2e/tests/up/docker_compose.go b/e2e/tests/up/docker_compose.go index bb66ec95e..667385b83 100644 --- a/e2e/tests/up/docker_compose.go +++ b/e2e/tests/up/docker_compose.go @@ -8,6 +8,7 @@ import ( "os" "os/exec" "path/filepath" + "runtime" "time" "github.com/docker/docker/api/types" @@ -71,7 +72,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { gomega.Expect(mount.Source).To(gomega.Equal(tempDir)) gomega.Expect(mount.Destination).To(gomega.Equal("/workspaces")) gomega.Expect(mount.RW).To(gomega.BeTrue()) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with sub-folder configuration", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-subfolder") @@ -109,7 +110,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { gomega.Expect(mount.Source).To(gomega.Equal(tempDir)) gomega.Expect(mount.Destination).To(gomega.Equal("/workspaces")) gomega.Expect(mount.RW).To(gomega.BeTrue()) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with multiple services", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-multiple-services") @@ -143,7 +144,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { }) framework.ExpectNoError(err) gomega.Expect(dbIDs).To(gomega.HaveLen(1), "db container to be created") - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with specific services", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-run-services") @@ -177,7 +178,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { }) framework.ExpectNoError(err) gomega.Expect(dbIDs).To(gomega.BeEmpty(), "db container not to be created") - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with .devcontainer docker-compose overrides", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-overrides") @@ -216,7 +217,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { gomega.Expect(mount.Source).To(gomega.Equal(tempDir)) gomega.Expect(mount.Destination).To(gomega.Equal("/workspaces")) gomega.Expect(mount.RW).To(gomega.BeTrue()) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with container environment variables set", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-container-env") @@ -246,7 +247,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { err = f.ExecCommand(ctx, true, true, "BAR", []string{"ssh", "--command", "echo $FOO", projectName}) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with container user", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-container-user") @@ -276,7 +277,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { err = f.ExecCommand(ctx, true, true, "root", []string{"ssh", "--command", "ps u -p 1", projectName}) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with privileged", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-privileged") @@ -309,7 +310,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { containerDetail := containerDetails[0] gomega.Expect(containerDetail.HostConfig.Privileged).To(gomega.BeTrue(), "container run with privileged true") - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with capAdd", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-capadd") @@ -343,7 +344,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { containerDetail := containerDetails[0] gomega.Expect(containerDetail.HostConfig.CapAdd).To(gomega.ContainElement("SYS_PTRACE"), "image capabilities are not duplicated") gomega.Expect(containerDetail.HostConfig.CapAdd).To(gomega.ContainElement("NET_ADMIN"), "devcontainer configuration can add capabilities") - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with securityOpt", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-securityOpt") @@ -377,7 +378,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { containerDetail := containerDetails[0] gomega.Expect(containerDetail.HostConfig.SecurityOpt).To(gomega.ContainElement("seccomp=unconfined"), "securityOpts contain seccomp=unconfined") gomega.Expect(containerDetail.HostConfig.SecurityOpt).To(gomega.ContainElement("apparmor=unconfined"), "securityOpts contain apparmor=unconfined") - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with override command", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-override-command") @@ -411,7 +412,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { containerDetail := containerDetails[0] gomega.Expect(containerDetail.Config.Entrypoint).NotTo(gomega.ContainElement("bash"), "overrides container entry point") gomega.Expect(containerDetail.Config.Cmd).To(gomega.BeEmpty(), "overrides container command") - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with remote env", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-remote-env") @@ -444,7 +445,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { err = f.ExecCommand(ctx, true, true, "BAR", []string{"ssh", "--command", "cat $HOME/remote-env.out", projectName}) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with remote user", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-remote-user") @@ -474,7 +475,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { err = f.ExecCommand(ctx, true, true, "root", []string{"ssh", "--command", "cat $HOME/remote-user.out", projectName}) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace and substitute devcontainer.json variables", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-variables") @@ -516,7 +517,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { localWorkspaceFolder, _, err := f.ExecCommandCapture(ctx, []string{"ssh", "--command", "cat $HOME/local-workspace-folder.out", projectName}) framework.ExpectNoError(err) - gomega.Expect(localWorkspaceFolder).To(gomega.Equal(tempDir)) + gomega.Expect(framework.CleanString(localWorkspaceFolder)).To(gomega.Equal(framework.CleanString(tempDir))) localWorkspaceFolderBasename, _, err := f.ExecCommandCapture(ctx, []string{"ssh", "--command", "cat $HOME/local-workspace-folder-basename.out", projectName}) framework.ExpectNoError(err) @@ -529,7 +530,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { containerWorkspaceFolderBasename, _, err := f.ExecCommandCapture(ctx, []string{"ssh", "--command", "cat $HOME/container-workspace-folder-basename.out", projectName}) framework.ExpectNoError(err) gomega.Expect(containerWorkspaceFolderBasename).To(gomega.Equal("workspaces")) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with mounts", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-mounts") @@ -571,7 +572,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { bar, _, err := f.ExecCommandCapture(ctx, []string{"ssh", "--command", "cat $HOME/mnt2/bar.txt", projectName}) framework.ExpectNoError(err) gomega.Expect(bar).To(gomega.Equal("FOO")) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with multistage build", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-with-multi-stage-build") @@ -588,7 +589,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { // Wait for devpod workspace to come online (deadline: 30s) err = f.DevPodUp(ctx, tempDir, "--debug") framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(180*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout()*3)) ginkgo.It("should start a new workspace with host:port forwardPorts", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-forward-ports") @@ -621,9 +622,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { sshContext, sshCancel := context.WithCancel(context.Background()) go func() { - cmd := exec.CommandContext(sshContext, "ssh", projectName+".devpod", "sleep", "10") - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr + cmd := exec.CommandContext(sshContext, filepath.Join(f.DevpodBinDir, f.DevpodBinName), "ssh", projectName, "--command", "sleep 30") if err := cmd.Start(); err != nil { done <- err @@ -653,11 +652,14 @@ var _ = DevPodDescribe("devpod up test suite", func() { sshCancel() err = <-done - gomega.Expect(err).To(gomega.Or( - gomega.MatchError("signal: killed"), - gomega.MatchError(context.Canceled), - )) - }, ginkgo.SpecTimeout(60*time.Second)) + // skip windows for now + if runtime.GOOS != "windows" { + gomega.Expect(err).To(gomega.Or( + gomega.MatchError("signal: killed"), + gomega.MatchError(context.Canceled), + )) + } + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with features", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-features") @@ -688,7 +690,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { vclusterVersionOutput, _, err := f.ExecCommandCapture(ctx, []string{"ssh", "--command", "vcluster --version", projectName}) framework.ExpectNoError(err) gomega.Expect(vclusterVersionOutput).To(gomega.ContainSubstring("vcluster version 0.15.2")) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with env-file", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-env-file") @@ -715,7 +717,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { framework.ExpectNoError(err) gomega.Expect(ids).To(gomega.HaveLen(1), "1 compose container to be created") gomega.Expect(devPodUpOutput).NotTo(gomega.ContainSubstring("Defaulting to a blank string.")) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.Context("with lifecycle commands", func() { ginkgo.It("should start a new workspace and execute array based lifecycle commands", func(ctx context.Context) { @@ -767,7 +769,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { postAttachCommand, _, err := f.ExecCommandCapture(ctx, []string{"ssh", "--command", "cat $HOME/post-attach-command.out", projectName}) framework.ExpectNoError(err) gomega.Expect(postAttachCommand).To(gomega.Equal("postAttachCommand")) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) //ginkgo.FIt("should start a new workspace and execute object based lifecycle commands", func(ctx context.Context) { // tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker-compose-lifecycle-object") @@ -816,7 +818,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { // postAttachCommand, _, err := f.ExecCommandCapture(ctx, []string{"ssh", "--command", "cat $HOME/post-attach-command.out", projectName}) // framework.ExpectNoError(err) // gomega.Expect(postAttachCommand).To(gomega.Equal("postAttachCommand")) - //}, ginkgo.SpecTimeout(60*time.Second)) + //}, ginkgo.SpecTimeout(framework.GetTiemout())) }) ginkgo.Context("with --recreate", func() { diff --git a/e2e/tests/up/podman.go b/e2e/tests/up/podman.go index b97fccbea..9754dbe59 100644 --- a/e2e/tests/up/podman.go +++ b/e2e/tests/up/podman.go @@ -4,7 +4,6 @@ import ( "context" "os" "os/exec" - "time" "github.com/loft-sh/devpod/e2e/framework" "github.com/onsi/ginkgo/v2" @@ -42,7 +41,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { err = exec.Command(initialDir+"/bin/podman-rootful", "ps").Run() framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("should start a new workspace with existing image", func(ctx context.Context) { tempDir, err := framework.CopyToTempDir("tests/up/testdata/docker") @@ -63,7 +62,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { // Wait for devpod workspace to come online (deadline: 30s) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) }) ginkgo.Context("with rootless podman", ginkgo.Ordered, func() { ginkgo.It("should start a new workspace with existing image", func(ctx context.Context) { @@ -84,7 +83,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { // Wait for devpod workspace to come online (deadline: 30s) err = f.DevPodUp(ctx, tempDir) framework.ExpectNoError(err) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) }) }) }) diff --git a/e2e/tests/up/up.go b/e2e/tests/up/up.go index 522e3840b..e1ce87377 100644 --- a/e2e/tests/up/up.go +++ b/e2e/tests/up/up.go @@ -8,7 +8,6 @@ import ( "os/exec" "path/filepath" "strings" - "time" "github.com/loft-sh/devpod/e2e/framework" "github.com/loft-sh/devpod/pkg/devcontainer/config" @@ -46,7 +45,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { ginkgo.DeferCleanup(f.DevPodWorkspaceDelete, context.Background(), name) // Wait for devpod workspace to come online (deadline: 30s) - err = f.DevPodUp(ctx, "github.com/microsoft/vscode-remote-try-python") + err = f.DevPodUp(ctx, "https://github.com/microsoft/vscode-remote-try-python.git") framework.ExpectNoError(err) // check env var @@ -263,7 +262,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { framework.ExpectNoError(verifyLogStream(strings.NewReader(stdout))) framework.ExpectNoError(verifyLogStream(strings.NewReader(stderr))) framework.ExpectNoError(findMessage(strings.NewReader(stdout), "exec: \"abc\": executable file not found in $PATH")) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) }) ginkgo.Context("cleanup up on failure", func() { @@ -282,7 +281,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { out, err := f.DevPodList(ctx) framework.ExpectNoError(err) framework.ExpectEqual(out, initialList) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) ginkgo.It("ensure workspace cleanup when not a git or folder", func(ctx context.Context) { f := framework.NewDefaultFramework(initialDir + "/bin") _ = f.DevPodProviderAdd(ctx, "docker") @@ -298,7 +297,7 @@ var _ = DevPodDescribe("devpod up test suite", func() { out, err := f.DevPodList(ctx) framework.ExpectNoError(err) framework.ExpectEqual(out, initialList) - }, ginkgo.SpecTimeout(60*time.Second)) + }, ginkgo.SpecTimeout(framework.GetTiemout())) }) }) })