@@ -2,11 +2,18 @@ package cmd
2
2
3
3
import (
4
4
"fmt"
5
+ "io"
6
+ "text/tabwriter"
5
7
6
- "github.com/davecgh/go-spew/spew"
7
8
"github.com/fntlnz/kubectl-trace/pkg/factory"
9
+ "github.com/fntlnz/kubectl-trace/pkg/meta"
10
+ "github.com/fntlnz/kubectl-trace/pkg/tracejob"
8
11
"github.com/spf13/cobra"
12
+ "k8s.io/apimachinery/pkg/types"
9
13
"k8s.io/cli-runtime/pkg/genericclioptions"
14
+ batchv1client "k8s.io/client-go/kubernetes/typed/batch/v1"
15
+ corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
16
+ "k8s.io/client-go/rest"
10
17
)
11
18
12
19
var (
@@ -38,12 +45,14 @@ type GetOptions struct {
38
45
genericclioptions.IOStreams
39
46
ResourceBuilderFlags * genericclioptions.ResourceBuilderFlags
40
47
41
- namespace string
42
- explicitNamespace bool
48
+ namespace string
43
49
44
50
// Local to this command
45
51
allNamespaces bool
46
52
traceArg string
53
+ clientConfig * rest.Config
54
+ traceID * types.UID
55
+ traceName * string
47
56
}
48
57
49
58
// NewGetOptions provides an instance of GetOptions with default values.
@@ -62,7 +71,7 @@ func NewGetCommand(factory factory.Factory, streams genericclioptions.IOStreams)
62
71
o := NewGetOptions (streams )
63
72
64
73
cmd := & cobra.Command {
65
- Use : fmt .Sprintf ("%s [ TRACE_ID] " , getCommand ),
74
+ Use : fmt .Sprintf ("%s ( TRACE_ID | TRACE_NAME) " , getCommand ),
66
75
Short : getShort ,
67
76
Long : getLong , // wrap with templates.LongDesc()
68
77
Example : fmt .Sprintf (getExamples , "kubectl" ), // wrap with templates.Examples()
@@ -87,57 +96,97 @@ func NewGetCommand(factory factory.Factory, streams genericclioptions.IOStreams)
87
96
return cmd
88
97
}
89
98
90
- // Validate validates the arguments and flags populating GetOptions accordingly.
91
99
func (o * GetOptions ) Validate (cmd * cobra.Command , args []string ) error {
92
100
switch len (args ) {
93
- case 0 :
94
- break
95
101
case 1 :
96
- o .traceArg = args [0 ]
102
+ if meta .IsObjectName (args [0 ]) {
103
+ o .traceName = & args [0 ]
104
+ } else {
105
+ tid := types .UID (args [0 ])
106
+ o .traceID = & tid
107
+ }
97
108
break
98
- default :
99
- return fmt .Errorf (argumentsErr )
100
109
}
101
110
102
111
return nil
103
112
}
104
113
105
- // Complete completes the setup of the command.
106
114
func (o * GetOptions ) Complete (factory factory.Factory , cmd * cobra.Command , args []string ) error {
107
115
// Prepare namespace
108
116
var err error
109
- o .namespace , o . explicitNamespace , _ = factory .ToRawKubeConfigLoader ().Namespace ()
117
+ o .namespace , _ , err = factory .ToRawKubeConfigLoader ().Namespace ()
110
118
if err != nil {
111
119
return err
112
120
}
113
121
114
122
// All namespaces, when present, overrides namespace flag
115
123
if cmd .Flag ("all-namespaces" ).Changed {
116
124
o .allNamespaces = * o .ResourceBuilderFlags .AllNamespaces
117
- o .explicitNamespace = false
118
125
o .namespace = ""
119
126
}
120
- // Need either a namespace, a trace ID, or all namespaces
121
- if o .traceArg == "" && ! o .allNamespaces && ! o .explicitNamespace {
122
- return fmt .Errorf (missingTargetErr )
123
- }
124
127
125
- // todo > init printers (need o.PrintFlags)
126
-
127
- // todo > setup printer
128
- // printer, err := o.PrintFlags.ToPrinter()
129
- // if err != nil {
130
- // return err
131
- // }
132
- // o.print = func(obj runtime.Object) error {
133
- // return printer.PrintObj(obj, o.Out)
134
- // }
128
+ //// Prepare client
129
+ o .clientConfig , err = factory .ToRESTConfig ()
130
+ if err != nil {
131
+ return err
132
+ }
135
133
136
134
return nil
137
135
}
138
136
139
- // Run executes the get command.
140
137
func (o * GetOptions ) Run () error {
141
- spew .Dump (o )
138
+ jobsClient , err := batchv1client .NewForConfig (o .clientConfig )
139
+ if err != nil {
140
+ return err
141
+ }
142
+
143
+ coreClient , err := corev1client .NewForConfig (o .clientConfig )
144
+ if err != nil {
145
+ return err
146
+ }
147
+
148
+ tc := & tracejob.TraceJobClient {
149
+ JobClient : jobsClient .Jobs (o .namespace ),
150
+ ConfigClient : coreClient .ConfigMaps (o .namespace ),
151
+ }
152
+
153
+ tc .WithOutStream (o .Out )
154
+
155
+ tf := tracejob.TraceJobFilter {
156
+ Name : o .traceName ,
157
+ ID : o .traceID ,
158
+ }
159
+
160
+ jobs , err := tc .GetJob (tf )
161
+
162
+ if err != nil {
163
+ return err
164
+ }
165
+
166
+ // TODO: support other output formats via the o flag, like json, yaml. Not sure if a good idea, trace is not a resource in k8s
167
+ jobsTablePrint (o .Out , jobs )
142
168
return nil
143
169
}
170
+
171
+ // TODO(fntlnz): This needs better printing, perhaps we could use the humanreadable table from k8s itself
172
+ // to be consistent with the main project.
173
+ func jobsTablePrint (o io.Writer , jobs []tracejob.TraceJob ) {
174
+ format := "%s\t %s\t %s\t %s\t %s\t "
175
+ if len (jobs ) == 0 {
176
+ fmt .Println ("No resources found." )
177
+ return
178
+ }
179
+ // initialize tabwriter
180
+ w := new (tabwriter.Writer )
181
+ // minwidth, tabwidth, padding, padchar, flags
182
+ w .Init (o , 8 , 8 , 0 , '\t' , 0 )
183
+ defer w .Flush ()
184
+
185
+ // TODO(fntlnz): Do the status and age fields, we don't have a way to get them now, so reporting
186
+ // them as missing.
187
+ fmt .Fprintf (w , format , "NAMESPACE" , "NODE" , "NAME" , "STATUS" , "AGE" )
188
+ for _ , j := range jobs {
189
+ fmt .Fprintf (w , "\n " + format , j .Namespace , j .Hostname , j .Name , "<missing>" , "<missing>" )
190
+ }
191
+ fmt .Fprintf (w , "\n " )
192
+ }
0 commit comments