1
1
package cli
2
2
3
3
import (
4
- "bytes"
5
- "context"
6
4
"encoding/base64"
7
5
"encoding/json"
8
6
"fmt"
9
- "io"
10
7
"io/ioutil"
11
8
"net/http"
12
9
"os"
@@ -18,22 +15,11 @@ import (
18
15
"github.com/pkg/errors"
19
16
analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
20
17
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
21
- collectrunner "github.com/replicatedhq/troubleshoot/pkg/collect"
18
+ "github.com/replicatedhq/troubleshoot/pkg/collect"
22
19
"github.com/replicatedhq/troubleshoot/pkg/logger"
23
20
"github.com/spf13/viper"
24
21
"github.com/tj/go-spin"
25
22
"gopkg.in/yaml.v2"
26
- corev1 "k8s.io/api/core/v1"
27
- kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
28
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29
- "k8s.io/apimachinery/pkg/fields"
30
- "k8s.io/apimachinery/pkg/runtime"
31
- "k8s.io/apimachinery/pkg/runtime/schema"
32
- types "k8s.io/apimachinery/pkg/types"
33
- "k8s.io/client-go/kubernetes"
34
- "k8s.io/client-go/tools/cache"
35
- "sigs.k8s.io/controller-runtime/pkg/client"
36
- "sigs.k8s.io/controller-runtime/pkg/client/config"
37
23
)
38
24
39
25
func runPreflightsNoCRD (v * viper.Viper , arg string ) error {
@@ -143,174 +129,36 @@ func runPreflightsNoCRD(v *viper.Viper, arg string) error {
143
129
}
144
130
145
131
func runCollectors (v * viper.Viper , preflight troubleshootv1beta1.Preflight ) (map [string ][]byte , error ) {
146
- cfg , err := config .GetConfig ()
147
- if err != nil {
148
- return nil , err
149
- }
150
-
151
- client , err := client .New (cfg , client.Options {})
152
- if err != nil {
153
- return nil , err
154
- }
155
- clientset , err := kubernetes .NewForConfig (cfg )
156
- if err != nil {
157
- return nil , err
158
- }
159
- restClient := clientset .CoreV1 ().RESTClient ()
160
-
161
- serviceAccountName := v .GetString ("serviceaccount" )
162
- if serviceAccountName == "" {
163
- generatedServiceAccountName , err := createServiceAccount (preflight , v .GetString ("namespace" ), clientset )
164
- if err != nil {
165
- return nil , err
166
- }
167
- defer removeServiceAccount (generatedServiceAccountName , v .GetString ("namespace" ), clientset )
168
-
169
- serviceAccountName = generatedServiceAccountName
170
- }
171
-
172
- // deploy an object that "owns" everything to aid in cleanup
173
- configMapNamespacedName := types.NamespacedName {
174
- Name : fmt .Sprintf ("preflight-%s-owner" , preflight .Name ),
175
- Namespace : v .GetString ("namespace" ),
176
- }
177
-
178
- foundConfigMap := & corev1.ConfigMap {}
179
- err = client .Get (context .Background (), configMapNamespacedName , foundConfigMap )
180
- if err == nil || ! kuberneteserrors .IsNotFound (err ) {
181
- return nil , errors .Wrap (err , "failed to get existing config map" )
182
- }
183
- owner := corev1.ConfigMap {
184
- ObjectMeta : metav1.ObjectMeta {
185
- Name : configMapNamespacedName .Name ,
186
- Namespace : configMapNamespacedName .Namespace ,
187
- },
188
- TypeMeta : metav1.TypeMeta {
189
- APIVersion : "v1" ,
190
- Kind : "ConfigMap" ,
191
- },
192
- Data : make (map [string ]string ),
193
- }
194
- if err := client .Create (context .Background (), & owner ); err != nil {
195
- return nil , errors .Wrap (err , "failed to create config map" )
196
- }
197
- defer func () {
198
- if err := client .Delete (context .Background (), & owner ); err != nil {
199
- fmt .Println ("failed to clean up preflight." )
200
- }
201
- }()
202
-
203
- // deploy all collectors
204
132
desiredCollectors := make ([]* troubleshootv1beta1.Collect , 0 , 0 )
205
133
for _ , definedCollector := range preflight .Spec .Collectors {
206
134
desiredCollectors = append (desiredCollectors , definedCollector )
207
135
}
208
136
desiredCollectors = ensureCollectorInList (desiredCollectors , troubleshootv1beta1.Collect {ClusterInfo : & troubleshootv1beta1.ClusterInfo {}})
209
137
desiredCollectors = ensureCollectorInList (desiredCollectors , troubleshootv1beta1.Collect {ClusterResources : & troubleshootv1beta1.ClusterResources {}})
210
138
211
- podsCreated := make ([]* corev1.Pod , 0 , 0 )
212
- podsDeleted := make ([]* corev1.Pod , 0 , 0 )
213
139
allCollectedData := make (map [string ][]byte )
214
140
215
- resyncPeriod := time .Second
216
- ctx := context .Background ()
217
- watchList := cache .NewListWatchFromClient (restClient , "pods" , "" , fields .Everything ())
218
- _ , controller := cache .NewInformer (watchList , & corev1.Pod {}, resyncPeriod ,
219
- cache.ResourceEventHandlerFuncs {
220
- UpdateFunc : func (oldObj interface {}, newObj interface {}) {
221
- newPod , ok := newObj .(* corev1.Pod )
222
- if ! ok {
223
- return
224
- }
225
- oldPod , ok := oldObj .(* corev1.Pod )
226
- if ! ok {
227
- return
228
- }
229
- labels := newPod .Labels
230
- troubleshootRole , ok := labels ["troubleshoot-role" ]
231
- if ! ok || troubleshootRole != "preflight" {
232
- return
233
- }
234
- preflightName , ok := labels ["preflight" ]
235
- if ! ok || preflightName != preflight .Name {
236
- return
237
- }
238
-
239
- if oldPod .Status .Phase == newPod .Status .Phase {
240
- return
241
- }
242
-
243
- if newPod .Status .Phase == corev1 .PodFailed {
244
- podsDeleted = append (podsDeleted , newPod )
245
- return
246
- }
247
-
248
- if newPod .Status .Phase != corev1 .PodSucceeded {
249
- return
250
- }
251
-
252
- podLogOpts := corev1.PodLogOptions {}
253
-
254
- req := clientset .CoreV1 ().Pods (newPod .Namespace ).GetLogs (newPod .Name , & podLogOpts )
255
- podLogs , err := req .Stream ()
256
- if err != nil {
257
- fmt .Println ("get stream" )
258
- return
259
- }
260
- defer podLogs .Close ()
261
-
262
- buf := new (bytes.Buffer )
263
- _ , err = io .Copy (buf , podLogs )
264
- if err != nil {
265
- fmt .Println ("copy logs" )
266
- return
267
- }
268
-
269
- collectedData , err := parseCollectorOutput (buf .String ())
270
- if err != nil {
271
- logger .Printf ("parse collected data: %v\n " , err )
272
- return
273
- }
274
- for k , v := range collectedData {
275
- allCollectedData [k ] = v
276
- }
277
-
278
- if err := client .Delete (context .Background (), newPod ); err != nil {
279
- fmt .Println ("delete pod" )
280
- }
281
- podsDeleted = append (podsDeleted , newPod )
282
- },
283
- })
284
- go func () {
285
- controller .Run (ctx .Done ())
286
- }()
141
+ // Run preflights collectors synchronously
142
+ for _ , desiredCollector := range desiredCollectors {
143
+ collector := collect.Collector {
144
+ Redact : true ,
145
+ Collect : desiredCollector ,
146
+ }
287
147
288
- s := runtime .NewScheme ()
289
- s .AddKnownTypes (schema.GroupVersion {Group : "" , Version : "v1" }, & corev1.ConfigMap {})
290
- for _ , collector := range desiredCollectors {
291
- _ , pod , err := collectrunner .CreateCollector (client , s , & owner , preflight .Name , v .GetString ("namespace" ), serviceAccountName , "preflight" , collector , v .GetString ("image" ), v .GetString ("pullpolicy" ))
148
+ result , err := collector .RunCollectorSync ()
292
149
if err != nil {
293
- return nil , errors .Wrap (err , "failed to create collector" )
150
+ return nil , errors .Wrap (err , "failed to run collector" )
294
151
}
295
- podsCreated = append (podsCreated , pod )
296
- }
297
152
298
- start := time .Now ()
299
- for {
300
- if start .Add (time .Second * 30 ).Before (time .Now ()) {
301
- fmt .Println ("timeout running preflight" )
302
- return nil , err
153
+ output , err := parseCollectorOutput (string (result ))
154
+ if err != nil {
155
+ return nil , errors .Wrap (err , "failed to parse collector output" )
303
156
}
304
-
305
- if len (podsDeleted ) == len (podsCreated ) {
306
- break
157
+ for k , v := range output {
158
+ allCollectedData [k ] = v
307
159
}
308
-
309
- time .Sleep (time .Millisecond * 200 )
310
160
}
311
161
312
- ctx .Done ()
313
-
314
162
return allCollectedData , nil
315
163
}
316
164
0 commit comments