From 7f2486760a682a803f2b0e1090e3e1f151b78c1b Mon Sep 17 00:00:00 2001 From: Eamonn O'Toole Date: Wed, 11 Sep 2024 09:48:23 +0100 Subject: [PATCH 1/9] Add morpheus_details data-source In this PR we add a data-source to fetch details for an on-prem Morpheus deployment. These details are: - access_token - access_token_expires_in - morpheus_url This data-source can be used to set the url and access_token fields in a Morpheus provider stanza, and should make it easier for customers to use the Morpheus provider with VMaaS deployments. The data-source is named hpegl_vmaas_morpheus_details The changes: - we've added tf examples in the examples directory - minimal.tf showing just one hpegl stanza for one location and/or space-name - multiple.tf showing two hpegl stanzas for two locations - we've added a tfdocs template that makes use of these examples in templates/data-sources/vmaas_morpheus_details.md.tmpl - we've added a definition of the data-source to resources/data_source_morpheus_token_broker.go - we've added a definition of a BrokerClient with a MorpheusDetails data-source to internal/cmp/broker_client.go - this BrokerClient is initialised with an APIClient instance created for the Broker API and a corresponding Configuration - we've added a newMorhpeusBroker definition in internal/cmp/morpheus_datasource_broker.go which is used in the above initialisation - we add a broker_url to the VMaaS provider block - we add the Broker Client to pgk/client - we add BrokerClient to the Client struct - we create the BrokerClient in NewClient - we add X-Tenant-ID to the headers for the BrokerClient - we don't add any default query parameters - we create a NewAPIClient with the broker_url - we create a new Configuration for the Broker, the main use of this configuration is to define the query parameters for use with one of the Broker API calls - we pass the Broker API Client and this new Configuration to the constructor defined in internal/cmp/broker_client.go --- .../hpegl_vmaas_morpheus_details/minimal.tf | 10 ++++ .../hpegl_vmaas_morpheus_details/multiple.tf | 44 ++++++++++++++ go.mod | 2 + internal/cmp/broker_client.go | 19 ++++++ internal/cmp/morpheus_datasource_broker.go | 45 ++++++++++++++ internal/resources/constants.go | 2 + .../data_source_morpheus_token_broker.go | 60 +++++++++++++++++++ pkg/client/client.go | 31 +++++++++- pkg/constants/constants.go | 3 + pkg/resources/registration.go | 10 +++- pkg/utils/meta.go | 20 +++++++ .../vmaas_morpheus_details.md.tmpl | 28 +++++++++ 12 files changed, 271 insertions(+), 3 deletions(-) create mode 100644 examples/data-sources/hpegl_vmaas_morpheus_details/minimal.tf create mode 100644 examples/data-sources/hpegl_vmaas_morpheus_details/multiple.tf create mode 100644 internal/cmp/broker_client.go create mode 100644 internal/cmp/morpheus_datasource_broker.go create mode 100644 internal/resources/data_source_morpheus_token_broker.go create mode 100644 templates/data-sources/vmaas_morpheus_details.md.tmpl diff --git a/examples/data-sources/hpegl_vmaas_morpheus_details/minimal.tf b/examples/data-sources/hpegl_vmaas_morpheus_details/minimal.tf new file mode 100644 index 00000000..5454e7a9 --- /dev/null +++ b/examples/data-sources/hpegl_vmaas_morpheus_details/minimal.tf @@ -0,0 +1,10 @@ +# (C) Copyright 2024 Hewlett Packard Enterprise Development LP + +data "hpegl_vmaas_morpheus_details" "morpheus_details" {} + +provider "morpheus" { + url = data.hpegl_vmaas_morpheus_details.morpheus_details.morpheus_url + access_token = data.hpegl_vmaas_morpheus_details.morpheus_details.access_token +} + + diff --git a/examples/data-sources/hpegl_vmaas_morpheus_details/multiple.tf b/examples/data-sources/hpegl_vmaas_morpheus_details/multiple.tf new file mode 100644 index 00000000..f7d59d9f --- /dev/null +++ b/examples/data-sources/hpegl_vmaas_morpheus_details/multiple.tf @@ -0,0 +1,44 @@ +# (C) Copyright 2024 Hewlett Packard Enterprise Development LP + +# Location 1 +provider "hpegl" { + vmaas { + location = var.location_1 + } + + alias = "location_1" +} + +data "hpegl_vmaas_morpheus_details" "location_1" { + provider = hpegl.location_1 +} + +provider "morpheus" { + url = data.hpegl_vmaas_morpheus_details.location_1.morpheus_url + access_token = data.hpegl_vmaas_morpheus_details.location_1.access_token + + alias = "morpheus_location_1" +} + + +# Location 2 +provider "hpegl" { + vmaas { + location = var.location_2 + } + + alias = "location_2" +} + +data "hpegl_vmaas_morpheus_details" "location_2" { + provider = hpegl.location_2 +} + +provider "morpheus" { + url = data.hpegl_vmaas_morpheus_details.location_2.morpheus_url + access_token = data.hpegl_vmaas_morpheus_details.location_2.access_token + + alias = "morpheus_location_2" +} + + diff --git a/go.mod b/go.mod index 8d04f832..40f46355 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,8 @@ require ( github.com/tshihad/tftags v0.0.10 ) +replace github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk => ../hpegl-vmaas-cmp-go-sdk + require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect diff --git a/internal/cmp/broker_client.go b/internal/cmp/broker_client.go new file mode 100644 index 00000000..d641c13f --- /dev/null +++ b/internal/cmp/broker_client.go @@ -0,0 +1,19 @@ +// (C) Copyright 2024 Hewlett Packard Enterprise Development LP + +package cmp + +import apiClient "github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk/pkg/client" + +// BrokerClient - struct to hold the broker client details +type BrokerClient struct { + DSMorpheusDetails DataSource +} + +// NewBrokerClient - function to create a new broker client +func NewBrokerClient(client *apiClient.APIClient, cfg apiClient.Configuration) *BrokerClient { + return &BrokerClient{ + DSMorpheusDetails: newMorpheusBroker( + &apiClient.BrokerAPIService{Client: client, Cfg: cfg}, + ), + } +} diff --git a/internal/cmp/morpheus_datasource_broker.go b/internal/cmp/morpheus_datasource_broker.go new file mode 100644 index 00000000..ce75e8ce --- /dev/null +++ b/internal/cmp/morpheus_datasource_broker.go @@ -0,0 +1,45 @@ +// (C) Copyright 2024 Hewlett Packard Enterprise Development LP + +package cmp + +import ( + "context" + "github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk/pkg/client" + + "github.com/HewlettPackard/hpegl-vmaas-terraform-resources/internal/utils" +) + +// morpheusBroker is used to read morpheus details using the Broker API +type morpheusBroker struct { + bClient *client.BrokerAPIService +} + +func newMorpheusBroker(bClient *client.BrokerAPIService) *morpheusBroker { + return &morpheusBroker{bClient: bClient} +} + +// Read reads the morpheus details using the Broker API +func (m *morpheusBroker) Read(ctx context.Context, d *utils.Data, meta interface{}) error { + setMeta(meta, m.bClient.Client) + + // Get Morpheus Tokens and URL + morpheusDetails, err := m.bClient.GetMorpheusDetails(ctx) + if err != nil { + return err + } + + // Set access_token, refresh_token and morpheus_url + if err = d.Set("access_token", morpheusDetails.AccessToken); err != nil { + return err + } + + if err = d.Set("refresh_token", morpheusDetails.RefreshToken); err != nil { + return err + } + + if err = d.Set("morpheus_url", morpheusDetails.RefreshToken); err != nil { + return err + } + + return nil +} diff --git a/internal/resources/constants.go b/internal/resources/constants.go index bd3549c7..cd3ce30d 100644 --- a/internal/resources/constants.go +++ b/internal/resources/constants.go @@ -33,6 +33,8 @@ const ( DSDhcpServer = "hpegl_vmaas_dhcp_server" DSInstanceStorageType = "hpegl_vmaas_instance_disk_type" + DSMorpheusDataSource = "hpegl_vmaas_morpheus_details" + // resource key ResInstance = "hpegl_vmaas_instance" ResInstanceClone = "hpegl_vmaas_instance_clone" diff --git a/internal/resources/data_source_morpheus_token_broker.go b/internal/resources/data_source_morpheus_token_broker.go new file mode 100644 index 00000000..1f6728b0 --- /dev/null +++ b/internal/resources/data_source_morpheus_token_broker.go @@ -0,0 +1,60 @@ +// (C) Copyright 2024 Hewlett Packard Enterprise Development LP + +package resources + +import ( + "context" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/HewlettPackard/hpegl-vmaas-terraform-resources/internal/utils" + "github.com/HewlettPackard/hpegl-vmaas-terraform-resources/pkg/client" +) + +// MorpheusDetailsBroker returns a schema.Resource for the MorpheusDetails data source +func MorpheusDetailsBroker() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "access_token": { + Type: schema.TypeString, + Computed: true, + Description: "Morpheus access_token", + Sensitive: true, + }, + "refresh_token": { + Type: schema.TypeString, + Computed: true, + Description: "Morpheus refresh_token", + Sensitive: true, + }, + "morpheus_url": { + Type: schema.TypeString, + Computed: true, + Description: "Morpheus URL", + Sensitive: false, + }, + }, + ReadContext: morpheusDetailsBrokerReadContext, + Description: `The ` + DSMorpheusDataSource + ` data source can be used to get a Morpheus token and URL using the IAM API Client creds provided`, + SchemaVersion: 0, + StateUpgraders: nil, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + } +} + +func morpheusDetailsBrokerReadContext(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + c, err := client.GetClientFromMetaMap(meta) + if err != nil { + return diag.FromErr(err) + } + + data := utils.NewData(d) + err = c.BrokerClient.DSMorpheusDetails.Read(ctx, data, meta) + if err != nil { + return diag.FromErr(err) + } + + return nil +} diff --git a/pkg/client/client.go b/pkg/client/client.go index a4317ea4..2e6b1800 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -6,12 +6,15 @@ import ( "fmt" "os" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/hewlettpackard/hpegl-provider-lib/pkg/client" + api_client "github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk/pkg/client" + cmp_client "github.com/HewlettPackard/hpegl-vmaas-terraform-resources/internal/cmp" "github.com/HewlettPackard/hpegl-vmaas-terraform-resources/pkg/constants" "github.com/HewlettPackard/hpegl-vmaas-terraform-resources/pkg/utils" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hewlettpackard/hpegl-provider-lib/pkg/client" ) // keyForGLClientMap is the key in the map[string]interface{} that is passed down by hpegl used to store *Client @@ -24,6 +27,8 @@ var _ client.Initialisation = (*InitialiseClient)(nil) // Client is the client struct that is used by the provider code type Client struct { CmpClient *cmp_client.Client + // BrokerClient is used to get Morpheus details + BrokerClient *cmp_client.BrokerClient } // Get env configurations for VmaaS services @@ -63,6 +68,7 @@ func (i InitialiseClient) NewClient(r *schema.ResourceData) (interface{}, error) queryParam[constants.SpaceKey] = vmaasProviderSettings[constants.SPACENAME].(string) } + // Create cmp client cfg := api_client.Configuration{ Host: vmaasProviderSettings[constants.APIURL].(string), DefaultHeader: getHeaders(), @@ -72,6 +78,27 @@ func (i InitialiseClient) NewClient(r *schema.ResourceData) (interface{}, error) utils.SetMeta(apiClient, r) client.CmpClient = cmp_client.NewClient(apiClient, cfg) + // Create broker client + brokerHeaders := getHeaders() + tenantID := r.Get(constants.TenantID).(string) + brokerHeaders["X-Tenant-ID"] = tenantID + // We don't add default query params to broker client + brokerCfgForAPIClient := api_client.Configuration{ + Host: vmaasProviderSettings[constants.BROKERRURL].(string), + DefaultHeader: brokerHeaders, + } + brokerApiClient := api_client.NewAPIClient(&brokerCfgForAPIClient) + utils.SetMetaFnAndVersion(brokerApiClient, r, apiClient.GetSCMVersion()) + + // brokerCfg is passed down to NewBrokerClient. It is used mainly to set the query params + // for the call to get SubscriptionDetails + brokerCfg := api_client.Configuration{ + Host: vmaasProviderSettings[constants.BROKERRURL].(string), + DefaultHeader: brokerHeaders, + DefaultQueryParams: queryParam, + } + client.BrokerClient = cmp_client.NewBrokerClient(brokerApiClient, brokerCfg) + return client, nil } diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 38b05508..9255d612 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -7,12 +7,15 @@ const ( // ServiceName - the service mnemonic ServiceName = "vmaas" ServiceURL = "https://iac-vmaas.us1.greenlake-hpe.com" + BrokerURL = "https://vmaas-broker.us1.greenlake-hpe.com" IamGlp string = "glp" IamGlcs string = "glcs" + TenantID string = "tenant_id" LOCATION = "location" SPACENAME = "space_name" APIURL = "api_url" + BROKERRURL = "broker_url" INSECURE = "allow_insecure" SpaceKey = "space" WorkspaceKey = "workspaceID" diff --git a/pkg/resources/registration.go b/pkg/resources/registration.go index feaa1e0b..312af728 100644 --- a/pkg/resources/registration.go +++ b/pkg/resources/registration.go @@ -5,9 +5,10 @@ package resources import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hewlettpackard/hpegl-provider-lib/pkg/registration" + "github.com/HewlettPackard/hpegl-vmaas-terraform-resources/internal/resources" "github.com/HewlettPackard/hpegl-vmaas-terraform-resources/pkg/constants" - "github.com/hewlettpackard/hpegl-provider-lib/pkg/registration" ) // Assert that Registration implements the ServiceRegistration interface @@ -48,6 +49,7 @@ func (r Registration) SupportedDataSources() map[string]*schema.Resource { resources.DSLBVirtualServerSslCert: resources.LBVirtualServerSslCertData(), resources.DSDhcpServer: resources.DhcpServerData(), resources.DSInstanceStorageType: resources.ReadInstanceStorageType(), + resources.DSMorpheusDataSource: resources.MorpheusDetailsBroker(), } } @@ -91,6 +93,12 @@ func (r Registration) ProviderSchemaEntry() *schema.Resource { DefaultFunc: schema.EnvDefaultFunc("HPEGL_VMAAS_API_URL", constants.ServiceURL), Description: "The URL to use for the VMaaS API, can also be set with the HPEGL_VMAAS_API_URL env var", }, + constants.BROKERRURL: { + Type: schema.TypeString, + Required: true, + DefaultFunc: schema.EnvDefaultFunc("HPEGL_VMAAS_BROKER_URL", constants.BrokerURL), + Description: "The URL to use for the VMaaS Broker API, can also be set with the HPEGL_VMAAS_BROKER_URL env var", + }, }, } } diff --git a/pkg/utils/meta.go b/pkg/utils/meta.go index 56fa749a..dac87499 100644 --- a/pkg/utils/meta.go +++ b/pkg/utils/meta.go @@ -31,3 +31,23 @@ func SetMeta(apiClient *client.APIClient, r *schema.ResourceData) { log.Printf("[WARN] Error: %s", err) } } + +// SetMetaFnAndVersion sets the token-generation function and version for the Broker API client +func SetMetaFnAndVersion(apiClient *client.APIClient, r *schema.ResourceData, version int) { + apiClient.SetMetaFnAndVersion(nil, version, func(ctx *context.Context, meta interface{}) { + // Initialise token handler + h, err := serviceclient.NewHandler(r) + if err != nil { + log.Printf("[WARN] Unable to fetch token for SCM client: %s", err) + } + + // Get token retrieve func and put in c + trf := retrieve.NewTokenRetrieveFunc(h) + token, err := trf(*ctx) + if err != nil { + log.Printf("[WARN] Unable to fetch token for SCM client: %s", err) + } else { + *ctx = context.WithValue(*ctx, client.ContextAccessToken, token) + } + }) +} diff --git a/templates/data-sources/vmaas_morpheus_details.md.tmpl b/templates/data-sources/vmaas_morpheus_details.md.tmpl new file mode 100644 index 00000000..148b85ea --- /dev/null +++ b/templates/data-sources/vmaas_morpheus_details.md.tmpl @@ -0,0 +1,28 @@ +--- +layout: "" +page_title: "hpegl_vmaas_morpheus_details Data-source - vmaas-terraform-data-sources" +subcategory: {{ $arr := split .Name "_" }}"{{ index $arr 1 }}" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +-> Compatible version >= 5.2.4 + +# Data-source hpegl_vmaas_morpheus_details + +{{ .Description | trimspace }} + +`hpegl_vmaas_morpheus_details` data-source supports fetching the details of the on-prem Morpheus instance. + +## Example usage with the Morpheus provider - one location and one space-name + +{{tffile "examples/data-sources/hpegl_vmaas_morpheus_details/minimal.tf"}} + +## Example usage with the Morpheus provider - multiple locations and/or space-names + +{{tffile "examples/data-sources/hpegl_vmaas_morpheus_details/multiple.tf"}} + +-> Note that multiple hpegl provider stanzas along with provider aliasing should be used in the case + where there are multiple VMaaS locations and/or space-names + +{{ .SchemaMarkdown | trimspace }} From d9a5ee59699fce588a76822fc1affba81357fd93 Mon Sep 17 00:00:00 2001 From: Eamonn O'Toole Date: Mon, 16 Sep 2024 17:41:57 +0100 Subject: [PATCH 2/9] Changes requested by Mahesh --- .../hpegl_vmaas_morpheus_details/minimal.tf | 2 +- .../hpegl_vmaas_morpheus_details/multiple.tf | 4 ++-- internal/cmp/morpheus_datasource_broker.go | 10 ++++++---- .../data_source_morpheus_token_broker.go | 17 +++++++++-------- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/examples/data-sources/hpegl_vmaas_morpheus_details/minimal.tf b/examples/data-sources/hpegl_vmaas_morpheus_details/minimal.tf index 5454e7a9..32951764 100644 --- a/examples/data-sources/hpegl_vmaas_morpheus_details/minimal.tf +++ b/examples/data-sources/hpegl_vmaas_morpheus_details/minimal.tf @@ -3,7 +3,7 @@ data "hpegl_vmaas_morpheus_details" "morpheus_details" {} provider "morpheus" { - url = data.hpegl_vmaas_morpheus_details.morpheus_details.morpheus_url + url = data.hpegl_vmaas_morpheus_details.morpheus_details.url access_token = data.hpegl_vmaas_morpheus_details.morpheus_details.access_token } diff --git a/examples/data-sources/hpegl_vmaas_morpheus_details/multiple.tf b/examples/data-sources/hpegl_vmaas_morpheus_details/multiple.tf index f7d59d9f..306d14e9 100644 --- a/examples/data-sources/hpegl_vmaas_morpheus_details/multiple.tf +++ b/examples/data-sources/hpegl_vmaas_morpheus_details/multiple.tf @@ -14,7 +14,7 @@ data "hpegl_vmaas_morpheus_details" "location_1" { } provider "morpheus" { - url = data.hpegl_vmaas_morpheus_details.location_1.morpheus_url + url = data.hpegl_vmaas_morpheus_details.location_1.url access_token = data.hpegl_vmaas_morpheus_details.location_1.access_token alias = "morpheus_location_1" @@ -35,7 +35,7 @@ data "hpegl_vmaas_morpheus_details" "location_2" { } provider "morpheus" { - url = data.hpegl_vmaas_morpheus_details.location_2.morpheus_url + url = data.hpegl_vmaas_morpheus_details.location_2.url access_token = data.hpegl_vmaas_morpheus_details.location_2.access_token alias = "morpheus_location_2" diff --git a/internal/cmp/morpheus_datasource_broker.go b/internal/cmp/morpheus_datasource_broker.go index ce75e8ce..07c54381 100644 --- a/internal/cmp/morpheus_datasource_broker.go +++ b/internal/cmp/morpheus_datasource_broker.go @@ -4,8 +4,8 @@ package cmp import ( "context" - "github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk/pkg/client" + "github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk/pkg/client" "github.com/HewlettPackard/hpegl-vmaas-terraform-resources/internal/utils" ) @@ -28,16 +28,18 @@ func (m *morpheusBroker) Read(ctx context.Context, d *utils.Data, meta interface return err } - // Set access_token, refresh_token and morpheus_url + // Set all of the details + d.SetId(morpheusDetails.ID) + if err = d.Set("access_token", morpheusDetails.AccessToken); err != nil { return err } - if err = d.Set("refresh_token", morpheusDetails.RefreshToken); err != nil { + if err = d.Set("access_token_expires_in", morpheusDetails.AccessTokenExpiresIn); err != nil { return err } - if err = d.Set("morpheus_url", morpheusDetails.RefreshToken); err != nil { + if err = d.Set("url", morpheusDetails.URL); err != nil { return err } diff --git a/internal/resources/data_source_morpheus_token_broker.go b/internal/resources/data_source_morpheus_token_broker.go index 1f6728b0..e1a4c1a2 100644 --- a/internal/resources/data_source_morpheus_token_broker.go +++ b/internal/resources/data_source_morpheus_token_broker.go @@ -21,21 +21,22 @@ func MorpheusDetailsBroker() *schema.Resource { Description: "Morpheus access_token", Sensitive: true, }, - "refresh_token": { - Type: schema.TypeString, + "access_token_expires_in": { + Type: schema.TypeInt, Computed: true, - Description: "Morpheus refresh_token", - Sensitive: true, + Description: "Seconds to expiry of access_token", + Sensitive: false, }, - "morpheus_url": { + "url": { Type: schema.TypeString, Computed: true, Description: "Morpheus URL", Sensitive: false, }, }, - ReadContext: morpheusDetailsBrokerReadContext, - Description: `The ` + DSMorpheusDataSource + ` data source can be used to get a Morpheus token and URL using the IAM API Client creds provided`, + ReadContext: MorpheusDetailsBrokerReadContext, + Description: `The ` + DSMorpheusDataSource + ` data source can be used to get a details of the Morpheus instance + used by VMaaS. The details that can be retrieved are the access_token, access_token_expires_in and the URL.`, SchemaVersion: 0, StateUpgraders: nil, Importer: &schema.ResourceImporter{ @@ -44,7 +45,7 @@ func MorpheusDetailsBroker() *schema.Resource { } } -func morpheusDetailsBrokerReadContext(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func MorpheusDetailsBrokerReadContext(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { c, err := client.GetClientFromMetaMap(meta) if err != nil { return diag.FromErr(err) From 7c41e8ea5d47d7ed4f15d6d976fc81b86d88e17d Mon Sep 17 00:00:00 2001 From: Eamonn O'Toole Date: Tue, 17 Sep 2024 16:07:16 +0100 Subject: [PATCH 3/9] Updates based on more Mahesh comments We've changed the MorpheusDetails response from the SDK, and we adapt the data-source definition and and API Read implementation accordingly. --- internal/cmp/morpheus_datasource_broker.go | 2 +- internal/resources/data_source_morpheus_token_broker.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/cmp/morpheus_datasource_broker.go b/internal/cmp/morpheus_datasource_broker.go index 07c54381..58d5a98a 100644 --- a/internal/cmp/morpheus_datasource_broker.go +++ b/internal/cmp/morpheus_datasource_broker.go @@ -35,7 +35,7 @@ func (m *morpheusBroker) Read(ctx context.Context, d *utils.Data, meta interface return err } - if err = d.Set("access_token_expires_in", morpheusDetails.AccessTokenExpiresIn); err != nil { + if err = d.Set("access_token_expires", morpheusDetails.AccessTokenExpires); err != nil { return err } diff --git a/internal/resources/data_source_morpheus_token_broker.go b/internal/resources/data_source_morpheus_token_broker.go index e1a4c1a2..6414fda1 100644 --- a/internal/resources/data_source_morpheus_token_broker.go +++ b/internal/resources/data_source_morpheus_token_broker.go @@ -21,10 +21,10 @@ func MorpheusDetailsBroker() *schema.Resource { Description: "Morpheus access_token", Sensitive: true, }, - "access_token_expires_in": { + "access_token_expires": { Type: schema.TypeInt, Computed: true, - Description: "Seconds to expiry of access_token", + Description: "Unix timestamp of when the access_token expires", Sensitive: false, }, "url": { @@ -36,7 +36,7 @@ func MorpheusDetailsBroker() *schema.Resource { }, ReadContext: MorpheusDetailsBrokerReadContext, Description: `The ` + DSMorpheusDataSource + ` data source can be used to get a details of the Morpheus instance - used by VMaaS. The details that can be retrieved are the access_token, access_token_expires_in and the URL.`, + used by VMaaS. The details that can be retrieved are the access_token, access_token_expires and the URL.`, SchemaVersion: 0, StateUpgraders: nil, Importer: &schema.ResourceImporter{ From 44773912f816c5ff7ed3520f0e5caf5acb4067eb Mon Sep 17 00:00:00 2001 From: Eamonn O'Toole Date: Thu, 19 Sep 2024 11:20:49 +0100 Subject: [PATCH 4/9] Update to import SDK v0.1.12 This version of the SDK supports creation of the Broker API Client. We've updated the fields returned from the data-source. --- .../data-sources/hpegl_vmaas_morpheus_details/multiple.tf | 6 ++++-- go.mod | 4 +--- go.sum | 4 ++-- internal/cmp/morpheus_datasource_broker.go | 3 +-- internal/resources/data_source_morpheus_token_broker.go | 7 ++++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/data-sources/hpegl_vmaas_morpheus_details/multiple.tf b/examples/data-sources/hpegl_vmaas_morpheus_details/multiple.tf index 306d14e9..79770f88 100644 --- a/examples/data-sources/hpegl_vmaas_morpheus_details/multiple.tf +++ b/examples/data-sources/hpegl_vmaas_morpheus_details/multiple.tf @@ -3,7 +3,8 @@ # Location 1 provider "hpegl" { vmaas { - location = var.location_1 + location = var.location_1 + space_name = var.space_1 } alias = "location_1" @@ -24,7 +25,8 @@ provider "morpheus" { # Location 2 provider "hpegl" { vmaas { - location = var.location_2 + location = var.location_2 + space_name = var.space_2 } alias = "location_2" diff --git a/go.mod b/go.mod index 40f46355..46fdea43 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/HewlettPackard/hpegl-vmaas-terraform-resources go 1.21 require ( - github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk v0.1.11 + github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk v0.1.12 github.com/golang/mock v1.6.0 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-docs v0.9.0 @@ -14,8 +14,6 @@ require ( github.com/tshihad/tftags v0.0.10 ) -replace github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk => ../hpegl-vmaas-cmp-go-sdk - require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect diff --git a/go.sum b/go.sum index 91f1cb79..6244f2a1 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk v0.1.11 h1:KnXixte97F83KVsqppc5olEjFmCmccIhIPfR0s3gSVw= -github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk v0.1.11/go.mod h1:UzXizYR6sUVsvDRMcLC2E4eabJsPH/3nM8rlKL2BLSc= +github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk v0.1.12 h1:AVRTfWXyDYEa5FdTVSDBH2MHw7Fy5X3W4mv89cnAwHc= +github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk v0.1.12/go.mod h1:tsKOAAbEQnpXAzqjcZUGzRiVp9QfRViKoTOdIltIMFI= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= diff --git a/internal/cmp/morpheus_datasource_broker.go b/internal/cmp/morpheus_datasource_broker.go index 58d5a98a..739a8eec 100644 --- a/internal/cmp/morpheus_datasource_broker.go +++ b/internal/cmp/morpheus_datasource_broker.go @@ -4,7 +4,6 @@ package cmp import ( "context" - "github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk/pkg/client" "github.com/HewlettPackard/hpegl-vmaas-terraform-resources/internal/utils" ) @@ -35,7 +34,7 @@ func (m *morpheusBroker) Read(ctx context.Context, d *utils.Data, meta interface return err } - if err = d.Set("access_token_expires", morpheusDetails.AccessTokenExpires); err != nil { + if err = d.Set("valid_till", morpheusDetails.ValidTill); err != nil { return err } diff --git a/internal/resources/data_source_morpheus_token_broker.go b/internal/resources/data_source_morpheus_token_broker.go index 6414fda1..5e244eca 100644 --- a/internal/resources/data_source_morpheus_token_broker.go +++ b/internal/resources/data_source_morpheus_token_broker.go @@ -21,10 +21,10 @@ func MorpheusDetailsBroker() *schema.Resource { Description: "Morpheus access_token", Sensitive: true, }, - "access_token_expires": { + "valid_till": { Type: schema.TypeInt, Computed: true, - Description: "Unix timestamp of when the access_token expires", + Description: "Unix timestamp of when the access_token expires, in seconds", Sensitive: false, }, "url": { @@ -36,7 +36,8 @@ func MorpheusDetailsBroker() *schema.Resource { }, ReadContext: MorpheusDetailsBrokerReadContext, Description: `The ` + DSMorpheusDataSource + ` data source can be used to get a details of the Morpheus instance - used by VMaaS. The details that can be retrieved are the access_token, access_token_expires and the URL.`, + used by VMaaS. The details that can be retrieved are the access_token, valid_till (the Unix timestamp of + access_token expiration) and the URL of the Morpheus instance.`, SchemaVersion: 0, StateUpgraders: nil, Importer: &schema.ResourceImporter{ From 8412fd1b51e472555b5decaaa12e41d97c4276e9 Mon Sep 17 00:00:00 2001 From: Eamonn O'Toole Date: Thu, 19 Sep 2024 12:02:01 +0100 Subject: [PATCH 5/9] Add acceptance test We add an acceptance test to internal/acceptance_test. We've had to add a new helper function getBrokerAPIClient() and move some shared code into getHeadersAndQueryParamsAndIAMVersion() and apiClientSetMeta(). --- .../data_source_morpheus_details.go | 29 ++++++++++ internal/acceptance_test/helper.go | 57 +++++++++++++++---- 2 files changed, 74 insertions(+), 12 deletions(-) create mode 100644 internal/acceptance_test/data_source_morpheus_details.go diff --git a/internal/acceptance_test/data_source_morpheus_details.go b/internal/acceptance_test/data_source_morpheus_details.go new file mode 100644 index 00000000..b24cb202 --- /dev/null +++ b/internal/acceptance_test/data_source_morpheus_details.go @@ -0,0 +1,29 @@ +// (C) Copyright 2024 Hewlett Packard Enterprise Development LP + +package acceptancetest + +import ( + "testing" + + api_client "github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk/pkg/client" + "github.com/HewlettPackard/hpegl-vmaas-terraform-resources/pkg/atf" +) + +func TestAccDataSourceMorpheusDetails(t *testing.T) { + acc := &atf.Acc{ + PreCheck: testAccPreCheck, + Providers: testAccProviders, + ResourceName: "hpegl_vmaas_morpheus_details", + GetAPI: func(attr map[string]string) (interface{}, error) { + cl, cfg := getBrokerAPIClient() + iClient := api_client.BrokerAPIService{ + Client: cl, + Cfg: cfg, + } + + return iClient.GetMorpheusDetails(getAccContext()) + }, + } + + acc.RunDataSourceTests(t) +} diff --git a/internal/acceptance_test/helper.go b/internal/acceptance_test/helper.go index a737d32e..4722d409 100644 --- a/internal/acceptance_test/helper.go +++ b/internal/acceptance_test/helper.go @@ -16,6 +16,45 @@ import ( ) func getAPIClient() (*api_client.APIClient, api_client.Configuration) { + headers, queryParam, iamVersion := getHeadersAndQueryParamsAndIAMVersion() + cfg := api_client.Configuration{ + Host: os.Getenv("HPEGL_VMAAS_API_URL"), + DefaultHeader: headers, + DefaultQueryParams: queryParam, + } + apiClient := api_client.NewAPIClient(&cfg) + err := apiClientSetMeta(apiClient, iamVersion) + if err != nil { + log.Printf("[WARN] Error: %s", err) + } + + return apiClient, cfg +} + +func getBrokerAPIClient() (*api_client.APIClient, api_client.Configuration) { + headers, queryParam, iamVersion := getHeadersAndQueryParamsAndIAMVersion() + // No need to set the default query params for broker API + cfg := api_client.Configuration{ + Host: os.Getenv("HPEGL_VMAAS_BROKER_URL"), + DefaultHeader: headers, + } + brokerAPIClient := api_client.NewAPIClient(&cfg) + err := apiClientSetMeta(brokerAPIClient, iamVersion) + if err != nil { + log.Printf("[WARN] Error: %s", err) + } + + // Return the configuration with the default query params + cfgForReturn := api_client.Configuration{ + Host: os.Getenv("HPEGL_VMAAS_BROKER_URL"), + DefaultHeader: headers, + DefaultQueryParams: queryParam, + } + + return brokerAPIClient, cfgForReturn +} + +func getHeadersAndQueryParamsAndIAMVersion() (map[string]string, map[string]string, string) { var headers map[string]string if utils.GetEnvBool("TF_ACC_MOCK_IAM") { headers = make(map[string]string) @@ -31,13 +70,12 @@ func getAPIClient() (*api_client.APIClient, api_client.Configuration) { } else { queryParam[constants.SpaceKey] = os.Getenv("HPEGL_VMAAS_SPACE_NAME") } - cfg := api_client.Configuration{ - Host: os.Getenv("HPEGL_VMAAS_API_URL"), - DefaultHeader: headers, - DefaultQueryParams: queryParam, - } - apiClient := api_client.NewAPIClient(&cfg) - err := apiClient.SetMeta(nil, func(ctx *context.Context, meta interface{}) { + + return headers, queryParam, iamVersion +} + +func apiClientSetMeta(apiClient *api_client.APIClient, iamVersion string) error { + return apiClient.SetMeta(nil, func(ctx *context.Context, meta interface{}) { d := &utils.ResourceData{ Data: map[string]interface{}{ "iam_service_url": os.Getenv("HPEGL_IAM_SERVICE_URL"), @@ -68,11 +106,6 @@ func getAPIClient() (*api_client.APIClient, api_client.Configuration) { *ctx = context.WithValue(*ctx, api_client.ContextAccessToken, token) } }) - if err != nil { - log.Printf("[WARN] Error: %s", err) - } - - return apiClient, cfg } func toInt(s string) int { From d9c24c861d9a57df8987759b6c85b58c2145aee7 Mon Sep 17 00:00:00 2001 From: Eamonn O'Toole Date: Thu, 19 Sep 2024 13:27:18 +0100 Subject: [PATCH 6/9] Acceptance test fixes Fixed name of test file and added acc-testcases/data-sources/morpheus_details.yaml --- acc-testcases/data-sources/morpheus_details.yaml | 2 ++ ...morpheus_details.go => data_source_morpheus_details_test.go} | 0 2 files changed, 2 insertions(+) create mode 100644 acc-testcases/data-sources/morpheus_details.yaml rename internal/acceptance_test/{data_source_morpheus_details.go => data_source_morpheus_details_test.go} (100%) diff --git a/acc-testcases/data-sources/morpheus_details.yaml b/acc-testcases/data-sources/morpheus_details.yaml new file mode 100644 index 00000000..4550d174 --- /dev/null +++ b/acc-testcases/data-sources/morpheus_details.yaml @@ -0,0 +1,2 @@ +acc: + - config: \ No newline at end of file diff --git a/internal/acceptance_test/data_source_morpheus_details.go b/internal/acceptance_test/data_source_morpheus_details_test.go similarity index 100% rename from internal/acceptance_test/data_source_morpheus_details.go rename to internal/acceptance_test/data_source_morpheus_details_test.go From cd017eb8cf96efea56d314ed207ecf3c5db638a9 Mon Sep 17 00:00:00 2001 From: Eamonn O'Toole Date: Fri, 20 Sep 2024 09:46:22 +0100 Subject: [PATCH 7/9] Convert Unix Epoch time to seconds --- internal/cmp/morpheus_datasource_broker.go | 7 ++++++- internal/resources/data_source_morpheus_token_broker.go | 6 +++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/internal/cmp/morpheus_datasource_broker.go b/internal/cmp/morpheus_datasource_broker.go index 739a8eec..e57207c9 100644 --- a/internal/cmp/morpheus_datasource_broker.go +++ b/internal/cmp/morpheus_datasource_broker.go @@ -4,6 +4,8 @@ package cmp import ( "context" + "time" + "github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk/pkg/client" "github.com/HewlettPackard/hpegl-vmaas-terraform-resources/internal/utils" ) @@ -27,6 +29,9 @@ func (m *morpheusBroker) Read(ctx context.Context, d *utils.Data, meta interface return err } + // Convert the Unix timestamp to Duration in seconds + validSeconds := time.Until(time.Unix(morpheusDetails.ValidTill, 0)) / time.Second + // Set all of the details d.SetId(morpheusDetails.ID) @@ -34,7 +39,7 @@ func (m *morpheusBroker) Read(ctx context.Context, d *utils.Data, meta interface return err } - if err = d.Set("valid_till", morpheusDetails.ValidTill); err != nil { + if err = d.Set("valid_till", validSeconds); err != nil { return err } diff --git a/internal/resources/data_source_morpheus_token_broker.go b/internal/resources/data_source_morpheus_token_broker.go index 5e244eca..5cb1d6c9 100644 --- a/internal/resources/data_source_morpheus_token_broker.go +++ b/internal/resources/data_source_morpheus_token_broker.go @@ -24,7 +24,7 @@ func MorpheusDetailsBroker() *schema.Resource { "valid_till": { Type: schema.TypeInt, Computed: true, - Description: "Unix timestamp of when the access_token expires, in seconds", + Description: "time until the token expires, in seconds", Sensitive: false, }, "url": { @@ -36,8 +36,8 @@ func MorpheusDetailsBroker() *schema.Resource { }, ReadContext: MorpheusDetailsBrokerReadContext, Description: `The ` + DSMorpheusDataSource + ` data source can be used to get a details of the Morpheus instance - used by VMaaS. The details that can be retrieved are the access_token, valid_till (the Unix timestamp of - access_token expiration) and the URL of the Morpheus instance.`, + used by VMaaS. The details that can be retrieved are the access_token, valid_till (time until the token expires, + in seconds), and the URL of the Morpheus instance.`, SchemaVersion: 0, StateUpgraders: nil, Importer: &schema.ResourceImporter{ From eb638cac23134995884b147ce2db7bd42acc8509 Mon Sep 17 00:00:00 2001 From: Eamonn O'Toole Date: Mon, 23 Sep 2024 10:49:18 +0100 Subject: [PATCH 8/9] Emit valid duration as seconds in a string --- internal/cmp/morpheus_datasource_broker.go | 11 ++++++++--- .../resources/data_source_morpheus_token_broker.go | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/internal/cmp/morpheus_datasource_broker.go b/internal/cmp/morpheus_datasource_broker.go index e57207c9..33657bc0 100644 --- a/internal/cmp/morpheus_datasource_broker.go +++ b/internal/cmp/morpheus_datasource_broker.go @@ -4,6 +4,8 @@ package cmp import ( "context" + "fmt" + "strconv" "time" "github.com/HewlettPackard/hpegl-vmaas-cmp-go-sdk/pkg/client" @@ -29,8 +31,11 @@ func (m *morpheusBroker) Read(ctx context.Context, d *utils.Data, meta interface return err } - // Convert the Unix timestamp to Duration in seconds - validSeconds := time.Until(time.Unix(morpheusDetails.ValidTill, 0)) / time.Second + // Convert the Unix timestamp to Duration in seconds expressed as a string + validDuration := time.Until(time.UnixMilli(morpheusDetails.ValidTill)) + // We do the following since this we cannot get a string representation of a Duration in seconds + validSeconds := validDuration.Round(time.Second).Seconds() // Round to the nearest second, in float64 + validSecondsString := fmt.Sprintf("%ss", strconv.FormatFloat(validSeconds, 'f', -1, 64)) // Set all of the details d.SetId(morpheusDetails.ID) @@ -39,7 +44,7 @@ func (m *morpheusBroker) Read(ctx context.Context, d *utils.Data, meta interface return err } - if err = d.Set("valid_till", validSeconds); err != nil { + if err = d.Set("valid_till", validSecondsString); err != nil { return err } diff --git a/internal/resources/data_source_morpheus_token_broker.go b/internal/resources/data_source_morpheus_token_broker.go index 5cb1d6c9..0488ae8e 100644 --- a/internal/resources/data_source_morpheus_token_broker.go +++ b/internal/resources/data_source_morpheus_token_broker.go @@ -22,7 +22,7 @@ func MorpheusDetailsBroker() *schema.Resource { Sensitive: true, }, "valid_till": { - Type: schema.TypeInt, + Type: schema.TypeString, Computed: true, Description: "time until the token expires, in seconds", Sensitive: false, From 65508cd09583cf991c88f6e460d103368a69f26c Mon Sep 17 00:00:00 2001 From: Eamonn O'Toole Date: Mon, 23 Sep 2024 11:00:59 +0100 Subject: [PATCH 9/9] Fix typo in code comment --- internal/cmp/morpheus_datasource_broker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmp/morpheus_datasource_broker.go b/internal/cmp/morpheus_datasource_broker.go index 33657bc0..f7319d56 100644 --- a/internal/cmp/morpheus_datasource_broker.go +++ b/internal/cmp/morpheus_datasource_broker.go @@ -33,7 +33,7 @@ func (m *morpheusBroker) Read(ctx context.Context, d *utils.Data, meta interface // Convert the Unix timestamp to Duration in seconds expressed as a string validDuration := time.Until(time.UnixMilli(morpheusDetails.ValidTill)) - // We do the following since this we cannot get a string representation of a Duration in seconds + // We do the following since we cannot get a string representation of a Duration in seconds validSeconds := validDuration.Round(time.Second).Seconds() // Round to the nearest second, in float64 validSecondsString := fmt.Sprintf("%ss", strconv.FormatFloat(validSeconds, 'f', -1, 64))