From ba1799719b3d3faf9ab3cbceac7381583aa36c94 Mon Sep 17 00:00:00 2001 From: Eamonn O'Toole Date: Tue, 10 Sep 2024 15:54:02 +0100 Subject: [PATCH] Add support for Broker API In this PR we add support for the Broker API. The Broker API will be used for two calls: - to get Subscription Details, from which we extract the Subscription ID and the Morpheus URL - to exchange the IAM API Client token for Morpheus access and refresh tokens The Morpheus URL and both tokens will then be returned to the calling terraform provider code. The Changes: - we add pkg/models/broker.go to define three structs, two for use with each broker API call and the third returned to the calling terraform provider code - we add pkg/client/broker.go to define the BrokerAPIService which implements GetMorpheusDetails, to make both broker API calls and return the details - we add a boolean removeVmaasCMPBasePath to pkg/client/api.go which is used to toggle removal of VmaasCmpAPIBasePath from the path if true (in the case of the broker API) or include it if false (in the case of the cmp API) - we add two methods to the APIClientHandler interface which will be used in broker client creation by the terraform provider code: - SetMetaFnAndVersion() which will be used to set the meta, tokenFunc and cmpVersion fields in APIClient, this avoids a call to the CMP API to get version information when initialising the Broker Client - GetSCMVersion() to return the CMP version when initialising the Broker Client after the CMP client, we add this as opposed to exporting the existing getVersion() to avoid approx 190 line changes - we add two constants to pkg/common used to set the Broker API paths --- pkg/client/api.go | 14 +++++++-- pkg/client/broker.go | 68 +++++++++++++++++++++++++++++++++++++++++ pkg/client/client.go | 19 ++++++++++-- pkg/common/constants.go | 6 +++- pkg/models/broker.go | 24 +++++++++++++++ 5 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 pkg/client/broker.go create mode 100644 pkg/models/broker.go diff --git a/pkg/client/api.go b/pkg/client/api.go index ef21d67..f8e5ce0 100644 --- a/pkg/client/api.go +++ b/pkg/client/api.go @@ -1,4 +1,4 @@ -// (C) Copyright 2021 Hewlett Packard Enterprise Development LP +// (C) Copyright 2021-2024 Hewlett Packard Enterprise Development LP package client @@ -25,6 +25,8 @@ type api struct { jsonParser jsonPareserFunc validations []validationFunc compatibleVersion string + // removeVmaasCMPBasePath is used to remove the base path of the vmaas-cmp API, for use by the broker API + removeVmaasCMPBasePath bool } // do will call the API provided. this function will not return any response, but @@ -49,7 +51,15 @@ func (a *api) do(ctx context.Context, request interface{}, queryParams map[strin if a.path == "" || a.method == "" || a.client == nil || a.jsonParser == nil { panic("api not properly configured") } - a.path = fmt.Sprintf("%s/%s/%s", a.client.getHost(), consts.VmaasCmpAPIBasePath, a.path) + + // Set the path + if !a.removeVmaasCMPBasePath { + // Add the base path of the vmaas-cmp API if we are calling the vmaas-cmp API + a.path = fmt.Sprintf("%s/%s/%s", a.client.getHost(), consts.VmaasCmpAPIBasePath, a.path) + } else { + // Don't use the base path of the vmaas-cmp API if we are calling the broker API + a.path = fmt.Sprintf("%s/%s", a.client.getHost(), a.path) + } for _, validations := range a.validations { err := validations() diff --git a/pkg/client/broker.go b/pkg/client/broker.go new file mode 100644 index 0000000..8730d6a --- /dev/null +++ b/pkg/client/broker.go @@ -0,0 +1,68 @@ +// (C) Copyright 2024 Hewlett Packard Enterprise Development LP + +package client + +import ( + "context" + "encoding/json" + "fmt" + "log" + + consts "github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk/pkg/common" + "github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk/pkg/models" +) + +// BrokerAPIService is a service that provides methods to interact with the broker API +type BrokerAPIService struct { + Client APIClientHandler + Cfg Configuration +} + +// GetMorpheusDetails returns Morpheus details to terraform +func (a *BrokerAPIService) GetMorpheusDetails(ctx context.Context) (models.MorpheusDetails, error) { + // Get the service instance ID and Morpheus URL + ServiceSubscriptionDetailsResp := models.SubscriptionDetailsResponse{} + serviceSubscriptionDetailsAPI := &api{ + method: "GET", + path: consts.SubscriptionDetails, + client: a.Client, + removeVmaasCMPBasePath: true, + + jsonParser: func(body []byte) error { + return json.Unmarshal(body, &ServiceSubscriptionDetailsResp) + }, + } + + // Use the default query params + if err := serviceSubscriptionDetailsAPI.do(ctx, nil, a.Cfg.DefaultQueryParams); err != nil { + return models.MorpheusDetails{}, fmt.Errorf("error getting service subscription details: %v", err) + } + + // Get the Morpheus token + MorpheusTokenResp := models.MorpheusTokenResponse{} + log.Printf(consts.MorpheusToken, ServiceSubscriptionDetailsResp.ServiceInstanceID) + morpheusTokenAPI := &api{ + method: "GET", + path: fmt.Sprintf(consts.MorpheusToken, ServiceSubscriptionDetailsResp.ServiceInstanceID), + client: a.Client, + removeVmaasCMPBasePath: true, + + jsonParser: func(body []byte) error { + return json.Unmarshal(body, &MorpheusTokenResp) + }, + } + + // No query params needed + if err := morpheusTokenAPI.do(ctx, nil, nil); err != nil { + return models.MorpheusDetails{}, fmt.Errorf("error getting Morpheus token: %v", err) + } + + // build response + ret := models.MorpheusDetails{ + AccessToken: MorpheusTokenResp.AccessToken, + RefreshToken: MorpheusTokenResp.RefreshToken, + URL: ServiceSubscriptionDetailsResp.URL, + } + + return ret, nil +} diff --git a/pkg/client/client.go b/pkg/client/client.go index 7e5a514..89c6d1f 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -1,4 +1,4 @@ -// (C) Copyright 2021 Hewlett Packard Enterprise Development LP +// (C) Copyright 2021-2024 Hewlett Packard Enterprise Development LP //go:generate go run github.com/golang/mock/mockgen -source ./client.go -package client -destination ./client_mock.go @@ -36,6 +36,11 @@ type APIClientHandler interface { SetMeta(meta interface{}, fn SetScmClientToken) error getVersion() int getHost() string + // The next two methods are for use when creating the Broker API client + // SetMetaFnAndVersion is used to set the client token function in meta and the SCM version for the Broker client + SetMetaFnAndVersion(meta interface{}, version int, fn SetScmClientToken) + // GetSCMVersion returns the SCM version for use when creating the Broker client + GetSCMVersion() int } // APIClient manages communication with the GreenLake Private Cloud VMaaS CMP API API v1.0.0 @@ -96,6 +101,12 @@ func (c *APIClient) SetMeta(meta interface{}, fn SetScmClientToken) error { return nil } +func (c *APIClient) SetMetaFnAndVersion(meta interface{}, version int, fn SetScmClientToken) { + c.meta = meta + c.tokenFunc = fn + c.cmpVersion = version +} + // callAPI do the request. func (c *APIClient) callAPI(request *http.Request) (*http.Response, error) { return c.cfg.HTTPClient.Do(request) @@ -110,8 +121,12 @@ func (c *APIClient) getVersion() int { return c.cmpVersion } +func (c *APIClient) GetSCMVersion() int { + return c.cmpVersion +} + // prepareRequest build the request -//nolint +// nolint func (c *APIClient) prepareRequest( ctx context.Context, path string, method string, diff --git a/pkg/common/constants.go b/pkg/common/constants.go index f19e26b..7e7403b 100644 --- a/pkg/common/constants.go +++ b/pkg/common/constants.go @@ -1,4 +1,4 @@ -// (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP +// (C) Copyright 2021-2024 Hewlett Packard Enterprise Development LP package common @@ -67,4 +67,8 @@ const ( // Morpheus version CMPSixZeroFiveVersion = "6.0.5" + + // Broker API paths + SubscriptionDetails = "vmaas/api/v1alpha1/subscription_details" + MorpheusToken = "vmaas/api/v1/service_instances/%s/cmp_access_token" ) diff --git a/pkg/models/broker.go b/pkg/models/broker.go new file mode 100644 index 0000000..248d4f6 --- /dev/null +++ b/pkg/models/broker.go @@ -0,0 +1,24 @@ +// (C) Copyright 2024 Hewlett Packard Enterprise Development LP + +package models + +// Broker structs go here + +// SubscriptionDetailsResponse is the response for Subscription Details from the broker +type SubscriptionDetailsResponse struct { + ServiceInstanceID string `json:"ServiceInstanceID"` + URL string `json:"URL"` +} + +// MorpheusTokenResponse is the response for Morpheus Token from the broker +type MorpheusTokenResponse struct { + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` +} + +// MorpheusDetails is what we return to terraform +type MorpheusDetails struct { + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` + URL string `json:"URL"` +}