Skip to content

Commit

Permalink
print the related namespace when login via manager cluster
Browse files Browse the repository at this point in the history
  • Loading branch information
bmeng committed Dec 14, 2023
1 parent d01e44d commit 005f458
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 16 deletions.
48 changes: 46 additions & 2 deletions cmd/ocm-backplane/login/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,29 @@ func runLogin(cmd *cobra.Command, argv []string) (err error) {

if globalOpts.Manager {
logger.WithField("Cluster ID", clusterID).Debugln("Finding managing cluster")
clusterID, clusterName, err = ocm.DefaultOCMInterface.GetManagingCluster(clusterID)
var isHostedControlPlane bool
targetClusterID := clusterID
targetClusterName := clusterName

clusterID, clusterName, isHostedControlPlane, err = ocm.DefaultOCMInterface.GetManagingCluster(clusterID)
if err != nil {
return err
}

logger.WithFields(logger.Fields{
"ID": clusterID,
"Name": clusterName}).Infoln("Management cluster")

// Print the related namespace if login to manager cluster
var namespaces []string
namespaces, err = listNamespaces(targetClusterID, targetClusterName, isHostedControlPlane)
if err != nil {
return err
}
fmt.Println("A list of associated namespaces for your given cluster:")
for _, ns := range namespaces {
fmt.Println(" " + ns)
}
}

if globalOpts.Service {
Expand All @@ -153,7 +168,7 @@ func runLogin(cmd *cobra.Command, argv []string) (err error) {
return fmt.Errorf("can't save the kube config into a specific location if multi-cluster is not enabled. Please specify --multi flag")
}
if _, err := os.Stat(args.kubeConfigPath); errors.Is(err, os.ErrNotExist) {
return fmt.Errorf("kube config save path is not exist")
return fmt.Errorf("the save path for the kubeconfig does not exist")
}
}

Expand Down Expand Up @@ -354,3 +369,32 @@ func doLogin(api, clusterID, accessToken string) (string, error) {

return api + *loginResp.JSON200.ProxyUri, nil
}

func listNamespaces(clusterID, clusterName string, isHostedControlPlane bool) ([]string, error) {

env, err := ocm.DefaultOCMInterface.GetOCMEnvironment()
if err != nil {
return []string{}, err
}
envName := env.Name()

klusterletPrefix := "klusterlet-"
hivePrefix := fmt.Sprintf("uhc-%s-", envName)
hcpPrefix := fmt.Sprintf("ocm-%s-", envName)

var nsList []string

if isHostedControlPlane {
nsList = []string{
klusterletPrefix + clusterID,
hcpPrefix + clusterID,
hcpPrefix + clusterID + "-" + clusterName,
}
} else {
nsList = []string{
hivePrefix + clusterID,
}
}

return nsList, nil
}
24 changes: 23 additions & 1 deletion cmd/ocm-backplane/login/login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"k8s.io/client-go/tools/clientcmd/api"

cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1"

"github.com/openshift/backplane-cli/pkg/backplaneapi"
backplaneapiMock "github.com/openshift/backplane-cli/pkg/backplaneapi/mocks"
"github.com/openshift/backplane-cli/pkg/client/mocks"
Expand Down Expand Up @@ -47,6 +48,7 @@ var _ = Describe("Login command", func() {
serviceClusterName string
fakeResp *http.Response
ocmEnv *cmv1.Environment
kubeConfigPath string
)

BeforeEach(func() {
Expand All @@ -67,6 +69,7 @@ var _ = Describe("Login command", func() {
serviceClusterID = "hs-sc-123456"
serviceClusterName = "hs-sc-654321"
backplaneAPIURI = "https://shard.apps"
kubeConfigPath = "filepath"

mockClientWithResp.EXPECT().LoginClusterWithResponse(gomock.Any(), gomock.Any()).Return(nil, nil).Times(0)

Expand Down Expand Up @@ -249,7 +252,7 @@ var _ = Describe("Login command", func() {
globalOpts.Manager = true
mockOcmInterface.EXPECT().GetOCMEnvironment().Return(ocmEnv, nil).AnyTimes()
mockOcmInterface.EXPECT().GetTargetCluster(testClusterID).Return(trueClusterID, testClusterID, nil)
mockOcmInterface.EXPECT().GetManagingCluster(trueClusterID).Return(managingClusterID, managingClusterID, nil)
mockOcmInterface.EXPECT().GetManagingCluster(trueClusterID).Return(managingClusterID, managingClusterID, true, nil)
mockOcmInterface.EXPECT().IsClusterHibernating(gomock.Eq(managingClusterID)).Return(false, nil).AnyTimes()
mockOcmInterface.EXPECT().GetOCMAccessToken().Return(&testToken, nil)
mockClientUtil.EXPECT().MakeRawBackplaneAPIClientWithAccessToken(backplaneAPIURI, testToken).Return(mockClient, nil)
Expand All @@ -267,6 +270,7 @@ var _ = Describe("Login command", func() {
mockOcmInterface.EXPECT().GetManagingCluster(trueClusterID).Return(
managingClusterID,
managingClusterID,
false,
fmt.Errorf("failed to find management cluster for cluster %s in %s env", testClusterID, "http://test.env"),
)
mockOcmInterface.EXPECT().IsClusterHibernating(gomock.Eq(managingClusterID)).Return(false, nil).AnyTimes()
Expand Down Expand Up @@ -364,5 +368,23 @@ var _ = Describe("Login command", func() {
Expect(err).To(BeNil())

})

It("should fail if specify kubeconfigpath but not in multicluster mode", func() {
globalOpts.Manager = false
args.multiCluster = false
args.kubeConfigPath = kubeConfigPath

err := login.SetKubeConfigBasePath(args.kubeConfigPath)
Expect(err).To(BeNil())

mockOcmInterface.EXPECT().GetOCMEnvironment().Return(ocmEnv, nil).AnyTimes()
mockOcmInterface.EXPECT().GetTargetCluster(testClusterID).Return(trueClusterID, testClusterID, nil)

err = runLogin(nil, []string{testClusterID})

Expect(err.Error()).Should(ContainSubstring("can't save the kube config into a specific location if multi-cluster is not enabled"))

})

})
})
3 changes: 2 additions & 1 deletion pkg/cli/session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ func (e *BackplaneSession) RunCommand(cmd *cobra.Command, args []string) error {
}

if e.Options.GlobalOpts.Manager {
clusterID, clusterName, err = ocm.DefaultOCMInterface.GetManagingCluster(clusterID)
clusterID, clusterName, _, err = ocm.DefaultOCMInterface.GetManagingCluster(clusterID)

e.Options.Alias = clusterID
if err != nil {
return err
Expand Down
7 changes: 4 additions & 3 deletions pkg/ocm/mocks/ocmWrapperMock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 11 additions & 9 deletions pkg/ocm/ocmWrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
type OCMInterface interface {
IsClusterHibernating(clusterID string) (bool, error)
GetTargetCluster(clusterKey string) (clusterID, clusterName string, err error)
GetManagingCluster(clusterKey string) (clusterID, clusterName string, err error)
GetManagingCluster(clusterKey string) (clusterID, clusterName string, isHostedControlPlane bool, err error)
GetOCMAccessToken() (*string, error)
GetServiceCluster(clusterKey string) (clusterID, clusterName string, err error)
GetClusterInfoByID(clusterID string) (*cmv1.Cluster, error)
Expand Down Expand Up @@ -85,14 +85,15 @@ func (*DefaultOCMInterfaceImpl) GetTargetCluster(clusterKey string) (clusterID,

// GetManagingCluster returns the managing cluster (hive shard or hypershift management cluster)
// for the given clusterID
func (o *DefaultOCMInterfaceImpl) GetManagingCluster(targetClusterID string) (clusterID, clusterName string, err error) {
func (o *DefaultOCMInterfaceImpl) GetManagingCluster(targetClusterID string) (clusterID, clusterName string, isHostedControlPlane bool, err error) {
// Create the client for the OCM API:
connection, err := ocm.NewConnection().Build()
if err != nil {
return "", "", fmt.Errorf("failed to create OCM connection: %v", err)
return "", "", false, fmt.Errorf("failed to create OCM connection: %v", err)
}
defer connection.Close()

isHostedControlPlane = false
var managingCluster string
// Check if cluster has hypershift enabled
hypershiftResp, err := connection.ClustersMgmt().V1().Clusters().
Expand All @@ -102,13 +103,14 @@ func (o *DefaultOCMInterfaceImpl) GetManagingCluster(targetClusterID string) (cl
Send()
if err == nil && hypershiftResp != nil {
managingCluster = hypershiftResp.Body().ManagementCluster()
isHostedControlPlane = true
} else {
// Get the client for the resource that manages the collection of clusters:
clusterCollection := connection.ClustersMgmt().V1().Clusters()
resource := clusterCollection.Cluster(targetClusterID).ProvisionShard()
response, err := resource.Get().Send()
if err != nil {
return "", "", fmt.Errorf("failed to find management cluster for cluster %s: %v", targetClusterID, err)
return "", "", isHostedControlPlane, fmt.Errorf("failed to find management cluster for cluster %s: %v", targetClusterID, err)
}
shard := response.Body()
hiveAPI := shard.HiveConfig().Server()
Expand All @@ -120,23 +122,23 @@ func (o *DefaultOCMInterfaceImpl) GetManagingCluster(targetClusterID string) (cl
Send()

if err != nil {
return "", "", fmt.Errorf("failed to find management cluster for cluster %s: %v", targetClusterID, err)
return "", "", isHostedControlPlane, fmt.Errorf("failed to find management cluster for cluster %s: %v", targetClusterID, err)
}
if mcResp.Items().Len() == 0 {
return "", "", fmt.Errorf("failed to find management cluster for cluster %s in %s env", targetClusterID, connection.URL())
return "", "", isHostedControlPlane, fmt.Errorf("failed to find management cluster for cluster %s in %s env", targetClusterID, connection.URL())
}
managingCluster = mcResp.Items().Get(0).Name()
}

if managingCluster == "" {
return "", "", fmt.Errorf("failed to lookup managing cluster for cluster %s", targetClusterID)
return "", "", isHostedControlPlane, fmt.Errorf("failed to lookup managing cluster for cluster %s", targetClusterID)
}

mcid, _, err := o.GetTargetCluster(managingCluster)
if err != nil {
return "", "", fmt.Errorf("failed to lookup managing cluster %s: %v", managingCluster, err)
return "", "", isHostedControlPlane, fmt.Errorf("failed to lookup managing cluster %s: %v", managingCluster, err)
}
return mcid, managingCluster, nil
return mcid, managingCluster, isHostedControlPlane, nil
}

// GetServiceCluster gets the service cluster for a given hpyershift hosted cluster
Expand Down

0 comments on commit 005f458

Please sign in to comment.