From 8f0ff4fb6c7dfe1345e8537f4d23395b317cc816 Mon Sep 17 00:00:00 2001 From: Nico Berlee Date: Wed, 10 Jul 2024 09:10:19 +0200 Subject: [PATCH] chore: refactor wait.Poll* to wait.PollUntilContext Signed-off-by: Nico Berlee --- e2e/framework/helper.go | 18 ++++++------- e2e/tests/dependencies/dependencies.go | 8 +++--- e2e/tests/devspacehelper/inject.go | 11 ++++---- e2e/tests/hooks/hooks.go | 11 ++++---- e2e/tests/proxycommands/proxycommands.go | 4 +-- e2e/tests/replacepods/replacepods.go | 27 ++++++++++--------- e2e/tests/sync/sync.go | 12 ++++----- e2e/tests/terminal/terminal.go | 19 ++++++------- helper/util/restart_linux.go | 3 ++- pkg/devspace/analyze/analyze.go | 6 +++-- pkg/devspace/build/builder/kaniko/kaniko.go | 13 ++++----- .../build/localregistry/deployment.go | 6 ++--- .../build/localregistry/local_registry.go | 6 +++-- pkg/devspace/build/localregistry/service.go | 2 +- .../build/localregistry/statefulset.go | 2 +- pkg/devspace/config/remotecache/schema.go | 2 +- pkg/devspace/devpod/devpod.go | 9 ++++--- pkg/devspace/hook/wait.go | 7 ++--- pkg/devspace/kubectl/client.go | 11 ++++---- pkg/devspace/pipeline/pipeline.go | 2 +- pkg/devspace/pullsecrets/init.go | 7 ++--- pkg/devspace/pullsecrets/registry.go | 7 ++--- pkg/devspace/services/podreplace/replace.go | 5 ++-- .../targetselector/target_selector.go | 7 ++--- .../client-go/transport/cert_rotation.go | 11 ++++++-- 25 files changed, 120 insertions(+), 96 deletions(-) diff --git a/e2e/framework/helper.go b/e2e/framework/helper.go index 40ed181a60..8e845cc6b9 100644 --- a/e2e/framework/helper.go +++ b/e2e/framework/helper.go @@ -66,8 +66,8 @@ func ExpectNamespace(namespace string) { kubeClient, err := kube.NewKubeHelper() ExpectNoErrorWithOffset(1, err) - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { - ns, err := kubeClient.Client().KubeClient().CoreV1().Namespaces().Get(context.TODO(), namespace, metav1.GetOptions{}) + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(ctx context.Context) (done bool, err error) { + ns, err := kubeClient.Client().KubeClient().CoreV1().Namespaces().Get(ctx, namespace, metav1.GetOptions{}) if err != nil { return false, nil } @@ -81,7 +81,7 @@ func ExpectRemoteFileContents(imageSelector string, namespace string, filePath s kubeClient, err := kube.NewKubeHelper() ExpectNoErrorWithOffset(1, err) - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { out, err := kubeClient.ExecByImageSelector(imageSelector, namespace, []string{"cat", filePath}) if err != nil { return false, nil @@ -94,7 +94,7 @@ func ExpectRemoteFileContents(imageSelector string, namespace string, filePath s func ExpectLocalCurlContents(urlString string, contents string) { client := resty.New() - err := wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err := wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { resp, _ := client.R(). EnableTrace(). Get(urlString) @@ -106,7 +106,7 @@ func ExpectLocalCurlContents(urlString string, contents string) { func ExpectContainerNameAndImageEqual(namespace, deploymentName, containerImage, containerName string) { kubeClient, err := kube.NewKubeHelper() ExpectNoErrorWithOffset(1, err) - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { deploy, err := kubeClient.RawClient().AppsV1().Deployments(namespace).Get(context.TODO(), deploymentName, metav1.GetOptions{}) if err != nil { @@ -121,7 +121,7 @@ func ExpectContainerNameAndImageEqual(namespace, deploymentName, containerImage, func ExpectRemoteCurlContents(imageSelector string, namespace string, urlString string, contents string) { kubeClient, err := kube.NewKubeHelper() ExpectNoErrorWithOffset(1, err) - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { out, err := kubeClient.ExecByImageSelector(imageSelector, namespace, []string{"curl", urlString}) if err != nil { return false, nil @@ -137,7 +137,7 @@ func ExpectRemoteFileNotFound(imageSelector string, namespace string, filePath s fileExists := "file exists" fileNotFound := "file not found" - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { test := []string{"sh", "-c", fmt.Sprintf("test -e %s && echo %s || echo %s", filePath, fileExists, fileNotFound)} out, err := kubeClient.ExecByImageSelector(imageSelector, namespace, test) if err != nil { @@ -159,7 +159,7 @@ func ExpectRemoteContainerFileContents(labelSelector, container string, namespac kubeClient, err := kube.NewKubeHelper() ExpectNoErrorWithOffset(1, err) - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { out, err := kubeClient.ExecByContainer(labelSelector, container, namespace, []string{"cat", filePath}) if err != nil { return false, nil @@ -182,7 +182,7 @@ func ExpectLocalFileContainSubstringImmediately(filePath string, contents string } func ExpectLocalFileContents(filePath string, contents string) { - err := wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err := wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { out, err := os.ReadFile(filePath) if err != nil { if !os.IsNotExist(err) { diff --git a/e2e/tests/dependencies/dependencies.go b/e2e/tests/dependencies/dependencies.go index 4f074a36ad..b33fd9f92c 100644 --- a/e2e/tests/dependencies/dependencies.go +++ b/e2e/tests/dependencies/dependencies.go @@ -492,8 +492,8 @@ dep2dep2wait // wait until a pod has started var pods *corev1.PodList - err = wait.Poll(time.Second, time.Minute, func() (done bool, err error) { - pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute, false, func(ctx context.Context) (done bool, err error) { + pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(ctx, metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) if err != nil { return false, err } @@ -515,8 +515,8 @@ dep2dep2wait framework.ExpectNoError(err) // wait until all pods are killed - err = wait.Poll(time.Second, time.Minute, func() (done bool, err error) { - pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute, false, func(ctx context.Context) (done bool, err error) { + pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(ctx, metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) if err != nil { return false, err } diff --git a/e2e/tests/devspacehelper/inject.go b/e2e/tests/devspacehelper/inject.go index 15ebae332a..bd33ccc8b5 100644 --- a/e2e/tests/devspacehelper/inject.go +++ b/e2e/tests/devspacehelper/inject.go @@ -2,10 +2,11 @@ package devspacehelper import ( "context" - "github.com/onsi/ginkgo/v2" "os" "time" + "github.com/onsi/ginkgo/v2" + "github.com/loft-sh/devspace/cmd" "github.com/loft-sh/devspace/cmd/flags" "github.com/loft-sh/devspace/e2e/framework" @@ -65,8 +66,8 @@ var _ = DevSpaceDescribe("devspacehelper", func() { // wait until nginx pod is reachable var pods *corev1.PodList - err = wait.Poll(time.Second, time.Minute, func() (done bool, err error) { - pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{LabelSelector: "app=curl-container"}) + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute, false, func(ctx context.Context) (done bool, err error) { + pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(ctx, metav1.ListOptions{LabelSelector: "app=curl-container"}) if err != nil { return false, err } else if len(pods.Items) == 0 || len(pods.Items[0].Status.ContainerStatuses) == 0 { @@ -116,8 +117,8 @@ var _ = DevSpaceDescribe("devspacehelper", func() { // wait until nginx pod is reachable var pods *corev1.PodList - err = wait.Poll(time.Second, time.Minute, func() (done bool, err error) { - pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{LabelSelector: "app=non-curl-container"}) + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute, false, func(ctx context.Context) (done bool, err error) { + pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(ctx, metav1.ListOptions{LabelSelector: "app=non-curl-container"}) if err != nil { return false, err } diff --git a/e2e/tests/hooks/hooks.go b/e2e/tests/hooks/hooks.go index 64dcaa2be0..3e96de0f98 100644 --- a/e2e/tests/hooks/hooks.go +++ b/e2e/tests/hooks/hooks.go @@ -2,11 +2,12 @@ package hooks import ( "context" - "github.com/onsi/ginkgo/v2" "os" "sync" "time" + "github.com/onsi/ginkgo/v2" + "github.com/loft-sh/devspace/cmd" "github.com/loft-sh/devspace/cmd/flags" "github.com/loft-sh/devspace/e2e/framework" @@ -147,7 +148,7 @@ var _ = DevSpaceDescribe("hooks", func() { // Read the 'once' hook output onceOutput1 := "" - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { onceOutput1, err = kubeClient.ExecByImageSelector("node", ns, []string{"cat", "/app/once.out"}) if err != nil { return false, nil @@ -159,7 +160,7 @@ var _ = DevSpaceDescribe("hooks", func() { // Read the 'each' hook output eachOutput1 := "" - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { eachOutput1, err = kubeClient.ExecByImageSelector("node", ns, []string{"cat", "/app/each.out"}) if err != nil { return false, nil @@ -196,7 +197,7 @@ var _ = DevSpaceDescribe("hooks", func() { // Wait for 'each' hook output to change eachOutput2 := "" - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { eachOutput2, err = kubeClient.ExecByImageSelector("node", ns, []string{"cat", "/app/each.out"}) if err != nil { return false, nil @@ -208,7 +209,7 @@ var _ = DevSpaceDescribe("hooks", func() { // Read the 'once' hook output again onceOutput2 := "" - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { onceOutput2, err = kubeClient.ExecByImageSelector("node", ns, []string{"cat", "/app/once.out"}) if err != nil { return false, nil diff --git a/e2e/tests/proxycommands/proxycommands.go b/e2e/tests/proxycommands/proxycommands.go index 2e7c0a7c52..e623d49545 100644 --- a/e2e/tests/proxycommands/proxycommands.go +++ b/e2e/tests/proxycommands/proxycommands.go @@ -78,8 +78,8 @@ var _ = DevSpaceDescribe("proxyCommands", func() { // Get the expected Pod hostname var pods *corev1.PodList - err = wait.Poll(time.Second, time.Minute, func() (done bool, err error) { - pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{LabelSelector: "app.kubernetes.io/component=test"}) + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute, false, func(ctx context.Context) (done bool, err error) { + pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(ctx, metav1.ListOptions{LabelSelector: "app.kubernetes.io/component=test"}) if err != nil { return false, err } diff --git a/e2e/tests/replacepods/replacepods.go b/e2e/tests/replacepods/replacepods.go index 7d87a53871..1040369264 100644 --- a/e2e/tests/replacepods/replacepods.go +++ b/e2e/tests/replacepods/replacepods.go @@ -2,11 +2,12 @@ package replacepods import ( "context" - "github.com/onsi/ginkgo/v2" "os" "strings" "time" + "github.com/onsi/ginkgo/v2" + "github.com/loft-sh/devspace/cmd" "github.com/loft-sh/devspace/cmd/flags" "github.com/loft-sh/devspace/e2e/framework" @@ -115,8 +116,8 @@ var _ = DevSpaceDescribe("replacepods", func() { // wait until a pod has started var pods *corev1.PodList - err = wait.Poll(time.Second, time.Minute*3, func() (done bool, err error) { - pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*3, false, func(ctx context.Context) (done bool, err error) { + pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(ctx, metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) if err != nil { return false, err } @@ -156,8 +157,8 @@ var _ = DevSpaceDescribe("replacepods", func() { framework.ExpectEqual(len(list.Items), 1) // wait until a pod has started - err = wait.Poll(time.Second, time.Minute*3, func() (done bool, err error) { - pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*3, false, func(ctx context.Context) (done bool, err error) { + pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(ctx, metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) if err != nil { return false, err } @@ -179,8 +180,8 @@ var _ = DevSpaceDescribe("replacepods", func() { framework.ExpectNoError(err) // wait until all pods are killed - err = wait.Poll(time.Second, time.Minute*3, func() (done bool, err error) { - pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*3, false, func(ctx context.Context) (done bool, err error) { + pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(ctx, metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) if err != nil { return false, err } @@ -222,8 +223,8 @@ var _ = DevSpaceDescribe("replacepods", func() { // wait until a pod has started var pods *corev1.PodList - err = wait.Poll(time.Second, time.Minute, func() (done bool, err error) { - pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute, false, func(ctx context.Context) (done bool, err error) { + pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(ctx, metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) if err != nil { return false, err } @@ -258,8 +259,8 @@ var _ = DevSpaceDescribe("replacepods", func() { framework.ExpectEqual(len(list.Items), 1) // wait until a pod has started - err = wait.Poll(time.Second, time.Minute, func() (done bool, err error) { - pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute, false, func(ctx context.Context) (done bool, err error) { + pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(ctx, metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) if err != nil { return false, err } @@ -312,8 +313,8 @@ var _ = DevSpaceDescribe("replacepods", func() { framework.ExpectNoError(err) // wait until all pods are killed - err = wait.Poll(time.Second, time.Minute, func() (done bool, err error) { - pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute, false, func(ctx context.Context) (done bool, err error) { + pods, err = kubeClient.RawClient().CoreV1().Pods(ns).List(ctx, metav1.ListOptions{LabelSelector: selector.ReplacedLabel}) if err != nil { return false, err } diff --git a/e2e/tests/sync/sync.go b/e2e/tests/sync/sync.go index 88cad1d56f..82382051ef 100644 --- a/e2e/tests/sync/sync.go +++ b/e2e/tests/sync/sync.go @@ -211,7 +211,7 @@ var _ = DevSpaceDescribe("sync", func() { }() // wait until files were synced - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { out, err := kubeClient.ExecByImageSelector("node", ns, []string{"cat", "/app/file1.txt"}) if err != nil { return false, nil @@ -236,7 +236,7 @@ var _ = DevSpaceDescribe("sync", func() { framework.ExpectNoError(err) // wait for sync - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { out, err := kubeClient.ExecByImageSelector("node", ns, []string{"cat", "/app/file3.txt"}) if err != nil { return false, nil @@ -252,7 +252,7 @@ var _ = DevSpaceDescribe("sync", func() { framework.ExpectEqual(os.IsNotExist(err), true) // check if file was downloaded through after hook - err = wait.PollImmediate(time.Second, time.Minute, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute, true, func(_ context.Context) (done bool, err error) { out, err := os.ReadFile(filepath.Join(tempDir, "file5.txt")) if err != nil { if !os.IsNotExist(err) { @@ -311,7 +311,7 @@ var _ = DevSpaceDescribe("sync", func() { }() // wait until files were synced - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { out, err := kubeClient.ExecByImageSelector("node", ns, []string{"cat", "/watch/app/file1.txt"}) if err != nil { return false, nil @@ -335,7 +335,7 @@ var _ = DevSpaceDescribe("sync", func() { err = os.WriteFile(filepath.Join(tempDir, "/project1/app/file3.txt"), []byte(payload1), 0666) framework.ExpectNoError(err) - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { out, err := kubeClient.ExecByImageSelector("node", ns, []string{"cat", "/watch/app/file3.txt"}) if err != nil { return false, nil @@ -350,7 +350,7 @@ var _ = DevSpaceDescribe("sync", func() { err = os.WriteFile(filepath.Join(tempDir, "/project2/file4.txt"), []byte(payload2), 0666) framework.ExpectNoError(err) - err = wait.PollImmediate(time.Second, time.Minute*2, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*2, true, func(_ context.Context) (done bool, err error) { out, err := kubeClient.ExecByImageSelector("node", ns, []string{"cat", "/watch/app/file4.txt"}) if err != nil { return false, nil diff --git a/e2e/tests/terminal/terminal.go b/e2e/tests/terminal/terminal.go index d316215a6d..0ca590f8a3 100644 --- a/e2e/tests/terminal/terminal.go +++ b/e2e/tests/terminal/terminal.go @@ -3,6 +3,12 @@ package terminal import ( "bytes" "context" + "os" + "path/filepath" + "strings" + "sync" + "time" + "github.com/loft-sh/devspace/cmd" "github.com/loft-sh/devspace/cmd/flags" "github.com/loft-sh/devspace/e2e/framework" @@ -13,11 +19,6 @@ import ( kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" - "os" - "path/filepath" - "strings" - "sync" - "time" ) var _ = DevSpaceDescribe("terminal", func() { @@ -126,7 +127,7 @@ sleep 1000000 // wait until we get the first hostnames var podName string - err = wait.PollImmediate(time.Second, time.Minute*3, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*3, true, func(_ context.Context) (done bool, err error) { lines := strings.Split(buffer.String(), "\n") if len(lines) <= 1 { return false, nil @@ -142,8 +143,8 @@ sleep 1000000 framework.ExpectNoError(err) // wait until pod is terminated - err = wait.PollImmediate(time.Second, time.Minute*3, func() (done bool, err error) { - _, err = kubeClient.RawClient().CoreV1().Pods(ns).Get(context.TODO(), podName, metav1.GetOptions{}) + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*3, true, func(ctx context.Context) (done bool, err error) { + _, err = kubeClient.RawClient().CoreV1().Pods(ns).Get(ctx, podName, metav1.GetOptions{}) if err != nil { if kerrors.IsNotFound(err) { return true, nil @@ -157,7 +158,7 @@ sleep 1000000 framework.ExpectNoError(err) // get new pod name - err = wait.PollImmediate(time.Second, time.Minute*3, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute*3, true, func(_ context.Context) (done bool, err error) { lines := strings.Split(buffer.String(), "\n") if len(lines) <= 1 { return false, nil diff --git a/helper/util/restart_linux.go b/helper/util/restart_linux.go index d543c26e8e..1d8f796dca 100644 --- a/helper/util/restart_linux.go +++ b/helper/util/restart_linux.go @@ -4,6 +4,7 @@ package util import ( + "context" "fmt" "os" "strconv" @@ -79,7 +80,7 @@ func (*containerRestarter) RestartContainer() error { if err != nil { return nil } - err = wait.PollImmediate(time.Second, 5*time.Second, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.TODO(), time.Second, 5*time.Second, true, func(_ context.Context) (done bool, err error) { _, err = os.Stat(procPath) return os.IsNotExist(err), nil }) diff --git a/pkg/devspace/analyze/analyze.go b/pkg/devspace/analyze/analyze.go index 279514f0c7..780da0dbe6 100644 --- a/pkg/devspace/analyze/analyze.go +++ b/pkg/devspace/analyze/analyze.go @@ -1,10 +1,12 @@ package analyze import ( + "context" "fmt" - "github.com/sirupsen/logrus" "time" + "github.com/sirupsen/logrus" + "k8s.io/apimachinery/pkg/util/wait" "github.com/loft-sh/devspace/pkg/devspace/kubectl" @@ -82,7 +84,7 @@ func (a *analyzer) CreateReport(namespace string, options Options) ([]*ReportIte } // Loop as long as we have a timeout - err := wait.Poll(time.Second, timeout, func() (bool, error) { + err := wait.PollUntilContextTimeout(context.TODO(), time.Second, timeout, false, func(_ context.Context) (bool, error) { report = []*ReportItem{} // Analyze pods diff --git a/pkg/devspace/build/builder/kaniko/kaniko.go b/pkg/devspace/build/builder/kaniko/kaniko.go index b51aeb03ad..fa70974171 100644 --- a/pkg/devspace/build/builder/kaniko/kaniko.go +++ b/pkg/devspace/build/builder/kaniko/kaniko.go @@ -1,6 +1,7 @@ package kaniko import ( + "context" "fmt" "io" "strings" @@ -169,8 +170,8 @@ func (b *Builder) BuildImage(ctx devspacecontext.Context, contextPath, dockerfil } ctx.Log().Info("Waiting for build init container to start...") - err = wait.PollImmediate(time.Second, waitTimeout, func() (done bool, err error) { - buildPod, err = ctx.KubeClient().KubeClient().CoreV1().Pods(b.BuildNamespace).Get(ctx.Context(), buildPodCreated.Name, metav1.GetOptions{}) + err = wait.PollUntilContextTimeout(ctx.Context(), time.Second, waitTimeout, true, func(ctxPollUntil context.Context) (done bool, err error) { + buildPod, err = ctx.KubeClient().KubeClient().CoreV1().Pods(b.BuildNamespace).Get(ctxPollUntil, buildPodCreated.Name, metav1.GetOptions{}) if err != nil { if kerrors.IsNotFound(err) { return false, nil @@ -181,7 +182,7 @@ func (b *Builder) BuildImage(ctx devspacecontext.Context, contextPath, dockerfil status := buildPod.Status.InitContainerStatuses[0] if status.State.Terminated != nil { errorLog := "" - reader, _ := ctx.KubeClient().Logs(ctx.Context(), b.BuildNamespace, buildPodCreated.Name, buildPod.Spec.InitContainers[0].Name, false, nil, false) + reader, _ := ctx.KubeClient().Logs(ctxPollUntil, b.BuildNamespace, buildPodCreated.Name, buildPod.Spec.InitContainers[0].Name, false, nil, false) if reader != nil { out, err := io.ReadAll(reader) if err == nil { @@ -310,8 +311,8 @@ func (b *Builder) BuildImage(ctx devspacecontext.Context, contextPath, dockerfil ctx.Log().Done("Uploaded files to container") ctx.Log().Info("Waiting for kaniko container to start...") - err = wait.PollImmediate(time.Second, waitTimeout, func() (done bool, err error) { - buildPod, err = ctx.KubeClient().KubeClient().CoreV1().Pods(b.BuildNamespace).Get(ctx.Context(), buildPodCreated.Name, metav1.GetOptions{}) + err = wait.PollUntilContextTimeout(ctx.Context(), time.Second, waitTimeout, true, func(ctxPollUntil context.Context) (done bool, err error) { + buildPod, err = ctx.KubeClient().KubeClient().CoreV1().Pods(b.BuildNamespace).Get(ctxPollUntil, buildPodCreated.Name, metav1.GetOptions{}) if err != nil { if kerrors.IsNotFound(err) { return false, nil @@ -326,7 +327,7 @@ func (b *Builder) BuildImage(ctx devspacecontext.Context, contextPath, dockerfil } errorLog := "" - reader, _ := ctx.KubeClient().Logs(ctx.Context(), b.BuildNamespace, buildPodCreated.Name, status.Name, false, nil, false) + reader, _ := ctx.KubeClient().Logs(ctxPollUntil, b.BuildNamespace, buildPodCreated.Name, status.Name, false, nil, false) if reader != nil { out, err := io.ReadAll(reader) if err == nil { diff --git a/pkg/devspace/build/localregistry/deployment.go b/pkg/devspace/build/localregistry/deployment.go index ff9676624f..7f1dd6902d 100644 --- a/pkg/devspace/build/localregistry/deployment.go +++ b/pkg/devspace/build/localregistry/deployment.go @@ -31,7 +31,7 @@ func (r *LocalRegistry) ensureDeployment(ctx devspacecontext.Context) (*appsv1.D var existing *appsv1.Deployment desired := r.getDeployment() kubeClient := ctx.KubeClient() - err = wait.PollImmediateWithContext(ctx.Context(), time.Second, 30*time.Second, func(ctx context.Context) (bool, error) { + err = wait.PollUntilContextTimeout(ctx.Context(), time.Second, 30*time.Second, true, func(ctx context.Context) (bool, error) { var err error existing, err = kubeClient.KubeClient().AppsV1().Deployments(r.Namespace).Get(ctx, r.Name, metav1.GetOptions{}) @@ -125,7 +125,7 @@ func getAnnotations(localbuild bool) map[string]string { // this returns a different deployment, if we're using a local docker build or not. func getContainers(registryImage, buildKitImage, volume string, port int32, localbuild bool) []corev1.Container { - buildContainers := getRegistryContainers(registryImage, buildKitImage, volume, port) + buildContainers := getRegistryContainers(registryImage, volume, port) if localbuild { // in case we're using local builds just return the deployment with only the // registry container inside @@ -186,7 +186,7 @@ func getContainers(registryImage, buildKitImage, volume string, port int32, loca return append(buildKitContainer, buildContainers...) } -func getRegistryContainers(registryImage, buildKitImage, volume string, port int32) []corev1.Container { +func getRegistryContainers(registryImage, volume string, port int32) []corev1.Container { return []corev1.Container{ { Name: "registry", diff --git a/pkg/devspace/build/localregistry/local_registry.go b/pkg/devspace/build/localregistry/local_registry.go index 5167727eb0..126d4c4436 100644 --- a/pkg/devspace/build/localregistry/local_registry.go +++ b/pkg/devspace/build/localregistry/local_registry.go @@ -190,10 +190,11 @@ func (r *LocalRegistry) waitForNodePort(ctx devspacecontext.Context) (*corev1.Se var servicePort *corev1.ServicePort kubeClient := ctx.KubeClient().KubeClient() - err := wait.PollImmediateWithContext( + err := wait.PollUntilContextTimeout( ctx.Context(), time.Second, 30*time.Second, + true, func(ctx context.Context) (done bool, err error) { service, err := kubeClient.CoreV1(). Services(r.Namespace). @@ -271,10 +272,11 @@ func (r *LocalRegistry) startPortForwarding( } func (r *LocalRegistry) waitForRegistry(ctx context.Context) error { - return wait.PollImmediateWithContext( + return wait.PollUntilContextTimeout( ctx, time.Second, 30*time.Second, + true, func(ctx context.Context) (done bool, err error) { return r.ping(ctx) }, diff --git a/pkg/devspace/build/localregistry/service.go b/pkg/devspace/build/localregistry/service.go index 4828c7730c..95ab82505b 100644 --- a/pkg/devspace/build/localregistry/service.go +++ b/pkg/devspace/build/localregistry/service.go @@ -18,7 +18,7 @@ func (r *LocalRegistry) ensureService(ctx devspacecontext.Context) (*corev1.Serv var existing *corev1.Service desired := r.getService() kubeClient := ctx.KubeClient() - err := wait.PollImmediateWithContext(ctx.Context(), time.Second, 30*time.Second, func(ctx context.Context) (bool, error) { + err := wait.PollUntilContextTimeout(ctx.Context(), time.Second, 30*time.Second, true, func(ctx context.Context) (bool, error) { var err error existing, err = kubeClient.KubeClient().CoreV1().Services(r.Namespace).Get(ctx, r.Name, metav1.GetOptions{}) diff --git a/pkg/devspace/build/localregistry/statefulset.go b/pkg/devspace/build/localregistry/statefulset.go index 5d5463097c..7af17bc0d8 100644 --- a/pkg/devspace/build/localregistry/statefulset.go +++ b/pkg/devspace/build/localregistry/statefulset.go @@ -27,7 +27,7 @@ func (r *LocalRegistry) ensureStatefulset(ctx devspacecontext.Context) (*appsv1. var existing *appsv1.StatefulSet desired := r.getStatefulSet() kubeClient := ctx.KubeClient() - err = wait.PollImmediateWithContext(ctx.Context(), time.Second, 30*time.Second, func(ctx context.Context) (bool, error) { + err = wait.PollUntilContextTimeout(ctx.Context(), time.Second, 30*time.Second, true, func(ctx context.Context) (bool, error) { var err error existing, err = kubeClient.KubeClient().AppsV1().StatefulSets(r.Namespace).Get(ctx, r.Name, metav1.GetOptions{}) diff --git a/pkg/devspace/config/remotecache/schema.go b/pkg/devspace/config/remotecache/schema.go index f97ce21e21..0511e09388 100644 --- a/pkg/devspace/config/remotecache/schema.go +++ b/pkg/devspace/config/remotecache/schema.go @@ -315,7 +315,7 @@ func (l *RemoteCache) Save(ctx context.Context, client kubectl.Client) error { namespace = client.Namespace() } - waitErr := wait.PollImmediate(time.Second, time.Second*10, func() (done bool, err error) { + waitErr := wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Second*10, true, func(_ context.Context) (done bool, err error) { secret, err := client.KubeClient().CoreV1().Secrets(namespace).Get(ctx, l.secretName, metav1.GetOptions{}) if err != nil { if !kerrors.IsNotFound(err) && !kerrors.IsForbidden(err) { diff --git a/pkg/devspace/devpod/devpod.go b/pkg/devspace/devpod/devpod.go index b81f0842ec..e50c746b8a 100644 --- a/pkg/devspace/devpod/devpod.go +++ b/pkg/devspace/devpod/devpod.go @@ -4,12 +4,13 @@ import ( "context" "crypto/tls" "fmt" - "github.com/loft-sh/devspace/pkg/devspace/kill" "io" "net/http" "os" syncpkg "sync" + "github.com/loft-sh/devspace/pkg/devspace/kill" + "github.com/loft-sh/devspace/pkg/devspace/deploy" "github.com/mgutz/ansi" kerrors "k8s.io/apimachinery/pkg/api/errors" @@ -146,7 +147,7 @@ func (d *devPod) startWithRetry(ctx devspacecontext.Context, devPodConfig *lates // check if we need to restart if selectedPod != nil { shouldRestart := false - err := wait.PollImmediateUntil(time.Second, func() (bool, error) { + err := wait.PollUntilContextCancel(context.TODO(), time.Second, true, func(context.Context) (bool, error) { pod, err := ctx.KubeClient().KubeClient().CoreV1().Pods(selectedPod.Pod.Namespace).Get(ctx.Context(), selectedPod.Pod.Name, metav1.GetOptions{}) if err != nil { if kerrors.IsNotFound(err) { @@ -165,9 +166,9 @@ func (d *devPod) startWithRetry(ctx devspacecontext.Context, devPodConfig *lates } return true, nil - }, ctx.Context().Done()) + }) if err != nil { - if err != wait.ErrWaitTimeout { + if wait.Interrupted(err) { ctx.Log().Errorf("error restarting dev: %v", err) } } else if shouldRestart { diff --git a/pkg/devspace/hook/wait.go b/pkg/devspace/hook/wait.go index a7008f9c31..a79040cb32 100644 --- a/pkg/devspace/hook/wait.go +++ b/pkg/devspace/hook/wait.go @@ -2,11 +2,12 @@ package hook import ( "context" + "sync" + "time" + "github.com/loft-sh/devspace/pkg/devspace/config/loader/variable/runtime" devspacecontext "github.com/loft-sh/devspace/pkg/devspace/context" "github.com/loft-sh/devspace/pkg/devspace/imageselector" - "sync" - "time" "github.com/loft-sh/devspace/pkg/devspace/config/versions/latest" "github.com/loft-sh/devspace/pkg/devspace/kubectl" @@ -72,7 +73,7 @@ func (r *waitHook) execute(ctx context.Context, hook *latest.HookConfig, client } // wait until the defined condition will be true, this will wait initially 2 seconds - err := wait.Poll(time.Second*2, time.Duration(timeout)*time.Second, func() (done bool, err error) { + err := wait.PollUntilContextTimeout(ctx, time.Second*2, time.Duration(timeout)*time.Second, false, func(ctx context.Context) (done bool, err error) { podContainers, err := selector.NewFilter(client).SelectContainers(ctx, selector.Selector{ ImageSelector: targetselector.ToStringImageSelector(imageSelector), LabelSelector: labelSelector, diff --git a/pkg/devspace/kubectl/client.go b/pkg/devspace/kubectl/client.go index 57c1bc0ca5..7352267de0 100644 --- a/pkg/devspace/kubectl/client.go +++ b/pkg/devspace/kubectl/client.go @@ -3,6 +3,11 @@ package kubectl import ( "context" "fmt" + "io" + "net/http" + "os" + "time" + "github.com/loft-sh/devspace/pkg/devspace/config/localcache" "github.com/loft-sh/devspace/pkg/devspace/kill" "github.com/loft-sh/devspace/pkg/devspace/kubectl/util" @@ -12,11 +17,7 @@ import ( "github.com/loft-sh/devspace/pkg/util/log" "github.com/loft-sh/devspace/pkg/util/survey" "github.com/loft-sh/devspace/pkg/util/terminal" - "io" "k8s.io/apimachinery/pkg/util/wait" - "net/http" - "os" - "time" "github.com/mgutz/ansi" "github.com/pkg/errors" @@ -417,7 +418,7 @@ func wakeUp(ctx context.Context, client Client, log log.Logger) error { log.Infof("DevSpace is waking up the Kubernetes environment, please wait a moment...") // wake up the environment - waitErr := wait.PollImmediate(time.Second, time.Second*30, func() (done bool, err error) { + waitErr := wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Second*30, true, func(_ context.Context) (done bool, err error) { _, err = kubeClient.CoreV1().Pods(client.Namespace()).List(ctx, metav1.ListOptions{LabelSelector: "devspace=wakeup"}) if err != nil { return false, nil diff --git a/pkg/devspace/pipeline/pipeline.go b/pkg/devspace/pipeline/pipeline.go index e94580910a..b74a83f132 100644 --- a/pkg/devspace/pipeline/pipeline.go +++ b/pkg/devspace/pipeline/pipeline.go @@ -276,7 +276,7 @@ func waitForDependency(ctx context.Context, start types.Pipeline, dependencyName // try to find the dependency var pipeline types.Pipeline - err := wait.PollImmediateWithContext(ctx, time.Millisecond*10, time.Second, func(_ context.Context) (bool, error) { + err := wait.PollUntilContextTimeout(ctx, time.Millisecond*10, time.Second, true, func(_ context.Context) (bool, error) { pipeline = findDependencies(start, dependencyName) return pipeline != nil, nil }) diff --git a/pkg/devspace/pullsecrets/init.go b/pkg/devspace/pullsecrets/init.go index 7952c9c8ab..83b489dc50 100644 --- a/pkg/devspace/pullsecrets/init.go +++ b/pkg/devspace/pullsecrets/init.go @@ -1,6 +1,7 @@ package pullsecrets import ( + "context" "time" devspacecontext "github.com/loft-sh/devspace/pkg/devspace/context" @@ -120,9 +121,9 @@ func (r *client) addPullSecretsToServiceAccount(ctx devspacecontext.Context, nam serviceAccount = "default" } - err := wait.PollImmediate(time.Second, time.Second*30, func() (bool, error) { + err := wait.PollUntilContextTimeout(ctx.Context(), time.Second, time.Second*30, true, func(ctxPollUntil context.Context) (bool, error) { // Get default service account - sa, err := ctx.KubeClient().KubeClient().CoreV1().ServiceAccounts(namespace).Get(ctx.Context(), serviceAccount, metav1.GetOptions{}) + sa, err := ctx.KubeClient().KubeClient().CoreV1().ServiceAccounts(namespace).Get(ctxPollUntil, serviceAccount, metav1.GetOptions{}) if err != nil { if kerrors.IsNotFound(err) { return false, nil @@ -142,7 +143,7 @@ func (r *client) addPullSecretsToServiceAccount(ctx devspacecontext.Context, nam } if !found { sa.ImagePullSecrets = append(sa.ImagePullSecrets, v1.LocalObjectReference{Name: pullSecretName}) - _, err := ctx.KubeClient().KubeClient().CoreV1().ServiceAccounts(namespace).Update(ctx.Context(), sa, metav1.UpdateOptions{}) + _, err := ctx.KubeClient().KubeClient().CoreV1().ServiceAccounts(namespace).Update(ctxPollUntil, sa, metav1.UpdateOptions{}) if err != nil { if kerrors.IsConflict(err) { return false, nil diff --git a/pkg/devspace/pullsecrets/registry.go b/pkg/devspace/pullsecrets/registry.go index 4e84dc849a..c6cf9802a8 100644 --- a/pkg/devspace/pullsecrets/registry.go +++ b/pkg/devspace/pullsecrets/registry.go @@ -1,6 +1,7 @@ package pullsecrets import ( + "context" "crypto/sha256" "encoding/base64" "encoding/hex" @@ -67,8 +68,8 @@ func (r *client) CreatePullSecret(ctx devspacecontext.Context, options *PullSecr email = "noreply@devspace.sh" } - err := wait.PollImmediate(time.Second, time.Second*30, func() (bool, error) { - secret, err := ctx.KubeClient().KubeClient().CoreV1().Secrets(options.Namespace).Get(ctx.Context(), pullSecretName, metav1.GetOptions{}) + err := wait.PollUntilContextTimeout(ctx.Context(), time.Second, time.Second*30, true, func(ctxPollUntil context.Context) (bool, error) { + secret, err := ctx.KubeClient().KubeClient().CoreV1().Secrets(options.Namespace).Get(ctxPollUntil, pullSecretName, metav1.GetOptions{}) if err != nil { if kerrors.IsNotFound(err) { // Create the pull secret @@ -77,7 +78,7 @@ func (r *client) CreatePullSecret(ctx devspacecontext.Context, options *PullSecr return false, err } - _, err = ctx.KubeClient().KubeClient().CoreV1().Secrets(options.Namespace).Create(ctx.Context(), secret, metav1.CreateOptions{}) + _, err = ctx.KubeClient().KubeClient().CoreV1().Secrets(options.Namespace).Create(ctxPollUntil, secret, metav1.CreateOptions{}) if err != nil { if kerrors.IsAlreadyExists(err) { // Retry diff --git a/pkg/devspace/services/podreplace/replace.go b/pkg/devspace/services/podreplace/replace.go index 696cc2a13f..48bbea99e1 100644 --- a/pkg/devspace/services/podreplace/replace.go +++ b/pkg/devspace/services/podreplace/replace.go @@ -1,6 +1,7 @@ package podreplace import ( + "context" "fmt" "strconv" "time" @@ -273,8 +274,8 @@ func updatePVC(ctx devspacecontext.Context, deployment *appsv1.Deployment, devPo // delete the old one and wait _ = ctx.KubeClient().KubeClient().CoreV1().PersistentVolumeClaims(deployment.Namespace).Delete(ctx.Context(), deployment.Name, metav1.DeleteOptions{}) ctx.Log().Infof("Waiting for old persistent volume claim to terminate") - err = wait.Poll(time.Second, time.Minute*2, func() (done bool, err error) { - _, err = ctx.KubeClient().KubeClient().CoreV1().PersistentVolumeClaims(deployment.Namespace).Get(ctx.Context(), deployment.Name, metav1.GetOptions{}) + err = wait.PollUntilContextTimeout(ctx.Context(), time.Second, time.Minute*2, false, func(ctxPullUntil context.Context) (done bool, err error) { + _, err = ctx.KubeClient().KubeClient().CoreV1().PersistentVolumeClaims(deployment.Namespace).Get(ctxPullUntil, deployment.Name, metav1.GetOptions{}) return kerrors.IsNotFound(err), nil }) if err != nil { diff --git a/pkg/devspace/services/targetselector/target_selector.go b/pkg/devspace/services/targetselector/target_selector.go index 5c257dc3e2..5a482ae7ce 100644 --- a/pkg/devspace/services/targetselector/target_selector.go +++ b/pkg/devspace/services/targetselector/target_selector.go @@ -3,9 +3,10 @@ package targetselector import ( "context" "fmt" - "github.com/loft-sh/devspace/pkg/devspace/imageselector" "time" + "github.com/loft-sh/devspace/pkg/devspace/imageselector" + "github.com/loft-sh/devspace/pkg/devspace/kubectl/selector" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/wait" @@ -234,7 +235,7 @@ func (t *targetSelector) selectSingle(ctx context.Context, client kubectl.Client } var out interface{} - err := wait.PollImmediateWithContext(ctx, time.Millisecond*500, timeout, func(ctx context.Context) (done bool, err error) { + err := wait.PollUntilContextTimeout(ctx, time.Millisecond*500, timeout, true, func(ctx context.Context) (done bool, err error) { done, o, err := selectFn(ctx, client, options, log) if err != nil { return false, err @@ -246,7 +247,7 @@ func (t *targetSelector) selectSingle(ctx context.Context, client kubectl.Client return true, nil }) if err != nil { - if err == wait.ErrWaitTimeout { + if wait.Interrupted(err) { return nil, &NotFoundErr{ Timeout: true, Selector: options.selector.String(), diff --git a/vendor/k8s.io/client-go/transport/cert_rotation.go b/vendor/k8s.io/client-go/transport/cert_rotation.go index dc22b6ec4c..b20430f601 100644 --- a/vendor/k8s.io/client-go/transport/cert_rotation.go +++ b/vendor/k8s.io/client-go/transport/cert_rotation.go @@ -18,6 +18,7 @@ package transport import ( "bytes" + "context" "crypto/tls" "fmt" "reflect" @@ -139,10 +140,16 @@ func (c *dynamicClientCert) Run(stopCh <-chan struct{}) { go wait.Until(c.runWorker, time.Second, stopCh) - go wait.PollImmediateUntil(CertCallbackRefreshDuration, func() (bool, error) { + ctx, cancel := context.WithCancel(context.Background()) + go func() { + <-stopCh + cancel() + }() + + go wait.PollUntilContextCancel(ctx, CertCallbackRefreshDuration, true, func(ctx context.Context) (bool, error) { c.queue.Add(workItemKey) return false, nil - }, stopCh) + }) <-stopCh }