@@ -18,6 +18,8 @@ import (
1818 "syscall"
1919 "time"
2020
21+ ocmsdk "github.com/openshift-online/ocm-sdk-go"
22+ cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1"
2123 "github.com/openshift/osdctl/cmd/common"
2224 "github.com/openshift/osdctl/cmd/dynatrace"
2325 "github.com/openshift/osdctl/pkg/osdctlConfig"
@@ -45,7 +47,6 @@ func NewCmdMustGather() *cobra.Command {
4547 Long : "Create a must-gather for an HCP cluster with optional gather targets" ,
4648 Example : "osdctl hcp must-gather --cluster-id CLUSTER_ID --gather sc,mc,sc_acm --reason OHSS-1234" ,
4749 RunE : func (cmd * cobra.Command , args []string ) error {
48-
4950 return mg .Run ()
5051 },
5152 }
@@ -74,26 +75,6 @@ func (mg *mustGather) Run() error {
7475 return fmt .Errorf ("failed to get OCM cluster info for %s: %s" , mg .clusterId , err )
7576 }
7677
77- mc , err := utils .GetManagementCluster (cluster .ID ())
78- if err != nil {
79- return err
80- }
81-
82- sc , err := utils .GetServiceCluster (cluster .ID ())
83- if err != nil {
84- return err
85- }
86-
87- _ , mcRestCfg , mcK8sCli , err := common .GetKubeConfigAndClient (mc .ID (), mg .reason )
88- if err != nil {
89- return err
90- }
91-
92- _ , scRestCfg , scK8sCli , err := common .GetKubeConfigAndClient (sc .ID (), mg .reason )
93- if err != nil {
94- return err
95- }
96-
9778 // hack(typeid): work around backplane overwriting our config
9879 err = osdctlConfig .EnsureConfigFile ()
9980 if err != nil {
@@ -107,7 +88,7 @@ func (mg *mustGather) Run() error {
10788 tarballName := fmt .Sprintf ("cluster_dump_%s_%s.tar.gz" , mg .clusterId , timestamp )
10889 outputTarballTmp := fmt .Sprintf ("%s/%s" , baseDir , tarballName )
10990 outputTarballPath := fmt .Sprintf ("%s/%s" , outputDir , tarballName )
110- err = os .MkdirAll (outputDir , 0750 )
91+ err = os .MkdirAll (outputDir , 0o750 )
11192 if err != nil {
11293 return err
11394 }
@@ -118,7 +99,7 @@ func (mg *mustGather) Run() error {
11899
119100 // Progress tracking
120101 var completed sync.Map
121- var totalGatherTargets = len (gatherTargets )
102+ totalGatherTargets : = len (gatherTargets )
122103 go func () {
123104 ticker := time .NewTicker (30 * time .Second )
124105 defer ticker .Stop ()
@@ -156,20 +137,40 @@ func (mg *mustGather) Run() error {
156137 switch gatherTarget {
157138 case "sc" :
158139 destDir := outputDir + "/sc_infra"
140+ scRestCfg , scK8sCli , err := resolveSCRestConfig (ocmClient , cluster , mg .reason )
141+ if err != nil {
142+ fmt .Printf ("failed to resolve service cluster for %s: %v\n " , gatherTarget , err )
143+ return
144+ }
159145 if err := createMustGather (scRestCfg , scK8sCli , []string {"--dest-dir=" + destDir }); err != nil {
160146 fmt .Printf ("failed to gather %s: %v\n " , gatherTarget , err )
161147 }
162148 case "sc_acm" :
163149 destDir := outputDir + "/sc_acm"
150+ scRestCfg , scK8sCli , err := resolveSCRestConfig (ocmClient , cluster , mg .reason )
151+ if err != nil {
152+ fmt .Printf ("failed to resolve service cluster for %s: %v\n " , gatherTarget , err )
153+ return
154+ }
164155 if err := createMustGather (scRestCfg , scK8sCli , []string {"--dest-dir=" + destDir , "--image=" + mg .acmMustGatherImage }); err != nil {
165156 fmt .Printf ("failed to gather %s: %v\n " , gatherTarget , err )
166157 }
167158 case "mc" :
168159 destDir := outputDir + "/mc_infra"
160+ mcRestCfg , mcK8sCli , err := resolveMCRestConfig (ocmClient , cluster , mg .reason )
161+ if err != nil {
162+ fmt .Printf ("failed to resolve management cluster for %s: %v\n " , gatherTarget , err )
163+ return
164+ }
169165 if err := createMustGather (mcRestCfg , mcK8sCli , []string {"--dest-dir=" + destDir }); err != nil {
170166 fmt .Printf ("failed to gather %s: %v\n " , gatherTarget , err )
171167 }
172168 case "hcp" :
169+ if ! cluster .Hypershift ().Enabled () {
170+ fmt .Printf ("--gather hcp requires an HCP cluster ID; %s is not an HCP cluster\n " , mg .clusterId )
171+ return
172+ }
173+
173174 destDir := outputDir + "/hcp"
174175
175176 // 1. Gather logs from DT
@@ -194,10 +195,14 @@ func (mg *mustGather) Run() error {
194195 hcName := cluster .DomainPrefix ()
195196 hcNamespace := strings .TrimSuffix (hcpNamespace , "-" + hcName )
196197
197- // TODO(ACM-16170): replace this with an official ACM release image once it's available
198- acmHyperShiftImage := "quay.io/rokejungrh/must-gather:v2.13.0-33-linux"
198+ mcRestCfg , mcK8sCli , err := resolveMCRestConfig (ocmClient , cluster , mg .reason )
199+ if err != nil {
200+ fmt .Printf ("gathered DT logs but failed to resolve MC for ACM must-gather: %v\n " , err )
201+ return
202+ }
203+
199204 gatherScript := fmt .Sprintf ("/usr/bin/gather hosted-cluster-namespace=%s hosted-cluster-name=%s" , hcNamespace , hcName )
200- if err := createMustGather (mcRestCfg , mcK8sCli , []string {"--dest-dir=" + destDir , "--image=" + acmHyperShiftImage , gatherScript }); err != nil {
205+ if err := createMustGather (mcRestCfg , mcK8sCli , []string {"--dest-dir=" + destDir , "--image=" + mg . acmMustGatherImage , gatherScript }); err != nil {
201206 fmt .Printf ("collected HCP dynatrace logs but failed to gather %s: %v\n " , gatherTarget , err .Error ())
202207 }
203208
@@ -228,6 +233,90 @@ func (mg *mustGather) Run() error {
228233 return nil
229234}
230235
236+ // resolveMCRestConfig returns the REST config and k8s client for the management cluster.
237+ func resolveMCRestConfig (ocmClient * ocmsdk.Connection , cluster * cmv1.Cluster , reason string ) (* rest.Config , * kubernetes.Clientset , error ) {
238+ mcID := cluster .ID ()
239+
240+ if cluster .Hypershift ().Enabled () {
241+ hypershiftResp , err := ocmClient .ClustersMgmt ().V1 ().Clusters ().
242+ Cluster (cluster .ID ()).
243+ Hypershift ().
244+ Get ().
245+ Send ()
246+ if err != nil {
247+ return nil , nil , fmt .Errorf ("failed to get hypershift info for %s: %w" , cluster .ID (), err )
248+ }
249+
250+ mgmtClusterName , ok := hypershiftResp .Body ().GetManagementCluster ()
251+ if ! ok || mgmtClusterName == "" {
252+ return nil , nil , fmt .Errorf ("no management cluster found for %s" , cluster .ID ())
253+ }
254+
255+ mc , err := utils .GetClusterAnyStatus (ocmClient , mgmtClusterName )
256+ if err != nil {
257+ return nil , nil , fmt .Errorf ("failed to get management cluster %s: %w" , mgmtClusterName , err )
258+ }
259+ mcID = mc .ID ()
260+ }
261+
262+ _ , restCfg , k8sCli , err := common .GetKubeConfigAndClientWithConn (mcID , ocmClient , reason )
263+ if err != nil {
264+ return nil , nil , fmt .Errorf ("failed to get kubeconfig for management cluster %s: %w" , mcID , err )
265+ }
266+
267+ return restCfg , k8sCli , nil
268+ }
269+
270+ // resolveSCRestConfig returns the REST config and k8s client for the service cluster.
271+ func resolveSCRestConfig (ocmClient * ocmsdk.Connection , cluster * cmv1.Cluster , reason string ) (* rest.Config , * kubernetes.Clientset , error ) {
272+ scID := cluster .ID ()
273+
274+ if cluster .Hypershift ().Enabled () {
275+ hypershiftResp , err := ocmClient .ClustersMgmt ().V1 ().Clusters ().
276+ Cluster (cluster .ID ()).
277+ Hypershift ().
278+ Get ().
279+ Send ()
280+ if err != nil {
281+ return nil , nil , fmt .Errorf ("failed to get hypershift info for %s: %w" , cluster .ID (), err )
282+ }
283+
284+ mgmtClusterName := hypershiftResp .Body ().ManagementCluster ()
285+ if mgmtClusterName == "" {
286+ return nil , nil , fmt .Errorf ("failed to lookup management cluster for cluster %s" , cluster .ID ())
287+ }
288+
289+ ofmResp , err := ocmClient .OSDFleetMgmt ().V1 ().ManagementClusters ().
290+ List ().
291+ Parameter ("search" , fmt .Sprintf ("name='%s'" , mgmtClusterName )).
292+ Send ()
293+ if err != nil {
294+ return nil , nil , fmt .Errorf ("failed to get fleet manager info for management cluster %s: %w" , mgmtClusterName , err )
295+ }
296+
297+ var svcClusterName string
298+ if kind := ofmResp .Items ().Get (0 ).Parent ().Kind (); kind == "ServiceCluster" {
299+ svcClusterName = ofmResp .Items ().Get (0 ).Parent ().Name ()
300+ }
301+ if svcClusterName == "" {
302+ return nil , nil , fmt .Errorf ("no service cluster found for management cluster %s" , mgmtClusterName )
303+ }
304+
305+ sc , err := utils .GetClusterAnyStatus (ocmClient , svcClusterName )
306+ if err != nil {
307+ return nil , nil , fmt .Errorf ("failed to get service cluster %s: %w" , svcClusterName , err )
308+ }
309+ scID = sc .ID ()
310+ }
311+
312+ _ , restCfg , k8sCli , err := common .GetKubeConfigAndClientWithConn (scID , ocmClient , reason )
313+ if err != nil {
314+ return nil , nil , fmt .Errorf ("failed to get kubeconfig for service cluster %s: %w" , scID , err )
315+ }
316+
317+ return restCfg , k8sCli , nil
318+ }
319+
231320func createMustGather (restCfg * rest.Config , k8sCli * kubernetes.Clientset , additionalFlags []string ) error {
232321 // We used to run this programatically by directly using the must-gather package (see https://github.com/openshift/osdctl/pull/660)
233322 // from the oc cli, but decided to opt for oc.Exec instead.
@@ -379,7 +468,6 @@ func createTarball(sourceDir, tarballName string) error {
379468
380469 return nil
381470 })
382-
383471 if err != nil {
384472 return fmt .Errorf ("error walking source directory: %v" , err )
385473 }
0 commit comments