refactor: migrate USG setting resource to Terraform Plugin Framework (#42)
* refactor: migrate USG setting resource to Terraform Plugin Framework * remove setting_usg from old provider * add USG resource to provider v2
This commit is contained in:
committed by
GitHub
parent
eb8fc3871e
commit
35c74bf59d
@@ -22,17 +22,17 @@ func TestAccSettingUsg_mdns_v6(t *testing.T) {
|
||||
Config: testAccSettingUsgConfig_mdns(true),
|
||||
Check: resource.ComposeTestCheckFunc(),
|
||||
},
|
||||
pt.ImportStep("unifi_setting_usg.test"),
|
||||
pt.ImportStepWithSite("unifi_setting_usg.test"),
|
||||
{
|
||||
Config: testAccSettingUsgConfig_mdns(false),
|
||||
Check: resource.ComposeTestCheckFunc(),
|
||||
},
|
||||
pt.ImportStep("unifi_setting_usg.test"),
|
||||
pt.ImportStepWithSite("unifi_setting_usg.test"),
|
||||
{
|
||||
Config: testAccSettingUsgConfig_mdns(true),
|
||||
Check: resource.ComposeTestCheckFunc(),
|
||||
},
|
||||
pt.ImportStep("unifi_setting_usg.test"),
|
||||
pt.ImportStepWithSite("unifi_setting_usg.test"),
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -58,7 +58,7 @@ func TestAccSettingUsg_dhcpRelay(t *testing.T) {
|
||||
Config: testAccSettingUsgConfig_dhcpRelay(),
|
||||
Check: resource.ComposeTestCheckFunc(),
|
||||
},
|
||||
pt.ImportStep("unifi_setting_usg.test"),
|
||||
pt.ImportStepWithSite("unifi_setting_usg.test"),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
type Resource interface {
|
||||
SetClient(client *Client)
|
||||
SetVersionValidator(validator ControllerVersionValidator)
|
||||
}
|
||||
|
||||
// ResourceModel defines the interface that all setting models must implement
|
||||
@@ -69,6 +70,7 @@ func ConfigureDatasource(base Resource, req datasource.ConfigureRequest, resp *d
|
||||
return
|
||||
}
|
||||
base.SetClient(cfg)
|
||||
base.SetVersionValidator(NewControllerVersionValidator(cfg))
|
||||
}
|
||||
|
||||
func ConfigureResource(base Resource, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||
@@ -86,4 +88,5 @@ func ConfigureResource(base Resource, req resource.ConfigureRequest, resp *resou
|
||||
return
|
||||
}
|
||||
base.SetClient(cfg)
|
||||
base.SetVersionValidator(NewControllerVersionValidator(cfg))
|
||||
}
|
||||
|
||||
188
internal/provider/base/controller_version.go
Normal file
188
internal/provider/base/controller_version.go
Normal file
@@ -0,0 +1,188 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/hashicorp/go-version"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func AsVersion(versionString string) *version.Version {
|
||||
return version.Must(version.NewVersion(versionString))
|
||||
}
|
||||
|
||||
// TODO remove this legacy
|
||||
var (
|
||||
ControllerV6 = AsVersion("6.0.0")
|
||||
ControllerV7 = AsVersion("7.0.0")
|
||||
ControllerV9 = AsVersion("9.0.0")
|
||||
ControllerVersionApiKeyAuth = AsVersion("9.0.108")
|
||||
// https://community.ui.com/releases/UniFi-Network-Application-8-2-93/fce86dc6-897a-4944-9c53-1eec7e37e738
|
||||
ControllerVersionDnsRecords = AsVersion("8.2.93")
|
||||
|
||||
// https://community.ui.com/releases/UniFi-Network-Controller-6-1-61/62f1ad38-1ac5-430c-94b0-becbb8f71d7d
|
||||
ControllerVersionWPA3 = AsVersion("6.1.61")
|
||||
)
|
||||
|
||||
func (c *Client) IsControllerV6() bool {
|
||||
return c.Version.GreaterThanOrEqual(ControllerV6)
|
||||
}
|
||||
|
||||
func (c *Client) IsControllerV7() bool {
|
||||
return c.Version.GreaterThanOrEqual(ControllerV7)
|
||||
}
|
||||
|
||||
func (c *Client) IsControllerV9() bool {
|
||||
return c.Version.GreaterThanOrEqual(ControllerV9)
|
||||
}
|
||||
|
||||
func (c *Client) SupportsApiKeyAuthentication() bool {
|
||||
return c.Version.GreaterThanOrEqual(ControllerVersionApiKeyAuth)
|
||||
}
|
||||
|
||||
func (c *Client) SupportsWPA3() bool {
|
||||
return c.Version.GreaterThanOrEqual(ControllerVersionWPA3)
|
||||
}
|
||||
|
||||
func (c *Client) SupportsDnsRecords() bool {
|
||||
return c.Version.GreaterThanOrEqual(ControllerVersionDnsRecords)
|
||||
}
|
||||
|
||||
func CheckMinimumControllerVersion(versionString string) error {
|
||||
v, err := version.NewVersion(versionString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if v.LessThan(ControllerV6) {
|
||||
return fmt.Errorf("Controller version %q or greater is required to use the provider, found %q.", ControllerV6, v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO remove until here
|
||||
|
||||
// ControllerVersionValidator is a validator that checks if the UniFi controller version
|
||||
// matches the specified constraints.
|
||||
type ControllerVersionValidator interface {
|
||||
RequireMinVersion(min string) diag.Diagnostics
|
||||
RequireMaxVersion(max string) diag.Diagnostics
|
||||
RequireVersionBetween(min, max string) diag.Diagnostics
|
||||
RequireMinVersionForPath(min string, attrPath path.Path, config tfsdk.Config) diag.Diagnostics
|
||||
RequireMaxVersionForPath(max string, attrPath path.Path, config tfsdk.Config) diag.Diagnostics
|
||||
RequireVersionBetweenForPath(min, max string, attrPath path.Path, config tfsdk.Config) diag.Diagnostics
|
||||
}
|
||||
|
||||
var _ ControllerVersionValidator = &controllerVersionValidator{}
|
||||
|
||||
func NewControllerVersionValidator(client *Client) ControllerVersionValidator {
|
||||
return &controllerVersionValidator{client: client}
|
||||
}
|
||||
|
||||
type controllerVersionValidator struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (v controllerVersionValidator) RequireMinVersion(min string) diag.Diagnostics {
|
||||
return v.requireVersion(minVersionRequirement(min), nil)
|
||||
}
|
||||
|
||||
func (v controllerVersionValidator) RequireMaxVersion(max string) diag.Diagnostics {
|
||||
return v.requireVersion(maxVersionRequirement(max), nil)
|
||||
}
|
||||
|
||||
func (v controllerVersionValidator) RequireVersionBetween(min, max string) diag.Diagnostics {
|
||||
return v.requireVersion(versionBetweenRequirement(min, max), nil)
|
||||
}
|
||||
|
||||
func (v controllerVersionValidator) RequireMinVersionForPath(min string, attrPath path.Path, config tfsdk.Config) diag.Diagnostics {
|
||||
return v.requireVersionForPath(minVersionRequirement(min), attrPath, config)
|
||||
}
|
||||
|
||||
func (v controllerVersionValidator) RequireMaxVersionForPath(max string, attrPath path.Path, config tfsdk.Config) diag.Diagnostics {
|
||||
return v.requireVersionForPath(maxVersionRequirement(max), attrPath, config)
|
||||
}
|
||||
|
||||
func (v controllerVersionValidator) RequireVersionBetweenForPath(min, max string, attrPath path.Path, config tfsdk.Config) diag.Diagnostics {
|
||||
return v.requireVersionForPath(versionBetweenRequirement(min, max), attrPath, config)
|
||||
}
|
||||
|
||||
func minVersionRequirement(min string) versionRequirement {
|
||||
return versionRequirement{minVersion: AsVersion(min)}
|
||||
}
|
||||
|
||||
func maxVersionRequirement(max string) versionRequirement {
|
||||
return versionRequirement{maxVersion: AsVersion(max)}
|
||||
}
|
||||
|
||||
func versionBetweenRequirement(min, max string) versionRequirement {
|
||||
return versionRequirement{minVersion: AsVersion(min), maxVersion: AsVersion(max)}
|
||||
}
|
||||
|
||||
type versionRequirement struct {
|
||||
minVersion *version.Version
|
||||
maxVersion *version.Version
|
||||
}
|
||||
|
||||
func (r versionRequirement) isBetweenRequirement() bool {
|
||||
return r.minVersion != nil && r.maxVersion != nil
|
||||
}
|
||||
|
||||
func (r versionRequirement) isMinRequirement() bool {
|
||||
return r.minVersion != nil && r.maxVersion == nil
|
||||
}
|
||||
|
||||
func (r versionRequirement) isMaxRequirement() bool {
|
||||
return r.minVersion == nil && r.maxVersion != nil
|
||||
}
|
||||
|
||||
const controllerVersionErrorMessage = "Controller version does not meet requirements"
|
||||
|
||||
func (v controllerVersionValidator) requireVersionForPath(req versionRequirement, attrPath path.Path, config tfsdk.Config) diag.Diagnostics {
|
||||
diags := diag.Diagnostics{}
|
||||
var val attr.Value
|
||||
diags.Append(config.GetAttribute(context.Background(), attrPath, &val)...)
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
if !IsDefined(val) {
|
||||
return diags
|
||||
}
|
||||
diags.Append(v.requireVersion(req, &attrPath)...)
|
||||
return diags
|
||||
}
|
||||
|
||||
// requireVersion checks if the controller version meets the constraints
|
||||
func (v controllerVersionValidator) requireVersion(req versionRequirement, attrPath *path.Path) diag.Diagnostics {
|
||||
diags := diag.Diagnostics{}
|
||||
if v.client == nil || v.client.Version == nil {
|
||||
diags.AddError("Controller version not available", "Provider was not initialized properly. UniFi client or controller version is not available")
|
||||
return diags
|
||||
}
|
||||
|
||||
controllerVersion := v.client.Version
|
||||
errorBuilder := strings.Builder{}
|
||||
if attrPath != nil {
|
||||
errorBuilder.WriteString(fmt.Sprintf("%s is not supported. ", attrPath.String()))
|
||||
}
|
||||
errorBuilder.WriteString(fmt.Sprintf("Controller version %s", controllerVersion))
|
||||
failed := false
|
||||
|
||||
if req.isBetweenRequirement() && (controllerVersion.LessThan(req.minVersion) || controllerVersion.GreaterThan(req.maxVersion)) {
|
||||
failed = true
|
||||
errorBuilder.WriteString(fmt.Sprintf(" is not between required %s and %s", req.minVersion, req.maxVersion))
|
||||
} else if req.isMinRequirement() && controllerVersion.LessThan(req.minVersion) {
|
||||
failed = true
|
||||
errorBuilder.WriteString(fmt.Sprintf(" is less than minimum required version %s", req.minVersion))
|
||||
} else if req.isMaxRequirement() && controllerVersion.GreaterThan(req.maxVersion) {
|
||||
failed = true
|
||||
errorBuilder.WriteString(fmt.Sprintf(" is greater than maximum required version %s", req.maxVersion))
|
||||
}
|
||||
if failed {
|
||||
diags.AddError(controllerVersionErrorMessage, errorBuilder.String())
|
||||
}
|
||||
return diags
|
||||
}
|
||||
192
internal/provider/base/controller_version_test.go
Normal file
192
internal/provider/base/controller_version_test.go
Normal file
@@ -0,0 +1,192 @@
|
||||
package base_test
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAsVersion(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
versionString string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "simple version",
|
||||
versionString: "1.0.0",
|
||||
expected: "1.0.0",
|
||||
},
|
||||
{
|
||||
name: "complex version",
|
||||
versionString: "7.2.95",
|
||||
expected: "7.2.95",
|
||||
},
|
||||
{
|
||||
name: "version with prerelease",
|
||||
versionString: "6.0.0-beta1",
|
||||
expected: "6.0.0-beta1",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
result := base.AsVersion(tt.versionString)
|
||||
assert.Equal(t, tt.expected, result.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckMinimumControllerVersion(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
versionString string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "version equal to minimum",
|
||||
versionString: "6.0.0",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "version greater than minimum",
|
||||
versionString: "7.0.0",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "version less than minimum",
|
||||
versionString: "5.9.9",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid version",
|
||||
versionString: "invalid",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := base.CheckMinimumControllerVersion(tt.versionString)
|
||||
if tt.expectError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestControllerVersionValidator(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
clientVer string
|
||||
testFunc func(v base.ControllerVersionValidator) diag.Diagnostics
|
||||
expectError bool
|
||||
errorMessage string
|
||||
}{
|
||||
{
|
||||
name: "min version satisfied",
|
||||
clientVer: "7.0.0",
|
||||
testFunc: func(v base.ControllerVersionValidator) diag.Diagnostics {
|
||||
return v.RequireMinVersion("6.0.0")
|
||||
},
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "min version not satisfied",
|
||||
clientVer: "6.0.0",
|
||||
testFunc: func(v base.ControllerVersionValidator) diag.Diagnostics {
|
||||
return v.RequireMinVersion("7.0.0")
|
||||
},
|
||||
expectError: true,
|
||||
errorMessage: "Controller version 6.0.0 is less than minimum required version 7.0.0",
|
||||
},
|
||||
{
|
||||
name: "max version satisfied",
|
||||
clientVer: "6.0.0",
|
||||
testFunc: func(v base.ControllerVersionValidator) diag.Diagnostics {
|
||||
return v.RequireMaxVersion("7.0.0")
|
||||
},
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "max version not satisfied",
|
||||
clientVer: "8.0.0",
|
||||
testFunc: func(v base.ControllerVersionValidator) diag.Diagnostics {
|
||||
return v.RequireMaxVersion("7.0.0")
|
||||
},
|
||||
expectError: true,
|
||||
errorMessage: "Controller version 8.0.0 is greater than maximum required version 7.0.0",
|
||||
},
|
||||
{
|
||||
name: "between version satisfied",
|
||||
clientVer: "7.0.0",
|
||||
testFunc: func(v base.ControllerVersionValidator) diag.Diagnostics {
|
||||
return v.RequireVersionBetween("6.0.0", "8.0.0")
|
||||
},
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "between version not satisfied - too low",
|
||||
clientVer: "5.0.0",
|
||||
testFunc: func(v base.ControllerVersionValidator) diag.Diagnostics {
|
||||
return v.RequireVersionBetween("6.0.0", "8.0.0")
|
||||
},
|
||||
expectError: true,
|
||||
errorMessage: "Controller version 5.0.0 is not between required 6.0.0 and 8.0.0",
|
||||
},
|
||||
{
|
||||
name: "between version not satisfied - too high",
|
||||
clientVer: "9.0.0",
|
||||
testFunc: func(v base.ControllerVersionValidator) diag.Diagnostics {
|
||||
return v.RequireVersionBetween("6.0.0", "8.0.0")
|
||||
},
|
||||
expectError: true,
|
||||
errorMessage: "Controller version 9.0.0 is not between required 6.0.0 and 8.0.0",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := &base.Client{
|
||||
Version: base.AsVersion(tt.clientVer),
|
||||
}
|
||||
validator := base.NewControllerVersionValidator(client)
|
||||
|
||||
diags := tt.testFunc(validator)
|
||||
|
||||
if tt.expectError {
|
||||
assert.True(t, diags.HasError())
|
||||
assert.Contains(t, diags.Errors()[0].Detail(), tt.errorMessage)
|
||||
} else {
|
||||
assert.False(t, diags.HasError())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestControllerVersionValidatorNilClient(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
validator := base.NewControllerVersionValidator(nil)
|
||||
diags := validator.RequireMinVersion("6.0.0")
|
||||
|
||||
assert.True(t, diags.HasError())
|
||||
assert.Contains(t, diags.Errors()[0].Summary(), "Controller version not available")
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/go-version"
|
||||
)
|
||||
|
||||
func asVersion(versionString string) *version.Version {
|
||||
return version.Must(version.NewVersion(versionString))
|
||||
}
|
||||
|
||||
// AsVersion converts a string version to a *version.Version
|
||||
// This is a utility function for consumers of this package
|
||||
func AsVersion(versionString string) *version.Version {
|
||||
return asVersion(versionString)
|
||||
}
|
||||
|
||||
var (
|
||||
ControllerV6 = asVersion("6.0.0")
|
||||
ControllerV7 = asVersion("7.0.0")
|
||||
ControllerV9 = asVersion("9.0.0")
|
||||
ControllerVersionApiKeyAuth = asVersion("9.0.108")
|
||||
// https://community.ui.com/releases/UniFi-Network-Application-8-2-93/fce86dc6-897a-4944-9c53-1eec7e37e738
|
||||
ControllerVersionDnsRecords = asVersion("8.2.93")
|
||||
|
||||
// https://community.ui.com/releases/UniFi-Network-Controller-6-1-61/62f1ad38-1ac5-430c-94b0-becbb8f71d7d
|
||||
ControllerVersionWPA3 = asVersion("6.1.61")
|
||||
)
|
||||
|
||||
func (c *Client) IsControllerV6() bool {
|
||||
return c.Version.GreaterThanOrEqual(ControllerV6)
|
||||
}
|
||||
|
||||
func (c *Client) IsControllerV7() bool {
|
||||
return c.Version.GreaterThanOrEqual(ControllerV7)
|
||||
}
|
||||
|
||||
func (c *Client) IsControllerV9() bool {
|
||||
return c.Version.GreaterThanOrEqual(ControllerV9)
|
||||
}
|
||||
|
||||
func (c *Client) SupportsApiKeyAuthentication() bool {
|
||||
return c.Version.GreaterThanOrEqual(ControllerVersionApiKeyAuth)
|
||||
}
|
||||
|
||||
func (c *Client) SupportsWPA3() bool {
|
||||
return c.Version.GreaterThanOrEqual(ControllerVersionWPA3)
|
||||
}
|
||||
|
||||
func (c *Client) SupportsDnsRecords() bool {
|
||||
return c.Version.GreaterThanOrEqual(ControllerVersionDnsRecords)
|
||||
}
|
||||
|
||||
func CheckMinimumControllerVersion(versionString string) error {
|
||||
v, err := version.NewVersion(versionString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if v.LessThan(ControllerV6) {
|
||||
return fmt.Errorf("Controller version %q or greater is required to use the provider, found %q.", ControllerV6, v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -23,6 +23,7 @@ var (
|
||||
)
|
||||
|
||||
type dnsRecordDatasource struct {
|
||||
base.ControllerVersionValidator
|
||||
client *base.Client
|
||||
}
|
||||
|
||||
@@ -43,6 +44,10 @@ func (d *dnsRecordDatasource) SetClient(client *base.Client) {
|
||||
d.client = client
|
||||
}
|
||||
|
||||
func (d *dnsRecordDatasource) SetVersionValidator(validator base.ControllerVersionValidator) {
|
||||
d.ControllerVersionValidator = validator
|
||||
}
|
||||
|
||||
func (d *dnsRecordDatasource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
|
||||
base.ConfigureDatasource(d, req, resp)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ var (
|
||||
)
|
||||
|
||||
type dnsRecordsDatasource struct {
|
||||
base.ControllerVersionValidator
|
||||
client *base.Client
|
||||
}
|
||||
|
||||
@@ -27,6 +28,10 @@ func (d *dnsRecordsDatasource) SetClient(client *base.Client) {
|
||||
d.client = client
|
||||
}
|
||||
|
||||
func (d *dnsRecordsDatasource) SetVersionValidator(validator base.ControllerVersionValidator) {
|
||||
d.ControllerVersionValidator = validator
|
||||
}
|
||||
|
||||
func (d *dnsRecordsDatasource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
|
||||
base.ConfigureDatasource(d, req, resp)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ var (
|
||||
)
|
||||
|
||||
type dnsRecordResource struct {
|
||||
base.ControllerVersionValidator
|
||||
client *base.Client
|
||||
}
|
||||
|
||||
@@ -30,6 +31,10 @@ func (d *dnsRecordResource) SetClient(client *base.Client) {
|
||||
d.client = client
|
||||
}
|
||||
|
||||
func (d *dnsRecordResource) SetVersionValidator(validator base.ControllerVersionValidator) {
|
||||
d.ControllerVersionValidator = validator
|
||||
}
|
||||
|
||||
func NewDnsRecordResource() resource.Resource {
|
||||
return &dnsRecordResource{}
|
||||
}
|
||||
|
||||
@@ -115,10 +115,8 @@ func New(version string) func() *schema.Provider {
|
||||
"unifi_site": site.ResourceSite(),
|
||||
"unifi_account": radius.ResourceAccount(),
|
||||
"unifi_radius_profile": radius.ResourceRadiusProfile(),
|
||||
|
||||
"unifi_setting_mgmt": settings.ResourceSettingMgmt(),
|
||||
"unifi_setting_radius": settings.ResourceSettingRadius(),
|
||||
"unifi_setting_usg": settings.ResourceSettingUsg(),
|
||||
"unifi_user_group": user.ResourceUserGroup(),
|
||||
"unifi_user": user.ResourceUser(),
|
||||
},
|
||||
|
||||
@@ -104,8 +104,8 @@ func (p *unifiProvider) Configure(ctx context.Context, req provider.ConfigureReq
|
||||
path.Root("api_url"),
|
||||
"Unknown UniFi Controller API URL",
|
||||
"The provider cannot create the UniFi Controller API client as there is an unknown configuration value "+
|
||||
"for the API endpoint. Either target apply the source of the value first, set the value statically in "+
|
||||
"the configuration, or use the UNIFI_API environment variable.",
|
||||
"for the API endpoint. Either target apply the source of the value first, set the value statically in "+
|
||||
"the configuration, or use the UNIFI_API environment variable.",
|
||||
)
|
||||
}
|
||||
|
||||
@@ -182,6 +182,7 @@ func (p *unifiProvider) Resources(_ context.Context) []func() resource.Resource
|
||||
settings.NewNtpResource,
|
||||
settings.NewSslInspectionResource,
|
||||
settings.NewTeleportResource,
|
||||
settings.NewUsgResource,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
// BaseSettingResource provides common functionality for all setting resources
|
||||
type BaseSettingResource[T base.ResourceModel] struct {
|
||||
base.ControllerVersionValidator
|
||||
client *base.Client
|
||||
typeName string
|
||||
modelFactory func() T
|
||||
@@ -45,6 +46,10 @@ func (b *BaseSettingResource[T]) SetClient(client *base.Client) {
|
||||
b.client = client
|
||||
}
|
||||
|
||||
func (b *BaseSettingResource[T]) SetVersionValidator(validator base.ControllerVersionValidator) {
|
||||
b.ControllerVersionValidator = validator
|
||||
}
|
||||
|
||||
func (b *BaseSettingResource[T]) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||
base.ConfigureResource(b, req, resp)
|
||||
}
|
||||
|
||||
@@ -48,17 +48,21 @@ func (d *teleportModel) Merge(other interface{}) diag.Diagnostics {
|
||||
}
|
||||
|
||||
var (
|
||||
_ base.ResourceModel = &teleportModel{}
|
||||
_ resource.Resource = &teleportResource{}
|
||||
_ resource.ResourceWithConfigure = &teleportResource{}
|
||||
_ resource.ResourceWithImportState = &teleportResource{}
|
||||
_ resource.ResourceWithConfigValidators = &teleportResource{}
|
||||
_ base.ResourceModel = &teleportModel{}
|
||||
_ resource.Resource = &teleportResource{}
|
||||
_ resource.ResourceWithConfigure = &teleportResource{}
|
||||
_ resource.ResourceWithImportState = &teleportResource{}
|
||||
_ resource.ResourceWithModifyPlan = &teleportResource{}
|
||||
)
|
||||
|
||||
type teleportResource struct {
|
||||
*BaseSettingResource[*teleportModel]
|
||||
}
|
||||
|
||||
func (r *teleportResource) ModifyPlan(_ context.Context, _ resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
|
||||
resp.Diagnostics.Append(r.RequireMinVersion("7.1")...)
|
||||
}
|
||||
|
||||
func (r *teleportResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "Manages Teleport settings for a UniFi site. Teleport is a secure remote access technology that allows authorized users to connect to UniFi devices from anywhere.",
|
||||
@@ -81,12 +85,6 @@ func (r *teleportResource) Schema(_ context.Context, _ resource.SchemaRequest, r
|
||||
}
|
||||
}
|
||||
|
||||
func (r *teleportResource) ConfigValidators(_ context.Context) []resource.ConfigValidator {
|
||||
return []resource.ConfigValidator{
|
||||
validators.ResourceRequireMinVersion(r.GetClient(), "7.1", "Teleport requires UniFi controller version 7.1 or higher"),
|
||||
}
|
||||
}
|
||||
|
||||
func NewTeleportResource() resource.Resource {
|
||||
r := &teleportResource{}
|
||||
r.BaseSettingResource = NewBaseSettingResource(
|
||||
|
||||
@@ -2,32 +2,110 @@ package settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
|
||||
var resourceSettingUsgLock = sync.Mutex{}
|
||||
|
||||
func resourceSettingUsgLocker(f func(context.Context, *schema.ResourceData, interface{}) diag.Diagnostics) func(context.Context, *schema.ResourceData, interface{}) diag.Diagnostics {
|
||||
return func(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
resourceSettingUsgLock.Lock()
|
||||
defer resourceSettingUsgLock.Unlock()
|
||||
return f(ctx, d, meta)
|
||||
}
|
||||
// usgModel represents the data model for USG (UniFi Security Gateway) settings.
|
||||
// It defines how USG features like mDNS and DHCP relay are configured for a UniFi site.
|
||||
type usgModel struct {
|
||||
base.Model
|
||||
MulticastDnsEnabled types.Bool `tfsdk:"multicast_dns_enabled"`
|
||||
DhcpRelayServers types.List `tfsdk:"dhcp_relay_servers"`
|
||||
}
|
||||
|
||||
func ResourceSettingUsg() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Description: "The `unifi_setting_usg` resource manages advanced settings for UniFi Security Gateways (USG) and UniFi Dream Machines (UDM/UDM-Pro).\n\n" +
|
||||
func (d *usgModel) AsUnifiModel() (interface{}, diag.Diagnostics) {
|
||||
diags := diag.Diagnostics{}
|
||||
|
||||
model := &unifi.SettingUsg{
|
||||
ID: d.ID.ValueString(),
|
||||
MdnsEnabled: d.MulticastDnsEnabled.ValueBool(),
|
||||
}
|
||||
|
||||
// Extract DHCP relay servers from the list
|
||||
var dhcpRelayServers []string
|
||||
diags.Append(utils.ListElementsAs(d.DhcpRelayServers, &dhcpRelayServers)...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
// Assign DHCP relay servers to the model (up to 5)
|
||||
model.DHCPRelayServer1 = append(dhcpRelayServers, "")[0]
|
||||
model.DHCPRelayServer2 = append(dhcpRelayServers, "", "")[1]
|
||||
model.DHCPRelayServer3 = append(dhcpRelayServers, "", "", "")[2]
|
||||
model.DHCPRelayServer4 = append(dhcpRelayServers, "", "", "", "")[3]
|
||||
model.DHCPRelayServer5 = append(dhcpRelayServers, "", "", "", "", "")[4]
|
||||
|
||||
return model, diags
|
||||
}
|
||||
|
||||
func (d *usgModel) Merge(other interface{}) diag.Diagnostics {
|
||||
diags := diag.Diagnostics{}
|
||||
|
||||
model, ok := other.(*unifi.SettingUsg)
|
||||
if !ok {
|
||||
diags.AddError("Cannot merge", "Cannot merge type that is not *unifi.SettingUsg")
|
||||
return diags
|
||||
}
|
||||
|
||||
d.ID = types.StringValue(model.ID)
|
||||
d.MulticastDnsEnabled = types.BoolValue(model.MdnsEnabled)
|
||||
|
||||
// Extract non-empty DHCP relay servers
|
||||
dhcpRelay := []string{}
|
||||
for _, s := range []string{
|
||||
model.DHCPRelayServer1,
|
||||
model.DHCPRelayServer2,
|
||||
model.DHCPRelayServer3,
|
||||
model.DHCPRelayServer4,
|
||||
model.DHCPRelayServer5,
|
||||
} {
|
||||
if s == "" {
|
||||
continue
|
||||
}
|
||||
dhcpRelay = append(dhcpRelay, s)
|
||||
}
|
||||
|
||||
// Set the DHCP relay servers list
|
||||
dhcpRelayServers, diags := types.ListValueFrom(context.Background(), types.StringType, dhcpRelay)
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
d.DhcpRelayServers = dhcpRelayServers
|
||||
|
||||
return diags
|
||||
}
|
||||
|
||||
var (
|
||||
_ base.ResourceModel = &usgModel{}
|
||||
_ resource.Resource = &usgResource{}
|
||||
_ resource.ResourceWithConfigure = &usgResource{}
|
||||
_ resource.ResourceWithImportState = &usgResource{}
|
||||
_ resource.ResourceWithModifyPlan = &usgResource{}
|
||||
)
|
||||
|
||||
type usgResource struct {
|
||||
*BaseSettingResource[*usgModel]
|
||||
}
|
||||
|
||||
func (r *usgResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
|
||||
resp.Diagnostics.Append(r.RequireMaxVersionForPath("7.0", path.Root("multicast_dns_enabled"), req.Config)...)
|
||||
}
|
||||
|
||||
func (r *usgResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "The `unifi_setting_usg` resource manages advanced settings for UniFi Security Gateways (USG) and UniFi Dream Machines (UDM/UDM-Pro).\n\n" +
|
||||
"This resource allows you to configure gateway-specific features including:\n" +
|
||||
" * Multicast DNS (mDNS) for service discovery\n" +
|
||||
" * DHCP relay for forwarding DHCP requests to external servers\n\n" +
|
||||
@@ -36,146 +114,44 @@ func ResourceSettingUsg() *schema.Resource {
|
||||
" * Centralizing DHCP management in enterprise environments\n" +
|
||||
" * Integration with existing network infrastructure\n\n" +
|
||||
"Note: Some settings may not be available on all controller versions. For example, multicast_dns_enabled is not supported on UniFi OS v7+.",
|
||||
|
||||
CreateContext: resourceSettingUsgLocker(resourceSettingUsgUpsert),
|
||||
ReadContext: resourceSettingUsgLocker(resourceSettingUsgRead),
|
||||
UpdateContext: resourceSettingUsgLocker(resourceSettingUsgUpsert),
|
||||
DeleteContext: schema.NoopContext,
|
||||
Importer: &schema.ResourceImporter{
|
||||
StateContext: base.ImportSiteAndID,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"id": {
|
||||
Description: "The unique identifier of the USG settings configuration in the UniFi controller.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"site": {
|
||||
Description: "The name of the UniFi site where these USG settings should be applied. If not specified, the default site will be used.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"multicast_dns_enabled": {
|
||||
Description: "Enable multicast DNS (mDNS/Bonjour/Avahi) forwarding across VLANs. This allows devices to discover services " +
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"multicast_dns_enabled": schema.BoolAttribute{
|
||||
MarkdownDescription: "Enable multicast DNS (mDNS/Bonjour/Avahi) forwarding across VLANs. This allows devices to discover services " +
|
||||
"(like printers, Chromecasts, etc.) even when they are on different networks. Note: Not supported on UniFi OS v7+.",
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"dhcp_relay_servers": {
|
||||
Description: "List of up to 5 DHCP relay servers (specified by IP address) that will receive forwarded DHCP requests. " +
|
||||
"dhcp_relay_servers": schema.ListAttribute{
|
||||
MarkdownDescription: "List of up to 5 DHCP relay servers (specified by IP address) that will receive forwarded DHCP requests. " +
|
||||
"This is useful when you want to use external DHCP servers instead of the built-in DHCP server. " +
|
||||
"Example: ['192.168.1.5', '192.168.2.5']",
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
MaxItems: 5,
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validation.All(
|
||||
validation.IsIPv4Address,
|
||||
// this doesn't let blank through
|
||||
validation.StringLenBetween(1, 50),
|
||||
),
|
||||
ElementType: types.StringType,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Default: listdefault.StaticValue(types.ListValueMust(types.StringType, []attr.Value{})),
|
||||
Validators: []validator.List{
|
||||
listvalidator.SizeAtMost(5),
|
||||
listvalidator.ValueStringsAre(validators.IPv4()),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceSettingUsgUpdateResourceData(d *schema.ResourceData, meta interface{}, setting *unifi.SettingUsg) error {
|
||||
c := meta.(*base.Client)
|
||||
|
||||
//nolint // GetOkExists is deprecated, but using here:
|
||||
if mdns, hasMdns := d.GetOkExists("multicast_dns_enabled"); hasMdns {
|
||||
if c.IsControllerV7() {
|
||||
return fmt.Errorf("multicast_dns_enabled is not supported on controller version %v", c.Version)
|
||||
}
|
||||
|
||||
setting.MdnsEnabled = mdns.(bool)
|
||||
}
|
||||
|
||||
dhcpRelay, err := utils.ListToStringSlice(d.Get("dhcp_relay_servers").([]interface{}))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to convert dhcp_relay_servers to string slice: %w", err)
|
||||
}
|
||||
setting.DHCPRelayServer1 = append(dhcpRelay, "")[0]
|
||||
setting.DHCPRelayServer2 = append(dhcpRelay, "", "")[1]
|
||||
setting.DHCPRelayServer3 = append(dhcpRelay, "", "", "")[2]
|
||||
setting.DHCPRelayServer4 = append(dhcpRelay, "", "", "", "")[3]
|
||||
setting.DHCPRelayServer5 = append(dhcpRelay, "", "", "", "", "")[4]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceSettingUsgUpsert(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
c := meta.(*base.Client)
|
||||
|
||||
site := d.Get("site").(string)
|
||||
if site == "" {
|
||||
site = c.Site
|
||||
}
|
||||
|
||||
req, err := c.GetSettingUsg(ctx, c.Site)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
err = resourceSettingUsgUpdateResourceData(d, meta, req)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
resp, err := c.UpdateSettingUsg(ctx, site, req)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
d.SetId(resp.ID)
|
||||
return resourceSettingUsgSetResourceData(resp, d, meta, site)
|
||||
}
|
||||
|
||||
func resourceSettingUsgSetResourceData(resp *unifi.SettingUsg, d *schema.ResourceData, meta interface{}, site string) diag.Diagnostics {
|
||||
d.Set("site", site)
|
||||
d.Set("multicast_dns_enabled", resp.MdnsEnabled)
|
||||
|
||||
dhcpRelay := []string{}
|
||||
for _, s := range []string{
|
||||
resp.DHCPRelayServer1,
|
||||
resp.DHCPRelayServer2,
|
||||
resp.DHCPRelayServer3,
|
||||
resp.DHCPRelayServer4,
|
||||
resp.DHCPRelayServer5,
|
||||
} {
|
||||
if s == "" {
|
||||
continue
|
||||
}
|
||||
dhcpRelay = append(dhcpRelay, s)
|
||||
}
|
||||
d.Set("dhcp_relay_servers", dhcpRelay)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceSettingUsgRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
c := meta.(*base.Client)
|
||||
|
||||
site := d.Get("site").(string)
|
||||
if site == "" {
|
||||
site = c.Site
|
||||
}
|
||||
|
||||
resp, err := c.GetSettingUsg(ctx, site)
|
||||
if errors.Is(err, unifi.ErrNotFound) {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
return resourceSettingUsgSetResourceData(resp, d, meta, site)
|
||||
// NewUsgResource creates a new instance of the USG resource.
|
||||
func NewUsgResource() resource.Resource {
|
||||
r := &usgResource{}
|
||||
r.BaseSettingResource = NewBaseSettingResource(
|
||||
"unifi_setting_usg",
|
||||
func() *usgModel { return &usgModel{} },
|
||||
func(ctx context.Context, client *base.Client, site string) (interface{}, error) {
|
||||
return client.GetSettingUsg(ctx, site)
|
||||
},
|
||||
func(ctx context.Context, client *base.Client, site string, body interface{}) (interface{}, error) {
|
||||
return client.UpdateSettingUsg(ctx, site, body.(*unifi.SettingUsg))
|
||||
},
|
||||
)
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -1,437 +0,0 @@
|
||||
package validators
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/hashicorp/go-version"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
|
||||
"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/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
)
|
||||
|
||||
var (
|
||||
_ resource.ConfigValidator = &ControllerVersionValidator{}
|
||||
_ datasource.ConfigValidator = &ControllerVersionValidator{}
|
||||
_ validator.String = &ControllerVersionValidator{}
|
||||
_ validator.Bool = &ControllerVersionValidator{}
|
||||
_ validator.Int64 = &ControllerVersionValidator{}
|
||||
_ validator.Float64 = &ControllerVersionValidator{}
|
||||
_ validator.List = &ControllerVersionValidator{}
|
||||
_ validator.Map = &ControllerVersionValidator{}
|
||||
_ validator.Object = &ControllerVersionValidator{}
|
||||
_ validator.Set = &ControllerVersionValidator{}
|
||||
)
|
||||
|
||||
// ControllerVersionValidator is a validator that checks if the UniFi controller version
|
||||
// matches the specified constraints.
|
||||
type ControllerVersionValidator struct {
|
||||
client *base.Client
|
||||
minVersion *version.Version
|
||||
maxVersion *version.Version
|
||||
exactVersion *version.Version
|
||||
conditionMessage string
|
||||
}
|
||||
|
||||
// Description returns a description of the validator.
|
||||
func (v ControllerVersionValidator) Description(ctx context.Context) string {
|
||||
return v.MarkdownDescription(ctx)
|
||||
}
|
||||
|
||||
// MarkdownDescription returns a markdown description of the validator.
|
||||
func (v ControllerVersionValidator) MarkdownDescription(_ context.Context) string {
|
||||
if v.exactVersion != nil {
|
||||
return fmt.Sprintf("Validates that the controller version is exactly %s", v.exactVersion)
|
||||
}
|
||||
if v.minVersion != nil && v.maxVersion != nil {
|
||||
return fmt.Sprintf("Validates that the controller version is between %s and %s", v.minVersion, v.maxVersion)
|
||||
}
|
||||
if v.minVersion != nil {
|
||||
return fmt.Sprintf("Validates that the controller version is at least %s", v.minVersion)
|
||||
}
|
||||
if v.maxVersion != nil {
|
||||
return fmt.Sprintf("Validates that the controller version is at most %s", v.maxVersion)
|
||||
}
|
||||
return "Validates the controller version"
|
||||
}
|
||||
|
||||
// ValidateResource validates the resource configuration.
|
||||
func (v ControllerVersionValidator) ValidateResource(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) {
|
||||
if v.client == nil || v.client.Version == nil {
|
||||
resp.Diagnostics.AddWarning("Controller version not available", "Provider was not initialized properly. UniFi client or controller version is not available")
|
||||
return
|
||||
}
|
||||
|
||||
v.validateVersion(ctx, &resp.Diagnostics)
|
||||
}
|
||||
|
||||
// ValidateDataSource validates the datasource configuration.
|
||||
func (v ControllerVersionValidator) ValidateDataSource(ctx context.Context, req datasource.ValidateConfigRequest, resp *datasource.ValidateConfigResponse) {
|
||||
if v.client == nil || v.client.Version == nil {
|
||||
resp.Diagnostics.AddWarning("Controller version not available", "Provider was not initialized properly. UniFi client or controller version is not available")
|
||||
return
|
||||
}
|
||||
|
||||
v.validateVersion(ctx, &resp.Diagnostics)
|
||||
}
|
||||
|
||||
// validateVersion checks if the controller version meets the constraints
|
||||
func (v ControllerVersionValidator) validateVersion(_ context.Context, diags *diag.Diagnostics) {
|
||||
controllerVersion := v.client.Version
|
||||
|
||||
message := v.conditionMessage
|
||||
if message == "" {
|
||||
message = "Controller version does not meet requirements"
|
||||
}
|
||||
|
||||
if v.exactVersion != nil && !controllerVersion.Equal(v.exactVersion) {
|
||||
diags.AddError(
|
||||
message,
|
||||
fmt.Sprintf("Controller version %s does not match required version %s", controllerVersion, v.exactVersion),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if v.minVersion != nil && controllerVersion.LessThan(v.minVersion) {
|
||||
diags.AddError(
|
||||
message,
|
||||
fmt.Sprintf("Controller version %s is less than minimum required version %s", controllerVersion, v.minVersion),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if v.maxVersion != nil && controllerVersion.GreaterThan(v.maxVersion) {
|
||||
diags.AddError(
|
||||
message,
|
||||
fmt.Sprintf("Controller version %s is greater than maximum allowed version %s", controllerVersion, v.maxVersion),
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// validateAttributeVersion is a helper function for attribute validators
|
||||
func (v ControllerVersionValidator) validateAttributeVersion(ctx context.Context, req path.Path) diag.Diagnostics {
|
||||
diags := diag.Diagnostics{}
|
||||
|
||||
if v.client == nil || v.client.Version == nil {
|
||||
diags.AddWarning("Controller version not available", "Provider was not initialized properly. UniFi client or controller version is not available")
|
||||
return diags
|
||||
}
|
||||
|
||||
controllerVersion := v.client.Version
|
||||
|
||||
message := v.conditionMessage
|
||||
if message == "" {
|
||||
message = "Controller version does not meet requirements"
|
||||
}
|
||||
|
||||
if v.exactVersion != nil && !controllerVersion.Equal(v.exactVersion) {
|
||||
diags.Append(validatordiag.InvalidAttributeValueDiagnostic(
|
||||
req,
|
||||
message,
|
||||
fmt.Sprintf("Controller version %s does not match required version %s to use given attribute", controllerVersion, v.exactVersion),
|
||||
))
|
||||
return diags
|
||||
}
|
||||
|
||||
if v.minVersion != nil && controllerVersion.LessThan(v.minVersion) {
|
||||
diags.Append(validatordiag.InvalidAttributeValueDiagnostic(
|
||||
req,
|
||||
message,
|
||||
fmt.Sprintf("Controller version %s is less than minimum required version %s to use given attribute", controllerVersion, v.minVersion),
|
||||
))
|
||||
return diags
|
||||
}
|
||||
|
||||
if v.maxVersion != nil && controllerVersion.GreaterThan(v.maxVersion) {
|
||||
diags.Append(validatordiag.InvalidAttributeValueDiagnostic(
|
||||
req,
|
||||
message,
|
||||
fmt.Sprintf("Controller version %s is greater than maximum allowed version %s to use given attribute", controllerVersion, v.maxVersion),
|
||||
))
|
||||
return diags
|
||||
}
|
||||
|
||||
return diags
|
||||
}
|
||||
|
||||
// ValidateString implements validator.String
|
||||
func (v ControllerVersionValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
|
||||
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
resp.Diagnostics.Append(v.validateAttributeVersion(ctx, req.Path)...)
|
||||
}
|
||||
|
||||
// ValidateBool implements validator.Bool
|
||||
func (v ControllerVersionValidator) ValidateBool(ctx context.Context, req validator.BoolRequest, resp *validator.BoolResponse) {
|
||||
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
resp.Diagnostics.Append(v.validateAttributeVersion(ctx, req.Path)...)
|
||||
}
|
||||
|
||||
// ValidateInt64 implements validator.Int64
|
||||
func (v ControllerVersionValidator) ValidateInt64(ctx context.Context, req validator.Int64Request, resp *validator.Int64Response) {
|
||||
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
resp.Diagnostics.Append(v.validateAttributeVersion(ctx, req.Path)...)
|
||||
}
|
||||
|
||||
// ValidateFloat64 implements validator.Float64
|
||||
func (v ControllerVersionValidator) ValidateFloat64(ctx context.Context, req validator.Float64Request, resp *validator.Float64Response) {
|
||||
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
resp.Diagnostics.Append(v.validateAttributeVersion(ctx, req.Path)...)
|
||||
}
|
||||
|
||||
// ValidateList implements validator.List
|
||||
func (v ControllerVersionValidator) ValidateList(ctx context.Context, req validator.ListRequest, resp *validator.ListResponse) {
|
||||
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
resp.Diagnostics.Append(v.validateAttributeVersion(ctx, req.Path)...)
|
||||
}
|
||||
|
||||
// ValidateMap implements validator.Map
|
||||
func (v ControllerVersionValidator) ValidateMap(ctx context.Context, req validator.MapRequest, resp *validator.MapResponse) {
|
||||
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
resp.Diagnostics.Append(v.validateAttributeVersion(ctx, req.Path)...)
|
||||
}
|
||||
|
||||
// ValidateObject implements validator.Object
|
||||
func (v ControllerVersionValidator) ValidateObject(ctx context.Context, req validator.ObjectRequest, resp *validator.ObjectResponse) {
|
||||
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
resp.Diagnostics.Append(v.validateAttributeVersion(ctx, req.Path)...)
|
||||
}
|
||||
|
||||
// ValidateSet implements validator.Set
|
||||
func (v ControllerVersionValidator) ValidateSet(ctx context.Context, req validator.SetRequest, resp *validator.SetResponse) {
|
||||
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
resp.Diagnostics.Append(v.validateAttributeVersion(ctx, req.Path)...)
|
||||
}
|
||||
|
||||
// ResourceRequireMinVersion returns a resource validator that checks if the controller version
|
||||
// is at least the specified version.
|
||||
func ResourceRequireMinVersion(client *base.Client, minVersion string, conditionMessage string) resource.ConfigValidator {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
minVersion: base.AsVersion(minVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// ResourceRequireMaxVersion returns a resource validator that checks if the controller version
|
||||
// is at most the specified version.
|
||||
func ResourceRequireMaxVersion(client *base.Client, maxVersion string, conditionMessage string) resource.ConfigValidator {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
maxVersion: base.AsVersion(maxVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// ResourceRequireVersionRange returns a resource validator that checks if the controller version
|
||||
// is within the specified range (inclusive).
|
||||
func ResourceRequireVersionRange(client *base.Client, minVersion, maxVersion string, conditionMessage string) resource.ConfigValidator {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
minVersion: base.AsVersion(minVersion),
|
||||
maxVersion: base.AsVersion(maxVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// ResourceRequireExactVersion returns a resource validator that checks if the controller version
|
||||
// matches the specified version exactly.
|
||||
func ResourceRequireExactVersion(client *base.Client, exactVersion string, conditionMessage string) resource.ConfigValidator {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
exactVersion: base.AsVersion(exactVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// DatasourceRequireMinVersion returns a datasource validator that checks if the controller version
|
||||
// is at least the specified version.
|
||||
func DatasourceRequireMinVersion(client *base.Client, minVersion string, conditionMessage string) datasource.ConfigValidator {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
minVersion: base.AsVersion(minVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// DatasourceRequireMaxVersion returns a datasource validator that checks if the controller version
|
||||
// is at most the specified version.
|
||||
func DatasourceRequireMaxVersion(client *base.Client, maxVersion string, conditionMessage string) datasource.ConfigValidator {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
maxVersion: base.AsVersion(maxVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// DatasourceRequireVersionRange returns a datasource validator that checks if the controller version
|
||||
// is within the specified range (inclusive).
|
||||
func DatasourceRequireVersionRange(client *base.Client, minVersion, maxVersion string, conditionMessage string) datasource.ConfigValidator {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
minVersion: base.AsVersion(minVersion),
|
||||
maxVersion: base.AsVersion(maxVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// DatasourceRequireExactVersion returns a datasource validator that checks if the controller version
|
||||
// matches the specified version exactly.
|
||||
func DatasourceRequireExactVersion(client *base.Client, exactVersion string, conditionMessage string) datasource.ConfigValidator {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
exactVersion: base.AsVersion(exactVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// StringRequireMinVersion returns a string validator that checks if the controller version
|
||||
// is at least the specified version.
|
||||
func StringRequireMinVersion(client *base.Client, minVersion string, conditionMessage string) validator.String {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
minVersion: base.AsVersion(minVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// StringRequireMaxVersion returns a string validator that checks if the controller version
|
||||
// is at most the specified version.
|
||||
func StringRequireMaxVersion(client *base.Client, maxVersion string, conditionMessage string) validator.String {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
maxVersion: base.AsVersion(maxVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// StringRequireVersionRange returns a string validator that checks if the controller version
|
||||
// is within the specified range (inclusive).
|
||||
func StringRequireVersionRange(client *base.Client, minVersion, maxVersion string, conditionMessage string) validator.String {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
minVersion: base.AsVersion(minVersion),
|
||||
maxVersion: base.AsVersion(maxVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// StringRequireExactVersion returns a string validator that checks if the controller version
|
||||
// matches the specified version exactly.
|
||||
func StringRequireExactVersion(client *base.Client, exactVersion string, conditionMessage string) validator.String {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
exactVersion: base.AsVersion(exactVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// BoolRequireMinVersion returns a bool validator that checks if the controller version
|
||||
// is at least the specified version.
|
||||
func BoolRequireMinVersion(client *base.Client, minVersion string, conditionMessage string) validator.Bool {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
minVersion: base.AsVersion(minVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// BoolRequireMaxVersion returns a bool validator that checks if the controller version
|
||||
// is at most the specified version.
|
||||
func BoolRequireMaxVersion(client *base.Client, maxVersion string, conditionMessage string) validator.Bool {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
maxVersion: base.AsVersion(maxVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// BoolRequireVersionRange returns a bool validator that checks if the controller version
|
||||
// is within the specified range (inclusive).
|
||||
func BoolRequireVersionRange(client *base.Client, minVersion, maxVersion string, conditionMessage string) validator.Bool {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
minVersion: base.AsVersion(minVersion),
|
||||
maxVersion: base.AsVersion(maxVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// BoolRequireExactVersion returns a bool validator that checks if the controller version
|
||||
// matches the specified version exactly.
|
||||
func BoolRequireExactVersion(client *base.Client, exactVersion string, conditionMessage string) validator.Bool {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
exactVersion: base.AsVersion(exactVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// Int64RequireMinVersion returns an int64 validator that checks if the controller version
|
||||
// is at least the specified version.
|
||||
func Int64RequireMinVersion(client *base.Client, minVersion string, conditionMessage string) validator.Int64 {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
minVersion: base.AsVersion(minVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// Int64RequireMaxVersion returns an int64 validator that checks if the controller version
|
||||
// is at most the specified version.
|
||||
func Int64RequireMaxVersion(client *base.Client, maxVersion string, conditionMessage string) validator.Int64 {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
maxVersion: base.AsVersion(maxVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// Int64RequireVersionRange returns an int64 validator that checks if the controller version
|
||||
// is within the specified range (inclusive).
|
||||
func Int64RequireVersionRange(client *base.Client, minVersion, maxVersion string, conditionMessage string) validator.Int64 {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
minVersion: base.AsVersion(minVersion),
|
||||
maxVersion: base.AsVersion(maxVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
// Int64RequireExactVersion returns an int64 validator that checks if the controller version
|
||||
// matches the specified version exactly.
|
||||
func Int64RequireExactVersion(client *base.Client, exactVersion string, conditionMessage string) validator.Int64 {
|
||||
return ControllerVersionValidator{
|
||||
client: client,
|
||||
exactVersion: base.AsVersion(exactVersion),
|
||||
conditionMessage: conditionMessage,
|
||||
}
|
||||
}
|
||||
@@ -1,375 +0,0 @@
|
||||
package validators
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/hashicorp/go-version"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestControllerVersionValidator_Description(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
validator ControllerVersionValidator
|
||||
expected string
|
||||
description string
|
||||
}{
|
||||
{
|
||||
name: "exact version",
|
||||
validator: ControllerVersionValidator{
|
||||
exactVersion: base.AsVersion("7.0.0"),
|
||||
},
|
||||
expected: "Validates that the controller version is exactly 7.0.0",
|
||||
description: "Should describe exact version check",
|
||||
},
|
||||
{
|
||||
name: "min version",
|
||||
validator: ControllerVersionValidator{
|
||||
minVersion: base.AsVersion("7.0.0"),
|
||||
},
|
||||
expected: "Validates that the controller version is at least 7.0.0",
|
||||
description: "Should describe minimum version check",
|
||||
},
|
||||
{
|
||||
name: "max version",
|
||||
validator: ControllerVersionValidator{
|
||||
maxVersion: base.AsVersion("7.0.0"),
|
||||
},
|
||||
expected: "Validates that the controller version is at most 7.0.0",
|
||||
description: "Should describe maximum version check",
|
||||
},
|
||||
{
|
||||
name: "version range",
|
||||
validator: ControllerVersionValidator{
|
||||
minVersion: base.AsVersion("7.0.0"),
|
||||
maxVersion: base.AsVersion("8.0.0"),
|
||||
},
|
||||
expected: "Validates that the controller version is between 7.0.0 and 8.0.0",
|
||||
description: "Should describe version range check",
|
||||
},
|
||||
{
|
||||
name: "no constraint",
|
||||
validator: ControllerVersionValidator{},
|
||||
expected: "Validates the controller version",
|
||||
description: "Should provide generic description when no constraints",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
actual := test.validator.Description(ctx)
|
||||
assert.Equal(t, test.expected, actual, test.description)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestControllerVersionValidator_ValidateResource(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
controllerVersion string
|
||||
validator ControllerVersionValidator
|
||||
expectError bool
|
||||
description string
|
||||
}{
|
||||
{
|
||||
name: "exact version match",
|
||||
controllerVersion: "7.0.0",
|
||||
validator: ControllerVersionValidator{
|
||||
exactVersion: base.AsVersion("7.0.0"),
|
||||
},
|
||||
expectError: false,
|
||||
description: "Should pass when exact version matches",
|
||||
},
|
||||
{
|
||||
name: "exact version mismatch",
|
||||
controllerVersion: "7.0.0",
|
||||
validator: ControllerVersionValidator{
|
||||
exactVersion: base.AsVersion("7.1.0"),
|
||||
},
|
||||
expectError: true,
|
||||
description: "Should fail when exact version doesn't match",
|
||||
},
|
||||
{
|
||||
name: "min version satisfied",
|
||||
controllerVersion: "7.5.0",
|
||||
validator: ControllerVersionValidator{
|
||||
minVersion: base.AsVersion("7.0.0"),
|
||||
},
|
||||
expectError: false,
|
||||
description: "Should pass when version meets minimum",
|
||||
},
|
||||
{
|
||||
name: "min version not satisfied",
|
||||
controllerVersion: "6.5.0",
|
||||
validator: ControllerVersionValidator{
|
||||
minVersion: base.AsVersion("7.0.0"),
|
||||
},
|
||||
expectError: true,
|
||||
description: "Should fail when version doesn't meet minimum",
|
||||
},
|
||||
{
|
||||
name: "max version satisfied",
|
||||
controllerVersion: "6.5.0",
|
||||
validator: ControllerVersionValidator{
|
||||
maxVersion: base.AsVersion("7.0.0"),
|
||||
},
|
||||
expectError: false,
|
||||
description: "Should pass when version is below maximum",
|
||||
},
|
||||
{
|
||||
name: "max version not satisfied",
|
||||
controllerVersion: "7.5.0",
|
||||
validator: ControllerVersionValidator{
|
||||
maxVersion: base.AsVersion("7.0.0"),
|
||||
},
|
||||
expectError: true,
|
||||
description: "Should fail when version exceeds maximum",
|
||||
},
|
||||
{
|
||||
name: "version in range",
|
||||
controllerVersion: "7.5.0",
|
||||
validator: ControllerVersionValidator{
|
||||
minVersion: base.AsVersion("7.0.0"),
|
||||
maxVersion: base.AsVersion("8.0.0"),
|
||||
},
|
||||
expectError: false,
|
||||
description: "Should pass when version is in range",
|
||||
},
|
||||
{
|
||||
name: "version below range",
|
||||
controllerVersion: "6.5.0",
|
||||
validator: ControllerVersionValidator{
|
||||
minVersion: base.AsVersion("7.0.0"),
|
||||
maxVersion: base.AsVersion("8.0.0"),
|
||||
},
|
||||
expectError: true,
|
||||
description: "Should fail when version is below range",
|
||||
},
|
||||
{
|
||||
name: "version above range",
|
||||
controllerVersion: "8.5.0",
|
||||
validator: ControllerVersionValidator{
|
||||
minVersion: base.AsVersion("7.0.0"),
|
||||
maxVersion: base.AsVersion("8.0.0"),
|
||||
},
|
||||
expectError: true,
|
||||
description: "Should fail when version is above range",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create a mock client with the specified version
|
||||
mockClient := &base.Client{
|
||||
Version: version.Must(version.NewVersion(test.controllerVersion)),
|
||||
}
|
||||
|
||||
// Update the validator with the mock client
|
||||
test.validator.client = mockClient
|
||||
|
||||
// Create request and response objects
|
||||
req := resource.ValidateConfigRequest{}
|
||||
resp := resource.ValidateConfigResponse{
|
||||
Diagnostics: diag.Diagnostics{},
|
||||
}
|
||||
|
||||
// Call the validator
|
||||
test.validator.ValidateResource(ctx, req, &resp)
|
||||
|
||||
// Check if the result matches expectations
|
||||
if test.expectError {
|
||||
assert.True(t, resp.Diagnostics.HasError(), test.description)
|
||||
} else {
|
||||
assert.False(t, resp.Diagnostics.HasError(), test.description)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceHelperFunctions(t *testing.T) {
|
||||
mockClient := &base.Client{
|
||||
Version: base.AsVersion("7.5.0"),
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
validator resource.ConfigValidator
|
||||
expectError bool
|
||||
description string
|
||||
}{
|
||||
{
|
||||
name: "ResourceRequireMinVersion passing",
|
||||
validator: ResourceRequireMinVersion(mockClient, "7.0.0", ""),
|
||||
expectError: false,
|
||||
description: "ResourceRequireMinVersion should pass with sufficient version",
|
||||
},
|
||||
{
|
||||
name: "ResourceRequireMinVersion failing",
|
||||
validator: ResourceRequireMinVersion(mockClient, "8.0.0", ""),
|
||||
expectError: true,
|
||||
description: "ResourceRequireMinVersion should fail with insufficient version",
|
||||
},
|
||||
{
|
||||
name: "ResourceRequireMaxVersion passing",
|
||||
validator: ResourceRequireMaxVersion(mockClient, "8.0.0", ""),
|
||||
expectError: false,
|
||||
description: "ResourceRequireMaxVersion should pass with acceptable version",
|
||||
},
|
||||
{
|
||||
name: "ResourceRequireMaxVersion failing",
|
||||
validator: ResourceRequireMaxVersion(mockClient, "7.0.0", ""),
|
||||
expectError: true,
|
||||
description: "ResourceRequireMaxVersion should fail with too high version",
|
||||
},
|
||||
{
|
||||
name: "ResourceRequireVersionRange passing",
|
||||
validator: ResourceRequireVersionRange(mockClient, "7.0.0", "8.0.0", ""),
|
||||
expectError: false,
|
||||
description: "ResourceRequireVersionRange should pass with version in range",
|
||||
},
|
||||
{
|
||||
name: "ResourceRequireVersionRange failing (below)",
|
||||
validator: ResourceRequireVersionRange(mockClient, "7.6.0", "8.0.0", ""),
|
||||
expectError: true,
|
||||
description: "ResourceRequireVersionRange should fail with version below range",
|
||||
},
|
||||
{
|
||||
name: "ResourceRequireVersionRange failing (above)",
|
||||
validator: ResourceRequireVersionRange(mockClient, "6.0.0", "7.0.0", ""),
|
||||
expectError: true,
|
||||
description: "ResourceRequireVersionRange should fail with version above range",
|
||||
},
|
||||
{
|
||||
name: "ResourceRequireExactVersion passing",
|
||||
validator: ResourceRequireExactVersion(mockClient, "7.5.0", ""),
|
||||
expectError: false,
|
||||
description: "ResourceRequireExactVersion should pass with exact version match",
|
||||
},
|
||||
{
|
||||
name: "ResourceRequireExactVersion failing",
|
||||
validator: ResourceRequireExactVersion(mockClient, "7.5.1", ""),
|
||||
expectError: true,
|
||||
description: "ResourceRequireExactVersion should fail with version mismatch",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create request and response objects
|
||||
req := resource.ValidateConfigRequest{}
|
||||
resp := resource.ValidateConfigResponse{
|
||||
Diagnostics: diag.Diagnostics{},
|
||||
}
|
||||
|
||||
// Call the validator
|
||||
test.validator.(ControllerVersionValidator).ValidateResource(ctx, req, &resp)
|
||||
|
||||
// Check if the result matches expectations
|
||||
if test.expectError {
|
||||
assert.True(t, resp.Diagnostics.HasError(), test.description)
|
||||
} else {
|
||||
assert.False(t, resp.Diagnostics.HasError(), test.description)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDatasourceHelperFunctions(t *testing.T) {
|
||||
mockClient := &base.Client{
|
||||
Version: base.AsVersion("7.5.0"),
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
validator datasource.ConfigValidator
|
||||
expectError bool
|
||||
description string
|
||||
}{
|
||||
{
|
||||
name: "DatasourceRequireMinVersion passing",
|
||||
validator: DatasourceRequireMinVersion(mockClient, "7.0.0", ""),
|
||||
expectError: false,
|
||||
description: "DatasourceRequireMinVersion should pass with sufficient version",
|
||||
},
|
||||
{
|
||||
name: "DatasourceRequireMinVersion failing",
|
||||
validator: DatasourceRequireMinVersion(mockClient, "8.0.0", ""),
|
||||
expectError: true,
|
||||
description: "DatasourceRequireMinVersion should fail with insufficient version",
|
||||
},
|
||||
{
|
||||
name: "DatasourceRequireMaxVersion passing",
|
||||
validator: DatasourceRequireMaxVersion(mockClient, "8.0.0", ""),
|
||||
expectError: false,
|
||||
description: "DatasourceRequireMaxVersion should pass with acceptable version",
|
||||
},
|
||||
{
|
||||
name: "DatasourceRequireMaxVersion failing",
|
||||
validator: DatasourceRequireMaxVersion(mockClient, "7.0.0", ""),
|
||||
expectError: true,
|
||||
description: "DatasourceRequireMaxVersion should fail with too high version",
|
||||
},
|
||||
{
|
||||
name: "DatasourceRequireVersionRange passing",
|
||||
validator: DatasourceRequireVersionRange(mockClient, "7.0.0", "8.0.0", ""),
|
||||
expectError: false,
|
||||
description: "DatasourceRequireVersionRange should pass with version in range",
|
||||
},
|
||||
{
|
||||
name: "DatasourceRequireVersionRange failing (below)",
|
||||
validator: DatasourceRequireVersionRange(mockClient, "7.6.0", "8.0.0", ""),
|
||||
expectError: true,
|
||||
description: "DatasourceRequireVersionRange should fail with version below range",
|
||||
},
|
||||
{
|
||||
name: "DatasourceRequireVersionRange failing (above)",
|
||||
validator: DatasourceRequireVersionRange(mockClient, "6.0.0", "7.0.0", ""),
|
||||
expectError: true,
|
||||
description: "DatasourceRequireVersionRange should fail with version above range",
|
||||
},
|
||||
{
|
||||
name: "DatasourceRequireExactVersion passing",
|
||||
validator: DatasourceRequireExactVersion(mockClient, "7.5.0", ""),
|
||||
expectError: false,
|
||||
description: "DatasourceRequireExactVersion should pass with exact version match",
|
||||
},
|
||||
{
|
||||
name: "DatasourceRequireExactVersion failing",
|
||||
validator: DatasourceRequireExactVersion(mockClient, "7.5.1", ""),
|
||||
expectError: true,
|
||||
description: "DatasourceRequireExactVersion should fail with version mismatch",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create request and response objects
|
||||
req := datasource.ValidateConfigRequest{}
|
||||
resp := datasource.ValidateConfigResponse{
|
||||
Diagnostics: diag.Diagnostics{},
|
||||
}
|
||||
|
||||
// Call the validator
|
||||
test.validator.(ControllerVersionValidator).ValidateDataSource(ctx, req, &resp)
|
||||
|
||||
// Check if the result matches expectations
|
||||
if test.expectError {
|
||||
assert.True(t, resp.Diagnostics.HasError(), test.description)
|
||||
} else {
|
||||
assert.False(t, resp.Diagnostics.HasError(), test.description)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user