11package mustgather
22
33import (
4+ "context"
45 "fmt"
56 "math/rand"
67 "path"
@@ -16,11 +17,14 @@ import (
1617 "k8s.io/cli-runtime/pkg/genericclioptions/printers"
1718 "k8s.io/client-go/kubernetes"
1819 "k8s.io/client-go/rest"
20+ "k8s.io/kubernetes/pkg/kubectl/cmd/logs"
1921 kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
22+ "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
2023 "k8s.io/kubernetes/pkg/kubectl/scheme"
2124 "k8s.io/kubernetes/pkg/kubectl/util/templates"
2225
2326 "github.com/openshift/client-go/image/clientset/versioned/typed/image/v1"
27+ "github.com/openshift/library-go/pkg/operator/resource/retry"
2428
2529 "github.com/openshift/origin/pkg/image/util"
2630 "github.com/openshift/origin/pkg/oc/cli/rsync"
@@ -87,6 +91,7 @@ func (o *MustGatherOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, arg
8791 } else {
8892 o .Command = args
8993 }
94+ o .RESTClientGetter = f
9095 var err error
9196 if o .Config , err = f .ToRESTConfig (); err != nil {
9297 return err
@@ -127,8 +132,9 @@ func (o *MustGatherOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, arg
127132type MustGatherOptions struct {
128133 genericclioptions.IOStreams
129134
130- Config * rest.Config
131- Client kubernetes.Interface
135+ Config * rest.Config
136+ Client kubernetes.Interface
137+ RESTClientGetter genericclioptions.RESTClientGetter
132138
133139 NodeName string
134140 DestDir string
@@ -198,6 +204,16 @@ func (o *MustGatherOptions) Run(rsyncCmd *cobra.Command) error {
198204 return err
199205 }
200206
207+ // wait for gather container to be running (gather is running)
208+ if err := o .waitForGatherContainerRunning (pod ); err != nil {
209+ return err
210+ }
211+
212+ // stream gather container logs
213+ if err := o .getInitContainerLogs (pod ); err != nil {
214+ fmt .Fprintf (o .Out , "container logs unavailable: %v" , err )
215+ }
216+
201217 // wait for pod to be running (gather has completed)
202218 if err := o .waitForPodRunning (pod ); err != nil {
203219 return err
@@ -224,6 +240,22 @@ func (o *MustGatherOptions) copyFilesFromPod(pod *corev1.Pod) error {
224240
225241}
226242
243+ func (o * MustGatherOptions ) getInitContainerLogs (pod * corev1.Pod ) error {
244+ return (& logs.LogsOptions {
245+ Namespace : pod .Namespace ,
246+ ResourceArg : pod .Name ,
247+ Options : & corev1.PodLogOptions {
248+ Follow : true ,
249+ Container : pod .Spec .InitContainers [0 ].Name ,
250+ },
251+ RESTClientGetter : o .RESTClientGetter ,
252+ Object : pod ,
253+ ConsumeRequestFn : logs .DefaultConsumeRequest ,
254+ LogsForObject : polymorphichelpers .LogsForObjectFn ,
255+ IOStreams : genericclioptions.IOStreams {Out : o .Out },
256+ }).RunLogs ()
257+ }
258+
227259func (o * MustGatherOptions ) waitForPodRunning (pod * corev1.Pod ) error {
228260 phase := pod .Status .Phase
229261 err := wait .PollImmediate (time .Second , 10 * time .Minute , func () (bool , error ) {
@@ -243,6 +275,22 @@ func (o *MustGatherOptions) waitForPodRunning(pod *corev1.Pod) error {
243275 return nil
244276}
245277
278+ func (o * MustGatherOptions ) waitForGatherContainerRunning (pod * corev1.Pod ) error {
279+ ctx , cancel := context .WithTimeout (context .Background (), 10 * time .Minute )
280+ defer cancel ()
281+ return retry .RetryOnConnectionErrors (ctx , func (ctx context.Context ) (bool , error ) {
282+ var err error
283+ if pod , err := o .Client .CoreV1 ().Pods (pod .Namespace ).Get (pod .Name , metav1.GetOptions {}); err == nil {
284+ if len (pod .Status .InitContainerStatuses ) == 0 {
285+ return false , nil
286+ }
287+ state := pod .Status .InitContainerStatuses [0 ].State
288+ return (state .Running != nil ) || (state .Terminated != nil ), nil
289+ }
290+ return false , err
291+ })
292+ }
293+
246294func (o * MustGatherOptions ) newClusterRoleBinding (ns string ) * rbacv1.ClusterRoleBinding {
247295 return & rbacv1.ClusterRoleBinding {
248296 ObjectMeta : metav1.ObjectMeta {
0 commit comments