@@ -10,6 +10,7 @@ import (
1010
1111 "github.com/pkg/errors"
1212 troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
13+ "github.com/replicatedhq/troubleshoot/pkg/constants"
1314 "github.com/replicatedhq/troubleshoot/pkg/logger"
1415 corev1 "k8s.io/api/core/v1"
1516 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -20,7 +21,7 @@ import (
2021type CollectLogs struct {
2122 Collector * troubleshootv1beta2.Logs
2223 BundlePath string
23- Namespace string // There is a Namespace parameter in troubleshootv1beta2.Logs. Should we remove this?
24+ Namespace string // TODO: There is a Namespace parameter in troubleshootv1beta2.Logs. Should we remove this?
2425 ClientConfig * rest.Config
2526 Client kubernetes.Interface
2627 Context context.Context
@@ -42,24 +43,30 @@ func (c *CollectLogs) Collect(progressChan chan<- interface{}) (CollectorResult,
4243 return nil , err
4344 }
4445
45- output := NewResult ( )
46+ return c . CollectWithClient ( progressChan , client )
4647
47- ctx := context . Background ()
48+ }
4849
49- const timeout = 60 //timeout in seconds used for context timeout value
50+ // CollectWithClient is a helper function that allows passing in a kubernetes client
51+ // It's a stopgap implementation before it's decided whether to either always use a single
52+ // client for collectors or leave the implementation as is.
53+ // Ref: https://github.com/replicatedhq/troubleshoot/pull/821#discussion_r1026258904
54+ func (c * CollectLogs ) CollectWithClient (progressChan chan <- interface {}, client kubernetes.Interface ) (CollectorResult , error ) {
55+ out := NewResult ()
5056
51- // timeout context
52- ctxTimeout , cancel := context .WithTimeout (context .Background (), timeout * time .Second )
57+ ctx , cancel := context .WithTimeout (c .Context , constants .DEFAULT_LOGS_COLLECTOR_TIMEOUT )
5358 defer cancel ()
5459
5560 errCh := make (chan error , 1 )
56- resultCh := make (chan CollectorResult , 1 )
57-
58- //wrapped code go func for context timeout solution
59- go func () {
60-
61- output := NewResult ()
62-
61+ done := make (chan struct {}, 1 )
62+
63+ // Collect logs in a go routine to allow timing out of long running operations
64+ // If a timeout occurs, the passed in collector result will contain logs collected
65+ // prior. We want this to be the case so as to have some logs in the support bundle
66+ // even if not from all expected pods.
67+ // TODO: In future all collectors will have a timeout. This will be implemented in the
68+ // framework level (caller of Collect function). Remove this code when we get there.
69+ go func (output CollectorResult ) {
6370 if c .SinceTime != nil {
6471 if c .Collector .Limits == nil {
6572 c .Collector .Limits = new (troubleshootv1beta2.LogLimits )
@@ -98,8 +105,6 @@ func (c *CollectLogs) Collect(progressChan chan<- interface{}) (CollectorResult,
98105 continue
99106 }
100107 output .AddResult (podLogs )
101-
102- resultCh <- output
103108 }
104109 } else {
105110 for _ , container := range c .Collector .ContainerNames {
@@ -113,24 +118,24 @@ func (c *CollectLogs) Collect(progressChan chan<- interface{}) (CollectorResult,
113118 continue
114119 }
115120 output .AddResult (containerLogs )
116- resultCh <- output
117121 }
118122 }
119123 }
120- } else {
121- resultCh <- output
122124 }
123- }()
125+
126+ // Send a signal to indicate that we are done collecting logs
127+ done <- struct {}{}
128+ }(out )
124129
125130 select {
126- case <- ctxTimeout .Done ():
127- return nil , fmt .Errorf ("%s (%s) collector timeout exceeded" , c .Title (), c .Collector .CollectorName )
128- case o := <- resultCh :
129- output = o
131+ case <- ctx .Done ():
132+ // When we timeout, return the logs we have collected so far
133+ return out , fmt .Errorf ("%s (%s) collector timeout exceeded" , c .Title (), c .Collector .CollectorName )
134+ case <- done :
135+ return out , nil
130136 case err := <- errCh :
131137 return nil , err
132138 }
133- return output , nil
134139}
135140
136141func listPodsInSelectors (ctx context.Context , client kubernetes.Interface , namespace string , selector []string ) ([]corev1.Pod , []string ) {
@@ -149,19 +154,6 @@ func listPodsInSelectors(ctx context.Context, client kubernetes.Interface, names
149154}
150155
151156func savePodLogs (
152- ctx context.Context ,
153- bundlePath string ,
154- client * kubernetes.Clientset ,
155- pod * corev1.Pod ,
156- collectorName , container string ,
157- limits * troubleshootv1beta2.LogLimits ,
158- follow bool ,
159- createSymLinks bool ,
160- ) (CollectorResult , error ) {
161- return savePodLogsWithInterface (ctx , bundlePath , client , pod , collectorName , container , limits , follow , createSymLinks )
162- }
163-
164- func savePodLogsWithInterface (
165157 ctx context.Context ,
166158 bundlePath string ,
167159 client kubernetes.Interface ,
0 commit comments