Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ require (
github.com/mitchellh/go-ps v1.0.0
github.com/nais/device v0.0.0-20250703090236-08bd8b276591
github.com/nais/liberator v0.0.0-20250703075635-7da81032e1ae
github.com/nais/naistrix v0.3.1
github.com/nais/naistrix v0.4.0
github.com/pterm/pterm v0.12.81
github.com/savioxavier/termlink v1.4.3
github.com/sethvargo/go-retry v0.3.0
Expand Down Expand Up @@ -70,6 +70,7 @@ require (
dario.cat/mergo v1.0.2 // indirect
github.com/AlekSi/pointer v1.2.0 // indirect
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect
github.com/MakeNowJust/heredoc v1.0.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.3.1 // indirect
github.com/Masterminds/sprig/v3 v3.3.0 // indirect
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ github.com/GoogleCloudPlatform/cloudsql-proxy v1.37.7 h1:+ugXZyYXIb2NFWaXleLbouy
github.com/GoogleCloudPlatform/cloudsql-proxy v1.37.7/go.mod h1:9iAgV6bpVWBq2BpG4J691fNCdKYd4JqR5ey9m4odfHE=
github.com/Khan/genqlient v0.8.1 h1:wtOCc8N9rNynRLXN3k3CnfzheCUNKBcvXmVv5zt6WCs=
github.com/Khan/genqlient v0.8.1/go.mod h1:R2G6DzjBvCbhjsEajfRjbWdVglSH/73kSivC9TLWVjU=
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/MakeNowJust/heredoc/v2 v2.0.1 h1:rlCHh70XXXv7toz95ajQWOWQnN4WNLt0TdpZYIR/J6A=
github.com/MakeNowJust/heredoc/v2 v2.0.1/go.mod h1:6/2Abh5s+hc3g9nbWLe9ObDIOhaRrqsyY9MWy+4JdRM=
github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs=
Expand Down Expand Up @@ -414,8 +416,8 @@ github.com/nais/device v0.0.0-20250703090236-08bd8b276591 h1:MgFQR6KwI6nB8Dl8c6I
github.com/nais/device v0.0.0-20250703090236-08bd8b276591/go.mod h1:5EJDz4LiIliyvsUZb8gRDwpqihR7r4J+T4pJxUjBc9I=
github.com/nais/liberator v0.0.0-20250703075635-7da81032e1ae h1:aZqDazMXxDdL1qSG9SpTMm+WZYY0RJp0yTrs8TSzJ+0=
github.com/nais/liberator v0.0.0-20250703075635-7da81032e1ae/go.mod h1:Z0ycpT5Ug9Edacd5173bShlh9vCtogCwoLCbjv/pz18=
github.com/nais/naistrix v0.3.1 h1:9/S297620cAtbFRN51105kJNKKVBXasa2ALmWbrITlM=
github.com/nais/naistrix v0.3.1/go.mod h1:lLHnRUy/wzrjr79pH1PqdzUDc3N7hp9Ex+H76RytWAw=
github.com/nais/naistrix v0.4.0 h1:Pf3bdnhWSnVDqwoJ496ZyupXvv5Gf4uu6BKXhFmj0CA=
github.com/nais/naistrix v0.4.0/go.mod h1:KQj7//htD3ZW/93v+6eyHjL/x6w93sc5dUBFCC/QdKY=
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
Expand Down
4 changes: 2 additions & 2 deletions internal/application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func newApplication(flags *root.Flags) *naistrix.Application {
func Run(ctx context.Context, w io.Writer) error {
flags := &root.Flags{}
app := newApplication(flags)
executedCommand, err := app.Run(ctx, naistrix.NewWriter(w), os.Args[1:])
err := app.Run(naistrix.RunWithContext(ctx), naistrix.RunWithOutput(naistrix.NewWriter(w)))
autoComplete := slices.Contains(os.Args[1:], "__complete")

if !autoComplete {
Expand All @@ -57,7 +57,7 @@ func Run(ctx context.Context, w io.Writer) error {
}()
}

if !autoComplete && executedCommand != nil {
if executedCommand := app.ExecutedCommand(); !autoComplete && executedCommand != nil {
collectCommandHistogram(ctx, executedCommand, err)
}

Expand Down
2 changes: 1 addition & 1 deletion internal/application/application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func runCommand(t *testing.T, ctx context.Context, cmd *naistrix.Command, parent
t.Fatalf("failed to run command %q: %v", strings.Join(helpCmd, " "), err)
}
}()
_, err := newApplication(&root.Flags{}).Run(ctx, naistrix.Discard(), helpCmd)
err := newApplication(&root.Flags{}).Run(naistrix.RunWithContext(ctx), naistrix.RunWithOutput(naistrix.Discard()), naistrix.RunWithArgs(helpCmd))
if err != nil {
t.Fatalf("failed to run command %s: %v", strings.Join(helpCmd, " "), err)
}
Expand Down
19 changes: 11 additions & 8 deletions internal/debug/command.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,41 @@
package debug

import (
"context"
"fmt"

"github.com/nais/cli/internal/debug/command/flag"
"github.com/nais/cli/internal/k8s"
"k8s.io/client-go/kubernetes"
)

const debugImageDefault = "europe-north1-docker.pkg.dev/nais-io/nais/images/debug:latest"

func Run(workloadName string, flags *flag.Debug) error {
clientSet, err := SetupClient(flags.DebugSticky, flags.Context)
func Run(ctx context.Context, workloadName string, flags *flag.Debug) error {
clientSet, err := SetupClient(flags, flags.Context)
if err != nil {
return err
}

dg := Setup(clientSet, flags.DebugSticky, workloadName, debugImageDefault, flags.ByPod)
if err := dg.Debug(); err != nil {
dg := &Debug{
podsClient: clientSet.CoreV1().Pods(flags.Namespace),
flags: flags,
workloadName: workloadName,
}
if err := dg.Debug(ctx); err != nil {
return fmt.Errorf("debugging instance: %w", err)
}

return nil
}

func SetupClient(flags *flag.DebugSticky, cluster flag.Context) (kubernetes.Interface, error) {
func SetupClient(flags *flag.Debug, cluster flag.Context) (kubernetes.Interface, error) {
client := k8s.SetupControllerRuntimeClient(k8s.WithKubeContext(string(cluster)))

if flags.Namespace == "" {
flags.Namespace = client.CurrentNamespace
}

if cluster != "" {
flags.Context = flag.Context(cluster)
flags.Context = cluster
}

clientSet, err := k8s.SetupClientGo(string(cluster))
Expand Down
42 changes: 6 additions & 36 deletions internal/debug/command/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,70 +2,40 @@ package command

import (
"context"
"time"

"github.com/MakeNowJust/heredoc/v2"
"github.com/nais/cli/internal/debug"
"github.com/nais/cli/internal/debug/command/flag"
"github.com/nais/cli/internal/debug/tidy"
"github.com/nais/cli/internal/k8s"
"github.com/nais/cli/internal/root"
"github.com/nais/naistrix"
)

func Debug(parentFlags *root.Flags) *naistrix.Command {
defaultContext, defaultNamespace := k8s.GetDefaultContextAndNamespace()
stickyFlags := &flag.DebugSticky{
flags := &flag.Debug{
Flags: parentFlags,
Context: flag.Context(defaultContext),
Namespace: defaultNamespace,
}

debugFlags := &flag.Debug{
DebugSticky: stickyFlags,
TTL: 24 * time.Hour,
Timeout: 30 * time.Second,
}

return &naistrix.Command{
Name: "debug",
Title: "Create and attach to a debug container.",
Description: heredoc.Doc(`
When flag "--copy" is set, the command can be used to debug a copy of the original pod, allowing you to troubleshoot without affecting the live pod.
When "--copy" is used the command can be used to debug a copy of the original pod, allowing you to troubleshoot without affecting the live pod.

To debug a live pod, run the command without the "--copy" flag.

You can only reconnect to the debug session if the pod is running.
`),
Args: []naistrix.Argument{
{Name: "app_name"},
},
Flags: debugFlags,
StickyFlags: stickyFlags,
RunFunc: func(ctx context.Context, out naistrix.Output, args []string) error {
return debug.Run(args[0], debugFlags)
},
SubCommands: []*naistrix.Command{
tidyCommand(stickyFlags),
},
}
}

func tidyCommand(parentFlags *flag.DebugSticky) *naistrix.Command {
flags := &flag.DebugTidy{
DebugSticky: parentFlags,
}
return &naistrix.Command{
Name: "tidy",
Title: "Clean up debug containers and debug pods.",
Description: heredoc.Doc(`
Remove debug containers created by the "nais debug" command.

Set the "--copy" flag to delete copy pods.
`),
Args: []naistrix.Argument{
{Name: "app_name"},
},
Flags: flags,
RunFunc: func(ctx context.Context, out naistrix.Output, args []string) error {
return tidy.Run(args[0], flags)
return debug.Run(ctx, args[0], flags)
},
}
}
24 changes: 9 additions & 15 deletions internal/debug/command/flag/flag.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
package flag

import (
"time"

"github.com/nais/cli/internal/root"
)

type (
Context string
DebugSticky struct {
*root.Flags
Context Context `name:"context" short:"c" usage:"The kubeconfig |CONTEXT| to use. Defaults to current context."`
Namespace string `name:"namespace" short:"n" usage:"The kubernetes |NAMESPACE| to use. Defaults to current namespace."`
Copy bool `name:"copy" usage:"Create a copy of the pod with a debug container. The original pod remains running and unaffected."`
}
)
type Context string

type Debug struct {
*DebugSticky
ByPod bool `name:"by-pod" short:"b" usage:"Attach to a specific |BY-POD| in a workload."`
}

type DebugTidy struct {
*DebugSticky
*root.Flags
Context Context `short:"c" usage:"The kubeconfig |context| to use. Defaults to current context."`
Namespace string `short:"n" usage:"The kubernetes |namespace| to use. Defaults to current namespace."`
Copy bool `usage:"Create a copy of the pod with a debug container. The original pod remains running and unaffected."`
TTL time.Duration `usage:"|Duration| the debug pod remains after exit. Only has effect when --copy is specified."`
Timeout time.Duration `usage:"|Duration| to wait for each remote interaction this command does. Usually the default is sufficient."`
}
Loading