diff --git a/delve.go b/delve.go index d1a709c..40822bd 100644 --- a/delve.go +++ b/delve.go @@ -15,9 +15,11 @@ import ( const delveBin = "dlv" -func (g Grapple) Delve(pod, container, sourcePath string, binArgs []string, host string, port int, delveContinue, vscode bool) error { +func (g Grapple) Delve(pod, container, sourcePath string, binArgs []string, host string, + port int, delveContinue, vscode bool) error { + validateCtx := context.Background() // validate k8s resources for delve session - if err := g.kubeCmd.ValidatePod(g.deployment, &pod); err != nil { + if err := g.kubeCmd.ValidatePod(validateCtx, g.deployment, &pod); err != nil { return err } if err := g.kubeCmd.ValidateContainer(g.deployment, &container); err != nil { @@ -29,7 +31,8 @@ func (g Grapple) Delve(pod, container, sourcePath string, binArgs []string, host // populate bin args if empty if len(binArgs) == 0 { var err error - d, err := g.kubeCmd.GetDeploymentFromConfigMap(g.DeploymentConfigMapName(), defaultConfigMapDeploymentKey) + d, err := g.kubeCmd.GetDeploymentFromConfigMap(validateCtx, g.DeploymentConfigMapName(), + defaultConfigMapDeploymentKey) if err != nil { return err } @@ -98,11 +101,11 @@ func (g Grapple) binDestination() string { func (g Grapple) cleanupPIDs(ctx context.Context, pod, container string) error { // get pids of delve and app were debugging - binPids, errBinPids := g.kubeCmd.GetPIDsOf(pod, container, g.binName()) + binPids, errBinPids := g.kubeCmd.GetPIDsOf(ctx, pod, container, g.binName()) if errBinPids != nil { return errBinPids } - delvePids, errDelvePids := g.kubeCmd.GetPIDsOf(pod, container, delveBin) + delvePids, errDelvePids := g.kubeCmd.GetPIDsOf(ctx, pod, container, delveBin) if errDelvePids != nil { return errDelvePids } @@ -110,7 +113,7 @@ func (g Grapple) cleanupPIDs(ctx context.Context, pod, container string) error { maxTries := 10 pids := append(binPids, delvePids...) return tryCallWithContext(ctx, maxTries, time.Millisecond*200, func(i int) error { - killErrs := g.kubeCmd.KillPidsOnPod(pod, container, pids, true) + killErrs := g.kubeCmd.KillPidsOnPod(ctx, pod, container, pids, true) if len(killErrs) == 0 { return nil } @@ -132,7 +135,8 @@ func (g Grapple) deployBin(ctx context.Context, pod, container, goModPath, sourc } else { for _, file := range files { if path.Ext(file.Name()) == ".go" { - relInputs = append(relInputs, strings.TrimPrefix(path.Join(sourcePath, file.Name()), goModPath+string(filepath.Separator))) + relInputs = append(relInputs, strings.TrimPrefix(path.Join(sourcePath, + file.Name()), goModPath+string(filepath.Separator))) } } } @@ -140,12 +144,12 @@ func (g Grapple) deployBin(ctx context.Context, pod, container, goModPath, sourc relInputs = append(relInputs, strings.TrimPrefix(sourcePath, goModPath+string(filepath.Separator))) } - _, errBuild := g.goCmd.Build(goModPath, binSource, relInputs, `-gcflags="all=-N -l"`).Env("GOOS=linux").RunCtx(ctx) + _, errBuild := g.goCmd.Build(goModPath, binSource, relInputs, `-gcflags="all=-N -l"`).Env("GOOS=linux").Run(ctx) if errBuild != nil { return errBuild } // copy bin to pod - _, errCopyToPod := g.kubeCmd.CopyToPod(pod, container, binSource, g.binDestination()).RunCtx(ctx) + _, errCopyToPod := g.kubeCmd.CopyToPod(pod, container, binSource, g.binDestination()).Run(ctx) return errCopyToPod } @@ -153,7 +157,7 @@ func (g Grapple) portForwardDelve(l *logrus.Entry, ctx context.Context, pod, hos l.Info("port-forwarding pod for delve server") cmd := g.kubeCmd.PortForwardPod(pod, host, port) go func() { - _, err := cmd.RunCtx(ctx) + _, err := cmd.Run(ctx) if err != nil && err.Error() != "signal: killed" { l.WithError(err).Errorf("port-forwarding %v pod failed", pod) } diff --git a/delve/server.go b/delve/server.go index cab643d..d21a906 100644 --- a/delve/server.go +++ b/delve/server.go @@ -26,8 +26,8 @@ func (kds KubeDelveServer) Port() int { } func NewKubeDelveServer(l *logrus.Entry, namespace, host string, port int) *KubeDelveServer { - kubectl := exec.NewKubectlCommand(l) - kubectl.Args("-n", namespace) + kubectl := exec.NewKubectlCommand() + kubectl.Logger(l).Args("-n", namespace) return &KubeDelveServer{host, port, kubectl, nil} } @@ -38,7 +38,7 @@ func (kds *KubeDelveServer) StartNoWait(ctx context.Context, pod, container stri func(p *os.Process) error { kds.process = p return nil - }).NoWait().RunCtx(ctx) + }).NoWait().Run(ctx) <-cmd.Started() } @@ -50,7 +50,7 @@ func (kds *KubeDelveServer) Start(ctx context.Context, pod, container string, bi func(p *os.Process) error { kds.process = p return nil - }).RunCtx(ctx) + }).Run(ctx) return errors.WithMessage(err, out) } diff --git a/exec/cmd.go b/exec/cmd.go index a97fe8a..0aabbca 100644 --- a/exec/cmd.go +++ b/exec/cmd.go @@ -6,7 +6,6 @@ import ( "io" "os" goexec "os/exec" - "time" "github.com/sirupsen/logrus" ) @@ -21,7 +20,7 @@ type Cmd struct { stdoutWriters []io.Writer stderrWriters []io.Writer wait bool - t time.Duration + // t time.Duration preStartFunc func() error postStartFunc func(p *os.Process) error postEndFunc func() error @@ -29,9 +28,8 @@ type Cmd struct { chanDone chan struct{} } -func NewCommand(l *logrus.Entry, name string) *Cmd { +func NewCommand(name string) *Cmd { return &Cmd{ - l: l, command: []string{name}, wait: true, env: os.Environ(), @@ -85,11 +83,6 @@ func (c *Cmd) Stderr(w io.Writer) *Cmd { return c } -func (c *Cmd) Timeout(t time.Duration) *Cmd { - c.t = t - return c -} - func (c *Cmd) NoWait() *Cmd { c.wait = false return c @@ -110,20 +103,25 @@ func (c *Cmd) PostEnd(f func() error) *Cmd { return c } -func (c *Cmd) Started() <-chan struct{} { - return c.chanStarted +func (c *Cmd) Logger(l *logrus.Entry) *Cmd { + c.l = l + return c } -func (c *Cmd) Done() <-chan struct{} { - return c.chanDone +// func (c *Cmd) Run() (string, error) { +// return c.run(goexec.Command(c.command[0], c.command[1:]...)) +// } + +func (c *Cmd) Run(ctx context.Context) (string, error) { + return c.run(goexec.CommandContext(ctx, c.command[0], c.command[1:]...)) } -func (c *Cmd) Run() (string, error) { - return c.run(goexec.Command(c.command[0], c.command[1:]...)) +func (c *Cmd) Started() <-chan struct{} { + return c.chanStarted } -func (c *Cmd) RunCtx(ctx context.Context) (string, error) { - return c.run(goexec.CommandContext(ctx, c.command[0], c.command[1:]...)) +func (c *Cmd) Done() <-chan struct{} { + return c.chanDone } func (c *Cmd) run(cmd *goexec.Cmd) (string, error) { @@ -134,11 +132,12 @@ func (c *Cmd) run(cmd *goexec.Cmd) (string, error) { c.l.Tracef("executing %q", cmd.String()) combinedBuf := new(bytes.Buffer) - traceWriter := c.l.WriterLevel(logrus.TraceLevel) - warnWriter := c.l.WriterLevel(logrus.WarnLevel) - - c.stdoutWriters = append(c.stdoutWriters, combinedBuf, traceWriter) - c.stderrWriters = append(c.stderrWriters, combinedBuf, warnWriter) + if c.l != nil { + traceWriter := c.l.WriterLevel(logrus.TraceLevel) + warnWriter := c.l.WriterLevel(logrus.WarnLevel) + c.stdoutWriters = append(c.stdoutWriters, combinedBuf, traceWriter) + c.stderrWriters = append(c.stderrWriters, combinedBuf, warnWriter) + } cmd.Stdout = io.MultiWriter(c.stdoutWriters...) cmd.Stderr = io.MultiWriter(c.stderrWriters...) @@ -163,17 +162,8 @@ func (c *Cmd) run(cmd *goexec.Cmd) (string, error) { }() if c.wait { - if c.t != 0 { - timer := time.AfterFunc(c.t, func() { - cmd.Process.Kill() - }) - defer timer.Stop() - } - if err := cmd.Wait(); err != nil { - if c.t == 0 { - return "", err - } + return "", err } if c.postEndFunc != nil { if err := c.postEndFunc(); err != nil { diff --git a/exec/docker.go b/exec/docker.go index f6e5d51..e06eed9 100644 --- a/exec/docker.go +++ b/exec/docker.go @@ -2,22 +2,20 @@ package exec import ( "fmt" - - "github.com/sirupsen/logrus" ) type DockerCmd struct { Cmd } -func NewDockerCommand(l *logrus.Entry) *DockerCmd { - return &DockerCmd{*NewCommand(l, "docker")} +func NewDockerCommand() *DockerCmd { + return &DockerCmd{*NewCommand("docker")} } func (c DockerCmd) Build(workDir string, options ...string) *Cmd { return c.Args("build", workDir).Args(options...) } -func (c DockerCmd) Push(image, tag string, options ...string) (string, error) { - return c.Args("push", fmt.Sprintf("%v:%v", image, tag)).Args(options...).Run() +func (c DockerCmd) Push(image, tag string, options ...string) *Cmd { + return c.Args("push", fmt.Sprintf("%v:%v", image, tag)).Args(options...) } diff --git a/exec/go.go b/exec/go.go index 7877ad3..13a9f2f 100644 --- a/exec/go.go +++ b/exec/go.go @@ -1,15 +1,11 @@ package exec -import ( - "github.com/sirupsen/logrus" -) - type GoCmd struct { Cmd } -func NewGoCommand(l *logrus.Entry) *GoCmd { - return &GoCmd{*NewCommand(l, "go")} +func NewGoCommand() *GoCmd { + return &GoCmd{*NewCommand("go")} } func (c GoCmd) Build(workDir, output string, inputs []string, flags ...string) *Cmd { diff --git a/exec/kubectl.go b/exec/kubectl.go index 85ab067..d6a859b 100644 --- a/exec/kubectl.go +++ b/exec/kubectl.go @@ -1,6 +1,7 @@ package exec import ( + "context" "encoding/json" "errors" "fmt" @@ -8,7 +9,6 @@ import ( "strconv" "strings" - "github.com/sirupsen/logrus" apps "k8s.io/api/apps/v1" core "k8s.io/api/core/v1" ) @@ -17,8 +17,8 @@ type KubectlCmd struct { Cmd } -func NewKubectlCommand(l *logrus.Entry) *KubectlCmd { - return &KubectlCmd{*NewCommand(l, "kubectl")} +func NewKubectlCommand() *KubectlCmd { + return &KubectlCmd{*NewCommand("kubectl")} } func (c KubectlCmd) RollbackDeployment(deployment string) *Cmd { @@ -30,13 +30,14 @@ func (c KubectlCmd) WaitForRollout(deployment, timeout string) *Cmd { "-w", "--timeout", timeout) } -func (c KubectlCmd) GetMostRecentPodBySelectors(selectors map[string]string) (string, error) { +func (c KubectlCmd) GetMostRecentPodBySelectors(ctx context.Context, + selectors map[string]string) (string, error) { var selector []string for k, v := range selectors { selector = append(selector, fmt.Sprintf("%v=%v", k, v)) } out, err := c.Args("--selector", strings.Join(selector, ","), - "get", "pods", "--sort-by=.status.startTime", "-o", "name").Run() + "get", "pods", "--sort-by=.status.startTime", "-o", "name").Run(ctx) if err != nil { return "", err } @@ -92,8 +93,8 @@ func (c KubectlCmd) DeleteService(service string) *Cmd { return c.Args("delete", "service", service) } -func (c KubectlCmd) GetDeployment(deployment string) (*apps.Deployment, error) { - out, err := c.Args("get", "deployment", deployment, "-o", "json").Run() +func (c KubectlCmd) GetDeployment(ctx context.Context, deployment string) (*apps.Deployment, error) { + out, err := c.Args("get", "deployment", deployment, "-o", "json").Run(ctx) if err != nil { return nil, err } @@ -104,30 +105,30 @@ func (c KubectlCmd) GetDeployment(deployment string) (*apps.Deployment, error) { return &d, nil } -func (c KubectlCmd) GetNamespaces() ([]string, error) { - out, err := c.Args("get", "namespace", "-o", "name").Run() +func (c KubectlCmd) GetNamespaces(ctx context.Context) ([]string, error) { + out, err := c.Args("get", "namespace", "-o", "name").Run(ctx) if err != nil { return nil, err } return parseResources(out, "\n", "namespace/") } -func (c KubectlCmd) GetDeployments() ([]string, error) { - out, err := c.Args("get", "deployment", "-o", "name").Run() +func (c KubectlCmd) GetDeployments(ctx context.Context) ([]string, error) { + out, err := c.Args("get", "deployment", "-o", "name").Run(ctx) if err != nil { return nil, err } return parseResources(out, "\n", "deployment.apps/") } -func (c KubectlCmd) GetPods(selectors map[string]string) ([]string, error) { +func (c KubectlCmd) GetPods(ctx context.Context, selectors map[string]string) ([]string, error) { var selector []string for k, v := range selectors { selector = append(selector, fmt.Sprintf("%v=%v", k, v)) } out, err := c.Args("--selector", strings.Join(selector, ","), "get", "pods", "--sort-by=.status.startTime", - "-o", "name").Run() + "-o", "name").Run(ctx) if err != nil { return nil, err } @@ -142,8 +143,8 @@ func (c KubectlCmd) GetContainers(deployment apps.Deployment) []string { return containers } -func (c KubectlCmd) GetPodsByLabels(labels []string) ([]string, error) { - out, err := c.Args("get", "pods", "-l", strings.Join(labels, ","), "-o", "name", "-A").Run() +func (c KubectlCmd) GetPodsByLabels(ctx context.Context, labels []string) ([]string, error) { + out, err := c.Args("get", "pods", "-l", strings.Join(labels, ","), "-o", "name", "-A").Run(ctx) if err != nil { return nil, err } @@ -154,27 +155,27 @@ func (c KubectlCmd) RestartDeployment(deployment string) *Cmd { return c.Args("rollout", "restart", fmt.Sprintf("deployment/%v", deployment)) } -func (c KubectlCmd) CreateConfigMapFromFile(name, path string) (string, error) { - return c.Args("create", "configmap", name, "--from-file", path).Run() +func (c KubectlCmd) CreateConfigMapFromFile(name, path string) *Cmd { + return c.Args("create", "configmap", name, "--from-file", path) } -func (c KubectlCmd) CreateConfigMap(name string, keyMap map[string]string) (string, error) { +func (c KubectlCmd) CreateConfigMap(name string, keyMap map[string]string) *KubectlCmd { c.Args("create", "configmap", name) for key, value := range keyMap { c.Args(fmt.Sprintf("--from-literal=%v=%v", key, value)) } - return c.Run() + return &c } -func (c KubectlCmd) DeleteConfigMap(name string) (string, error) { - return c.Args("delete", "configmap", name).Run() +func (c KubectlCmd) DeleteConfigMap(name string) *Cmd { + return c.Args("delete", "configmap", name) } -func (c KubectlCmd) GetConfigMapKey(name, key string) (string, error) { +func (c KubectlCmd) GetConfigMapKey(ctx context.Context, name, key string) (string, error) { key = strings.ReplaceAll(key, ".", "\\.") // jsonpath map key is not very fond of dots out, err := c.Args("get", "configmap", name, "-o", - fmt.Sprintf("jsonpath={.data.%v}", key)).Run() + fmt.Sprintf("jsonpath={.data.%v}", key)).Run(ctx) if err != nil { return out, err } @@ -206,7 +207,7 @@ func parseResources(out, delimiter, prefix string) ([]string, error) { return res, nil } -func (c KubectlCmd) KillPidsOnPod(pod, container string, pids []string, murder bool) []error { +func (c KubectlCmd) KillPidsOnPod(ctx context.Context, pod, container string, pids []string, murder bool) []error { var errs []error for _, pid := range pids { cmd := []string{"kill"} @@ -214,7 +215,7 @@ func (c KubectlCmd) KillPidsOnPod(pod, container string, pids []string, murder b cmd = append(cmd, "-s", "9") } cmd = append(cmd, pid) - _, errKill := c.ExecPod(pod, container, cmd).Run() + _, errKill := c.ExecPod(pod, container, cmd).Run(ctx) if errKill != nil { errs = append(errs, errKill) } @@ -222,8 +223,8 @@ func (c KubectlCmd) KillPidsOnPod(pod, container string, pids []string, murder b return errs } -func (c KubectlCmd) GetDeploymentFromConfigMap(deployment, configMapKey string) (*apps.Deployment, error) { - out, err := c.GetConfigMapKey(deployment, configMapKey) +func (c KubectlCmd) GetDeploymentFromConfigMap(ctx context.Context, deployment, configMapKey string) (*apps.Deployment, error) { + out, err := c.GetConfigMapKey(ctx, deployment, configMapKey) if err != nil { return nil, err } @@ -244,8 +245,8 @@ func (_ KubectlCmd) GetContainerFromDeployment(container string, d *apps.Deploym return nil, fmt.Errorf("no container %q found in deployment %q", container, d.Name) } -func (c KubectlCmd) GetPIDsOf(pod, container, process string) (pids []string, err error) { - rawPids, errExec := c.ExecPod(pod, container, []string{"pidof", process}).Run() +func (c KubectlCmd) GetPIDsOf(ctx context.Context, pod, container, process string) (pids []string, err error) { + rawPids, errExec := c.ExecPod(pod, container, []string{"pidof", process}).Run(ctx) if errExec != nil { if errExec.Error() == "exit status 1" { return []string{}, nil @@ -259,32 +260,32 @@ func (c KubectlCmd) GetPIDsOf(pod, container, process string) (pids []string, er return stripped, nil } -func (c KubectlCmd) ValidateNamespace(namespace string) error { - available, err := c.GetNamespaces() +func (c KubectlCmd) ValidateNamespace(ctx context.Context, namespace string) error { + available, err := c.GetNamespaces(ctx) if err != nil { return err } return validateResource("namespace", namespace, "", available) } -func (c KubectlCmd) ValidateDeployment(namespace, deployment string) error { - available, err := c.GetDeployments() +func (c KubectlCmd) ValidateDeployment(ctx context.Context, namespace, deployment string) error { + available, err := c.GetDeployments(ctx) if err != nil { return err } return validateResource("deployment", deployment, fmt.Sprintf("for namespace %q", namespace), available) } -func (c KubectlCmd) ValidatePod(d apps.Deployment, pod *string) error { +func (c KubectlCmd) ValidatePod(ctx context.Context, d apps.Deployment, pod *string) error { if *pod == "" { var err error - *pod, err = c.GetMostRecentPodBySelectors(d.Spec.Selector.MatchLabels) + *pod, err = c.GetMostRecentPodBySelectors(ctx, d.Spec.Selector.MatchLabels) if err != nil || *pod == "" { return err } return nil } - available, err := c.GetPods(d.Spec.Selector.MatchLabels) + available, err := c.GetPods(ctx, d.Spec.Selector.MatchLabels) if err != nil { return err } diff --git a/gograpple.go b/gograpple.go index 64c0cf0..5bd0e0a 100644 --- a/gograpple.go +++ b/gograpple.go @@ -1,6 +1,8 @@ package gograpple import ( + "context" + "github.com/foomo/gograpple/exec" "github.com/sirupsen/logrus" v1 "k8s.io/api/apps/v1" @@ -27,19 +29,23 @@ type Grapple struct { func NewGrapple(l *logrus.Entry, namespace, deployment string) (*Grapple, error) { g := &Grapple{l: l} - g.kubeCmd = exec.NewKubectlCommand(l) - g.dockerCmd = exec.NewDockerCommand(l) - g.goCmd = exec.NewGoCommand(l) + g.kubeCmd = exec.NewKubectlCommand() + g.dockerCmd = exec.NewDockerCommand() + g.goCmd = exec.NewGoCommand() + g.kubeCmd.Logger(l) + g.dockerCmd.Logger(l) + g.goCmd.Logger(l) g.kubeCmd.Args("-n", namespace) - if err := g.kubeCmd.ValidateNamespace(namespace); err != nil { + validateCtx := context.Background() + if err := g.kubeCmd.ValidateNamespace(validateCtx, namespace); err != nil { return nil, err } - if err := g.kubeCmd.ValidateDeployment(namespace, deployment); err != nil { + if err := g.kubeCmd.ValidateDeployment(validateCtx, namespace, deployment); err != nil { return nil, err } - d, err := g.kubeCmd.GetDeployment(deployment) + d, err := g.kubeCmd.GetDeployment(validateCtx, deployment) if err != nil { return nil, err } diff --git a/patch.go b/patch.go index fdee783..9eb91fe 100644 --- a/patch.go +++ b/patch.go @@ -1,6 +1,7 @@ package gograpple import ( + "context" "encoding/json" "fmt" "os" @@ -35,9 +36,10 @@ func (g Grapple) newPatchValues(deployment, container, image string, mounts []Mo } func (g Grapple) Patch(repo, image, tag, container string, mounts []Mount) error { + ctx := context.Background() if g.isPatched() { g.l.Warn("deployment already patched, rolling back first") - if err := g.rollbackUntilUnpatched(); err != nil { + if err := g.rollbackUntilUnpatched(ctx); err != nil { return err } } @@ -53,15 +55,15 @@ func (g Grapple) Patch(repo, image, tag, container string, mounts []Mount) error if err != nil { return err } - _, err = g.kubeCmd.DeleteConfigMap(g.DeploymentConfigMapName()) + _, _ = g.kubeCmd.DeleteConfigMap(g.DeploymentConfigMapName()).Run(ctx) data := map[string]string{defaultConfigMapDeploymentKey: string(bs)} - _, err = g.kubeCmd.CreateConfigMap(g.DeploymentConfigMapName(), data) + _, err = g.kubeCmd.CreateConfigMap(g.DeploymentConfigMapName(), data).Run(ctx) if err != nil { return err } g.l.Infof("waiting for deployment to get ready") - _, err = g.kubeCmd.WaitForRollout(g.deployment.Name, defaultWaitTimeout).Run() + _, err = g.kubeCmd.WaitForRollout(g.deployment.Name, defaultWaitTimeout).Run(ctx) if err != nil { return err } @@ -76,7 +78,7 @@ func (g Grapple) Patch(repo, image, tag, container string, mounts []Mount) error pathedImageName := g.patchedImageName(repo) g.l.Infof("building patch image with %v:%v", pathedImageName, tag) _, err = g.dockerCmd.Build(theHookPath, "--build-arg", - fmt.Sprintf("IMAGE=%v:%v", image, tag), "-t", pathedImageName).Run() + fmt.Sprintf("IMAGE=%v:%v", image, tag), "-t", pathedImageName).Run(ctx) if err != nil { return err } @@ -84,7 +86,7 @@ func (g Grapple) Patch(repo, image, tag, container string, mounts []Mount) error if repo != "" { //contains a repo, push the built image g.l.Infof("pushing patch image with %v:%v", pathedImageName, tag) - _, err = g.dockerCmd.Push(pathedImageName, tag) + _, err = g.dockerCmd.Push(pathedImageName, tag).Run(ctx) if err != nil { return err } @@ -100,7 +102,7 @@ func (g Grapple) Patch(repo, image, tag, container string, mounts []Mount) error } g.l.Infof("patching deployment for development %s with patch %s", g.deployment.Name, patch) - _, err = g.kubeCmd.PatchDeployment(patch, g.deployment.Name).Run() + _, err = g.kubeCmd.PatchDeployment(patch, g.deployment.Name).Run(ctx) return err } @@ -108,7 +110,7 @@ func (g *Grapple) Rollback() error { if !g.isPatched() { return fmt.Errorf("deployment not patched, stopping rollback") } - return g.rollbackUntilUnpatched() + return g.rollbackUntilUnpatched(context.Background()) } func (g Grapple) isPatched() bool { @@ -116,29 +118,29 @@ func (g Grapple) isPatched() bool { return ok } -func (g *Grapple) rollbackUntilUnpatched() error { +func (g *Grapple) rollbackUntilUnpatched(ctx context.Context) error { if !g.isPatched() { return nil } - if err := g.rollback(); err != nil { + if err := g.rollback(ctx); err != nil { return err } if err := g.updateDeployment(); err != nil { return err } - return g.rollbackUntilUnpatched() + return g.rollbackUntilUnpatched(ctx) } -func (g Grapple) rollback() error { +func (g Grapple) rollback(ctx context.Context) error { g.l.Infof("removing ConfigMap %v", g.DeploymentConfigMapName()) - _, err := g.kubeCmd.DeleteConfigMap(g.DeploymentConfigMapName()) + _, err := g.kubeCmd.DeleteConfigMap(g.DeploymentConfigMapName()).Run(ctx) if err != nil { // may not exist g.l.Warn(err) } g.l.Infof("rolling back deployment %v", g.deployment.Name) - _, err = g.kubeCmd.RollbackDeployment(g.deployment.Name).Run() + _, err = g.kubeCmd.RollbackDeployment(g.deployment.Name).Run(ctx) if err != nil { return err } @@ -157,7 +159,7 @@ func (g Grapple) patchedImageName(repo string) string { } func (g *Grapple) updateDeployment() error { - d, err := g.kubeCmd.GetDeployment(g.deployment.Name) + d, err := g.kubeCmd.GetDeployment(context.Background(), g.deployment.Name) if err != nil { return err } diff --git a/shell.go b/shell.go index 6576d8b..6ee47c6 100644 --- a/shell.go +++ b/shell.go @@ -1,21 +1,25 @@ package gograpple -import "fmt" +import ( + "context" + "fmt" +) func (g Grapple) Shell(pod string) error { + ctx := context.Background() if !g.isPatched() { return fmt.Errorf("deployment not patched, stopping shell") } - if err := g.kubeCmd.ValidatePod(g.deployment, &pod); err != nil { + if err := g.kubeCmd.ValidatePod(context.Background(), g.deployment, &pod); err != nil { return err } g.l.Infof("waiting for pod %v with %q", pod, conditionContainersReady) - _, err := g.kubeCmd.WaitForPodState(pod, conditionContainersReady, defaultWaitTimeout).Run() + _, err := g.kubeCmd.WaitForPodState(pod, conditionContainersReady, defaultWaitTimeout).Run(ctx) if err != nil { return err } g.l.Infof("running interactive shell for patched deployment %v", g.deployment.Name) - _, err = g.kubeCmd.ExecShell(fmt.Sprintf("pod/%v", pod), "/").Run() + _, err = g.kubeCmd.ExecShell(fmt.Sprintf("pod/%v", pod), "/").Run(ctx) return err } diff --git a/utils.go b/utils.go index 074ad3f..bf924de 100644 --- a/utils.go +++ b/utils.go @@ -40,15 +40,15 @@ func Open(l *logrus.Entry, ctx context.Context, path string) (string, error) { var cmd *exec.Cmd switch runtime.GOOS { case "linux": - cmd = exec.NewCommand(l, "xdg-open").Args(path) + cmd = exec.NewCommand("xdg-open").Logger(l).Args(path) case "windows": - cmd = exec.NewCommand(l, "rundll32").Args("url.dll,FileProtocolHandler", path) + cmd = exec.NewCommand("rundll32").Logger(l).Args("url.dll,FileProtocolHandler", path) case "darwin": - cmd = exec.NewCommand(l, "open").Args(path) + cmd = exec.NewCommand("open").Logger(l).Args(path) default: return "", fmt.Errorf("unsupported platform") } - return cmd.RunCtx(ctx) + return cmd.Run(ctx) } func TryCall(tries int, waitBetweenAttempts time.Duration, f func(i int) error) error { diff --git a/vscode.go b/vscode.go index 34dc878..db11b5c 100644 --- a/vscode.go +++ b/vscode.go @@ -66,13 +66,13 @@ func launchVSCode(ctx context.Context, l *logrus.Entry, goModDir, host string, p } } - exec.NewCommand(l, "code").Args(openFile).PostEnd(func() error { + exec.NewCommand("code").Logger(l).Args(openFile).PostEnd(func() error { return tryCallWithContext(ctx, tries, 200*time.Millisecond, func(i int) error { l.Infof("waiting for vscode status (%v/%v)", i, tries) - _, err := exec.NewCommand(l, "code").Args("-s").Run() + _, err := exec.NewCommand("code").Logger(l).Args("-s").Run(ctx) return err }) - }).Run() + }).Run(ctx) l.Infof("opening debug configuration") la, err := newLaunchArgs(host, port, workspaceFolder).toJson()