Skip to content

Commit e276eac

Browse files
leodidofntlnz
authored andcommitted
feat(pkg/cmd): run command
1 parent db2296e commit e276eac

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed

pkg/cmd/run.go

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/davecgh/go-spew/spew"
7+
"github.com/fntlnz/kubectl-trace/factory"
8+
"github.com/spf13/cobra"
9+
"k8s.io/cli-runtime/pkg/genericclioptions"
10+
// "k8s.io/kubernetes/pkg/kubectl/util/templates"
11+
)
12+
13+
var (
14+
runShort = `Execute a bpftrace program on resources` // Wrap with i18n.T()
15+
16+
runLong = runShort
17+
18+
runExamples = `
19+
# Count system calls using tracepoints on a specific node
20+
%[1]s trace run node/kubernetes-node-emt8.c.myproject.internal -e 'kprobe:do_sys_open { printf("%s: %s\n", comm, str(arg1)) }'
21+
22+
# Execute a bpftrace program from file on a specific node
23+
%[1]s trace run node/kubernetes-node-emt8.c.myproject.internal -p read.bt
24+
25+
# Run an bpftrace inline program on a pod container
26+
%[1]s trace run pod/nginx -c nginx -e "tracepoint:syscalls:sys_enter_* { @[probe] = count(); }"
27+
%[1]s trace run pod/nginx nginx -e "tracepoint:syscalls:sys_enter_* { @[probe] = count(); }"`
28+
29+
runCommand = "run"
30+
usageString = "(POD | TYPE/NAME)"
31+
requiredArgErrString = fmt.Sprintf("%s is a required argument for the %s command", usageString, runCommand)
32+
containerAsArgOrFlagErrString = "specify container inline as argument or via its flag"
33+
bpftraceMissingErrString = "the bpftrace program is mandatory"
34+
)
35+
36+
// RunOptions ...
37+
type RunOptions struct {
38+
genericclioptions.IOStreams
39+
40+
namespace string
41+
42+
// Local to this command
43+
container string
44+
eval string
45+
program string
46+
resourceArg string
47+
}
48+
49+
// NewRunOptions provides an instance of RunOptions with default values.
50+
func NewRunOptions(streams genericclioptions.IOStreams) *RunOptions {
51+
return &RunOptions{
52+
IOStreams: streams,
53+
}
54+
}
55+
56+
// NewRunCommand provides the run command wrapping RunOptions.
57+
func NewRunCommand(factory factory.Factory, streams genericclioptions.IOStreams) *cobra.Command {
58+
o := NewRunOptions(streams)
59+
60+
cmd := &cobra.Command{
61+
Use: fmt.Sprintf("%s %s [-c CONTAINER]", runCommand, usageString),
62+
Short: runShort,
63+
Long: runLong, // Wrap with templates.LongDesc()
64+
Example: fmt.Sprintf(runExamples, "kubectl"), // Wrap with templates.Examples()
65+
SilenceUsage: true,
66+
PreRunE: func(c *cobra.Command, args []string) error {
67+
return o.Validate(c, args)
68+
},
69+
RunE: func(c *cobra.Command, args []string) error {
70+
if err := o.Complete(factory, c, args); err != nil {
71+
return err
72+
}
73+
return nil
74+
},
75+
}
76+
77+
cmd.Flags().StringVarP(&o.container, "container", "c", o.container, "Specify the container")
78+
cmd.Flags().StringVarP(&o.eval, "eval", "e", "", "Literal string to be evaluated as a bpftrace program")
79+
cmd.Flags().StringVarP(&o.program, "program", "p", "", "File containing a bpftrace program")
80+
81+
return cmd
82+
}
83+
84+
// Validate validates the arguments and flags populating RunOptions accordingly.
85+
func (o *RunOptions) Validate(cmd *cobra.Command, args []string) error {
86+
containerDefined := cmd.Flag("container").Changed
87+
switch len(args) {
88+
case 1:
89+
o.resourceArg = args[0]
90+
if !containerDefined {
91+
return fmt.Errorf(containerAsArgOrFlagErrString)
92+
}
93+
break
94+
// 2nd argument interpreted as container when provided
95+
case 2:
96+
o.resourceArg = args[0]
97+
o.container = args[1]
98+
if containerDefined {
99+
return fmt.Errorf(containerAsArgOrFlagErrString)
100+
}
101+
break
102+
default:
103+
return fmt.Errorf(requiredArgErrString)
104+
}
105+
106+
if !cmd.Flag("eval").Changed && !cmd.Flag("program").Changed {
107+
return fmt.Errorf(bpftraceMissingErrString)
108+
}
109+
110+
// todo > complete validation
111+
// - make errors
112+
// - make validators
113+
if len(o.container) == 0 {
114+
return fmt.Errorf("invalid container")
115+
}
116+
// if len(o.eval) == 0 || file not exist(o.program) || file is empty(o.program) {
117+
// return fmt.Errorf("invalid bpftrace program")
118+
// }
119+
120+
return nil
121+
}
122+
123+
// Complete completes the setup of the command.
124+
func (o *RunOptions) Complete(factory factory.Factory, cmd *cobra.Command, args []string) error {
125+
spew.Dump(o)
126+
127+
o.namespace, _, _ = factory.ToRawKubeConfigLoader().Namespace()
128+
129+
spew.Dump(o)
130+
131+
// get resource by pof | type/name
132+
// get container
133+
134+
return nil
135+
}

0 commit comments

Comments
 (0)