@@ -12,6 +12,7 @@ import (
1212 "time"
1313
1414 "github.com/ahmetalpbalkan/go-cursor"
15+ "github.com/fatih/color"
1516 "github.com/pkg/errors"
1617 analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
1718 troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
@@ -65,22 +66,35 @@ func runPreflights(v *viper.Viper, arg string) error {
6566
6667 s := spin .New ()
6768 finishedCh := make (chan bool , 1 )
69+ progressChan := make (chan interface {}, 0 ) // non-zero buffer will result in missed messages
6870 go func () {
6971 for {
7072 select {
71- case <- finishedCh :
72- fmt .Printf ("\r " )
73- return
73+ case msg , ok := <- progressChan :
74+ if ! ok {
75+ continue
76+ }
77+ switch msg := msg .(type ) {
78+ case error :
79+ c := color .New (color .FgHiRed )
80+ c .Println (fmt .Sprintf ("%s\r * %v" , cursor .ClearEntireLine (), msg ))
81+ case string :
82+ c := color .New (color .FgCyan )
83+ c .Println (fmt .Sprintf ("%s\r * %s" , cursor .ClearEntireLine (), msg ))
84+ }
7485 case <- time .After (time .Millisecond * 100 ):
7586 fmt .Printf ("\r \033 [36mRunning Preflight checks\033 [m %s " , s .Next ())
87+ case <- finishedCh :
88+ fmt .Printf ("\r %s\r " , cursor .ClearEntireLine ())
89+ return
7690 }
7791 }
7892 }()
7993 defer func () {
80- finishedCh <- true
94+ close ( finishedCh )
8195 }()
8296
83- allCollectedData , err := runCollectors (v , preflight )
97+ allCollectedData , err := runCollectors (v , preflight , progressChan )
8498 if err != nil {
8599 return err
86100 }
@@ -117,25 +131,30 @@ func runPreflights(v *viper.Viper, arg string) error {
117131 }
118132 }
119133
120- finishedCh <- true
121-
122134 if preflight .Spec .UploadResultsTo != "" {
123- tryUploadResults (preflight .Spec .UploadResultsTo , preflight .Name , analyzeResults )
135+ err := uploadResults (preflight .Spec .UploadResultsTo , analyzeResults )
136+ if err != nil {
137+ progressChan <- err
138+ }
124139 }
140+
141+ finishedCh <- true
142+
125143 if v .GetBool ("interactive" ) {
144+ if len (analyzeResults ) == 0 {
145+ return errors .New ("no data has been collected" )
146+ }
126147 return showInteractiveResults (preflight .Name , analyzeResults )
127148 }
128149
129150 return showStdoutResults (v .GetString ("format" ), preflight .Name , analyzeResults )
130151}
131152
132- func runCollectors (v * viper.Viper , preflight troubleshootv1beta1.Preflight ) (map [string ][]byte , error ) {
133- desiredCollectors := make ([]* troubleshootv1beta1.Collect , 0 , 0 )
134- for _ , definedCollector := range preflight .Spec .Collectors {
135- desiredCollectors = append (desiredCollectors , definedCollector )
136- }
137- desiredCollectors = ensureCollectorInList (desiredCollectors , troubleshootv1beta1.Collect {ClusterInfo : & troubleshootv1beta1.ClusterInfo {}})
138- desiredCollectors = ensureCollectorInList (desiredCollectors , troubleshootv1beta1.Collect {ClusterResources : & troubleshootv1beta1.ClusterResources {}})
153+ func runCollectors (v * viper.Viper , preflight troubleshootv1beta1.Preflight , progressChan chan interface {}) (map [string ][]byte , error ) {
154+ collectSpecs := make ([]* troubleshootv1beta1.Collect , 0 , 0 )
155+ collectSpecs = append (collectSpecs , preflight .Spec .Collectors ... )
156+ collectSpecs = ensureCollectorInList (collectSpecs , troubleshootv1beta1.Collect {ClusterInfo : & troubleshootv1beta1.ClusterInfo {}})
157+ collectSpecs = ensureCollectorInList (collectSpecs , troubleshootv1beta1.Collect {ClusterResources : & troubleshootv1beta1.ClusterResources {}})
139158
140159 allCollectedData := make (map [string ][]byte )
141160
@@ -144,24 +163,56 @@ func runCollectors(v *viper.Viper, preflight troubleshootv1beta1.Preflight) (map
144163 return nil , errors .Wrap (err , "failed to convert kube flags to rest config" )
145164 }
146165
147- // Run preflights collectors synchronously
148- for _ , desiredCollector := range desiredCollectors {
166+ var collectors collect. Collectors
167+ for _ , desiredCollector := range collectSpecs {
149168 collector := collect.Collector {
150169 Redact : true ,
151170 Collect : desiredCollector ,
152171 ClientConfig : config ,
153172 Namespace : v .GetString ("namespace" ),
154173 }
174+ collectors = append (collectors , & collector )
175+ }
176+
177+ if err := collectors .CheckRBAC (); err != nil {
178+ return nil , errors .Wrap (err , "failed to check RBAC for collectors" )
179+ }
180+
181+ foundForbidden := false
182+ for _ , c := range collectors {
183+ for _ , e := range c .RBACErrors {
184+ foundForbidden = true
185+ progressChan <- e
186+ }
187+ }
188+
189+ if foundForbidden && ! v .GetBool ("collect-without-permissions" ) {
190+ if preflight .Spec .UploadResultsTo != "" {
191+ err := uploadErrors (preflight .Spec .UploadResultsTo , collectors )
192+ if err != nil {
193+ progressChan <- err
194+ }
195+ }
196+ return nil , errors .New ("insufficient permissions to run all collectors" )
197+ }
198+
199+ // Run preflights collectors synchronously
200+ for _ , collector := range collectors {
201+ if len (collector .RBACErrors ) > 0 {
202+ continue
203+ }
155204
156205 result , err := collector .RunCollectorSync ()
157206 if err != nil {
158- return nil , errors .Wrap (err , "failed to run collector" )
207+ progressChan <- errors .Errorf ("failed to run collector %s: %v\n " , collector .GetDisplayName (), err )
208+ continue
159209 }
160210
161211 if result != nil {
162212 output , err := parseCollectorOutput (string (result ))
163213 if err != nil {
164- return nil , errors .Wrap (err , "failed to parse collector output" )
214+ progressChan <- errors .Errorf ("failed to parse collector output %s: %v\n " , collector .GetDisplayName (), err )
215+ continue
165216 }
166217 for k , v := range output {
167218 allCollectedData [k ] = v
0 commit comments