Skip to content

Commit 80fae2b

Browse files
authored
OSD-28241: Allow building backplane config, login with provided OCM connections (#657)
* OSD-28241: Allow building backplane connections with provided OCM sdk connections * OSD-28241: Remove ineffectual assignment to err * OSD-28241: Remove defered close() to allow new OCM connection persistence
1 parent 8d74d7c commit 80fae2b

6 files changed

Lines changed: 137 additions & 18 deletions

File tree

cmd/ocm-backplane/login/login.go

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -487,9 +487,12 @@ func GetRestConfig(bp config.BackplaneConfiguration, clusterID string) (*rest.Co
487487
return BuildRestConfig(bpAPIClusterURL, accessToken, proxyURL)
488488
}
489489

490-
// GetRestConfig returns a client-go *rest.Config which can be used to programmatically interact with the
491-
// Kubernetes API of a provided clusterID
490+
// GetRestConfigWithConn returns a client-go *rest.Config which can be used to programmatically interact with the
491+
// Kubernetes API of a provided clusterID, using a provided OCM connection.
492492
func GetRestConfigWithConn(bp config.BackplaneConfiguration, ocmConnection *ocmsdk.Connection, clusterID string) (*rest.Config, error) {
493+
if ocmConnection == nil {
494+
return nil, fmt.Errorf("nil OCM connection provided to GetRestConfigWithConn()")
495+
}
493496
cluster, err := ocm.DefaultOCMInterface.GetClusterInfoByIDWithConn(ocmConnection, clusterID)
494497
if err != nil {
495498
return nil, err
@@ -500,7 +503,7 @@ func GetRestConfigWithConn(bp config.BackplaneConfiguration, ocmConnection *ocms
500503
return nil, err
501504
}
502505

503-
bpAPIClusterURL, err := doLogin(bp.URL, clusterID, *accessToken)
506+
bpAPIClusterURL, err := doLoginWithConn(bp.URL, clusterID, *accessToken, ocmConnection)
504507
if err != nil {
505508
return nil, fmt.Errorf("failed to backplane login to cluster %s: %v", cluster.Name(), err)
506509
}
@@ -533,11 +536,40 @@ func GetRestConfigAsUser(bp config.BackplaneConfiguration, clusterID, username s
533536
return cfg, nil
534537
}
535538

539+
// GetRestConfigAsUserWithConn returns a client-go *rest.Config like GetRestConfig, but supports configuring an
540+
// impersonation username. Commonly, this is "backplane-cluster-admin"
541+
// best practice would be to add at least one elevationReason in order to justity the impersonation
542+
// Uses provided OCM connection for attributes
543+
func GetRestConfigAsUserWithConn(bp config.BackplaneConfiguration, ocmConn *ocmsdk.Connection, clusterID, username string, elevationReasons ...string) (*rest.Config, error) {
544+
cfg, err := GetRestConfigWithConn(bp, ocmConn, clusterID)
545+
if err != nil {
546+
return nil, err
547+
}
548+
549+
cfg.Impersonate = rest.ImpersonationConfig{
550+
UserName: username,
551+
}
552+
553+
if len(elevationReasons) > 0 {
554+
cfg.Impersonate.Extra = map[string][]string{"reason": elevationReasons}
555+
}
556+
557+
return cfg, nil
558+
}
559+
536560
// doLogin returns the proxy url for the target cluster.
537561
func doLogin(api, clusterID, accessToken string) (string, error) {
562+
return doLoginWithConn(api, clusterID, accessToken, nil)
563+
}
538564

539-
client, err := backplaneapi.DefaultClientUtils.MakeRawBackplaneAPIClientWithAccessToken(api, accessToken)
540-
565+
func doLoginWithConn(api, clusterID, accessToken string, ocmConn *ocmsdk.Connection) (string, error) {
566+
var client BackplaneApi.ClientInterface
567+
var err error = nil
568+
if ocmConn != nil {
569+
client, err = backplaneapi.DefaultClientUtils.MakeRawBackplaneAPIClientWithAccessTokenWithConn(api, accessToken, ocmConn)
570+
} else {
571+
client, err = backplaneapi.DefaultClientUtils.MakeRawBackplaneAPIClientWithAccessToken(api, accessToken)
572+
}
541573
if err != nil {
542574
return "", fmt.Errorf("unable to create backplane api client")
543575
}

pkg/backplaneapi/clientUtils.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,19 @@ import (
77
"net/http"
88
"net/url"
99

10+
ocmsdk "github.com/openshift-online/ocm-sdk-go"
1011
BackplaneApi "github.com/openshift/backplane-api/pkg/client"
11-
logger "github.com/sirupsen/logrus"
12-
1312
"github.com/openshift/backplane-cli/pkg/cli/config"
1413
"github.com/openshift/backplane-cli/pkg/info"
1514
"github.com/openshift/backplane-cli/pkg/ocm"
15+
logger "github.com/sirupsen/logrus"
1616
)
1717

1818
type ClientUtils interface {
1919
MakeBackplaneAPIClient(base string) (BackplaneApi.ClientWithResponsesInterface, error)
2020
MakeBackplaneAPIClientWithAccessToken(base, accessToken string) (BackplaneApi.ClientWithResponsesInterface, error)
2121
MakeRawBackplaneAPIClientWithAccessToken(base, accessToken string) (BackplaneApi.ClientInterface, error)
22+
MakeRawBackplaneAPIClientWithAccessTokenWithConn(base, accessToken string, ocmConn *ocmsdk.Connection) (BackplaneApi.ClientInterface, error)
2223
MakeRawBackplaneAPIClient(base string) (BackplaneApi.ClientInterface, error)
2324
GetBackplaneClient(backplaneURL string, ocmToken string, proxyURL *string) (client BackplaneApi.ClientInterface, err error)
2425
SetClientProxyURL(proxyURL string) error
@@ -45,9 +46,20 @@ func makeClientOptions(accessToken string) BackplaneApi.ClientOption {
4546
}
4647

4748
func (s *DefaultClientUtilsImpl) MakeRawBackplaneAPIClientWithAccessToken(base, accessToken string) (BackplaneApi.ClientInterface, error) {
49+
return s.MakeRawBackplaneAPIClientWithAccessTokenWithConn(base, accessToken, nil)
50+
}
51+
52+
func (s *DefaultClientUtilsImpl) MakeRawBackplaneAPIClientWithAccessTokenWithConn(base, accessToken string, ocmConn *ocmsdk.Connection) (BackplaneApi.ClientInterface, error) {
53+
4854
// Inject client Proxy Url from config
4955
if s.clientProxyURL == "" {
50-
bpConfig, err := config.GetBackplaneConfiguration()
56+
var bpConfig config.BackplaneConfiguration
57+
var err error
58+
if ocmConn != nil {
59+
bpConfig, err = config.GetBackplaneConfigurationWithConn(ocmConn)
60+
} else {
61+
bpConfig, err = config.GetBackplaneConfiguration()
62+
}
5163
if err != nil {
5264
return nil, err
5365
}

pkg/backplaneapi/mocks/clientUtilsMock.go

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/cli/config/config.go

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
logger "github.com/sirupsen/logrus"
1414
"github.com/spf13/viper"
1515

16+
ocmsdk "github.com/openshift-online/ocm-sdk-go"
1617
"github.com/openshift/backplane-cli/pkg/info"
1718
"github.com/openshift/backplane-cli/pkg/ocm"
1819
)
@@ -102,6 +103,12 @@ func GetConfigFilePath() (string, error) {
102103

103104
// GetBackplaneConfiguration parses and returns the given backplane configuration
104105
func GetBackplaneConfiguration() (bpConfig BackplaneConfiguration, err error) {
106+
return GetBackplaneConfigurationWithConn(nil)
107+
}
108+
109+
// GetBackplaneConfiguration parses and returns the given backplane configuration using attributes
110+
// from provided OCM connection
111+
func GetBackplaneConfigurationWithConn(ocmConn *ocmsdk.Connection) (bpConfig BackplaneConfiguration, err error) {
105112
viper.SetDefault(prodEnvNameKey, prodEnvNameDefaultValue)
106113
viper.SetDefault(jiraBaseURLKey, JiraBaseURLDefaultValue)
107114
viper.SetDefault(JiraConfigForAccessRequestsKey, JiraConfigForAccessRequestsDefaultValue)
@@ -145,22 +152,31 @@ func GetBackplaneConfiguration() (bpConfig BackplaneConfiguration, err error) {
145152
} else {
146153
logger.Debug("This is govcloud, no proxy to use")
147154
}
148-
149155
// Warn user if url defined in the config file
150156
if viper.GetString("url") != "" {
151157
logger.Warn("Manual URL configuration is deprecated, please remove URL key from Backplane configuration")
152158
}
153-
154159
// Warn if user has explicitly defined backplane URL via env
155-
url, ok := getBackplaneEnv(info.BackplaneURLEnvName)
156-
if ok {
157-
logger.Warn(fmt.Sprintf("Manual URL configuration is deprecated, please unset the environment %s", info.BackplaneURLEnvName))
158-
bpConfig.URL = url
159-
} else {
160-
// Fetch backplane URL from ocm env
161-
if bpConfig.URL, err = bpConfig.GetBackplaneURL(); err != nil {
160+
url, envURLok := getBackplaneEnv(info.BackplaneURLEnvName)
161+
if envURLok {
162+
logger.Warn(fmt.Printf("Manual URL configuration is deprecated, please unset the environment %s", info.BackplaneURLEnvName))
163+
}
164+
165+
if ocmConn != nil {
166+
// If an OCM connection is provided use this to fetch BP URL
167+
// from its v1.environment info
168+
if bpConfig.URL, err = bpConfig.GetBackplaneURLWithConn(ocmConn); err != nil {
162169
return bpConfig, err
163170
}
171+
} else {
172+
if envURLok {
173+
bpConfig.URL = url
174+
} else {
175+
// Fetch backplane URL from ocm env
176+
if bpConfig.URL, err = bpConfig.GetBackplaneURL(); err != nil {
177+
return bpConfig, err
178+
}
179+
}
164180
}
165181

166182
// proxyURL is required
@@ -258,6 +274,10 @@ var testProxy = func(ctx context.Context, testURL string, proxyURL url.URL) erro
258274
return nil
259275
}
260276

277+
func (config *BackplaneConfiguration) GetFirstWorkingProxyURL(s []string) string {
278+
return config.getFirstWorkingProxyURL(s)
279+
}
280+
261281
func (config *BackplaneConfiguration) getFirstWorkingProxyURL(s []string) string {
262282
if len(s) == 0 {
263283
logger.Debug("No proxy to use")
@@ -374,6 +394,20 @@ func GetConfigDirectory() (string, error) {
374394
return configDirectory, nil
375395
}
376396

397+
// GetBackplaneURL returns API URL
398+
func (config *BackplaneConfiguration) GetBackplaneURLWithConn(ocmConn *ocmsdk.Connection) (string, error) {
399+
ocmEnv, err := ocm.DefaultOCMInterface.GetOCMEnvironmentWithConn(ocmConn)
400+
if err != nil {
401+
return "", err
402+
}
403+
url, ok := ocmEnv.GetBackplaneURL()
404+
if !ok {
405+
return "", fmt.Errorf("the requested API endpoint is not available for the OCM environment: %v", ocmEnv.Name())
406+
}
407+
logger.Infof("Backplane URL retrieved via OCM environment: %s", url)
408+
return url, nil
409+
}
410+
377411
// GetBackplaneURL returns API URL
378412
func (config *BackplaneConfiguration) GetBackplaneURL() (string, error) {
379413
ocmEnv, err := ocm.DefaultOCMInterface.GetOCMEnvironment()

pkg/ocm/mocks/ocmWrapperMock.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/ocm/ocm.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type OCMInterface interface {
3636
GetOCMEnvironment() (*cmv1.Environment, error)
3737
GetOCMAccessTokenWithConn(ocmConnection *ocmsdk.Connection) (*string, error)
3838
GetClusterInfoByIDWithConn(ocmConnection *ocmsdk.Connection, clusterID string) (*cmv1.Cluster, error)
39+
GetOCMEnvironmentWithConn(connection *ocmsdk.Connection) (*cmv1.Environment, error)
3940
IsClusterAccessProtectionEnabled(ocmConnection *ocmsdk.Connection, clusterID string) (bool, error)
4041
GetClusterActiveAccessRequest(ocmConnection *ocmsdk.Connection, clusterID string) (*acctrspv1.AccessRequest, error)
4142
CreateClusterAccessRequest(ocmConnection *ocmsdk.Connection, clusterID, reason, jiraIssueID, approvalDuration string) (*acctrspv1.AccessRequest, error)
@@ -387,14 +388,23 @@ func (o *DefaultOCMInterfaceImpl) GetStsSupportJumpRoleARN(ocmConnection *ocmsdk
387388
return response.Body().RoleArn(), nil
388389
}
389390

390-
// GetOCMEnvironment returns the Backplane API URL based on the OCM env
391+
// GetOCMEnvironment returns the OCM v1.environment response (containing the Backplane API URL).
391392
func (o *DefaultOCMInterfaceImpl) GetOCMEnvironment() (*cmv1.Environment, error) {
392393
// Create the client for the OCM API
393394
connection, err := o.SetupOCMConnection()
394395
if err != nil {
395396
return nil, fmt.Errorf("failed to create OCM connection: %v", err)
396397
}
397398

399+
return o.GetOCMEnvironmentWithConn(connection)
400+
}
401+
402+
// GetOCMEnvironmentWithConn returns the v1.environment response for the provided
403+
// OCM connection (containing the Backplane API URL)
404+
func (o *DefaultOCMInterfaceImpl) GetOCMEnvironmentWithConn(connection *ocmsdk.Connection) (*cmv1.Environment, error) {
405+
if connection == nil {
406+
return nil, fmt.Errorf("err GetOCMEnvironmentWithConn() provided nil OCM connection")
407+
}
398408
responseEnv, err := connection.ClustersMgmt().V1().Environment().Get().Send()
399409
if err != nil {
400410
// Check if the error indicates a forbidden status

0 commit comments

Comments
 (0)