refactor: reorganize code to make it more readable (#71)
This commit is contained in:
committed by
GitHub
parent
86fdc0b27a
commit
cdc0254289
@@ -3,11 +3,8 @@ package base
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
@@ -44,20 +41,6 @@ type DatasourceModel interface {
|
||||
Merge(context.Context, interface{}) diag.Diagnostics
|
||||
}
|
||||
|
||||
type NestedObject interface {
|
||||
AttributeTypes() map[string]attr.Type
|
||||
}
|
||||
|
||||
func ObjectNull(obj interface{}) (basetypes.ObjectValue, diag.Diagnostics) {
|
||||
diags := diag.Diagnostics{}
|
||||
if nested, ok := obj.(NestedObject); ok {
|
||||
obj := types.ObjectNull(nested.AttributeTypes())
|
||||
return obj, diags
|
||||
}
|
||||
diags.AddError("Invalid object type", fmt.Sprintf("Expected NestedObject, got: %T", obj))
|
||||
return types.ObjectNull(map[string]attr.Type{}), diags
|
||||
}
|
||||
|
||||
type Model struct {
|
||||
ID types.String `tfsdk:"id"`
|
||||
Site types.String `tfsdk:"site"`
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"github.com/hashicorp/go-version"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
@@ -90,7 +92,7 @@ func (c *RetryableUnifiClient) relogin(err error) error {
|
||||
|
||||
func (c *RetryableUnifiClient) Do(ctx context.Context, method string, apiPath string, reqBody interface{}, respBody interface{}) error {
|
||||
err := c.Client.Do(ctx, method, apiPath, reqBody, respBody)
|
||||
if err != nil && IsServerErrorStatusCode(err, 401) {
|
||||
if err != nil && utils.IsServerErrorStatusCode(err, 401) {
|
||||
err := c.relogin(err)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -107,7 +109,7 @@ type Client struct {
|
||||
}
|
||||
|
||||
func (c *Client) ResolveSite(res SiteAware) string {
|
||||
if res == nil || IsEmptyString(res.GetRawSite()) {
|
||||
if res == nil || ut.IsEmptyString(res.GetRawSite()) {
|
||||
return c.Site
|
||||
}
|
||||
return res.GetSite()
|
||||
@@ -119,7 +121,7 @@ func (c *Client) ResolveSiteFromConfig(ctx context.Context, config tfsdk.Config)
|
||||
if diags.HasError() {
|
||||
return "", diags
|
||||
}
|
||||
if IsEmptyString(site) {
|
||||
if ut.IsEmptyString(site) {
|
||||
return c.Site, diags
|
||||
}
|
||||
return site.ValueString(), diags
|
||||
|
||||
@@ -3,6 +3,7 @@ package base
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/hashicorp/go-version"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
@@ -29,18 +30,6 @@ var (
|
||||
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)
|
||||
}
|
||||
@@ -149,7 +138,7 @@ func (v controllerVersionValidator) requireVersionForPath(req versionRequirement
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
if !IsDefined(val) {
|
||||
if !types.IsDefined(val) {
|
||||
return diags
|
||||
}
|
||||
diags.Append(v.requireVersion(req, &attrPath)...)
|
||||
|
||||
@@ -3,6 +3,7 @@ package base
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -119,7 +120,7 @@ func (v *featureEnabledValidator) RequireFeaturesEnabledForPath(ctx context.Cont
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
if !IsDefined(val) {
|
||||
if !types.IsDefined(val) {
|
||||
return diags
|
||||
}
|
||||
diags.Append(v.requireFeatures(ctx, site, &attrPath, features...)...)
|
||||
|
||||
@@ -3,6 +3,7 @@ package base
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
@@ -574,7 +575,7 @@ func TestIsDefined(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equal(t, tt.expected, IsDefined(tt.value))
|
||||
assert.Equal(t, tt.expected, ut.IsDefined(tt.value))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -640,7 +641,7 @@ func (v *testFeatureValidator) TestRequireFeaturesEnabledForPath(ctx context.Con
|
||||
return diags
|
||||
}
|
||||
|
||||
if !IsDefined(v.attrValue) {
|
||||
if !ut.IsDefined(v.attrValue) {
|
||||
return diags
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// for Terraform Plugin SDK v2
|
||||
func ImportSiteAndID(_ context.Context, d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) {
|
||||
if id := d.Id(); strings.Contains(id, ":") {
|
||||
importParts := strings.SplitN(id, ":", 2)
|
||||
@@ -16,6 +17,7 @@ func ImportSiteAndID(_ context.Context, d *schema.ResourceData, _ interface{}) (
|
||||
return []*schema.ResourceData{d}, nil
|
||||
}
|
||||
|
||||
// for Terraform Plugin Framework
|
||||
func ImportIDWithSite(req resource.ImportStateRequest, resp *resource.ImportStateResponse) (string, string) {
|
||||
id := req.ID
|
||||
if id == "" {
|
||||
|
||||
@@ -4,14 +4,13 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
@@ -316,7 +315,7 @@ func resourceDeviceDelete(ctx context.Context, d *schema.ResourceData, meta inte
|
||||
if internalErr == nil {
|
||||
return nil
|
||||
}
|
||||
if base.IsServerErrorContains(internalErr, "api.err.DeviceBusy") {
|
||||
if utils.IsServerErrorContains(internalErr, "api.err.DeviceBusy") {
|
||||
return retry.RetryableError(internalErr)
|
||||
}
|
||||
return retry.NonRetryableError(internalErr)
|
||||
|
||||
@@ -3,11 +3,10 @@ package device
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"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"
|
||||
|
||||
@@ -3,10 +3,10 @@ package dns
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
@@ -49,7 +50,7 @@ func (d *dnsRecordsDatasource) Schema(_ context.Context, _ datasource.SchemaRequ
|
||||
resp.Schema = schema.Schema{
|
||||
Description: "Retrieves information about a all DNS records.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"site": base.SiteAttribute(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"result": schema.ListNestedAttribute{
|
||||
Description: "The list of DNS records.",
|
||||
Computed: true,
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
@@ -46,8 +47,8 @@ func (b *dnsRecordsDatasourceModel) SetSite(site string) {
|
||||
}
|
||||
|
||||
var dnsRecordDatasourceAttributes = map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"name": schema.StringAttribute{
|
||||
Description: "DNS record name.",
|
||||
Optional: true,
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/int32validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
@@ -78,8 +79,8 @@ func (d *dnsRecordResource) Schema(_ context.Context, _ resource.SchemaRequest,
|
||||
" * Adding TXT records for service verification\n\n",
|
||||
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"name": schema.StringAttribute{
|
||||
MarkdownDescription: "DNS record name.",
|
||||
Required: true,
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
@@ -52,8 +53,8 @@ func (d *firewallZoneDatasource) Schema(_ context.Context, _ datasource.SchemaRe
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "The `unifi_firewall_zone` datsources allows retrieving existing firewall zone details from the UniFi controller by the zone name.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"name": schema.StringAttribute{
|
||||
MarkdownDescription: "The name of the firewall zone.",
|
||||
Required: true,
|
||||
|
||||
@@ -3,11 +3,10 @@ package firewall
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"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"
|
||||
@@ -90,7 +89,7 @@ func resourceFirewallGroupCreate(ctx context.Context, d *schema.ResourceData, me
|
||||
|
||||
resp, err := c.CreateFirewallGroup(ctx, site, req)
|
||||
if err != nil {
|
||||
if base.IsServerErrorContains(err, "api.err.FirewallGroupExisted") {
|
||||
if utils.IsServerErrorContains(err, "api.err.FirewallGroupExisted") {
|
||||
return diag.Errorf("firewall groups must have unique names: %s", err)
|
||||
}
|
||||
return diag.FromErr(err)
|
||||
|
||||
@@ -3,12 +3,12 @@ package firewall
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
|
||||
"regexp"
|
||||
|
||||
"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/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"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"
|
||||
@@ -184,7 +184,7 @@ func ResourceFirewallRule() *schema.Resource {
|
||||
" * A list of ports/ranges separated by commas",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ValidateFunc: utils.ValidatePortRange,
|
||||
ValidateFunc: validators.PortRangeV2,
|
||||
},
|
||||
"src_mac": {
|
||||
Description: "The source MAC address this rule applies to. Use this to create rules that match specific devices " +
|
||||
@@ -235,7 +235,7 @@ func ResourceFirewallRule() *schema.Resource {
|
||||
" * A list of ports/ranges separated by commas",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ValidateFunc: utils.ValidatePortRange,
|
||||
ValidateFunc: validators.PortRangeV2,
|
||||
},
|
||||
|
||||
// advanced
|
||||
@@ -293,7 +293,7 @@ func resourceFirewallRuleCreate(ctx context.Context, d *schema.ResourceData, met
|
||||
|
||||
resp, err := c.CreateFirewallRule(ctx, site, req)
|
||||
if err != nil {
|
||||
if base.IsServerErrorContains(err, "api.err.FirewallGroupTypeExists") {
|
||||
if utils.IsServerErrorContains(err, "api.err.FirewallGroupTypeExists") {
|
||||
return diag.Errorf("firewall rule groups must be of different group types (ie. a port group and address group): %s", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@ package firewall
|
||||
import (
|
||||
"context"
|
||||
"github.com/filipowm/go-unifi/unifi/features"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
@@ -33,7 +33,7 @@ func (m *firewallZoneModel) AsUnifiModel(_ context.Context) (interface{}, diag.D
|
||||
diags := diag.Diagnostics{}
|
||||
var networkIDs []string
|
||||
|
||||
diags.Append(utils.ListElementsAs(m.Networks, &networkIDs)...)
|
||||
diags.Append(ut.ListElementsAs(m.Networks, &networkIDs)...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
@@ -111,8 +111,8 @@ func (r *firewallZoneResource) Schema(_ context.Context, _ resource.SchemaReques
|
||||
"This resource allows you to create, update, and delete firewall zones.",
|
||||
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"name": schema.StringAttribute{
|
||||
MarkdownDescription: "The name of the firewall zone.",
|
||||
Required: true,
|
||||
@@ -122,7 +122,7 @@ func (r *firewallZoneResource) Schema(_ context.Context, _ resource.SchemaReques
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
Default: utils.DefaultEmptyList(types.StringType),
|
||||
Default: ut.DefaultEmptyList(types.StringType),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2,10 +2,9 @@ package network
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
@@ -4,13 +4,12 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"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/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"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"
|
||||
|
||||
@@ -4,11 +4,10 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"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"
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/dns"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/firewall"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/settings"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
|
||||
@@ -3,11 +3,11 @@ package routing
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"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"
|
||||
@@ -48,7 +48,7 @@ func ResourcePortForward() *schema.Resource {
|
||||
Description: "The external port(s) that will be forwarded. Can be a single port (e.g., '80') or a port range (e.g., '8080:8090').",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ValidateFunc: utils.ValidatePortRange,
|
||||
ValidateFunc: validators.PortRangeV2,
|
||||
},
|
||||
// TODO: remove this, disabled rules should just be deleted.
|
||||
"enabled": {
|
||||
@@ -69,7 +69,7 @@ func ResourcePortForward() *schema.Resource {
|
||||
Description: "The internal port(s) that will receive the forwarded traffic. Can be a single port (e.g., '8080') or a port range (e.g., '8080:8090').",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ValidateFunc: utils.ValidatePortRange,
|
||||
ValidateFunc: validators.PortRangeV2,
|
||||
},
|
||||
"log": {
|
||||
Description: "Enable logging of traffic matching this port forwarding rule. Useful for monitoring and troubleshooting.",
|
||||
|
||||
@@ -4,10 +4,9 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"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/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"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"
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"fmt"
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
@@ -46,7 +48,7 @@ type autoSpeedtestResource struct {
|
||||
}
|
||||
|
||||
func checkAutoSpeedtestUnsupportedError(err error) error {
|
||||
if base.IsServerErrorContains(err, "api.err.SpeedTestNotSupported") {
|
||||
if utils.IsServerErrorContains(err, "api.err.SpeedTestNotSupported") {
|
||||
return fmt.Errorf("Auto Speedtest is not supported on this controller")
|
||||
}
|
||||
return err
|
||||
@@ -81,8 +83,8 @@ func (a *autoSpeedtestResource) Schema(_ context.Context, _ resource.SchemaReque
|
||||
"Automatic speedtests can be scheduled to run at regular intervals to monitor the network performance.\n\n" +
|
||||
"**NOTE:** Automatic speedtests where not verified and tested on all UniFi controller versions due to limitations of controller used in acceptance testing. ",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"cron": schema.StringAttribute{
|
||||
MarkdownDescription: "Cron expression defining the schedule for automatic speedtests.",
|
||||
Optional: true,
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/biter777/countries"
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
@@ -67,8 +68,8 @@ func (c *countryResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "The `unifi_setting_country` resource allows you to configure the country settings for your UniFi network. ",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"code": schema.StringAttribute{
|
||||
Description: "The country code to set for the UniFi site. The country code must be a valid ISO 3166-1 alpha-2 code.",
|
||||
Required: true,
|
||||
|
||||
@@ -2,6 +2,7 @@ package settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
@@ -60,8 +61,8 @@ func (r *dpiResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "Manages Deep Packet Inspection (DPI) settings for a UniFi site. DPI is a feature that allows the UniFi controller to analyze network traffic and identify applications and services being used on the network.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"enabled": schema.BoolAttribute{
|
||||
MarkdownDescription: "Whether Deep Packet Inspection is enabled.",
|
||||
Required: true,
|
||||
|
||||
@@ -3,7 +3,7 @@ package settings
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/int32validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
|
||||
@@ -355,7 +355,7 @@ func (d *guestAccessModel) AsUnifiModel(ctx context.Context) (interface{}, diag.
|
||||
VoucherCustomized: d.VoucherCustomized.ValueBool(),
|
||||
VoucherEnabled: d.VoucherEnabled.ValueBool(),
|
||||
}
|
||||
if base.IsEmptyString(d.Password) {
|
||||
if ut.IsEmptyString(d.Password) {
|
||||
model.PasswordEnabled = false
|
||||
} else {
|
||||
model.PasswordEnabled = true
|
||||
@@ -365,7 +365,7 @@ func (d *guestAccessModel) AsUnifiModel(ctx context.Context) (interface{}, diag.
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
if base.IsDefined(d.Redirect) {
|
||||
if ut.IsDefined(d.Redirect) {
|
||||
var redirect *redirectModel
|
||||
diags.Append(d.Redirect.As(ctx, &redirect, basetypes.ObjectAsOptions{})...)
|
||||
if diags.HasError() {
|
||||
@@ -379,7 +379,7 @@ func (d *guestAccessModel) AsUnifiModel(ctx context.Context) (interface{}, diag.
|
||||
model.RedirectEnabled = false
|
||||
}
|
||||
|
||||
if base.IsDefined(d.Facebook) {
|
||||
if ut.IsDefined(d.Facebook) {
|
||||
var facebook *facebookModel
|
||||
diags.Append(d.Facebook.As(ctx, &facebook, basetypes.ObjectAsOptions{})...)
|
||||
if diags.HasError() {
|
||||
@@ -393,7 +393,7 @@ func (d *guestAccessModel) AsUnifiModel(ctx context.Context) (interface{}, diag.
|
||||
model.FacebookEnabled = false
|
||||
}
|
||||
|
||||
if base.IsDefined(d.Google) {
|
||||
if ut.IsDefined(d.Google) {
|
||||
var google *googleModel
|
||||
diags.Append(d.Google.As(ctx, &google, basetypes.ObjectAsOptions{})...)
|
||||
if diags.HasError() {
|
||||
@@ -408,7 +408,7 @@ func (d *guestAccessModel) AsUnifiModel(ctx context.Context) (interface{}, diag.
|
||||
model.GoogleEnabled = false
|
||||
}
|
||||
|
||||
if base.IsDefined(d.Radius) {
|
||||
if ut.IsDefined(d.Radius) {
|
||||
var radius *radiusModel
|
||||
diags.Append(d.Radius.As(ctx, &radius, basetypes.ObjectAsOptions{})...)
|
||||
if diags.HasError() {
|
||||
@@ -423,7 +423,7 @@ func (d *guestAccessModel) AsUnifiModel(ctx context.Context) (interface{}, diag.
|
||||
model.RADIUSEnabled = false
|
||||
}
|
||||
|
||||
if base.IsDefined(d.Wechat) {
|
||||
if ut.IsDefined(d.Wechat) {
|
||||
var wechat *wechatModel
|
||||
diags.Append(d.Wechat.As(ctx, &wechat, basetypes.ObjectAsOptions{})...)
|
||||
if diags.HasError() {
|
||||
@@ -438,7 +438,7 @@ func (d *guestAccessModel) AsUnifiModel(ctx context.Context) (interface{}, diag.
|
||||
model.WechatEnabled = false
|
||||
}
|
||||
|
||||
if base.IsDefined(d.FacebookWifi) {
|
||||
if ut.IsDefined(d.FacebookWifi) {
|
||||
var facebookWifi *facebookWifiModel
|
||||
diags.Append(d.FacebookWifi.As(ctx, &facebookWifi, basetypes.ObjectAsOptions{})...)
|
||||
if diags.HasError() {
|
||||
@@ -450,9 +450,9 @@ func (d *guestAccessModel) AsUnifiModel(ctx context.Context) (interface{}, diag.
|
||||
model.XFacebookWifiGwSecret = facebookWifi.GwSecret.ValueString()
|
||||
}
|
||||
|
||||
if base.IsDefined(d.RestrictedDNSServers) {
|
||||
if ut.IsDefined(d.RestrictedDNSServers) {
|
||||
var servers []string
|
||||
diags := utils.ListElementsAs(d.RestrictedDNSServers, &servers)
|
||||
diags.Append(ut.ListElementsAs(d.RestrictedDNSServers, &servers)...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
@@ -464,14 +464,14 @@ func (d *guestAccessModel) AsUnifiModel(ctx context.Context) (interface{}, diag.
|
||||
model.RestrictedDNSEnabled = false
|
||||
}
|
||||
|
||||
if base.IsDefined(d.PortalCustomization) {
|
||||
if ut.IsDefined(d.PortalCustomization) {
|
||||
var portalCustomization *portalCustomizationModel
|
||||
diags.Append(d.PortalCustomization.As(ctx, &portalCustomization, basetypes.ObjectAsOptions{})...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
var languages []string
|
||||
diags := utils.ListElementsAs(portalCustomization.Languages, &languages)
|
||||
diags := ut.ListElementsAs(portalCustomization.Languages, &languages)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
@@ -511,7 +511,7 @@ func (d *guestAccessModel) AsUnifiModel(ctx context.Context) (interface{}, diag.
|
||||
|
||||
func (d *guestAccessModel) paymentAsUnifiModel(ctx context.Context, model *unifi.SettingGuestAccess) diag.Diagnostics {
|
||||
diags := diag.Diagnostics{}
|
||||
if base.IsEmptyString(d.PaymentGateway) {
|
||||
if ut.IsEmptyString(d.PaymentGateway) {
|
||||
model.PaymentEnabled = false
|
||||
} else {
|
||||
gateway := d.PaymentGateway.ValueString()
|
||||
@@ -524,7 +524,7 @@ func (d *guestAccessModel) paymentAsUnifiModel(ctx context.Context, model *unifi
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
if base.IsDefined(authorize.UseSandbox) {
|
||||
if ut.IsDefined(authorize.UseSandbox) {
|
||||
model.AuthorizeUseSandbox = authorize.UseSandbox.ValueBool()
|
||||
}
|
||||
model.XAuthorizeLoginid = authorize.LoginID.ValueString()
|
||||
@@ -535,7 +535,7 @@ func (d *guestAccessModel) paymentAsUnifiModel(ctx context.Context, model *unifi
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
if base.IsDefined(ippay.UseSandbox) {
|
||||
if ut.IsDefined(ippay.UseSandbox) {
|
||||
model.IPpayUseSandbox = ippay.UseSandbox.ValueBool()
|
||||
}
|
||||
model.XIPpayTerminalid = ippay.TerminalID.ValueString()
|
||||
@@ -545,7 +545,7 @@ func (d *guestAccessModel) paymentAsUnifiModel(ctx context.Context, model *unifi
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
if base.IsDefined(merchantWarrior.UseSandbox) {
|
||||
if ut.IsDefined(merchantWarrior.UseSandbox) {
|
||||
model.MerchantwarriorUseSandbox = merchantWarrior.UseSandbox.ValueBool()
|
||||
}
|
||||
model.XMerchantwarriorApikey = merchantWarrior.ApiKey.ValueString()
|
||||
@@ -557,7 +557,7 @@ func (d *guestAccessModel) paymentAsUnifiModel(ctx context.Context, model *unifi
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
if base.IsDefined(paypal.UseSandbox) {
|
||||
if ut.IsDefined(paypal.UseSandbox) {
|
||||
model.PaypalUseSandbox = paypal.UseSandbox.ValueBool()
|
||||
}
|
||||
model.XPaypalPassword = paypal.Password.ValueString()
|
||||
@@ -569,7 +569,7 @@ func (d *guestAccessModel) paymentAsUnifiModel(ctx context.Context, model *unifi
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
if base.IsDefined(quickpay.UseSandbox) {
|
||||
if ut.IsDefined(quickpay.UseSandbox) {
|
||||
model.QuickpayTestmode = quickpay.UseSandbox.ValueBool()
|
||||
}
|
||||
model.XQuickpayAgreementid = quickpay.AgreementID.ValueString()
|
||||
@@ -667,17 +667,17 @@ func (d *guestAccessModel) Merge(ctx context.Context, unifiModel interface{}) di
|
||||
|
||||
d.PaymentEnabled = types.BoolValue(model.PaymentEnabled)
|
||||
var od diag.Diagnostics
|
||||
d.Authorize, od = base.ObjectNull(&authorizeModel{})
|
||||
d.Authorize, od = ut.ObjectNull(&authorizeModel{})
|
||||
diags.Append(od...)
|
||||
d.Paypal, od = base.ObjectNull(&paypalModel{})
|
||||
d.Paypal, od = ut.ObjectNull(&paypalModel{})
|
||||
diags.Append(od...)
|
||||
d.IPpay, od = base.ObjectNull(&ipPayModel{})
|
||||
d.IPpay, od = ut.ObjectNull(&ipPayModel{})
|
||||
diags.Append(od...)
|
||||
d.MerchantWarrior, od = base.ObjectNull(&merchantWarriorModel{})
|
||||
d.MerchantWarrior, od = ut.ObjectNull(&merchantWarriorModel{})
|
||||
diags.Append(od...)
|
||||
d.Quickpay, od = base.ObjectNull(&quickpayModel{})
|
||||
d.Quickpay, od = ut.ObjectNull(&quickpayModel{})
|
||||
diags.Append(od...)
|
||||
d.Stripe, od = base.ObjectNull(&stripeModel{})
|
||||
d.Stripe, od = ut.ObjectNull(&stripeModel{})
|
||||
diags.Append(od...)
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
@@ -697,7 +697,7 @@ func (d *guestAccessModel) Merge(ctx context.Context, unifiModel interface{}) di
|
||||
}
|
||||
|
||||
d.RedirectEnabled = types.BoolValue(model.RedirectEnabled)
|
||||
d.Redirect, diags = base.ObjectNull(&redirectModel{})
|
||||
d.Redirect, diags = ut.ObjectNull(&redirectModel{})
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
@@ -714,7 +714,7 @@ func (d *guestAccessModel) Merge(ctx context.Context, unifiModel interface{}) di
|
||||
}
|
||||
|
||||
d.FacebookEnabled = types.BoolValue(model.FacebookEnabled)
|
||||
d.Facebook, diags = base.ObjectNull(&facebookModel{})
|
||||
d.Facebook, diags = ut.ObjectNull(&facebookModel{})
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
@@ -731,7 +731,7 @@ func (d *guestAccessModel) Merge(ctx context.Context, unifiModel interface{}) di
|
||||
}
|
||||
|
||||
d.GoogleEnabled = types.BoolValue(model.GoogleEnabled)
|
||||
d.Google, diags = base.ObjectNull(&googleModel{})
|
||||
d.Google, diags = ut.ObjectNull(&googleModel{})
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
@@ -749,7 +749,7 @@ func (d *guestAccessModel) Merge(ctx context.Context, unifiModel interface{}) di
|
||||
}
|
||||
|
||||
d.RadiusEnabled = types.BoolValue(model.RADIUSEnabled)
|
||||
d.Radius, diags = base.ObjectNull(&radiusModel{})
|
||||
d.Radius, diags = ut.ObjectNull(&radiusModel{})
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
@@ -767,7 +767,7 @@ func (d *guestAccessModel) Merge(ctx context.Context, unifiModel interface{}) di
|
||||
}
|
||||
|
||||
d.WechatEnabled = types.BoolValue(model.WechatEnabled)
|
||||
d.Wechat, diags = base.ObjectNull(&wechatModel{})
|
||||
d.Wechat, diags = ut.ObjectNull(&wechatModel{})
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
@@ -784,7 +784,7 @@ func (d *guestAccessModel) Merge(ctx context.Context, unifiModel interface{}) di
|
||||
}
|
||||
}
|
||||
|
||||
d.FacebookWifi, diags = base.ObjectNull(&facebookWifiModel{})
|
||||
d.FacebookWifi, diags = ut.ObjectNull(&facebookWifiModel{})
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
@@ -808,7 +808,7 @@ func (d *guestAccessModel) Merge(ctx context.Context, unifiModel interface{}) di
|
||||
return diags
|
||||
}
|
||||
} else {
|
||||
d.RestrictedDNSServers = utils.EmptyList(types.StringType)
|
||||
d.RestrictedDNSServers = ut.EmptyList(types.StringType)
|
||||
}
|
||||
|
||||
languages, diags := types.ListValueFrom(ctx, types.StringType, model.PortalCustomizedLanguages)
|
||||
@@ -950,8 +950,8 @@ func (g *guestAccessResource) Schema(_ context.Context, _ resource.SchemaRequest
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "The `unifi_setting_guest_access` resource manages the guest access settings in the UniFi controller.\n\nThis resource allows you to configure all aspects of guest network access including authentication methods, portal customization, and payment options.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"allowed_subnet": schema.StringAttribute{
|
||||
MarkdownDescription: "Subnet allowed for guest access.",
|
||||
Optional: true,
|
||||
@@ -1194,7 +1194,7 @@ func (g *guestAccessResource) Schema(_ context.Context, _ resource.SchemaRequest
|
||||
Required: true,
|
||||
Sensitive: true,
|
||||
Validators: []validator.String{
|
||||
validators.Email(),
|
||||
validators.Email,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1248,7 +1248,7 @@ func (g *guestAccessResource) Schema(_ context.Context, _ resource.SchemaRequest
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Validators: []validator.String{
|
||||
validators.HexColor(),
|
||||
validators.HexColor,
|
||||
},
|
||||
},
|
||||
"bg_image_tile": schema.BoolAttribute{
|
||||
@@ -1272,7 +1272,7 @@ func (g *guestAccessResource) Schema(_ context.Context, _ resource.SchemaRequest
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Validators: []validator.String{
|
||||
validators.HexColor(),
|
||||
validators.HexColor,
|
||||
},
|
||||
},
|
||||
"box_link_color": schema.StringAttribute{
|
||||
@@ -1280,7 +1280,7 @@ func (g *guestAccessResource) Schema(_ context.Context, _ resource.SchemaRequest
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Validators: []validator.String{
|
||||
validators.HexColor(),
|
||||
validators.HexColor,
|
||||
},
|
||||
},
|
||||
"box_opacity": schema.Int32Attribute{
|
||||
@@ -1304,7 +1304,7 @@ func (g *guestAccessResource) Schema(_ context.Context, _ resource.SchemaRequest
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Validators: []validator.String{
|
||||
validators.HexColor(),
|
||||
validators.HexColor,
|
||||
},
|
||||
},
|
||||
"button_color": schema.StringAttribute{
|
||||
@@ -1312,7 +1312,7 @@ func (g *guestAccessResource) Schema(_ context.Context, _ resource.SchemaRequest
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Validators: []validator.String{
|
||||
validators.HexColor(),
|
||||
validators.HexColor,
|
||||
},
|
||||
},
|
||||
"button_text": schema.StringAttribute{
|
||||
@@ -1325,7 +1325,7 @@ func (g *guestAccessResource) Schema(_ context.Context, _ resource.SchemaRequest
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Validators: []validator.String{
|
||||
validators.HexColor(),
|
||||
validators.HexColor,
|
||||
},
|
||||
},
|
||||
"languages": schema.ListAttribute{
|
||||
@@ -1339,7 +1339,7 @@ func (g *guestAccessResource) Schema(_ context.Context, _ resource.SchemaRequest
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Validators: []validator.String{
|
||||
validators.HexColor(),
|
||||
validators.HexColor,
|
||||
},
|
||||
},
|
||||
"logo_position": schema.StringAttribute{
|
||||
@@ -1368,7 +1368,7 @@ func (g *guestAccessResource) Schema(_ context.Context, _ resource.SchemaRequest
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Validators: []validator.String{
|
||||
validators.HexColor(),
|
||||
validators.HexColor,
|
||||
},
|
||||
},
|
||||
"title": schema.StringAttribute{
|
||||
@@ -1534,7 +1534,7 @@ func (g *guestAccessResource) Schema(_ context.Context, _ resource.SchemaRequest
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ElementType: types.StringType,
|
||||
Default: listdefault.StaticValue(utils.EmptyList(types.StringType)),
|
||||
Default: listdefault.StaticValue(ut.EmptyList(types.StringType)),
|
||||
Validators: []validator.List{
|
||||
listvalidator.ValueStringsAre(validators.IPv4()),
|
||||
},
|
||||
|
||||
@@ -5,8 +5,9 @@ import (
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/go-unifi/unifi/features"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"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-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
@@ -185,23 +186,23 @@ func (d *ipsModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
}
|
||||
|
||||
var enabledCategories []string
|
||||
diags.Append(utils.ListElementsAs(d.EnabledCategories, &enabledCategories)...)
|
||||
diags.Append(ut.ListElementsAs(d.EnabledCategories, &enabledCategories)...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
model.EnabledCategories = enabledCategories
|
||||
|
||||
var enabledNetworks []string
|
||||
diags.Append(utils.ListElementsAs(d.EnabledNetworks, &enabledNetworks)...)
|
||||
diags.Append(ut.ListElementsAs(d.EnabledNetworks, &enabledNetworks)...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
model.EnabledNetworks = enabledNetworks
|
||||
|
||||
// Handle AdBlockedNetworks - if any networks are configured, set AdBlockingEnabled to true
|
||||
if base.IsDefined(d.AdBlockedNetworks) {
|
||||
if ut.IsDefined(d.AdBlockedNetworks) {
|
||||
var adBlockedNetworks []string
|
||||
diags.Append(utils.ListElementsAs(d.AdBlockedNetworks, &adBlockedNetworks)...)
|
||||
diags.Append(ut.ListElementsAs(d.AdBlockedNetworks, &adBlockedNetworks)...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
@@ -221,9 +222,9 @@ func (d *ipsModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
}
|
||||
|
||||
// Handle DNSFilters - if any filters are configured, set DNSFiltering to true
|
||||
if base.IsDefined(d.DNSFilters) {
|
||||
if ut.IsDefined(d.DNSFilters) {
|
||||
var dnsFiltersObjects []DNSFilterModel
|
||||
diags.Append(utils.ListElementsAs(d.DNSFilters, &dnsFiltersObjects)...)
|
||||
diags.Append(ut.ListElementsAs(d.DNSFilters, &dnsFiltersObjects)...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
@@ -248,9 +249,9 @@ func (d *ipsModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
// Handle allowed sites
|
||||
|
||||
var allowedSites, blockedSites, blockedTlds []string
|
||||
diags.Append(utils.ListElementsAs(filterObj.AllowedSites, &allowedSites)...)
|
||||
diags.Append(utils.ListElementsAs(filterObj.BlockedSites, &blockedSites)...)
|
||||
diags.Append(utils.ListElementsAs(filterObj.BlockedTld, &blockedTlds)...)
|
||||
diags.Append(ut.ListElementsAs(filterObj.AllowedSites, &allowedSites)...)
|
||||
diags.Append(ut.ListElementsAs(filterObj.BlockedSites, &blockedSites)...)
|
||||
diags.Append(ut.ListElementsAs(filterObj.BlockedTld, &blockedTlds)...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
@@ -266,9 +267,9 @@ func (d *ipsModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
}
|
||||
|
||||
// Handle honeypot
|
||||
if base.IsDefined(d.Honeypots) {
|
||||
if ut.IsDefined(d.Honeypots) {
|
||||
var honeypotObjects []HoneypotModel
|
||||
diags.Append(utils.ListElementsAs(d.Honeypots, &honeypotObjects)...)
|
||||
diags.Append(ut.ListElementsAs(d.Honeypots, &honeypotObjects)...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
@@ -293,7 +294,7 @@ func (d *ipsModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
}
|
||||
|
||||
// Handle suppression
|
||||
if base.IsDefined(d.Suppression) {
|
||||
if ut.IsDefined(d.Suppression) {
|
||||
var suppressionObj SuppressionModel
|
||||
diags.Append(d.Suppression.As(ctx, &suppressionObj, basetypes.ObjectAsOptions{})...)
|
||||
if diags.HasError() {
|
||||
@@ -301,7 +302,7 @@ func (d *ipsModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
}
|
||||
|
||||
var alerts []AlertsModel
|
||||
diags.Append(utils.ListElementsAs(suppressionObj.Alerts, &alerts)...)
|
||||
diags.Append(ut.ListElementsAs(suppressionObj.Alerts, &alerts)...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
@@ -317,13 +318,13 @@ func (d *ipsModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
// Handle tracking
|
||||
|
||||
var trackings []TrackingModel
|
||||
diags.Append(utils.ListElementsAs(alertObj.Tracking, &trackings)...)
|
||||
diags.Append(ut.ListElementsAs(alertObj.Tracking, &trackings)...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
alert.Tracking = make([]unifi.SettingIpsTracking, 0)
|
||||
for _, trackingObj := range trackings {
|
||||
if base.IsEmptyString(trackingObj.Direction) || base.IsEmptyString(trackingObj.Mode) || base.IsEmptyString(trackingObj.Value) {
|
||||
if ut.IsEmptyString(trackingObj.Direction) || ut.IsEmptyString(trackingObj.Mode) || ut.IsEmptyString(trackingObj.Value) {
|
||||
continue
|
||||
}
|
||||
alert.Tracking = append(alert.Tracking, unifi.SettingIpsTracking{
|
||||
@@ -335,7 +336,7 @@ func (d *ipsModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
}
|
||||
|
||||
var whitelists []WhitelistModel
|
||||
diags.Append(utils.ListElementsAs(suppressionObj.Whitelist, &whitelists)...)
|
||||
diags.Append(ut.ListElementsAs(suppressionObj.Whitelist, &whitelists)...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
@@ -379,10 +380,10 @@ func (d *ipsModel) Merge(ctx context.Context, other interface{}) diag.Diagnostic
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
if base.IsDefined(enabledCategoriesList) {
|
||||
if ut.IsDefined(enabledCategoriesList) {
|
||||
d.EnabledCategories = enabledCategoriesList
|
||||
} else {
|
||||
d.EnabledCategories = utils.EmptyList(types.StringType)
|
||||
d.EnabledCategories = ut.EmptyList(types.StringType)
|
||||
}
|
||||
|
||||
// Handle enabled networks
|
||||
@@ -390,10 +391,10 @@ func (d *ipsModel) Merge(ctx context.Context, other interface{}) diag.Diagnostic
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
if base.IsDefined(enabledNetworksList) {
|
||||
if ut.IsDefined(enabledNetworksList) {
|
||||
d.EnabledNetworks = enabledNetworksList
|
||||
} else {
|
||||
d.EnabledNetworks = utils.EmptyList(types.StringType)
|
||||
d.EnabledNetworks = ut.EmptyList(types.StringType)
|
||||
}
|
||||
|
||||
//Handle AdBlockedNetworks - extract network IDs from AdBlockingConfigurations
|
||||
@@ -561,8 +562,8 @@ func (r *ipsResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "The `unifi_setting_ips` resource allows you to configure the Intrusion Prevention System (IPS) settings for your UniFi network. IPS provides network threat protection by monitoring, detecting, and preventing malicious traffic based on configured rules and policies. Requires controller version 7.4 or later",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"ad_blocked_networks": schema.ListAttribute{
|
||||
MarkdownDescription: "List of network IDs to enable ad blocking for. If any networks are configured, ad blocking will be automatically enabled. Each entry should be a valid network ID from your UniFi configuration. Leave empty to disable ad blocking.",
|
||||
ElementType: types.StringType,
|
||||
|
||||
@@ -2,6 +2,7 @@ package settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
|
||||
|
||||
@@ -102,8 +103,8 @@ func (r *lcmResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "Manages LCD Monitor (LCM) settings for UniFi devices with built-in displays, such as the UniFi Dream Machine Pro (UDM Pro) and UniFi Network Video Recorder (UNVR).",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"enabled": schema.BoolAttribute{
|
||||
MarkdownDescription: "Whether the LCD display is enabled.",
|
||||
Required: true,
|
||||
|
||||
@@ -2,6 +2,7 @@ package settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
@@ -59,8 +60,8 @@ func (r *localeResource) Schema(_ context.Context, _ resource.SchemaRequest, res
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "Manages locale settings for a UniFi site.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"timezone": schema.StringAttribute{
|
||||
Required: true,
|
||||
MarkdownDescription: "Timezone for the UniFi controller, e.g., `America/Los_Angeles`",
|
||||
|
||||
@@ -2,6 +2,7 @@ package settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
@@ -57,8 +58,8 @@ func (r *magicSiteToSiteVpnResource) Schema(_ context.Context, _ resource.Schema
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "Manages Magic Site to Site VPN settings for a UniFi site.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"enabled": schema.BoolAttribute{
|
||||
MarkdownDescription: "Whether the Magic Site to Site VPN is enabled.",
|
||||
Required: true,
|
||||
|
||||
@@ -3,6 +3,7 @@ package settings
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/int32validator"
|
||||
@@ -212,8 +213,8 @@ func (r *mgmtResource) Schema(_ context.Context, _ resource.SchemaRequest, resp
|
||||
" * Enabling secure remote administration\n" +
|
||||
" * Implementing SSH key-based authentication",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"auto_upgrade": schema.BoolAttribute{
|
||||
MarkdownDescription: "Enable automatic firmware upgrades for all UniFi devices at this site. When enabled, devices will automatically " +
|
||||
"update to the latest stable firmware version approved for your controller version.",
|
||||
|
||||
@@ -2,6 +2,7 @@ package settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
@@ -58,8 +59,8 @@ func (r *networkOptimizationResource) Schema(_ context.Context, _ resource.Schem
|
||||
MarkdownDescription: "Manages Network Optimization settings for a UniFi site. UniFi network optimization is a feature designed to automatically enhance the performance of a UniFi network" +
|
||||
" by making automatic adjustments to various settings such as channel selection, transmit power, or frequency usage",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"enabled": schema.BoolAttribute{
|
||||
MarkdownDescription: "Whether the Network Optimization is enabled.",
|
||||
Required: true,
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/resourcevalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
@@ -39,16 +40,16 @@ func (d *ntpModel) AsUnifiModel(_ context.Context) (interface{}, diag.Diagnostic
|
||||
model.NtpServer3 = ""
|
||||
model.NtpServer4 = ""
|
||||
} else {
|
||||
if !base.IsEmptyString(d.NtpServer1) {
|
||||
if !ut.IsEmptyString(d.NtpServer1) {
|
||||
model.NtpServer1 = d.NtpServer1.ValueString()
|
||||
}
|
||||
if !base.IsEmptyString(d.NtpServer2) {
|
||||
if !ut.IsEmptyString(d.NtpServer2) {
|
||||
model.NtpServer2 = d.NtpServer2.ValueString()
|
||||
}
|
||||
if !base.IsEmptyString(d.NtpServer3) {
|
||||
if !ut.IsEmptyString(d.NtpServer3) {
|
||||
model.NtpServer3 = d.NtpServer3.ValueString()
|
||||
}
|
||||
if !base.IsEmptyString(d.NtpServer4) {
|
||||
if !ut.IsEmptyString(d.NtpServer4) {
|
||||
model.NtpServer4 = d.NtpServer4.ValueString()
|
||||
}
|
||||
}
|
||||
@@ -115,8 +116,8 @@ func (r *ntpResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *
|
||||
MarkdownDescription: "The `unifi_setting_ntp` resource allows you to configure Network Time Protocol (NTP) server settings for your UniFi network.\n\n" +
|
||||
"NTP servers provide time synchronization for your network devices. This resource supports both automatic and manual NTP configuration modes.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"ntp_server_1": schema.StringAttribute{
|
||||
MarkdownDescription: "Primary NTP server hostname or IP address. Must be a valid hostname (e.g., `pool.ntp.org`) or IPv4 address. " +
|
||||
"Only applicable when `mode` is set to `manual`.",
|
||||
|
||||
@@ -2,8 +2,8 @@ package settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"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-validators/stringvalidator"
|
||||
|
||||
@@ -82,7 +82,7 @@ func (d *rsyslogdModel) AsUnifiModel(_ context.Context) (interface{}, diag.Diagn
|
||||
|
||||
if !d.Contents.IsNull() {
|
||||
var contents []string
|
||||
diags.Append(utils.ListElementsAs(d.Contents, &contents)...)
|
||||
diags.Append(ut.ListElementsAs(d.Contents, &contents)...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
@@ -133,7 +133,7 @@ func (d *rsyslogdModel) Merge(ctx context.Context, other interface{}) diag.Diagn
|
||||
d.Port = types.Int64Null()
|
||||
d.ThisController = types.BoolNull()
|
||||
d.ThisControllerEncryptedOnly = types.BoolNull()
|
||||
d.Contents = utils.EmptyList(types.StringType)
|
||||
d.Contents = ut.EmptyList(types.StringType)
|
||||
}
|
||||
|
||||
return diags
|
||||
@@ -178,8 +178,8 @@ func (r *rsyslogdResource) Schema(_ context.Context, _ resource.SchemaRequest, r
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "Manages Remote Syslog (rsyslogd) settings for UniFi devices. Controller version 8.5 or later is required.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"enabled": schema.BoolAttribute{
|
||||
MarkdownDescription: "Whether remote syslog is enabled.",
|
||||
Required: true,
|
||||
|
||||
@@ -2,6 +2,7 @@ package settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
@@ -59,8 +60,8 @@ func (r *sslInspectionResource) Schema(_ context.Context, _ resource.SchemaReque
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "Manages SSL Inspection settings for a UniFi site. SSL inspection is a security feature that allows the UniFi Security Gateway (USG) to inspect encrypted traffic for security threats.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"state": schema.StringAttribute{
|
||||
MarkdownDescription: "The mode of SSL inspection. Valid values are: `off`, `simple`, or `advanced`.",
|
||||
Required: true,
|
||||
|
||||
@@ -2,6 +2,7 @@ package settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
@@ -67,8 +68,8 @@ func (r *teleportResource) Schema(_ context.Context, _ resource.SchemaRequest, r
|
||||
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.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"enabled": schema.BoolAttribute{
|
||||
MarkdownDescription: "Whether Teleport is enabled.",
|
||||
Required: true,
|
||||
|
||||
@@ -2,6 +2,7 @@ package settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
|
||||
@@ -11,7 +12,6 @@ import (
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"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-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
@@ -206,7 +206,7 @@ func (d *usgModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
|
||||
// Extract DHCP relay servers from the list
|
||||
var dhcpRelayServers []string
|
||||
diags.Append(utils.ListElementsAs(d.DhcpRelayServers, &dhcpRelayServers)...)
|
||||
diags.Append(ut.ListElementsAs(d.DhcpRelayServers, &dhcpRelayServers)...)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
@@ -233,7 +233,7 @@ func (d *usgModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
// TODO end of deprecated
|
||||
|
||||
// Assign Geo IP filtering attributes
|
||||
if base.IsDefined(d.GeoIPFiltering) {
|
||||
if ut.IsDefined(d.GeoIPFiltering) {
|
||||
var geoIPFiltering *GeoIPFilteringModel
|
||||
diags.Append(d.GeoIPFiltering.As(ctx, &geoIPFiltering, basetypes.ObjectAsOptions{})...)
|
||||
if diags.HasError() {
|
||||
@@ -242,7 +242,7 @@ func (d *usgModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
|
||||
model.GeoIPFilteringBlock = geoIPFiltering.Mode.ValueString()
|
||||
model.GeoIPFilteringTrafficDirection = geoIPFiltering.TrafficDirection.ValueString()
|
||||
countries, diags := utils.ListElementsToString(ctx, geoIPFiltering.Countries)
|
||||
countries, diags := ut.ListElementsToString(ctx, geoIPFiltering.Countries)
|
||||
if diags.HasError() {
|
||||
return nil, diags
|
||||
}
|
||||
@@ -253,7 +253,7 @@ func (d *usgModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
}
|
||||
|
||||
// Assign UPNP attributes
|
||||
if base.IsDefined(d.Upnp) {
|
||||
if ut.IsDefined(d.Upnp) {
|
||||
var upnp *UpnpModel
|
||||
diags.Append(d.Upnp.As(ctx, &upnp, basetypes.ObjectAsOptions{})...)
|
||||
if diags.HasError() {
|
||||
@@ -268,7 +268,7 @@ func (d *usgModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
model.UpnpEnabled = false
|
||||
}
|
||||
|
||||
if base.IsDefined(d.TcpTimeouts) {
|
||||
if ut.IsDefined(d.TcpTimeouts) {
|
||||
var tcpTimeouts *TCPTimeoutModel
|
||||
diags.Append(d.TcpTimeouts.As(ctx, &tcpTimeouts, basetypes.ObjectAsOptions{})...)
|
||||
if diags.HasError() {
|
||||
@@ -286,7 +286,7 @@ func (d *usgModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
}
|
||||
|
||||
// Assign DNS Verification attributes
|
||||
if base.IsDefined(d.DnsVerification) {
|
||||
if ut.IsDefined(d.DnsVerification) {
|
||||
var dnsVerification *DNSVerificationModel
|
||||
diags.Append(d.DnsVerification.As(ctx, &dnsVerification, basetypes.ObjectAsOptions{})...)
|
||||
if diags.HasError() {
|
||||
@@ -301,7 +301,7 @@ func (d *usgModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnost
|
||||
}
|
||||
}
|
||||
|
||||
if base.IsDefined(d.DhcpRelay) {
|
||||
if ut.IsDefined(d.DhcpRelay) {
|
||||
var dhcpRelay *DHCPRelayModel
|
||||
diags.Append(d.DhcpRelay.As(ctx, &dhcpRelay, basetypes.ObjectAsOptions{})...)
|
||||
if diags.HasError() {
|
||||
@@ -365,7 +365,7 @@ func (d *usgModel) Merge(ctx context.Context, other interface{}) diag.Diagnostic
|
||||
TrafficDirection: types.StringValue(model.GeoIPFilteringTrafficDirection),
|
||||
}
|
||||
|
||||
countries, diags := utils.StringToListElements(ctx, model.GeoIPFilteringCountries)
|
||||
countries, diags := ut.StringToListElements(ctx, model.GeoIPFilteringCountries)
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
@@ -507,8 +507,8 @@ func (r *usgResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *
|
||||
" * MSS clamping for optimizing MTU issues\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+. Changes to certain attributes may not be reflected in the plan unless explicitly modified in the configuration.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.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, Apple devices, etc.) even when they are on different networks or VLANs. " +
|
||||
@@ -533,7 +533,7 @@ func (r *usgResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *
|
||||
PlanModifiers: []planmodifier.List{
|
||||
listplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
Default: utils.DefaultEmptyList(types.StringType),
|
||||
Default: ut.DefaultEmptyList(types.StringType),
|
||||
Validators: []validator.List{
|
||||
listvalidator.SizeAtMost(5),
|
||||
listvalidator.ValueStringsAre(validators.IPv4()),
|
||||
|
||||
@@ -2,6 +2,7 @@ package settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
@@ -57,8 +58,8 @@ func (r *uswResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "Manages UniFi Switch (USW) settings for a UniFi site. These settings control global switch behaviors such as DHCP snooping.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site": base.SiteAttribute(),
|
||||
"id": ut.ID(),
|
||||
"site": ut.SiteAttribute(),
|
||||
"dhcp_snoop": schema.BoolAttribute{
|
||||
MarkdownDescription: "Whether DHCP snooping is enabled. DHCP snooping is a security feature that filters untrusted DHCP messages and builds a binding database of valid hosts.",
|
||||
Required: true,
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package testing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-testing/plancheck"
|
||||
"github.com/hashicorp/terraform-plugin-testing/terraform"
|
||||
@@ -67,8 +71,8 @@ func SiteAndIDImportStateIDFunc(resourceName string) func(*terraform.State) (str
|
||||
// PreCheck checks if provided environment variables are set. If not, it will fail the test.
|
||||
func PreCheck(t *testing.T) {
|
||||
variables := []string{
|
||||
//"UNIFI_USERNAME",
|
||||
//"UNIFI_PASSWORD",
|
||||
"UNIFI_USERNAME",
|
||||
"UNIFI_PASSWORD",
|
||||
"UNIFI_API",
|
||||
}
|
||||
|
||||
@@ -109,3 +113,28 @@ func SkipIfEnvLocalMissing(t *testing.T, msg string) {
|
||||
t.Helper()
|
||||
SkipIfEnvMissing(t, msg, TfAccLocal)
|
||||
}
|
||||
|
||||
func CheckDestroy(resourceType string, read func(ctx context.Context, site, id string) error) func(s *terraform.State) error {
|
||||
return func(s *terraform.State) error {
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type == "" || rs.Type != resourceType {
|
||||
continue
|
||||
}
|
||||
site := "default"
|
||||
if s, ok := rs.Primary.Attributes["site"]; ok {
|
||||
if s != "" {
|
||||
site = s
|
||||
}
|
||||
}
|
||||
err := read(context.Background(), site, rs.Primary.ID)
|
||||
if err == nil {
|
||||
return fmt.Errorf("Resource with id %q still exists.", rs.Primary.ID)
|
||||
}
|
||||
if utils.IsServerErrorStatusCode(err, 404) || errors.Is(err, unifi.ErrNotFound) {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package base
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
|
||||
// ID generates an attribute definition suitable for the always-present `id` attribute.
|
||||
@@ -37,21 +35,7 @@ func SiteAttribute(desc ...string) schema.StringAttribute {
|
||||
}
|
||||
|
||||
if len(desc) > 0 {
|
||||
s.Description = desc[0]
|
||||
s.MarkdownDescription = desc[0]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// ShouldBeRemoved evaluates if an attribute should be removed from the plan during update.
|
||||
func ShouldBeRemoved(plan attr.Value, state attr.Value, isClone bool) bool {
|
||||
return !IsDefined(plan) && IsDefined(state) && !isClone
|
||||
}
|
||||
|
||||
// IsDefined returns true if attribute is known and not null.
|
||||
func IsDefined(v attr.Value) bool {
|
||||
return !v.IsNull() && !v.IsUnknown()
|
||||
}
|
||||
|
||||
func IsEmptyString(s types.String) bool {
|
||||
return s.IsNull() || s.IsUnknown() || s.ValueString() == ""
|
||||
}
|
||||
59
internal/provider/types/lists.go
Normal file
59
internal/provider/types/lists.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/defaults"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
|
||||
func DefaultEmptyList(elementType attr.Type) defaults.List {
|
||||
return listdefault.StaticValue(EmptyList(elementType))
|
||||
}
|
||||
|
||||
func EmptyList(elementType attr.Type) types.List {
|
||||
return types.ListValueMust(elementType, []attr.Value{})
|
||||
}
|
||||
|
||||
func ListElementsAs(list types.List, target interface{}) diag.Diagnostics {
|
||||
diags := diag.Diagnostics{}
|
||||
if !IsDefined(list) {
|
||||
return diags
|
||||
}
|
||||
if diagErr := list.ElementsAs(context.Background(), target, false); diagErr != nil {
|
||||
diags = append(diags, diagErr...)
|
||||
}
|
||||
return diags
|
||||
}
|
||||
|
||||
func ListElementsToString(ctx context.Context, list types.List) (string, diag.Diagnostics) {
|
||||
diags := diag.Diagnostics{}
|
||||
if !IsDefined(list) {
|
||||
return "", diags
|
||||
}
|
||||
if list.ElementType(ctx) == types.StringType {
|
||||
var target []string
|
||||
diags.Append(ListElementsAs(list, &target)...)
|
||||
if diags.HasError() {
|
||||
return "", diags
|
||||
}
|
||||
return utils.JoinNonEmpty(target, ","), diags
|
||||
}
|
||||
diags.AddError("List is not a list of types.StringType", "List is not a list of strings")
|
||||
return "", diags
|
||||
}
|
||||
|
||||
func StringToListElements(ctx context.Context, value string) (types.List, diag.Diagnostics) {
|
||||
countries := utils.SplitAndTrim(value, ",")
|
||||
if len(countries) == 0 {
|
||||
return types.ListNull(types.StringType), diag.Diagnostics{}
|
||||
}
|
||||
list, diags := types.ListValueFrom(ctx, types.StringType, countries)
|
||||
if diags.HasError() {
|
||||
return types.ListNull(types.StringType), diags
|
||||
}
|
||||
return list, diags
|
||||
}
|
||||
47
internal/provider/types/objects.go
Normal file
47
internal/provider/types/objects.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type NestedObject interface {
|
||||
AttributeTypes() map[string]attr.Type
|
||||
}
|
||||
|
||||
func ObjectNull(obj interface{}) (basetypes.ObjectValue, diag.Diagnostics) {
|
||||
diags := diag.Diagnostics{}
|
||||
if nested, ok := obj.(NestedObject); ok {
|
||||
obj := types.ObjectNull(nested.AttributeTypes())
|
||||
return obj, diags
|
||||
}
|
||||
diags.AddError("Invalid object type", fmt.Sprintf("Expected NestedObject, got: %T", obj))
|
||||
return types.ObjectNull(map[string]attr.Type{}), diags
|
||||
}
|
||||
|
||||
func ObjectValueMust(ctx context.Context, obj interface{}) basetypes.ObjectValue {
|
||||
if nested, ok := obj.(NestedObject); ok {
|
||||
val, diags := types.ObjectValueFrom(ctx, nested.AttributeTypes(), obj)
|
||||
if diags.HasError() {
|
||||
// This could potentially be added to the diag package.
|
||||
diagsStrings := make([]string, 0, len(diags))
|
||||
|
||||
for _, diagnostic := range diags {
|
||||
diagsStrings = append(diagsStrings, fmt.Sprintf(
|
||||
"%s | %s | %s",
|
||||
diagnostic.Severity(),
|
||||
diagnostic.Summary(),
|
||||
diagnostic.Detail()))
|
||||
}
|
||||
|
||||
panic("ObjectValueMust received error(s): " + strings.Join(diagsStrings, "\n"))
|
||||
}
|
||||
return val
|
||||
}
|
||||
panic(fmt.Sprintf("ObjectValueMust received invalid object type. Expected NestedObject, got: %T", obj))
|
||||
}
|
||||
20
internal/provider/types/utils.go
Normal file
20
internal/provider/types/utils.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
|
||||
// ShouldBeRemoved evaluates if an attribute should be removed from the plan during update.
|
||||
func ShouldBeRemoved(plan attr.Value, state attr.Value, isClone bool) bool {
|
||||
return !IsDefined(plan) && IsDefined(state) && !isClone
|
||||
}
|
||||
|
||||
// IsDefined returns true if attribute is known and not null.
|
||||
func IsDefined(v attr.Value) bool {
|
||||
return !v.IsNull() && !v.IsUnknown()
|
||||
}
|
||||
|
||||
func IsEmptyString(s types.String) bool {
|
||||
return s.IsNull() || s.IsUnknown() || s.ValueString() == ""
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package user
|
||||
import (
|
||||
"context"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
|
||||
@@ -3,10 +3,10 @@ package user
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
"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"
|
||||
@@ -163,7 +163,7 @@ func resourceUserCreate(ctx context.Context, d *schema.ResourceData, meta interf
|
||||
|
||||
resp, err := c.CreateUser(ctx, site, req)
|
||||
if err != nil {
|
||||
if !base.IsServerErrorContains(err, "api.err.MacUsed") || !allowExisting {
|
||||
if !utils.IsServerErrorContains(err, "api.err.MacUsed") || !allowExisting {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
|
||||
82
internal/provider/utils/cidr.go
Normal file
82
internal/provider/utils/cidr.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func CidrValidate(raw interface{}, key string) ([]string, []error) {
|
||||
v, ok := raw.(string)
|
||||
if !ok {
|
||||
return nil, []error{fmt.Errorf("expected string, got %T", raw)}
|
||||
}
|
||||
|
||||
_, _, err := net.ParseCIDR(v)
|
||||
if err != nil {
|
||||
return nil, []error{err}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func CidrZeroBased(cidr string) string {
|
||||
_, cidrNet, err := net.ParseCIDR(cidr)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return cidrNet.String()
|
||||
}
|
||||
|
||||
func CidrOneBased(cidr string) string {
|
||||
_, cidrNet, err := net.ParseCIDR(cidr)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
cidrNet.IP[3]++
|
||||
|
||||
return cidrNet.String()
|
||||
}
|
||||
|
||||
func CidrDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
|
||||
_, oldNet, err := net.ParseCIDR(old)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
_, newNet, err := net.ParseCIDR(new)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return oldNet.String() == newNet.String()
|
||||
}
|
||||
|
||||
// IsIPv4 checks if the provided address is a valid IPv4 address.
|
||||
// It returns true if the address is a valid IPv4 address, false otherwise.
|
||||
func IsIPv4(address string) bool {
|
||||
ip := net.ParseIP(address)
|
||||
return ip != nil && ip.To4() != nil
|
||||
}
|
||||
|
||||
// IsIPv6 checks if the provided address is a valid IPv6 address.
|
||||
// It returns true if the address is a valid IPv6 address, false otherwise.
|
||||
func IsIPv6(address string) bool {
|
||||
|
||||
// Handle zone index if present
|
||||
if idx := strings.Index(address, "%"); idx != -1 {
|
||||
address = address[:idx]
|
||||
}
|
||||
|
||||
// Handle IPv4-mapped addresses
|
||||
isIPv4Mapped := strings.Contains(address, "::ffff:") && strings.Count(address, ".") == 3
|
||||
|
||||
ip := net.ParseIP(address)
|
||||
if ip == nil || (!isIPv4Mapped && ip.To4() != nil) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
37
internal/provider/utils/cidr_test.go
Normal file
37
internal/provider/utils/cidr_test.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCIDRValidate(t *testing.T) {
|
||||
for _, c := range []struct {
|
||||
expectedError string
|
||||
cidr string
|
||||
}{
|
||||
{"invalid CIDR address: ", ""},
|
||||
{"invalid CIDR address: abc", "abc"},
|
||||
{"invalid CIDR address: 192.1.2.3", "192.1.2.3"},
|
||||
{"invalid CIDR address: 500.1.2.3/20", "500.1.2.3/20"},
|
||||
{"invalid CIDR address: 192.1.2.3/500", "192.1.2.3/500"},
|
||||
|
||||
{"", "192.1.2.1/20"},
|
||||
} {
|
||||
t.Run(c.cidr, func(t *testing.T) {
|
||||
_, actualErrs := CidrValidate(c.cidr, "key")
|
||||
switch len(actualErrs) {
|
||||
case 0:
|
||||
if c.expectedError != "" {
|
||||
t.Fatalf("expected no error, got %d: %#v", len(actualErrs), actualErrs)
|
||||
}
|
||||
case 1:
|
||||
actualErr := actualErrs[0].Error()
|
||||
if actualErr != c.expectedError {
|
||||
t.Fatalf("expected %q, got %q", c.expectedError, actualErr)
|
||||
}
|
||||
default:
|
||||
t.Fatalf("expected 0 or 1 errors, got %d: %#v", len(actualErrs), actualErrs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
50
internal/provider/utils/env.go
Normal file
50
internal/provider/utils/env.go
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// GetAnyStringEnv returns the first non-empty string value from the environment variables.
|
||||
func GetAnyStringEnv(ks ...string) string {
|
||||
for _, k := range ks {
|
||||
if v := os.Getenv(k); v != "" {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetAnyBoolEnv returns the first non-empty boolean value from the environment variables.
|
||||
func GetAnyBoolEnv(ks ...string) bool {
|
||||
val := ""
|
||||
|
||||
for _, k := range ks {
|
||||
if v := os.Getenv(k); v != "" {
|
||||
val = v
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return val == "true" || val == "1"
|
||||
}
|
||||
|
||||
// GetAnyIntEnv returns the first non-empty integer value from the environment variables.
|
||||
func GetAnyIntEnv(ks ...string) int {
|
||||
for _, k := range ks {
|
||||
if v := os.Getenv(k); v != "" {
|
||||
if i, err := strconv.Atoi(v); err == nil {
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package base
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
19
internal/provider/utils/mac.go
Normal file
19
internal/provider/utils/mac.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var MacAddressRegexp = regexp.MustCompile("^([0-9a-fA-F][0-9a-fA-F][-:]){5}([0-9a-fA-F][0-9a-fA-F])$")
|
||||
|
||||
func CleanMAC(mac string) string {
|
||||
return strings.TrimSpace(strings.ReplaceAll(strings.ToLower(mac), "-", ":"))
|
||||
}
|
||||
|
||||
func MacDiffSuppressFunc(k, old, new string, d *schema.ResourceData) bool {
|
||||
old = CleanMAC(old)
|
||||
new = CleanMAC(new)
|
||||
return old == new
|
||||
}
|
||||
27
internal/provider/utils/markdown.go
Normal file
27
internal/provider/utils/markdown.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package utils
|
||||
|
||||
import "strconv"
|
||||
|
||||
func MarkdownValueList[T any](strMapper func(T) string, values []T) string {
|
||||
switch {
|
||||
case len(values) == 0:
|
||||
return ""
|
||||
case len(values) == 1:
|
||||
return "`" + strMapper(values[0]) + "`"
|
||||
default:
|
||||
s := ""
|
||||
for i := 0; i < len(values)-1; i++ {
|
||||
s += "`" + strMapper(values[i]) + "`, "
|
||||
}
|
||||
s += " and `" + strMapper(values[len(values)-1]) + "`"
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
func MarkdownValueListInt(values []int) string {
|
||||
return MarkdownValueList(func(i int) string { return strconv.Itoa(i) }, values)
|
||||
}
|
||||
|
||||
func MarkdownValueListString(values []string) string {
|
||||
return MarkdownValueList(func(s string) string { return s }, values)
|
||||
}
|
||||
84
internal/provider/utils/strings.go
Normal file
84
internal/provider/utils/strings.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
func ListToStringSlice(src []interface{}) ([]string, error) {
|
||||
dst := make([]string, 0, len(src))
|
||||
for _, s := range src {
|
||||
d, ok := s.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unale to convert %v (%T) to string", s, s)
|
||||
}
|
||||
dst = append(dst, d)
|
||||
}
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
func SetToStringSlice(src *schema.Set) ([]string, error) {
|
||||
return ListToStringSlice(src.List())
|
||||
}
|
||||
|
||||
func StringSliceToList(list []string) []interface{} {
|
||||
vs := make([]interface{}, 0, len(list))
|
||||
for _, v := range list {
|
||||
vs = append(vs, v)
|
||||
}
|
||||
return vs
|
||||
}
|
||||
|
||||
func StringSliceToSet(src []string) *schema.Set {
|
||||
return schema.NewSet(schema.HashString, StringSliceToList(src))
|
||||
}
|
||||
|
||||
func IsStringValueNotEmpty(s basetypes.StringValue) bool {
|
||||
return !s.IsUnknown() && !s.IsNull() && s.ValueString() != ""
|
||||
}
|
||||
|
||||
// JoinNonEmpty joins non-empty strings from a slice with the specified separator.
|
||||
// Empty strings in the slice are filtered out.
|
||||
func JoinNonEmpty(elements []string, separator string) string {
|
||||
var nonEmpty []string
|
||||
for _, elem := range elements {
|
||||
if elem != "" {
|
||||
nonEmpty = append(nonEmpty, elem)
|
||||
}
|
||||
}
|
||||
return strings.Join(nonEmpty, separator)
|
||||
}
|
||||
|
||||
// SplitAndTrim splits a string by the specified separator and trims whitespace from each element.
|
||||
// Empty strings after trimming are filtered out.
|
||||
func SplitAndTrim(s string, separator string) []string {
|
||||
if s == "" {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
parts := strings.Split(s, separator)
|
||||
var result []string
|
||||
|
||||
for _, part := range parts {
|
||||
trimmed := strings.TrimSpace(part)
|
||||
if trimmed != "" {
|
||||
result = append(result, trimmed)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func RemoveElements[S ~[]E, E comparable](first S, second S) S {
|
||||
var result S
|
||||
for _, category := range first {
|
||||
if !slices.Contains(second, category) {
|
||||
result = append(result, category)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -30,15 +30,15 @@ type cidrValidator struct {
|
||||
allowEmpty bool
|
||||
}
|
||||
|
||||
func (v cidrValidator) Description(ctx context.Context) string {
|
||||
func (v cidrValidator) Description(_ context.Context) string {
|
||||
return "value must be a valid CIDR notation (e.g., '192.168.1.0/24')"
|
||||
}
|
||||
|
||||
func (v cidrValidator) MarkdownDescription(ctx context.Context) string {
|
||||
func (v cidrValidator) MarkdownDescription(_ context.Context) string {
|
||||
return "value must be a valid CIDR notation (e.g., `192.168.1.0/24`)"
|
||||
}
|
||||
|
||||
func (v cidrValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
|
||||
func (v cidrValidator) ValidateString(_ context.Context, req validator.StringRequest, resp *validator.StringResponse) {
|
||||
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package validators
|
||||
import (
|
||||
"context"
|
||||
"github.com/biter777/countries"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
)
|
||||
@@ -24,7 +24,7 @@ func (c countryCodeAlpha2Validator) MarkdownDescription(ctx context.Context) str
|
||||
|
||||
func (c countryCodeAlpha2Validator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
|
||||
code := req.ConfigValue
|
||||
if base.IsEmptyString(code) {
|
||||
if types.IsEmptyString(code) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package validators
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
)
|
||||
|
||||
// A common regex pattern for validating email addresses
|
||||
// This is a simplified version and may not catch all edge cases
|
||||
var emailRegex = regexp.MustCompile(`^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`)
|
||||
|
||||
// Email returns a validator which ensures that the string value is a valid email address.
|
||||
func Email() validator.String {
|
||||
return emailValidator{}
|
||||
}
|
||||
|
||||
type emailValidator struct{}
|
||||
|
||||
func (v emailValidator) Description(_ context.Context) string {
|
||||
return "must be a valid email address"
|
||||
}
|
||||
|
||||
func (v emailValidator) MarkdownDescription(ctx context.Context) string {
|
||||
return v.Description(ctx)
|
||||
}
|
||||
|
||||
func (v emailValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
|
||||
value := req.ConfigValue
|
||||
if !base.IsDefined(value) {
|
||||
return
|
||||
}
|
||||
|
||||
val := value.ValueString()
|
||||
if !emailRegex.MatchString(val) {
|
||||
resp.Diagnostics.Append(
|
||||
validatordiag.InvalidAttributeValueDiagnostic(
|
||||
req.Path,
|
||||
v.Description(ctx),
|
||||
fmt.Sprintf("%q is not a valid email address", val),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package validators_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
|
||||
func TestEmailValidator(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type testCase struct {
|
||||
val types.String
|
||||
expectError bool
|
||||
}
|
||||
tests := map[string]testCase{
|
||||
"unknown": {
|
||||
val: types.StringUnknown(),
|
||||
},
|
||||
"null": {
|
||||
val: types.StringNull(),
|
||||
},
|
||||
"valid-simple": {
|
||||
val: types.StringValue("test@example.com"),
|
||||
},
|
||||
"valid-with-dots": {
|
||||
val: types.StringValue("john.doe@example.com"),
|
||||
},
|
||||
"valid-with-plus": {
|
||||
val: types.StringValue("john+test@example.com"),
|
||||
},
|
||||
"valid-with-subdomain": {
|
||||
val: types.StringValue("john@sub.example.com"),
|
||||
},
|
||||
"valid-with-numbers": {
|
||||
val: types.StringValue("user123@example.com"),
|
||||
},
|
||||
"invalid-no-at": {
|
||||
val: types.StringValue("testexample.com"),
|
||||
expectError: true,
|
||||
},
|
||||
"invalid-no-domain": {
|
||||
val: types.StringValue("test@"),
|
||||
expectError: true,
|
||||
},
|
||||
"invalid-no-tld": {
|
||||
val: types.StringValue("test@example"),
|
||||
expectError: true,
|
||||
},
|
||||
"invalid-space": {
|
||||
val: types.StringValue("test user@example.com"),
|
||||
expectError: true,
|
||||
},
|
||||
"invalid-special-chars": {
|
||||
val: types.StringValue("test*user@example.com"),
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
name, test := name, test
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
request := validator.StringRequest{
|
||||
ConfigValue: test.val,
|
||||
}
|
||||
response := validator.StringResponse{}
|
||||
validators.Email().ValidateString(context.Background(), request, &response)
|
||||
|
||||
if !response.Diagnostics.HasError() && test.expectError {
|
||||
t.Fatal("expected error, got no error")
|
||||
}
|
||||
|
||||
if response.Diagnostics.HasError() && !test.expectError {
|
||||
t.Fatalf("got unexpected error: %s", response.Diagnostics)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package validators
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
)
|
||||
|
||||
var hexColorRegex = regexp.MustCompile("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$")
|
||||
|
||||
// HexColor returns a validator which ensures that the string value is a valid hex color code.
|
||||
// Valid formats are: #RGB or #RRGGBB
|
||||
func HexColor() validator.String {
|
||||
return hexColorValidator{}
|
||||
}
|
||||
|
||||
type hexColorValidator struct{}
|
||||
|
||||
func (v hexColorValidator) Description(_ context.Context) string {
|
||||
return "must be a valid hex color code (e.g., #FFF or #FFFFFF)"
|
||||
}
|
||||
|
||||
func (v hexColorValidator) MarkdownDescription(ctx context.Context) string {
|
||||
return v.Description(ctx)
|
||||
}
|
||||
|
||||
func (v hexColorValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
|
||||
value := req.ConfigValue
|
||||
if !base.IsDefined(value) {
|
||||
return
|
||||
}
|
||||
|
||||
val := value.ValueString()
|
||||
if !hexColorRegex.MatchString(val) {
|
||||
resp.Diagnostics.Append(
|
||||
validatordiag.InvalidAttributeValueDiagnostic(
|
||||
req.Path,
|
||||
v.Description(ctx),
|
||||
fmt.Sprintf("%q is not a valid hex color code", val),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
package validators_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
|
||||
func TestHexColorValidator(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type testCase struct {
|
||||
val types.String
|
||||
expectError bool
|
||||
}
|
||||
tests := map[string]testCase{
|
||||
"unknown": {
|
||||
val: types.StringUnknown(),
|
||||
},
|
||||
"null": {
|
||||
val: types.StringNull(),
|
||||
},
|
||||
"valid-6-digits": {
|
||||
val: types.StringValue("#123456"),
|
||||
},
|
||||
"valid-3-digits": {
|
||||
val: types.StringValue("#123"),
|
||||
},
|
||||
"valid-uppercase": {
|
||||
val: types.StringValue("#ABCDEF"),
|
||||
},
|
||||
"valid-mixed-case": {
|
||||
val: types.StringValue("#aBcDeF"),
|
||||
},
|
||||
"invalid-missing-hash": {
|
||||
val: types.StringValue("123456"),
|
||||
expectError: true,
|
||||
},
|
||||
"invalid-too-short": {
|
||||
val: types.StringValue("#12"),
|
||||
expectError: true,
|
||||
},
|
||||
"invalid-too-long": {
|
||||
val: types.StringValue("#1234567"),
|
||||
expectError: true,
|
||||
},
|
||||
"invalid-wrong-chars": {
|
||||
val: types.StringValue("#12345G"),
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
name, test := name, test
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
request := validator.StringRequest{
|
||||
ConfigValue: test.val,
|
||||
}
|
||||
response := validator.StringResponse{}
|
||||
validators.HexColor().ValidateString(context.Background(), request, &response)
|
||||
|
||||
if !response.Diagnostics.HasError() && test.expectError {
|
||||
t.Fatal("expected error, got no error")
|
||||
}
|
||||
|
||||
if response.Diagnostics.HasError() && !test.expectError {
|
||||
t.Fatalf("got unexpected error: %s", response.Diagnostics)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,10 @@ package validators
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
)
|
||||
@@ -32,7 +32,7 @@ func (v hostnameValidator) MarkdownDescription(ctx context.Context) string {
|
||||
|
||||
func (v hostnameValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
|
||||
value := req.ConfigValue
|
||||
if !base.IsDefined(value) {
|
||||
if !types.IsDefined(value) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package validators
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package validators
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/utils"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/utils"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
)
|
||||
|
||||
|
||||
1
internal/provider/validators/port_range.go
Normal file
1
internal/provider/validators/port_range.go
Normal file
@@ -0,0 +1 @@
|
||||
package validators
|
||||
27
internal/provider/validators/regex.go
Normal file
27
internal/provider/validators/regex.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package validators
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var (
|
||||
TimeFormatRegex = regexp.MustCompile(`^[0-9][0-9]:[0-9][0-9]$`)
|
||||
TimeFormat = stringvalidator.RegexMatches(TimeFormatRegex, "must be a valid time in 24-hour format (HH:MM)")
|
||||
|
||||
DateFormatRegex = regexp.MustCompile(`^(20[0-9]{2})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$`)
|
||||
DateFormat = stringvalidator.RegexMatches(DateFormatRegex, "must be a valid date in the format YYYY-MM-DD")
|
||||
|
||||
PortRangeRegexp = regexp.MustCompile("(([1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-4][0-9]{2}|[6][5][5][0-2][0-9]|[6][5][5][3][0-5])|([1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-4][0-9]{2}|[6][5][5][0-2][0-9]|[6][5][5][3][0-5])-([1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-4][0-9]{2}|[6][5][5][0-2][0-9]|[6][5][5][3][0-5]))+(,([1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-4][0-9]{2}|[6][5][5][0-2][0-9]|[6][5][5][3][0-5])|,([1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-4][0-9]{2}|[6][5][5][0-2][0-9]|[6][5][5][3][0-5])-([1-9][0-9]{0,3}|[1-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-4][0-9]{2}|[6][5][5][0-2][0-9]|[6][5][5][3][0-5])){0,14}")
|
||||
PortRangeV2 = validation.StringMatch(PortRangeRegexp, "invalid port range")
|
||||
|
||||
MacRegex = regexp.MustCompile(`^([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$`)
|
||||
Mac = stringvalidator.RegexMatches(MacRegex, "invalid MAC address")
|
||||
|
||||
HexColorRegex = regexp.MustCompile("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$")
|
||||
HexColor = stringvalidator.RegexMatches(HexColorRegex, "invalid hex color code")
|
||||
|
||||
EmailRegex = regexp.MustCompile(`^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`)
|
||||
Email = stringvalidator.RegexMatches(EmailRegex, "invalid email address")
|
||||
)
|
||||
@@ -3,6 +3,7 @@ package validators
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
@@ -182,6 +183,33 @@ func RequiredTogetherIf(conditionPath path.Expression, conditionValue attr.Value
|
||||
}
|
||||
}
|
||||
|
||||
func mapPathToExpression(p string) path.Expression {
|
||||
parts := strings.Split(p, ".")
|
||||
root := parts[0]
|
||||
exp := path.MatchRoot(root)
|
||||
for _, part := range parts[1:] {
|
||||
exp = exp.AtName(part)
|
||||
}
|
||||
return exp
|
||||
}
|
||||
|
||||
func mapPathsToExpressions(paths ...string) []path.Expression {
|
||||
var expressions []path.Expression
|
||||
for _, p := range paths {
|
||||
expressions = append(expressions, mapPathToExpression(p))
|
||||
}
|
||||
return expressions
|
||||
}
|
||||
|
||||
func RequiredSimpleTogetherIf(conditionPath string, conditionValue attr.Value, targetExpressions ...string) RequiredTogetherIfValidator {
|
||||
return RequiredTogetherIfValidator{
|
||||
ConditionPath: mapPathToExpression(conditionPath),
|
||||
ConditionValue: conditionValue,
|
||||
TargetExpressions: mapPathsToExpressions(targetExpressions...),
|
||||
CheckOnlyIfSet: false,
|
||||
}
|
||||
}
|
||||
|
||||
// RequiredTogetherIfSet creates a validator that ensures a set of target attributes
|
||||
// are configured together if a condition attribute is set (not null), regardless of its value.
|
||||
func RequiredTogetherIfSet(conditionPath path.Expression, targetExpressions ...path.Expression) RequiredTogetherIfValidator {
|
||||
|
||||
@@ -3,7 +3,7 @@ package validators
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
)
|
||||
@@ -41,7 +41,7 @@ func (v stringLengthExactlyValidator) ValidateString(ctx context.Context, req va
|
||||
}
|
||||
|
||||
value := req.ConfigValue
|
||||
if !base.IsDefined(value) {
|
||||
if !types.IsDefined(value) {
|
||||
return
|
||||
}
|
||||
val := value.ValueString()
|
||||
|
||||
@@ -3,10 +3,10 @@ package validators
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
)
|
||||
@@ -29,7 +29,7 @@ func (v timezoneValidator) MarkdownDescription(ctx context.Context) string {
|
||||
|
||||
func (v timezoneValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
|
||||
value := req.ConfigValue
|
||||
if !base.IsDefined(value) {
|
||||
if !types.IsDefined(value) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@ package validators
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
||||
"net/url"
|
||||
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||
)
|
||||
@@ -37,7 +37,7 @@ func (v urlValidator) MarkdownDescription(ctx context.Context) string {
|
||||
|
||||
func (v urlValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
|
||||
value := req.ConfigValue
|
||||
if !base.IsDefined(value) {
|
||||
if !types.IsDefined(value) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user