11package cli
22
33import (
4- "bytes"
5- "context"
64 "encoding/base64"
75 "encoding/json"
86 "fmt"
9- "io"
107 "io/ioutil"
118 "net/http"
129 "os"
@@ -16,20 +13,10 @@ import (
1613 "github.com/ahmetalpbalkan/go-cursor"
1714 "github.com/mholt/archiver"
1815 troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
19- collectrunner "github.com/replicatedhq/troubleshoot/pkg/collect"
20- "github.com/replicatedhq/troubleshoot/pkg/logger"
16+ "github.com/replicatedhq/troubleshoot/pkg/collect"
2117 "github.com/spf13/viper"
2218 "github.com/tj/go-spin"
2319 "gopkg.in/yaml.v2"
24- corev1 "k8s.io/api/core/v1"
25- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26- "k8s.io/apimachinery/pkg/fields"
27- "k8s.io/apimachinery/pkg/runtime"
28- "k8s.io/apimachinery/pkg/runtime/schema"
29- "k8s.io/client-go/kubernetes"
30- "k8s.io/client-go/tools/cache"
31- "sigs.k8s.io/controller-runtime/pkg/client"
32- "sigs.k8s.io/controller-runtime/pkg/client/config"
3320)
3421
3522func runTroubleshootNoCRD (v * viper.Viper , arg string ) error {
@@ -119,185 +106,53 @@ the %s Admin Console to begin analysis.`
119106}
120107
121108func runCollectors (v * viper.Viper , collector troubleshootv1beta1.Collector , progressChan chan string ) (string , error ) {
122- cfg , err := config . GetConfig ( )
109+ bundlePath , err := ioutil . TempDir ( "" , "troubleshoot" )
123110 if err != nil {
124111 return "" , err
125112 }
113+ defer os .RemoveAll (bundlePath )
126114
127- client , err := client .New (cfg , client.Options {})
128- if err != nil {
129- return "" , err
130- }
131- clientset , err := kubernetes .NewForConfig (cfg )
115+ versionFilename , err := writeVersionFile (bundlePath )
132116 if err != nil {
133117 return "" , err
134118 }
135- restClient := clientset .CoreV1 ().RESTClient ()
136-
137- serviceAccountName := v .GetString ("serviceaccount" )
138- if serviceAccountName == "" {
139- generatedServiceAccountName , err := createServiceAccount (collector , v .GetString ("namespace" ), clientset )
140- if err != nil {
141- return "" , err
142- }
143- defer removeServiceAccount (generatedServiceAccountName , v .GetString ("namespace" ), clientset )
144-
145- serviceAccountName = generatedServiceAccountName
146- }
147119
148- // deploy an object that "owns" everything to aid in cleanup
149- owner := corev1.ConfigMap {
150- ObjectMeta : metav1.ObjectMeta {
151- Name : fmt .Sprintf ("troubleshoot-%s-owner" , collector .Name ),
152- Namespace : v .GetString ("namespace" ),
153- },
154- TypeMeta : metav1.TypeMeta {
155- APIVersion : "v1" ,
156- Kind : "ConfigMap" ,
157- },
158- Data : make (map [string ]string ),
159- }
160- if err := client .Create (context .Background (), & owner ); err != nil {
161- return "" , err
162- }
163- defer func () {
164- if err := client .Delete (context .Background (), & owner ); err != nil {
165- fmt .Println ("failed to clean up preflight." )
166- }
167- }()
168-
169- // deploy all collectors
170120 desiredCollectors := make ([]* troubleshootv1beta1.Collect , 0 , 0 )
171121 for _ , definedCollector := range collector .Spec {
172122 desiredCollectors = append (desiredCollectors , definedCollector )
173123 }
174124 desiredCollectors = ensureCollectorInList (desiredCollectors , troubleshootv1beta1.Collect {ClusterInfo : & troubleshootv1beta1.ClusterInfo {}})
175125 desiredCollectors = ensureCollectorInList (desiredCollectors , troubleshootv1beta1.Collect {ClusterResources : & troubleshootv1beta1.ClusterResources {}})
176126
177- podsCreated := make ([]* corev1.Pod , 0 , 0 )
178- podsDeleted := make ([]* corev1.Pod , 0 , 0 )
179-
180127 collectorDirs := []string {}
181128
182- bundlePath , err := ioutil .TempDir ("" , "troubleshoot" )
183- if err != nil {
184- return "" , err
185- }
186- defer os .RemoveAll (bundlePath )
187-
188- versionFilename , err := writeVersionFile (bundlePath )
189- if err != nil {
190- return "" , err
191- }
192-
193- resyncPeriod := time .Second
194- ctx := context .Background ()
195- watchList := cache .NewListWatchFromClient (restClient , "pods" , "" , fields .Everything ())
196- _ , controller := cache .NewInformer (watchList , & corev1.Pod {}, resyncPeriod ,
197- cache.ResourceEventHandlerFuncs {
198- UpdateFunc : func (oldObj interface {}, newObj interface {}) {
199- newPod , ok := newObj .(* corev1.Pod )
200- if ! ok {
201- return
202- }
203- oldPod , ok := oldObj .(* corev1.Pod )
204- if ! ok {
205- return
206- }
207- labels := newPod .Labels
208-
209- troubleshootRole , ok := labels ["troubleshoot-role" ]
210- if ! ok || troubleshootRole != "troubleshoot" {
211- return
212- }
213-
214- collectorName , ok := labels ["troubleshoot" ]
215- if ! ok || collectorName != collector .Name {
216- return
217- }
218-
219- if oldPod .Status .Phase == newPod .Status .Phase {
220- return
221- }
222-
223- if newPod .Status .Phase == corev1 .PodFailed {
224- podsDeleted = append (podsDeleted , newPod )
225- return
226- }
227-
228- if newPod .Status .Phase != corev1 .PodSucceeded {
229- return
230- }
231-
232- podLogOpts := corev1.PodLogOptions {}
233-
234- req := clientset .CoreV1 ().Pods (newPod .Namespace ).GetLogs (newPod .Name , & podLogOpts )
235- podLogs , err := req .Stream ()
236- if err != nil {
237- fmt .Println ("get stream" )
238- return
239- }
240- defer podLogs .Close ()
241-
242- buf := new (bytes.Buffer )
243- _ , err = io .Copy (buf , podLogs )
244- if err != nil {
245- fmt .Println ("copy logs" )
246- return
247- }
248-
249- collectorDir , err := parseAndSaveCollectorOutput (buf .String (), bundlePath )
250- if err != nil {
251- logger .Printf ("parse collected data: %v\n " , err )
252- return
253- }
254-
255- // empty dir name will make tar fail
256- if collectorDir == "" {
257- logger .Printf ("pod %s did not return any files\n " , newPod .Name )
258- return
259- }
260-
261- progressChan <- collectorDir
262- collectorDirs = append (collectorDirs , collectorDir )
263-
264- if err := client .Delete (context .Background (), newPod ); err != nil {
265- fmt .Println ("delete pod error" , err )
266- }
267- podsDeleted = append (podsDeleted , newPod )
268- },
269- })
270- go func () {
271- controller .Run (ctx .Done ())
272- }()
129+ // Run preflights collectors synchronously
130+ for _ , desiredCollector := range desiredCollectors {
131+ collector := collect.Collector {
132+ Redact : true ,
133+ Collect : desiredCollector ,
134+ }
273135
274- s := runtime .NewScheme ()
275- s .AddKnownTypes (schema.GroupVersion {Group : "" , Version : "v1" }, & corev1.ConfigMap {})
276- for _ , collect := range desiredCollectors {
277- _ , pod , err := collectrunner .CreateCollector (client , s , & owner , collector .Name , v .GetString ("namespace" ), serviceAccountName , "troubleshoot" , collect , v .GetString ("image" ), v .GetString ("pullpolicy" ))
136+ result , err := collector .RunCollectorSync ()
278137 if err != nil {
279- logger . Printf ( "A collector pod cannot be created: %v \n " , err )
138+ progressChan <- fmt . Sprintf ( "failed to run collector %v " , collector )
280139 continue
281140 }
282- podsCreated = append (podsCreated , pod )
283- }
284141
285- start := time .Now ()
286- for {
287- if start .Add (time .Second * 30 ).Before (time .Now ()) {
288- fmt .Println ("timeout running troubleshoot" )
289- return "" , err
142+ collectorDir , err := parseAndSaveCollectorOutput (string (result ), bundlePath )
143+ if err != nil {
144+ progressChan <- fmt .Sprintf ("failed to parse collector spec: %v" , collector )
145+ continue
290146 }
291147
292- if len ( podsDeleted ) == len ( podsCreated ) {
293- break
148+ if collectorDir == "" {
149+ continue
294150 }
295151
296- time .Sleep (time .Millisecond * 200 )
152+ progressChan <- collectorDir
153+ collectorDirs = append (collectorDirs , collectorDir )
297154 }
298155
299- ctx .Done ()
300-
301156 tarGz := archiver.TarGz {
302157 Tar : & archiver.Tar {
303158 ImplicitTopLevelFolder : false ,
0 commit comments