@@ -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 }
@@ -75,26 +76,6 @@ func (mg *mustGather) Run() error {
7576 return fmt .Errorf ("failed to get OCM cluster info for %s: %s" , mg .clusterId , err )
7677 }
7778
78- mc , err := utils .GetManagementCluster (cluster .ID ())
79- if err != nil {
80- return err
81- }
82-
83- sc , err := utils .GetServiceCluster (cluster .ID ())
84- if err != nil {
85- return err
86- }
87-
88- _ , mcRestCfg , mcK8sCli , err := common .GetKubeConfigAndClient (mc .ID (), mg .reason )
89- if err != nil {
90- return err
91- }
92-
93- _ , scRestCfg , scK8sCli , err := common .GetKubeConfigAndClient (sc .ID (), mg .reason )
94- if err != nil {
95- return err
96- }
97-
9879 // hack(typeid): work around backplane overwriting our config
9980 err = osdctlConfig .EnsureConfigFile ()
10081 if err != nil {
@@ -108,7 +89,7 @@ func (mg *mustGather) Run() error {
10889 tarballName := fmt .Sprintf ("cluster_dump_%s_%s.tar.gz" , mg .clusterId , timestamp )
10990 outputTarballTmp := fmt .Sprintf ("%s/%s" , baseDir , tarballName )
11091 outputTarballPath := fmt .Sprintf ("%s/%s" , outputDir , tarballName )
111- err = os .MkdirAll (outputDir , 0750 )
92+ err = os .MkdirAll (outputDir , 0o750 )
11293 if err != nil {
11394 return err
11495 }
@@ -119,7 +100,7 @@ func (mg *mustGather) Run() error {
119100
120101 // Progress tracking
121102 var completed sync.Map
122- var totalGatherTargets = len (gatherTargets )
103+ totalGatherTargets : = len (gatherTargets )
123104 go func () {
124105 ticker := time .NewTicker (30 * time .Second )
125106 defer ticker .Stop ()
@@ -157,20 +138,40 @@ func (mg *mustGather) Run() error {
157138 switch gatherTarget {
158139 case "sc" :
159140 destDir := outputDir + "/sc_infra"
141+ scRestCfg , scK8sCli , err := resolveSCRestConfig (ocmClient , cluster , mg .reason )
142+ if err != nil {
143+ fmt .Printf ("failed to resolve service cluster for %s: %v\n " , gatherTarget , err )
144+ return
145+ }
160146 if err := createMustGather (scRestCfg , scK8sCli , []string {"--dest-dir=" + destDir }); err != nil {
161147 fmt .Printf ("failed to gather %s: %v\n " , gatherTarget , err )
162148 }
163149 case "sc_acm" :
164150 destDir := outputDir + "/sc_acm"
151+ scRestCfg , scK8sCli , err := resolveSCRestConfig (ocmClient , cluster , mg .reason )
152+ if err != nil {
153+ fmt .Printf ("failed to resolve service cluster for %s: %v\n " , gatherTarget , err )
154+ return
155+ }
165156 if err := createMustGather (scRestCfg , scK8sCli , []string {"--dest-dir=" + destDir , "--image=" + mg .acmMustGatherImage }); err != nil {
166157 fmt .Printf ("failed to gather %s: %v\n " , gatherTarget , err )
167158 }
168159 case "mc" :
169160 destDir := outputDir + "/mc_infra"
161+ mcRestCfg , mcK8sCli , err := resolveMCRestConfig (ocmClient , cluster , mg .reason )
162+ if err != nil {
163+ fmt .Printf ("failed to resolve management cluster for %s: %v\n " , gatherTarget , err )
164+ return
165+ }
170166 if err := createMustGather (mcRestCfg , mcK8sCli , []string {"--dest-dir=" + destDir }); err != nil {
171167 fmt .Printf ("failed to gather %s: %v\n " , gatherTarget , err )
172168 }
173169 case "hcp" :
170+ if ! cluster .Hypershift ().Enabled () {
171+ fmt .Printf ("--gather hcp requires an HCP cluster ID; %s is not an HCP cluster\n " , mg .clusterId )
172+ return
173+ }
174+
174175 destDir := outputDir + "/hcp"
175176
176177 // 1. Gather logs from DT
@@ -195,6 +196,12 @@ func (mg *mustGather) Run() error {
195196 hcName := cluster .DomainPrefix ()
196197 hcNamespace := strings .TrimSuffix (hcpNamespace , "-" + hcName )
197198
199+ mcRestCfg , mcK8sCli , err := resolveMCRestConfig (ocmClient , cluster , mg .reason )
200+ if err != nil {
201+ fmt .Printf ("gathered DT logs but failed to resolve MC for ACM must-gather: %v\n " , err )
202+ return
203+ }
204+
198205 gatherScript := fmt .Sprintf ("/usr/bin/gather hosted-cluster-namespace=%s hosted-cluster-name=%s" , hcNamespace , hcName )
199206 if err := createMustGather (mcRestCfg , mcK8sCli , []string {"--dest-dir=" + destDir , "--image=" + mg .acmMustGatherImage , gatherScript }); err != nil {
200207 fmt .Printf ("collected HCP dynatrace logs but failed to gather %s: %v\n " , gatherTarget , err .Error ())
@@ -227,6 +234,90 @@ func (mg *mustGather) Run() error {
227234 return nil
228235}
229236
237+ // resolveMCRestConfig returns the REST config and k8s client for the management cluster.
238+ func resolveMCRestConfig (ocmClient * ocmsdk.Connection , cluster * cmv1.Cluster , reason string ) (* rest.Config , * kubernetes.Clientset , error ) {
239+ mcID := cluster .ID ()
240+
241+ if cluster .Hypershift ().Enabled () {
242+ hypershiftResp , err := ocmClient .ClustersMgmt ().V1 ().Clusters ().
243+ Cluster (cluster .ID ()).
244+ Hypershift ().
245+ Get ().
246+ Send ()
247+ if err != nil {
248+ return nil , nil , fmt .Errorf ("failed to get hypershift info for %s: %w" , cluster .ID (), err )
249+ }
250+
251+ mgmtClusterName , ok := hypershiftResp .Body ().GetManagementCluster ()
252+ if ! ok || mgmtClusterName == "" {
253+ return nil , nil , fmt .Errorf ("no management cluster found for %s" , cluster .ID ())
254+ }
255+
256+ mc , err := utils .GetClusterAnyStatus (ocmClient , mgmtClusterName )
257+ if err != nil {
258+ return nil , nil , fmt .Errorf ("failed to get management cluster %s: %w" , mgmtClusterName , err )
259+ }
260+ mcID = mc .ID ()
261+ }
262+
263+ _ , restCfg , k8sCli , err := common .GetKubeConfigAndClientWithConn (mcID , ocmClient , reason )
264+ if err != nil {
265+ return nil , nil , fmt .Errorf ("failed to get kubeconfig for management cluster %s: %w" , mcID , err )
266+ }
267+
268+ return restCfg , k8sCli , nil
269+ }
270+
271+ // resolveSCRestConfig returns the REST config and k8s client for the service cluster.
272+ func resolveSCRestConfig (ocmClient * ocmsdk.Connection , cluster * cmv1.Cluster , reason string ) (* rest.Config , * kubernetes.Clientset , error ) {
273+ scID := cluster .ID ()
274+
275+ if cluster .Hypershift ().Enabled () {
276+ hypershiftResp , err := ocmClient .ClustersMgmt ().V1 ().Clusters ().
277+ Cluster (cluster .ID ()).
278+ Hypershift ().
279+ Get ().
280+ Send ()
281+ if err != nil {
282+ return nil , nil , fmt .Errorf ("failed to get hypershift info for %s: %w" , cluster .ID (), err )
283+ }
284+
285+ mgmtClusterName := hypershiftResp .Body ().ManagementCluster ()
286+ if mgmtClusterName == "" {
287+ return nil , nil , fmt .Errorf ("failed to lookup management cluster for cluster %s" , cluster .ID ())
288+ }
289+
290+ ofmResp , err := ocmClient .OSDFleetMgmt ().V1 ().ManagementClusters ().
291+ List ().
292+ Parameter ("search" , fmt .Sprintf ("name='%s'" , mgmtClusterName )).
293+ Send ()
294+ if err != nil {
295+ return nil , nil , fmt .Errorf ("failed to get fleet manager info for management cluster %s: %w" , mgmtClusterName , err )
296+ }
297+
298+ var svcClusterName string
299+ if kind := ofmResp .Items ().Get (0 ).Parent ().Kind (); kind == "ServiceCluster" {
300+ svcClusterName = ofmResp .Items ().Get (0 ).Parent ().Name ()
301+ }
302+ if svcClusterName == "" {
303+ return nil , nil , fmt .Errorf ("no service cluster found for management cluster %s" , mgmtClusterName )
304+ }
305+
306+ sc , err := utils .GetClusterAnyStatus (ocmClient , svcClusterName )
307+ if err != nil {
308+ return nil , nil , fmt .Errorf ("failed to get service cluster %s: %w" , svcClusterName , err )
309+ }
310+ scID = sc .ID ()
311+ }
312+
313+ _ , restCfg , k8sCli , err := common .GetKubeConfigAndClientWithConn (scID , ocmClient , reason )
314+ if err != nil {
315+ return nil , nil , fmt .Errorf ("failed to get kubeconfig for service cluster %s: %w" , scID , err )
316+ }
317+
318+ return restCfg , k8sCli , nil
319+ }
320+
230321func createMustGather (restCfg * rest.Config , k8sCli * kubernetes.Clientset , additionalFlags []string ) error {
231322 // We used to run this programatically by directly using the must-gather package (see https://github.com/openshift/osdctl/pull/660)
232323 // from the oc cli, but decided to opt for oc.Exec instead.
@@ -378,7 +469,6 @@ func createTarball(sourceDir, tarballName string) error {
378469
379470 return nil
380471 })
381-
382472 if err != nil {
383473 return fmt .Errorf ("error walking source directory: %v" , err )
384474 }
0 commit comments