Skip to content

Commit

Permalink
feat: integrate terraform-plugin-mux and reimplement resource_network…
Browse files Browse the repository at this point in the history
…_pool using the plugin framework

Signed-off-by: Stoyan Zhelyazkov <[email protected]>
  • Loading branch information
spacegospod committed Jul 8, 2024
1 parent 4ad8d1f commit f244831
Show file tree
Hide file tree
Showing 9 changed files with 439 additions and 116 deletions.
9 changes: 5 additions & 4 deletions docs/resources/network_pool.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ The following data is prerequisite for creating a new Network Pool

### Optional

- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
- `network` (Block List) Represents a network in a network pool (see [below for nested schema](#nestedblock--network))
- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))

### Read-Only

- `id` (String) The ID of this resource.
- `id` (String) Service generated identifier for the network pool.

<a id="nestedblock--network"></a>
### Nested Schema for `network`
Expand Down Expand Up @@ -67,9 +68,9 @@ Optional:



<a id="nestedblock--timeouts"></a>
<a id="nestedatt--timeouts"></a>
### Nested Schema for `timeouts`

Optional:

- `create` (String)
- `create` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours).
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ require (
github.com/go-openapi/runtime v0.28.0
github.com/go-openapi/strfmt v0.23.0
github.com/hashicorp/terraform-plugin-docs v0.19.4
github.com/hashicorp/terraform-plugin-framework v1.9.0
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0
github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1
github.com/hashicorp/terraform-plugin-go v0.23.0
github.com/hashicorp/terraform-plugin-log v0.9.0
github.com/hashicorp/terraform-plugin-mux v0.16.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0
github.com/stretchr/testify v1.9.0
github.com/vmware/vcf-sdk-go v0.3.2
Expand Down Expand Up @@ -57,7 +62,6 @@ require (
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/hashicorp/terraform-exec v0.21.0 // indirect
github.com/hashicorp/terraform-json v0.22.1 // indirect
github.com/hashicorp/terraform-plugin-go v0.23.0 // indirect
github.com/hashicorp/terraform-registry-address v0.2.3 // indirect
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,18 @@ github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7
github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A=
github.com/hashicorp/terraform-plugin-docs v0.19.4 h1:G3Bgo7J22OMtegIgn8Cd/CaSeyEljqjH3G39w28JK4c=
github.com/hashicorp/terraform-plugin-docs v0.19.4/go.mod h1:4pLASsatTmRynVzsjEhbXZ6s7xBlUw/2Kt0zfrq8HxA=
github.com/hashicorp/terraform-plugin-framework v1.9.0 h1:caLcDoxiRucNi2hk8+j3kJwkKfvHznubyFsJMWfZqKU=
github.com/hashicorp/terraform-plugin-framework v1.9.0/go.mod h1:qBXLDn69kM97NNVi/MQ9qgd1uWWsVftGSnygYG1tImM=
github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1 h1:gm5b1kHgFFhaKFhm4h2TgvMUlNzFAtUqlcOWnWPm+9E=
github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1/go.mod h1:MsjL1sQ9L7wGwzJ5RjcI6FzEMdyoBnw+XK8ZnOvQOLY=
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 h1:HOjBuMbOEzl7snOdOoUfE2Jgeto6JOjLVQ39Ls2nksc=
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0/go.mod h1:jfHGE/gzjxYz6XoUwi/aYiiKrJDeutQNUtGQXkaHklg=
github.com/hashicorp/terraform-plugin-go v0.23.0 h1:AALVuU1gD1kPb48aPQUjug9Ir/125t+AAurhqphJ2Co=
github.com/hashicorp/terraform-plugin-go v0.23.0/go.mod h1:1E3Cr9h2vMlahWMbsSEcNrOCxovCZhOOIXjFHbjc/lQ=
github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow=
github.com/hashicorp/terraform-plugin-mux v0.16.0 h1:RCzXHGDYwUwwqfYYWJKBFaS3fQsWn/ZECEiW7p2023I=
github.com/hashicorp/terraform-plugin-mux v0.16.0/go.mod h1:PF79mAsPc8CpusXPfEVa4X8PtkB+ngWoiUClMrNZlYo=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 h1:kJiWGx2kiQVo97Y5IOGR4EMcZ8DtMswHhUuFibsCQQE=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0/go.mod h1:sl/UoabMc37HA6ICVMmGO+/0wofkVIRxf+BMb/dnoIg=
github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI=
Expand Down
210 changes: 210 additions & 0 deletions internal/provider/framework_provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
// Copyright 2024 Broadcom. All Rights Reserved.
// SPDX-License-Identifier:" MPL-2.0

package provider

import (
"context"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/diag"
"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/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/vmware/terraform-provider-vcf/internal/api_client"
"github.com/vmware/terraform-provider-vcf/internal/constants"
"os"
"strconv"
)

type FrameworkProviderModel struct {
SddcManagerUsername types.String `tfsdk:"sddc_manager_username"`
SddcManagerPassword types.String `tfsdk:"sddc_manager_password"`
SddcManagerHost types.String `tfsdk:"sddc_manager_host"`

CloudBuilderUsername types.String `tfsdk:"cloud_builder_username"`
CloudBuilderPassword types.String `tfsdk:"cloud_builder_password"`
CloudBuilderHost types.String `tfsdk:"cloud_builder_host"`

AllowUnverifiedTls types.Bool `tfsdk:"allow_unverified_tls"`
}

type FrameworkProvider struct {
// The clients are exposed for the purpose of running the existing tests
// Individual resources should obtain access to these in their Configure methods
// via the ConfigureRequest
SddcManagerClient *api_client.SddcManagerClient
CloudBuilderClient *api_client.CloudBuilderClient
}

func New() provider.Provider {
return &FrameworkProvider{}
}

func (frameworkProvider *FrameworkProvider) Schema(ctx context.Context, req provider.SchemaRequest, res *provider.SchemaResponse) {
res.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"sddc_manager_username": schema.StringAttribute{
Optional: true,
Description: "Username to authenticate to SDDC Manager",
Validators: []validator.String{
getSddcManagerConflictsValidator(),
stringvalidator.AlsoRequires(
path.Expressions{
path.MatchRoot("sddc_manager_password"),
path.MatchRoot("sddc_manager_host"),
}...),
},
},
"sddc_manager_password": schema.StringAttribute{
Optional: true,
Description: "Password to authenticate to SDDC Manager",
Validators: []validator.String{
getSddcManagerConflictsValidator(),
stringvalidator.AlsoRequires(
path.Expressions{
path.MatchRoot("sddc_manager_username"),
path.MatchRoot("sddc_manager_host"),
}...),
},
},
"sddc_manager_host": schema.StringAttribute{
Optional: true,
Description: "Fully qualified domain name or IP address of the SDDC Manager",
Validators: []validator.String{
getSddcManagerConflictsValidator(),
stringvalidator.AlsoRequires(
path.Expressions{
path.MatchRoot("sddc_manager_username"),
path.MatchRoot("sddc_manager_password"),
}...),
},
},
"cloud_builder_username": schema.StringAttribute{
Optional: true,
Description: "Username to authenticate to CloudBuilder",
Validators: []validator.String{
getCloudBuilderConflictsValidator(),
stringvalidator.AlsoRequires(
path.Expressions{
path.MatchRoot("cloud_builder_password"),
path.MatchRoot("cloud_builder_host"),
}...),
},
},
"cloud_builder_password": schema.StringAttribute{
Optional: true,
Description: "Password to authenticate to CloudBuilder",
Validators: []validator.String{
getCloudBuilderConflictsValidator(),
stringvalidator.AlsoRequires(
path.Expressions{
path.MatchRoot("cloud_builder_username"),
path.MatchRoot("cloud_builder_host"),
}...),
},
},
"cloud_builder_host": schema.StringAttribute{
Optional: true,
Description: "Fully qualified domain name or IP address of the CloudBuilder",
Validators: []validator.String{
getCloudBuilderConflictsValidator(),
stringvalidator.AlsoRequires(
path.Expressions{
path.MatchRoot("cloud_builder_username"),
path.MatchRoot("cloud_builder_password"),
}...),
},
},
"allow_unverified_tls": schema.BoolAttribute{
Optional: true,
Description: "If set, VMware VCF client will permit unverifiable TLS certificates.",
},
},
}
}

func (frameworkProvider *FrameworkProvider) Metadata(ctx context.Context, req provider.MetadataRequest, res *provider.MetadataResponse) {
res.TypeName = "vcf"
}

func (frameworkProvider *FrameworkProvider) Resources(ctx context.Context) []func() resource.Resource {
return []func() resource.Resource{
func() resource.Resource {
return &ResourceNetworkPool{}
},
}
}

func (frameworkProvider *FrameworkProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{}
}

func (frameworkProvider *FrameworkProvider) Configure(ctx context.Context, req provider.ConfigureRequest, res *provider.ConfigureResponse) {
var data FrameworkProviderModel

res.Diagnostics.Append(req.Config.Get(ctx, &data)...)

sddcManagerUsername := getAttributeValue(data.SddcManagerUsername.ValueString(), constants.VcfTestUsername).(string)

if sddcManagerUsername != "" {
// Connect to SDDC Manager
client := api_client.NewSddcManagerClient(
sddcManagerUsername,
getAttributeValue(data.SddcManagerPassword.ValueString(), constants.VcfTestPassword).(string),
getAttributeValue(data.SddcManagerHost.ValueString(), constants.VcfTestUrl).(string),
getAttributeValue(data.AllowUnverifiedTls.ValueBool(), constants.VcfTestAllowUnverifiedTls).(bool),
)

if err := client.Connect(); err != nil {
res.Diagnostics.Append(diag.NewErrorDiagnostic("Failed to connect to the SDDC Manager", err.Error()))
}

frameworkProvider.SddcManagerClient = client
res.ResourceData = client
} else {
// Connect to Cloud Builder
client := api_client.NewCloudBuilderClient(
getAttributeValue(data.CloudBuilderUsername.ValueString(), constants.CloudBuilderTestUsername).(string),
getAttributeValue(data.CloudBuilderPassword.ValueString(), constants.CloudBuilderTestPassword).(string),
getAttributeValue(data.CloudBuilderHost.ValueString(), constants.CloudBuilderTestUrl).(string),
getAttributeValue(data.AllowUnverifiedTls.ValueBool(), constants.VcfTestAllowUnverifiedTls).(bool),
)

frameworkProvider.CloudBuilderClient = client
res.ResourceData = client
}
}

func getAttributeValue[T string | bool](data T, envVar string) interface{} {
if envVal := os.Getenv(envVar); envVal != "" {
if val, err := strconv.ParseBool(envVal); err == nil {
return val
}

return envVal
}

return data
}

func getSddcManagerConflictsValidator() validator.String {
return stringvalidator.ConflictsWith(
path.Expressions{
path.MatchRoot("cloud_builder_username"),
path.MatchRoot("cloud_builder_password"),
path.MatchRoot("cloud_builder_host"),
}...)
}

func getCloudBuilderConflictsValidator() validator.String {
return stringvalidator.ConflictsWith(
path.Expressions{
path.MatchRoot("sddc_manager_username"),
path.MatchRoot("sddc_manager_password"),
path.MatchRoot("sddc_manager_host"),
}...)
}
1 change: 0 additions & 1 deletion internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ func Provider() *schema.Provider {
ResourcesMap: map[string]*schema.Resource{
"vcf_instance": ResourceVcfInstance(),
"vcf_user": ResourceUser(),
"vcf_network_pool": ResourceNetworkPool(),
"vcf_ceip": ResourceCeip(),
"vcf_host": ResourceHost(),
"vcf_domain": ResourceDomain(),
Expand Down
11 changes: 11 additions & 0 deletions internal/provider/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
package provider

import (
"github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/providerserver"
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/vmware/terraform-provider-vcf/internal/constants"
validationUtils "github.com/vmware/terraform-provider-vcf/internal/validation"
Expand All @@ -12,6 +15,7 @@ import (
)

var testAccProvider *schema.Provider
var testAccFrameworkProvider provider.Provider

func init() {
testAccProvider = Provider()
Expand All @@ -29,6 +33,13 @@ var providerFactories = map[string]func() (*schema.Provider, error){
},
}

func protoV6ProviderFactories() map[string]func() (tfprotov6.ProviderServer, error) {
testAccFrameworkProvider = New()
return map[string]func() (tfprotov6.ProviderServer, error){
"vcf": providerserver.NewProtocol6WithError(testAccFrameworkProvider),
}
}

// testAccPreCheck validates all required environment variables for running acceptance
// tests are set.
func testAccPreCheck(t *testing.T) {
Expand Down
Loading

0 comments on commit f244831

Please sign in to comment.