From b169f0e2c1cf8a78d99b85b0a56b0d4d7751fdf5 Mon Sep 17 00:00:00 2001 From: 1riatsila1 Date: Tue, 3 Sep 2024 16:36:20 +0200 Subject: [PATCH 1/7] feat: integrate client into TF provider --- pkg/config-api-provider/go.mod | 8 +- pkg/config-api-provider/go.sum | 10 +- pkg/config-api-provider/provider/provider.go | 139 +++++++++++++++++- .../provider/resources/group.go | 65 ++++---- .../test/agent_group_assignment_test.go | 10 +- pkg/config-api-provider/test/group_test.go | 11 +- .../test/network_group_assignment_test.go | 20 +-- pkg/config-api-provider/test/provider_test.go | 6 +- .../test/sensor_group_assignment_test.go | 16 +- .../service_test_group_assignment_test.go | 13 +- pkg/config-api-provider/test/utils.go | 35 +++++ 11 files changed, 256 insertions(+), 77 deletions(-) diff --git a/pkg/config-api-provider/go.mod b/pkg/config-api-provider/go.mod index d4d44603..b6fd5005 100644 --- a/pkg/config-api-provider/go.mod +++ b/pkg/config-api-provider/go.mod @@ -6,10 +6,11 @@ toolchain go1.22.5 require ( github.com/aruba-uxi/configuration-api-terraform-provider/pkg/config-api-client v0.0.0-00010101000000-000000000000 + github.com/h2non/gock v1.2.0 github.com/hashicorp/terraform-plugin-framework v1.9.0 github.com/hashicorp/terraform-plugin-go v0.23.0 github.com/hashicorp/terraform-plugin-testing v1.10.0 - github.com/stretchr/testify v1.9.0 + golang.org/x/oauth2 v0.17.0 ) require ( @@ -17,10 +18,10 @@ require ( github.com/agext/levenshtein v1.2.2 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/cloudflare/circl v1.3.7 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.16.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.6.0 // indirect + github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -49,8 +50,6 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/oklog/run v1.0.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/objx v0.5.2 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect @@ -66,7 +65,6 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/grpc v1.63.2 // indirect google.golang.org/protobuf v1.34.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/aruba-uxi/configuration-api-terraform-provider/pkg/config-api-client => ../config-api-client diff --git a/pkg/config-api-provider/go.sum b/pkg/config-api-provider/go.sum index 4a663b0a..095e2aeb 100644 --- a/pkg/config-api-provider/go.sum +++ b/pkg/config-api-provider/go.sum @@ -42,6 +42,10 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE= +github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk= +github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= +github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= @@ -120,6 +124,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= +github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= @@ -131,8 +137,6 @@ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= @@ -163,6 +167,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/pkg/config-api-provider/provider/provider.go b/pkg/config-api-provider/provider/provider.go index 533f6b5f..be77be20 100644 --- a/pkg/config-api-provider/provider/provider.go +++ b/pkg/config-api-provider/provider/provider.go @@ -2,12 +2,21 @@ package provider import ( "context" + "os" "github.com/aruba-uxi/configuration-api-terraform-provider/pkg/terraform-provider-configuration/provider/resources" "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/provider" "github.com/hashicorp/terraform-plugin-framework/provider/schema" "github.com/hashicorp/terraform-plugin-framework/resource" + + "github.com/aruba-uxi/configuration-api-terraform-provider/pkg/config-api-client" + "github.com/hashicorp/terraform-plugin-framework/types" + "net/http" + + "golang.org/x/oauth2" + "golang.org/x/oauth2/clientcredentials" ) // Ensure the implementation satisfies the expected interfaces. @@ -24,6 +33,13 @@ func New(version string) func() provider.Provider { } } +// maps provider schema data to a Go type. +type uxiProviderModel struct { + Host types.String `tfsdk:"host"` + ClientID types.String `tfsdk:"client_id"` + ClientSecret types.String `tfsdk:"client_secret"` +} + type uxiConfigurationProvider struct { // version is set to the provider version on release, "dev" when the // provider is built and ran locally, and "test" when running acceptance @@ -39,14 +55,120 @@ func (p *uxiConfigurationProvider) Metadata(_ context.Context, _ provider.Metada // Schema defines the provider-level schema for configuration data. func (p *uxiConfigurationProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) { - resp.Schema = schema.Schema{} + resp.Schema = schema.Schema{Attributes: map[string]schema.Attribute{ + "host": schema.StringAttribute{Required: true}, + "client_id": schema.StringAttribute{Required: true}, + "client_secret": schema.StringAttribute{Required: true, Sensitive: true}, + }} } // TODO: Obtain a greenlake access token // Configure prepares a Configuration API client for data sources and resources. func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) { // Init + var config uxiProviderModel + diags := req.Config.Get(ctx, &config) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + // If practitioner provided a configuration value for any of the + // attributes, it must be a known value. + + if config.Host.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("host"), + "Unknown HashiCups API Host", + "The provider cannot create the HashiCups API client as there is an unknown configuration value for the HashiCups API host. "+ + "Either target apply the source of the value first, set the value statically in the configuration, or use the HASHICUPS_HOST environment variable.", + ) + } + + if config.ClientID.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("client_id"), + "Unknown HashiCups API Password", + "The provider cannot create the HashiCups API client as there is an unknown configuration value for the HashiCups API password. "+ + "Either target apply the source of the value first, set the value statically in the configuration, or use the HASHICUPS_PASSWORD environment variable.", + ) + } + + if config.ClientSecret.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("client_secret"), + "Unknown HashiCups API Password", + "The provider cannot create the HashiCups API client as there is an unknown configuration value for the HashiCups API password. "+ + "Either target apply the source of the value first, set the value statically in the configuration, or use the HASHICUPS_PASSWORD environment variable.", + ) + } + + if resp.Diagnostics.HasError() { + return + } + + host := os.Getenv("UXI_HOST") + clientID := os.Getenv("CLIENT_ID") + clientSecret := os.Getenv("CLIENT_SECRET") + + if !config.Host.IsNull() { + host = config.Host.ValueString() + } + + if !config.ClientID.IsNull() { + clientID = config.ClientID.ValueString() + } + + if !config.ClientSecret.IsNull() { + clientSecret = config.ClientSecret.ValueString() + } + + // If any of the expected configurations are missing, return + // errors with provider-specific guidance. + + if host == "" { + resp.Diagnostics.AddAttributeError( + path.Root("host"), + "Missing HashiCups API Host", + "The provider cannot create the HashiCups API client as there is a missing or empty value for the HashiCups API host. "+ + "Set the host value in the configuration or use the HASHICUPS_HOST environment variable. "+ + "If either is already set, ensure the value is not empty.", + ) + } + + if clientID == "" { + resp.Diagnostics.AddAttributeError( + path.Root("client_id"), + "Missing HashiCups API Password", + "The provider cannot create the HashiCups API client as there is a missing or empty value for the HashiCups API password. "+ + "Set the password value in the configuration or use the HASHICUPS_PASSWORD environment variable. "+ + "If either is already set, ensure the value is not empty.", + ) + } + + if clientSecret == "" { + resp.Diagnostics.AddAttributeError( + path.Root("client_secret"), + "Missing HashiCups API Password", + "The provider cannot create the HashiCups API client as there is a missing or empty value for the HashiCups API password. "+ + "Set the password value in the configuration or use the HASHICUPS_PASSWORD environment variable. "+ + "If either is already set, ensure the value is not empty.", + ) + } + + if resp.Diagnostics.HasError() { + return + } + // initialise client + uxiConfiguration := config_api_client.NewConfiguration() + uxiConfiguration.Host = host + uxiConfiguration.Scheme = "https" + uxiConfiguration.HTTPClient = getHttpClient(clientID, clientSecret) + uxiClient := config_api_client.NewAPIClient(uxiConfiguration) + + resp.DataSourceData = uxiClient + resp.ResourceData = uxiClient } // DataSources defines the data sources implemented in the provider. @@ -69,3 +191,18 @@ func (p *uxiConfigurationProvider) Resources(_ context.Context) []func() resourc resources.NewServiceTestGroupAssignmentResource, } } + +func getHttpClient(clientID string, clientSecret string) *http.Client { + tokenURL := "https://sso.common.cloud.hpe.com/as/token.oauth2" + + // Set up the client credentials config + config := &clientcredentials.Config{ + ClientID: clientID, + ClientSecret: clientSecret, + TokenURL: tokenURL, + AuthStyle: oauth2.AuthStyleInParams, + } + + // Create a context and fetch a tokencould + return config.Client(context.Background()) +} diff --git a/pkg/config-api-provider/provider/resources/group.go b/pkg/config-api-provider/provider/resources/group.go index d8566565..58086b0c 100644 --- a/pkg/config-api-provider/provider/resources/group.go +++ b/pkg/config-api-provider/provider/resources/group.go @@ -2,6 +2,9 @@ package resources import ( "context" + "fmt" + + "github.com/aruba-uxi/configuration-api-terraform-provider/pkg/config-api-client" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -24,10 +27,10 @@ type groupResourceModel struct { } type GroupResponseModel struct { - UID string - Name string - ParentUid *string - Path string + UID string `json:"uid"` + Name string `json:"name"` + ParentUid *string `json:"parent_uid"` + Path string `json:"path"` } type GroupCreateRequestModel struct { @@ -43,7 +46,9 @@ func NewGroupResource() resource.Resource { return &groupResource{} } -type groupResource struct{} +type groupResource struct { + client *config_api_client.APIClient +} func (r *groupResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_group" @@ -73,6 +78,24 @@ func (r *groupResource) Schema(_ context.Context, _ resource.SchemaRequest, resp } func (r *groupResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + // Add a nil check when handling ProviderData because Terraform + // sets that data after it calls the ConfigureProvider RPC. + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(*config_api_client.APIClient) + + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected *config_api_client.APIClient, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + + return + } + + r.client = client } func (r *groupResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { @@ -84,17 +107,20 @@ func (r *groupResource) Create(ctx context.Context, req resource.CreateRequest, return } - // TODO: Call client create-group method - // We are mocking the response of the client for this early stage of development - group := CreateGroup(GroupCreateRequestModel{ - Name: plan.Name.ValueString(), - ParentUid: plan.ParentGroupId.ValueString(), - }) + groups_post_request := config_api_client.NewGroupsPostRequest(plan.ParentGroupId.ValueString(), plan.Name.ValueString()) + group, _, err := r.client.ConfigurationAPI.GroupsPostConfigurationAppV1GroupsPost(context.Background()).GroupsPostRequest(*groups_post_request).Execute() + if err != nil { + resp.Diagnostics.AddError( + "Error creating group", + "Could not create group, unexpected error: "+err.Error(), + ) + return + } // Update the state to match the plan (replace with response from client) - plan.ID = types.StringValue(group.UID) + plan.ID = types.StringValue(group.Uid) plan.Name = types.StringValue(group.Name) - plan.ParentGroupId = types.StringValue(*group.ParentUid) + plan.ParentGroupId = types.StringValue(group.ParentUid) // Set state to fully populated data diags = resp.State.Set(ctx, plan) @@ -184,19 +210,6 @@ var GetGroup = func(uid string) GroupResponseModel { } } -var CreateGroup = func(request GroupCreateRequestModel) GroupResponseModel { - // TODO: Query the group using the client - - parent_uid := "mock_parent_uid" - - return GroupResponseModel{ - UID: "mock_uid", - Name: "mock_name", - ParentUid: &parent_uid, - Path: "mock_path", - } -} - var UpdateGroup = func(request GroupUpdateRequestModel) GroupResponseModel { // TODO: Query the group using the client diff --git a/pkg/config-api-provider/test/agent_group_assignment_test.go b/pkg/config-api-provider/test/agent_group_assignment_test.go index 8fc3f173..8e1f2351 100644 --- a/pkg/config-api-provider/test/agent_group_assignment_test.go +++ b/pkg/config-api-provider/test/agent_group_assignment_test.go @@ -15,15 +15,14 @@ func TestAgentGroupAssignmentResource(t *testing.T) { // Creating a agent group assignment { PreConfig: func() { + MockOAuth() // required for agent import resources.GetAgent = func(uid string) resources.AgentResponseModel { return GenerateAgentResponseModel(uid, "") } // required for group create - resources.CreateGroup = func(request resources.GroupCreateRequestModel) resources.GroupResponseModel { - return GenerateGroupResponseModel("group_uid", "", "") - } + MockPostGroup(StructToMap(GenerateGroupResponseModel("group_uid", "", ""))) resources.GetGroup = func(uid string) resources.GroupResponseModel { return GenerateGroupResponseModel("group_uid", "", "") } @@ -74,6 +73,7 @@ func TestAgentGroupAssignmentResource(t *testing.T) { // Update and Read testing { PreConfig: func() { + MockOAuth() resources.GetAgent = func(uid string) resources.AgentResponseModel { if uid == "agent_uid" { return GenerateAgentResponseModel(uid, "") @@ -83,9 +83,7 @@ func TestAgentGroupAssignmentResource(t *testing.T) { } // required for creating another group - resources.CreateGroup = func(request resources.GroupCreateRequestModel) resources.GroupResponseModel { - return GenerateGroupResponseModel("group_uid_2", "_2", "_2") - } + MockPostGroup(StructToMap(GenerateGroupResponseModel("group_uid_2", "_2", "_2"))) resources.GetGroup = func(uid string) resources.GroupResponseModel { if uid == "group_uid" { return GenerateGroupResponseModel(uid, "", "") diff --git a/pkg/config-api-provider/test/group_test.go b/pkg/config-api-provider/test/group_test.go index b8e69e9a..817bdbeb 100644 --- a/pkg/config-api-provider/test/group_test.go +++ b/pkg/config-api-provider/test/group_test.go @@ -19,9 +19,9 @@ func TestGroupResource(t *testing.T) { // Create and Read testing { PreConfig: func() { - resources.CreateGroup = func(request resources.GroupCreateRequestModel) resources.GroupResponseModel { - return GenerateGroupResponseModel("uid", "", "") - } + MockOAuth() + MockPostGroup(StructToMap(GenerateGroupResponseModel("uid", "", ""))) + resources.GetGroup = func(uid string) resources.GroupResponseModel { return GenerateGroupResponseModel(uid, "", "") } @@ -68,9 +68,8 @@ func TestGroupResource(t *testing.T) { // Update that does trigger a recreate { PreConfig: func() { - resources.CreateGroup = func(request resources.GroupCreateRequestModel) resources.GroupResponseModel { - return GenerateGroupResponseModel("new_uid", "", "_2") - } + MockOAuth() + MockPostGroup(StructToMap(GenerateGroupResponseModel("new_uid", "", "_2"))) resources.GetGroup = func(uid string) resources.GroupResponseModel { if uid == "uid" { return GenerateGroupResponseModel(uid, "", "") diff --git a/pkg/config-api-provider/test/network_group_assignment_test.go b/pkg/config-api-provider/test/network_group_assignment_test.go index 0f37cbdf..606f0eaa 100644 --- a/pkg/config-api-provider/test/network_group_assignment_test.go +++ b/pkg/config-api-provider/test/network_group_assignment_test.go @@ -16,15 +16,14 @@ func TestNetworkGroupAssignmentResource(t *testing.T) { // Creating a network group assignment { PreConfig: func() { + MockOAuth() // required for network import resources.GetWiredNetwork = func(uid string) resources.WiredNetworkResponseModel { return GenerateWiredNetworkResponseModel(uid, "") } // required for group create - resources.CreateGroup = func(request resources.GroupCreateRequestModel) resources.GroupResponseModel { - return GenerateGroupResponseModel("group_uid", "", "") - } + MockPostGroup(StructToMap(GenerateGroupResponseModel("group_uid", "", ""))) resources.GetGroup = func(uid string) resources.GroupResponseModel { return GenerateGroupResponseModel("group_uid", "", "") } @@ -72,6 +71,7 @@ func TestNetworkGroupAssignmentResource(t *testing.T) { // Update and Read testing { PreConfig: func() { + MockOAuth() resources.GetWiredNetwork = func(uid string) resources.WiredNetworkResponseModel { if uid == "network_uid" { return GenerateWiredNetworkResponseModel(uid, "") @@ -81,9 +81,7 @@ func TestNetworkGroupAssignmentResource(t *testing.T) { } // required for creating another group - resources.CreateGroup = func(request resources.GroupCreateRequestModel) resources.GroupResponseModel { - return GenerateGroupResponseModel("group_uid_2", "_2", "_2") - } + MockPostGroup(StructToMap(GenerateGroupResponseModel("group_uid_2", "_2", "_2"))) resources.GetGroup = func(uid string) resources.GroupResponseModel { if uid == "group_uid" { return GenerateGroupResponseModel("uid", "", "") @@ -176,15 +174,14 @@ func TestNetworkGroupAssignmentResource(t *testing.T) { // Creating a network group assignment { PreConfig: func() { + MockOAuth() // required for network import resources.GetWirelessNetwork = func(uid string) resources.WirelessNetworkResponseModel { return GenerateWirelessNetworkResponseModel(uid, "") } // required for group create - resources.CreateGroup = func(request resources.GroupCreateRequestModel) resources.GroupResponseModel { - return GenerateGroupResponseModel("group_uid", "", "") - } + MockPostGroup(StructToMap(GenerateGroupResponseModel("group_uid", "", ""))) resources.GetGroup = func(uid string) resources.GroupResponseModel { return GenerateGroupResponseModel(uid, "", "") } @@ -232,6 +229,7 @@ func TestNetworkGroupAssignmentResource(t *testing.T) { // Update and Read testing { PreConfig: func() { + MockOAuth() resources.GetWirelessNetwork = func(uid string) resources.WirelessNetworkResponseModel { if uid == "network_uid" { return GenerateWirelessNetworkResponseModel(uid, "") @@ -241,9 +239,7 @@ func TestNetworkGroupAssignmentResource(t *testing.T) { } // required for creating another group - resources.CreateGroup = func(request resources.GroupCreateRequestModel) resources.GroupResponseModel { - return GenerateGroupResponseModel("group_uid_2", "_2", "_2") - } + MockPostGroup(StructToMap(GenerateGroupResponseModel("group_uid_2", "_2", "_2"))) resources.GetGroup = func(uid string) resources.GroupResponseModel { if uid == "group_uid" { return GenerateGroupResponseModel(uid, "", "") diff --git a/pkg/config-api-provider/test/provider_test.go b/pkg/config-api-provider/test/provider_test.go index a181751e..8c0bca5f 100644 --- a/pkg/config-api-provider/test/provider_test.go +++ b/pkg/config-api-provider/test/provider_test.go @@ -7,7 +7,11 @@ import ( ) const ( - providerConfig = `provider "uxi" {}` + providerConfig = `provider "uxi" { + host = "test.api.capenetworks.com" + client_id = "client_id" + client_secret = "client_secret" + }` ) var ( diff --git a/pkg/config-api-provider/test/sensor_group_assignment_test.go b/pkg/config-api-provider/test/sensor_group_assignment_test.go index 06f90b5d..7a21d6c2 100644 --- a/pkg/config-api-provider/test/sensor_group_assignment_test.go +++ b/pkg/config-api-provider/test/sensor_group_assignment_test.go @@ -15,18 +15,16 @@ func TestSensorGroupAssignmentResource(t *testing.T) { // Creating a sensor group assignment { PreConfig: func() { + MockOAuth() // required for sensor import resources.GetSensor = func(uid string) resources.SensorResponseModel { return GenerateSensorResponseModel(uid, "") } // required for group create - groupResponse := GenerateGroupResponseModel("group_uid", "", "") - resources.CreateGroup = func(request resources.GroupCreateRequestModel) resources.GroupResponseModel { - return groupResponse - } + MockPostGroup(StructToMap(GenerateGroupResponseModel("group_uid", "", ""))) resources.GetGroup = func(uid string) resources.GroupResponseModel { - return groupResponse + return GenerateGroupResponseModel("group_uid", "", "") } // required for sensor group assignment create @@ -76,6 +74,7 @@ func TestSensorGroupAssignmentResource(t *testing.T) { // Update and Read testing { PreConfig: func() { + MockOAuth() resources.GetSensor = func(uid string) resources.SensorResponseModel { if uid == "sensor_uid" { return GenerateSensorResponseModel("sensor_uid", "") @@ -85,15 +84,12 @@ func TestSensorGroupAssignmentResource(t *testing.T) { } // required for creating another group - newGroupResponse := GenerateGroupResponseModel("group_uid_2", "_2", "_2") - resources.CreateGroup = func(request resources.GroupCreateRequestModel) resources.GroupResponseModel { - return newGroupResponse - } + MockPostGroup(StructToMap(GenerateGroupResponseModel("group_uid_2", "_2", "_2"))) resources.GetGroup = func(uid string) resources.GroupResponseModel { if uid == "group_uid" { return GenerateGroupResponseModel(uid, "", "") } else { - return newGroupResponse + return GenerateGroupResponseModel("group_uid_2", "_2", "_2") } } diff --git a/pkg/config-api-provider/test/service_test_group_assignment_test.go b/pkg/config-api-provider/test/service_test_group_assignment_test.go index 57c476ef..abf1d9b3 100644 --- a/pkg/config-api-provider/test/service_test_group_assignment_test.go +++ b/pkg/config-api-provider/test/service_test_group_assignment_test.go @@ -15,18 +15,16 @@ func TestServiceTestGroupAssignmentResource(t *testing.T) { // Creating a serviceTest group assignment { PreConfig: func() { + MockOAuth() // required for serviceTest import resources.GetServiceTest = func(uid string) resources.ServiceTestResponseModel { return GenerateServiceTestResponseModel(uid, "") } // required for group create - groupResponse := GenerateGroupResponseModel("group_uid", "", "") - resources.CreateGroup = func(request resources.GroupCreateRequestModel) resources.GroupResponseModel { - return groupResponse - } + MockPostGroup(StructToMap(GenerateGroupResponseModel("group_uid", "", ""))) resources.GetGroup = func(uid string) resources.GroupResponseModel { - return groupResponse + return GenerateGroupResponseModel("group_uid", "", "") } // required for serviceTest group assignment create @@ -73,6 +71,7 @@ func TestServiceTestGroupAssignmentResource(t *testing.T) { // Update and Read testing { PreConfig: func() { + MockOAuth() resources.GetServiceTest = func(uid string) resources.ServiceTestResponseModel { if uid == "service_test_uid" { return GenerateServiceTestResponseModel("service_test_uid", "") @@ -82,9 +81,7 @@ func TestServiceTestGroupAssignmentResource(t *testing.T) { } // required for creating another group - resources.CreateGroup = func(request resources.GroupCreateRequestModel) resources.GroupResponseModel { - return GenerateGroupResponseModel("group_uid_2", "_2", "_2") - } + MockPostGroup(StructToMap(GenerateGroupResponseModel("group_uid_2", "_2", "_2"))) resources.GetGroup = func(uid string) resources.GroupResponseModel { if uid == "group_uid" { return GenerateGroupResponseModel(uid, "", "") diff --git a/pkg/config-api-provider/test/utils.go b/pkg/config-api-provider/test/utils.go index f4f92dc1..ed4aee98 100644 --- a/pkg/config-api-provider/test/utils.go +++ b/pkg/config-api-provider/test/utils.go @@ -1,7 +1,10 @@ package test import ( + "encoding/json" + "github.com/aruba-uxi/configuration-api-terraform-provider/pkg/terraform-provider-configuration/provider/resources" + "github.com/h2non/gock" ) func GenerateSensorResponseModel(uid string, postfix string) resources.SensorResponseModel { @@ -119,3 +122,35 @@ func GenerateServiceTestGroupAssignmentResponse(uid string, postfix string) reso ServiceTestUID: "service_test_uid" + postfix, } } + +// Converts a struct to a map while maintaining the json alias as keys +func StructToMap(obj interface{}) map[string]interface{} { + data, _ := json.Marshal(obj) // Convert to a json string + + newMap := map[string]interface{}{} + + _ = json.Unmarshal(data, &newMap) // Convert to a map + return newMap +} + +func MockOAuth() { + gock.New("https://sso.common.cloud.hpe.com"). + Post("/as/token.oauth2"). + MatchHeader("Content-Type", "application/x-www-form-urlencoded"). + Reply(200). + JSON(map[string]interface{}{ + "access_token": "mock_token", + "token_type": "bearer", + "expires_in": 3600, + }) +} + +func MockPostGroup(response map[string]interface{}) { + gock.New("https://test.api.capenetworks.com"). + Post("/configuration/app/v1/groups"). + MatchHeader("Content-Type", "application/json"). + MatchHeader("Authorization", "mock_token"). + Reply(200). + JSON(response) + +} From 75709ce08a019808d65e324750e0ef82fb4a7931 Mon Sep 17 00:00:00 2001 From: 1riatsila1 Date: Tue, 3 Sep 2024 16:44:20 +0200 Subject: [PATCH 2/7] update error messages --- pkg/config-api-provider/provider/provider.go | 36 ++++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/pkg/config-api-provider/provider/provider.go b/pkg/config-api-provider/provider/provider.go index be77be20..5fee454c 100644 --- a/pkg/config-api-provider/provider/provider.go +++ b/pkg/config-api-provider/provider/provider.go @@ -79,27 +79,27 @@ func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.C if config.Host.IsUnknown() { resp.Diagnostics.AddAttributeError( path.Root("host"), - "Unknown HashiCups API Host", - "The provider cannot create the HashiCups API client as there is an unknown configuration value for the HashiCups API host. "+ - "Either target apply the source of the value first, set the value statically in the configuration, or use the HASHICUPS_HOST environment variable.", + "Unknown UXI API Host", + "The provider cannot create the UXI API client as there is an unknown configuration value for the UXI API host. "+ + "Either target apply the source of the value first, set the value statically in the configuration, or use the UXI_HOST environment variable.", ) } if config.ClientID.IsUnknown() { resp.Diagnostics.AddAttributeError( path.Root("client_id"), - "Unknown HashiCups API Password", - "The provider cannot create the HashiCups API client as there is an unknown configuration value for the HashiCups API password. "+ - "Either target apply the source of the value first, set the value statically in the configuration, or use the HASHICUPS_PASSWORD environment variable.", + "Unknown Client ID", + "The provider cannot create the UXI API client as there is an unknown configuration value for the Client ID. "+ + "Either target apply the source of the value first, set the value statically in the configuration, or use the CLIENT_ID environment variable.", ) } if config.ClientSecret.IsUnknown() { resp.Diagnostics.AddAttributeError( path.Root("client_secret"), - "Unknown HashiCups API Password", - "The provider cannot create the HashiCups API client as there is an unknown configuration value for the HashiCups API password. "+ - "Either target apply the source of the value first, set the value statically in the configuration, or use the HASHICUPS_PASSWORD environment variable.", + "Unknown Client Secret", + "The provider cannot create the UXI API client as there is an unknown configuration value for the Client Secret. "+ + "Either target apply the source of the value first, set the value statically in the configuration, or use the CLIENT_SECRET environment variable.", ) } @@ -129,9 +129,9 @@ func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.C if host == "" { resp.Diagnostics.AddAttributeError( path.Root("host"), - "Missing HashiCups API Host", - "The provider cannot create the HashiCups API client as there is a missing or empty value for the HashiCups API host. "+ - "Set the host value in the configuration or use the HASHICUPS_HOST environment variable. "+ + "Missing UXI API Host", + "The provider cannot create the UXI API client as there is a missing or empty value for the UXI API host. "+ + "Set the host value in the configuration or use the UXI_HOST environment variable. "+ "If either is already set, ensure the value is not empty.", ) } @@ -139,9 +139,9 @@ func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.C if clientID == "" { resp.Diagnostics.AddAttributeError( path.Root("client_id"), - "Missing HashiCups API Password", - "The provider cannot create the HashiCups API client as there is a missing or empty value for the HashiCups API password. "+ - "Set the password value in the configuration or use the HASHICUPS_PASSWORD environment variable. "+ + "Missing Client ID", + "The provider cannot create the UXI API client as there is a missing or empty value for the Client ID. "+ + "Set the Client ID value in the configuration or use the CLIENT_ID environment variable. "+ "If either is already set, ensure the value is not empty.", ) } @@ -149,9 +149,9 @@ func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.C if clientSecret == "" { resp.Diagnostics.AddAttributeError( path.Root("client_secret"), - "Missing HashiCups API Password", - "The provider cannot create the HashiCups API client as there is a missing or empty value for the HashiCups API password. "+ - "Set the password value in the configuration or use the HASHICUPS_PASSWORD environment variable. "+ + "Missing Client Secret", + "The provider cannot create the UXI API client as there is a missing or empty value for the Client Secret. "+ + "Set the Client Secret value in the configuration or use the CLIENT_SECRET environment variable. "+ "If either is already set, ensure the value is not empty.", ) } From 11a2137b82bce57bb586f4bba30c60568507d1f6 Mon Sep 17 00:00:00 2001 From: 1riatsila1 Date: Tue, 3 Sep 2024 17:03:43 +0200 Subject: [PATCH 3/7] TokenURL goes into provider config --- pkg/config-api-provider/provider/provider.go | 34 +++++++++++++++---- pkg/config-api-provider/test/provider_test.go | 1 + pkg/config-api-provider/test/utils.go | 2 +- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/pkg/config-api-provider/provider/provider.go b/pkg/config-api-provider/provider/provider.go index 5fee454c..50bfc054 100644 --- a/pkg/config-api-provider/provider/provider.go +++ b/pkg/config-api-provider/provider/provider.go @@ -24,6 +24,8 @@ var ( _ provider.Provider = &uxiConfigurationProvider{} ) +var tokenURLDefault = "https://sso.common.cloud.hpe.com/as/token.oauth2" + // New is a helper function to simplify provider server and testing implementation. func New(version string) func() provider.Provider { return func() provider.Provider { @@ -38,6 +40,7 @@ type uxiProviderModel struct { Host types.String `tfsdk:"host"` ClientID types.String `tfsdk:"client_id"` ClientSecret types.String `tfsdk:"client_secret"` + TokenURL types.String `tfsdk:"token_url"` } type uxiConfigurationProvider struct { @@ -56,9 +59,10 @@ func (p *uxiConfigurationProvider) Metadata(_ context.Context, _ provider.Metada // Schema defines the provider-level schema for configuration data. func (p *uxiConfigurationProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) { resp.Schema = schema.Schema{Attributes: map[string]schema.Attribute{ - "host": schema.StringAttribute{Required: true}, - "client_id": schema.StringAttribute{Required: true}, - "client_secret": schema.StringAttribute{Required: true, Sensitive: true}, + "host": schema.StringAttribute{Optional: true}, + "client_id": schema.StringAttribute{Optional: true}, + "client_secret": schema.StringAttribute{Optional: true, Sensitive: true}, + "token_url": schema.StringAttribute{Optional: true}, }} } @@ -103,6 +107,15 @@ func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.C ) } + if config.TokenURL.IsUnknown() { + resp.Diagnostics.AddAttributeError( + path.Root("token_url"), + "Unknown Token URL", + "The provider cannot create the UXI API client as there is an unknown configuration value for the Token URL. "+ + "Either target apply the source of the value first, set the value statically in the configuration, or use the TOKEN_URL environment variable.", + ) + } + if resp.Diagnostics.HasError() { return } @@ -110,6 +123,7 @@ func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.C host := os.Getenv("UXI_HOST") clientID := os.Getenv("CLIENT_ID") clientSecret := os.Getenv("CLIENT_SECRET") + tokenURL := os.Getenv("TOKEN_URL") if !config.Host.IsNull() { host = config.Host.ValueString() @@ -123,6 +137,10 @@ func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.C clientSecret = config.ClientSecret.ValueString() } + if !config.TokenURL.IsNull() { + tokenURL = config.TokenURL.ValueString() + } + // If any of the expected configurations are missing, return // errors with provider-specific guidance. @@ -156,6 +174,10 @@ func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.C ) } + if tokenURL == "" { + tokenURL = tokenURLDefault + } + if resp.Diagnostics.HasError() { return } @@ -164,7 +186,7 @@ func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.C uxiConfiguration := config_api_client.NewConfiguration() uxiConfiguration.Host = host uxiConfiguration.Scheme = "https" - uxiConfiguration.HTTPClient = getHttpClient(clientID, clientSecret) + uxiConfiguration.HTTPClient = getHttpClient(clientID, clientSecret, tokenURL) uxiClient := config_api_client.NewAPIClient(uxiConfiguration) resp.DataSourceData = uxiClient @@ -192,9 +214,7 @@ func (p *uxiConfigurationProvider) Resources(_ context.Context) []func() resourc } } -func getHttpClient(clientID string, clientSecret string) *http.Client { - tokenURL := "https://sso.common.cloud.hpe.com/as/token.oauth2" - +func getHttpClient(clientID string, clientSecret string, tokenURL string) *http.Client { // Set up the client credentials config config := &clientcredentials.Config{ ClientID: clientID, diff --git a/pkg/config-api-provider/test/provider_test.go b/pkg/config-api-provider/test/provider_test.go index 8c0bca5f..59710ad6 100644 --- a/pkg/config-api-provider/test/provider_test.go +++ b/pkg/config-api-provider/test/provider_test.go @@ -11,6 +11,7 @@ const ( host = "test.api.capenetworks.com" client_id = "client_id" client_secret = "client_secret" + token_url = "https://test.sso.common.cloud.hpe.com/as/token.oauth2" }` ) diff --git a/pkg/config-api-provider/test/utils.go b/pkg/config-api-provider/test/utils.go index ed4aee98..dc4abd6b 100644 --- a/pkg/config-api-provider/test/utils.go +++ b/pkg/config-api-provider/test/utils.go @@ -134,7 +134,7 @@ func StructToMap(obj interface{}) map[string]interface{} { } func MockOAuth() { - gock.New("https://sso.common.cloud.hpe.com"). + gock.New("https://test.sso.common.cloud.hpe.com"). Post("/as/token.oauth2"). MatchHeader("Content-Type", "application/x-www-form-urlencoded"). Reply(200). From 5398ff3c0f5aa648d1411d8181f19934b83cc0be Mon Sep 17 00:00:00 2001 From: 1riatsila1 Date: Wed, 4 Sep 2024 10:09:19 +0200 Subject: [PATCH 4/7] PR updates --- .../examples/full-demo/main.tf | 7 ++- .../examples/full-demo/variables.tf | 1 + pkg/config-api-provider/provider/provider.go | 53 ++----------------- 3 files changed, 12 insertions(+), 49 deletions(-) create mode 100644 pkg/config-api-provider/examples/full-demo/variables.tf diff --git a/pkg/config-api-provider/examples/full-demo/main.tf b/pkg/config-api-provider/examples/full-demo/main.tf index 5ae882f1..bf68f718 100644 --- a/pkg/config-api-provider/examples/full-demo/main.tf +++ b/pkg/config-api-provider/examples/full-demo/main.tf @@ -6,7 +6,12 @@ terraform { } } -provider "uxi" {} +provider "uxi" { + host = "test.api.capenetworks.com" + client_id = "client_id" + client_secret = var.client_secret + token_url = "https://test.sso.common.cloud.hpe.com/as/token.oauth2" +} data "uxi_root_group" "my_root_group" {} diff --git a/pkg/config-api-provider/examples/full-demo/variables.tf b/pkg/config-api-provider/examples/full-demo/variables.tf new file mode 100644 index 00000000..3bb3a5a6 --- /dev/null +++ b/pkg/config-api-provider/examples/full-demo/variables.tf @@ -0,0 +1 @@ +variable "client_secret" {} diff --git a/pkg/config-api-provider/provider/provider.go b/pkg/config-api-provider/provider/provider.go index ff16662a..75157d58 100644 --- a/pkg/config-api-provider/provider/provider.go +++ b/pkg/config-api-provider/provider/provider.go @@ -25,7 +25,7 @@ var ( _ provider.Provider = &uxiConfigurationProvider{} ) -var tokenURLDefault = "https://sso.common.cloud.hpe.com/as/token.oauth2" +const tokenURLDefault = "https://sso.common.cloud.hpe.com/as/token.oauth2" // New is a helper function to simplify provider server and testing implementation. func New(version string) func() provider.Provider { @@ -78,49 +78,6 @@ func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.C return } - // If practitioner provided a configuration value for any of the - // attributes, it must be a known value. - - if config.Host.IsUnknown() { - resp.Diagnostics.AddAttributeError( - path.Root("host"), - "Unknown UXI API Host", - "The provider cannot create the UXI API client as there is an unknown configuration value for the UXI API host. "+ - "Either target apply the source of the value first, set the value statically in the configuration, or use the UXI_HOST environment variable.", - ) - } - - if config.ClientID.IsUnknown() { - resp.Diagnostics.AddAttributeError( - path.Root("client_id"), - "Unknown Client ID", - "The provider cannot create the UXI API client as there is an unknown configuration value for the Client ID. "+ - "Either target apply the source of the value first, set the value statically in the configuration, or use the CLIENT_ID environment variable.", - ) - } - - if config.ClientSecret.IsUnknown() { - resp.Diagnostics.AddAttributeError( - path.Root("client_secret"), - "Unknown Client Secret", - "The provider cannot create the UXI API client as there is an unknown configuration value for the Client Secret. "+ - "Either target apply the source of the value first, set the value statically in the configuration, or use the CLIENT_SECRET environment variable.", - ) - } - - if config.TokenURL.IsUnknown() { - resp.Diagnostics.AddAttributeError( - path.Root("token_url"), - "Unknown Token URL", - "The provider cannot create the UXI API client as there is an unknown configuration value for the Token URL. "+ - "Either target apply the source of the value first, set the value statically in the configuration, or use the TOKEN_URL environment variable.", - ) - } - - if resp.Diagnostics.HasError() { - return - } - host := os.Getenv("UXI_HOST") clientID := os.Getenv("CLIENT_ID") clientSecret := os.Getenv("CLIENT_SECRET") @@ -148,8 +105,8 @@ func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.C if host == "" { resp.Diagnostics.AddAttributeError( path.Root("host"), - "Missing UXI API Host", - "The provider cannot create the UXI API client as there is a missing or empty value for the UXI API host. "+ + "Missing Host", + "The provider cannot initialize as there is a missing or empty value for the UXI API host. "+ "Set the host value in the configuration or use the UXI_HOST environment variable. "+ "If either is already set, ensure the value is not empty.", ) @@ -159,7 +116,7 @@ func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.C resp.Diagnostics.AddAttributeError( path.Root("client_id"), "Missing Client ID", - "The provider cannot create the UXI API client as there is a missing or empty value for the Client ID. "+ + "The provider cannot initialize as there is a missing or empty value for the Client ID. "+ "Set the Client ID value in the configuration or use the CLIENT_ID environment variable. "+ "If either is already set, ensure the value is not empty.", ) @@ -169,7 +126,7 @@ func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.C resp.Diagnostics.AddAttributeError( path.Root("client_secret"), "Missing Client Secret", - "The provider cannot create the UXI API client as there is a missing or empty value for the Client Secret. "+ + "The provider cannot initialize as there is a missing or empty value for the Client Secret. "+ "Set the Client Secret value in the configuration or use the CLIENT_SECRET environment variable. "+ "If either is already set, ensure the value is not empty.", ) From 5e3897a665a68929fc99e05f2da26ccf2b2eebee Mon Sep 17 00:00:00 2001 From: 1riatsila1 Date: Wed, 4 Sep 2024 10:12:19 +0200 Subject: [PATCH 5/7] Add in comment --- pkg/config-api-provider/provider/provider.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/config-api-provider/provider/provider.go b/pkg/config-api-provider/provider/provider.go index 75157d58..21cec468 100644 --- a/pkg/config-api-provider/provider/provider.go +++ b/pkg/config-api-provider/provider/provider.go @@ -147,6 +147,7 @@ func (p *uxiConfigurationProvider) Configure(ctx context.Context, req provider.C uxiConfiguration.HTTPClient = getHttpClient(clientID, clientSecret, tokenURL) uxiClient := config_api_client.NewAPIClient(uxiConfiguration) + // Make the client available during DataSource and Resource type Configure methods. resp.DataSourceData = uxiClient resp.ResourceData = uxiClient } From 82859c2aa960c2d31cc794cbbb7f29b0e191219e Mon Sep 17 00:00:00 2001 From: 1riatsila1 Date: Wed, 4 Sep 2024 10:19:33 +0200 Subject: [PATCH 6/7] client_secret to just file --- Justfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Justfile b/Justfile index a80c8035..37113c6b 100644 --- a/Justfile +++ b/Justfile @@ -87,10 +87,10 @@ fmt: clean: find . -name ".coverage*" -type f -delete -plan: +plan +ARGS='': cd {{ CONFIG_API_PROVIDER_DIR }} && go install . - cd {{ CONFIG_API_PROVIDER_DIR }}/examples/full-demo && terraform plan + cd {{ CONFIG_API_PROVIDER_DIR }}/examples/full-demo && terraform plan -var client_secret=secret {{ ARGS }} -apply: +apply +ARGS='': cd {{ CONFIG_API_PROVIDER_DIR }} && go install . - cd {{ CONFIG_API_PROVIDER_DIR }}/examples/full-demo && terraform apply + cd {{ CONFIG_API_PROVIDER_DIR }}/examples/full-demo && terraform apply -var client_secret=secret {{ ARGS }} From 28b8b5b28766d2c39fdc910e7ad80980187ee6a2 Mon Sep 17 00:00:00 2001 From: 1riatsila1 Date: Wed, 4 Sep 2024 11:17:29 +0200 Subject: [PATCH 7/7] error message and hardcode secret --- pkg/config-api-provider/examples/full-demo/main.tf | 2 +- pkg/config-api-provider/examples/full-demo/variables.tf | 1 - pkg/config-api-provider/provider/provider.go | 2 +- pkg/config-api-provider/provider/resources/group.go | 4 +--- 4 files changed, 3 insertions(+), 6 deletions(-) delete mode 100644 pkg/config-api-provider/examples/full-demo/variables.tf diff --git a/pkg/config-api-provider/examples/full-demo/main.tf b/pkg/config-api-provider/examples/full-demo/main.tf index bf68f718..d9b4696f 100644 --- a/pkg/config-api-provider/examples/full-demo/main.tf +++ b/pkg/config-api-provider/examples/full-demo/main.tf @@ -9,7 +9,7 @@ terraform { provider "uxi" { host = "test.api.capenetworks.com" client_id = "client_id" - client_secret = var.client_secret + client_secret = "some_random_secret" token_url = "https://test.sso.common.cloud.hpe.com/as/token.oauth2" } diff --git a/pkg/config-api-provider/examples/full-demo/variables.tf b/pkg/config-api-provider/examples/full-demo/variables.tf deleted file mode 100644 index 3bb3a5a6..00000000 --- a/pkg/config-api-provider/examples/full-demo/variables.tf +++ /dev/null @@ -1 +0,0 @@ -variable "client_secret" {} diff --git a/pkg/config-api-provider/provider/provider.go b/pkg/config-api-provider/provider/provider.go index 21cec468..32e0647a 100644 --- a/pkg/config-api-provider/provider/provider.go +++ b/pkg/config-api-provider/provider/provider.go @@ -184,6 +184,6 @@ func getHttpClient(clientID string, clientSecret string, tokenURL string) *http. AuthStyle: oauth2.AuthStyleInParams, } - // Create a context and fetch a tokencould + // Create a context and fetch a token return config.Client(context.Background()) } diff --git a/pkg/config-api-provider/provider/resources/group.go b/pkg/config-api-provider/provider/resources/group.go index 1d6e1c60..82c122fe 100644 --- a/pkg/config-api-provider/provider/resources/group.go +++ b/pkg/config-api-provider/provider/resources/group.go @@ -2,7 +2,6 @@ package resources import ( "context" - "fmt" "github.com/aruba-uxi/configuration-api-terraform-provider/pkg/config-api-client" @@ -89,9 +88,8 @@ func (r *groupResource) Configure(_ context.Context, req resource.ConfigureReque if !ok { resp.Diagnostics.AddError( "Unexpected Data Source Configure Type", - fmt.Sprintf("Expected *config_api_client.APIClient, got: %T. Please report this issue to the provider developers.", req.ProviderData), + "Resource type: Group. Please report this issue to the provider developers.", ) - return }