179 lines
6.4 KiB
Go
179 lines
6.4 KiB
Go
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"
|
|
"github.com/hashicorp/terraform-plugin-framework/path"
|
|
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
|
|
"strings"
|
|
)
|
|
|
|
func AsVersion(versionString string) *version.Version {
|
|
return version.Must(version.NewVersion(versionString))
|
|
}
|
|
|
|
// TODO remove this legacy
|
|
var (
|
|
ControllerV6 = AsVersion("6.0.0")
|
|
ControllerV7 = AsVersion("7.0.0")
|
|
ControllerV8 = AsVersion("8.0.0")
|
|
ControllerV9 = AsVersion("9.0.0")
|
|
ControllerVersionApiKeyAuth = AsVersion("9.0.108")
|
|
// https://community.ui.com/releases/UniFi-Network-Application-8-2-93/fce86dc6-897a-4944-9c53-1eec7e37e738
|
|
ControllerVersionDnsRecords = AsVersion("8.2.93")
|
|
|
|
// https://community.ui.com/releases/UniFi-Network-Controller-6-1-61/62f1ad38-1ac5-430c-94b0-becbb8f71d7d
|
|
ControllerVersionWPA3 = AsVersion("6.1.61")
|
|
)
|
|
|
|
func (c *Client) SupportsApiKeyAuthentication() bool {
|
|
return c.Version.GreaterThanOrEqual(ControllerVersionApiKeyAuth)
|
|
}
|
|
|
|
func (c *Client) SupportsWPA3() bool {
|
|
return c.Version.GreaterThanOrEqual(ControllerVersionWPA3)
|
|
}
|
|
|
|
func (c *Client) SupportsDnsRecords() bool {
|
|
return c.Version.GreaterThanOrEqual(ControllerVersionDnsRecords)
|
|
}
|
|
|
|
func CheckMinimumControllerVersion(versionString string) error {
|
|
v, err := version.NewVersion(versionString)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if v.LessThan(ControllerV6) {
|
|
return fmt.Errorf("Controller version %q or greater is required to use the provider, found %q.", ControllerV6, v)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// TODO remove until here
|
|
|
|
// ControllerVersionValidator is a validator that checks if the UniFi controller version
|
|
// matches the specified constraints.
|
|
type ControllerVersionValidator interface {
|
|
RequireMinVersion(min string) diag.Diagnostics
|
|
RequireMaxVersion(max string) diag.Diagnostics
|
|
RequireVersionBetween(min, max string) diag.Diagnostics
|
|
RequireMinVersionForPath(min string, attrPath path.Path, config tfsdk.Config) diag.Diagnostics
|
|
RequireMaxVersionForPath(max string, attrPath path.Path, config tfsdk.Config) diag.Diagnostics
|
|
RequireVersionBetweenForPath(min, max string, attrPath path.Path, config tfsdk.Config) diag.Diagnostics
|
|
}
|
|
|
|
var _ ControllerVersionValidator = &controllerVersionValidator{}
|
|
|
|
func NewControllerVersionValidator(client *Client) ControllerVersionValidator {
|
|
return &controllerVersionValidator{client: client}
|
|
}
|
|
|
|
type controllerVersionValidator struct {
|
|
client *Client
|
|
}
|
|
|
|
func (v controllerVersionValidator) RequireMinVersion(min string) diag.Diagnostics {
|
|
return v.requireVersion(minVersionRequirement(min), nil)
|
|
}
|
|
|
|
func (v controllerVersionValidator) RequireMaxVersion(max string) diag.Diagnostics {
|
|
return v.requireVersion(maxVersionRequirement(max), nil)
|
|
}
|
|
|
|
func (v controllerVersionValidator) RequireVersionBetween(min, max string) diag.Diagnostics {
|
|
return v.requireVersion(versionBetweenRequirement(min, max), nil)
|
|
}
|
|
|
|
func (v controllerVersionValidator) RequireMinVersionForPath(min string, attrPath path.Path, config tfsdk.Config) diag.Diagnostics {
|
|
return v.requireVersionForPath(minVersionRequirement(min), attrPath, config)
|
|
}
|
|
|
|
func (v controllerVersionValidator) RequireMaxVersionForPath(max string, attrPath path.Path, config tfsdk.Config) diag.Diagnostics {
|
|
return v.requireVersionForPath(maxVersionRequirement(max), attrPath, config)
|
|
}
|
|
|
|
func (v controllerVersionValidator) RequireVersionBetweenForPath(min, max string, attrPath path.Path, config tfsdk.Config) diag.Diagnostics {
|
|
return v.requireVersionForPath(versionBetweenRequirement(min, max), attrPath, config)
|
|
}
|
|
|
|
func minVersionRequirement(min string) versionRequirement {
|
|
return versionRequirement{minVersion: AsVersion(min)}
|
|
}
|
|
|
|
func maxVersionRequirement(max string) versionRequirement {
|
|
return versionRequirement{maxVersion: AsVersion(max)}
|
|
}
|
|
|
|
func versionBetweenRequirement(min, max string) versionRequirement {
|
|
return versionRequirement{minVersion: AsVersion(min), maxVersion: AsVersion(max)}
|
|
}
|
|
|
|
type versionRequirement struct {
|
|
minVersion *version.Version
|
|
maxVersion *version.Version
|
|
}
|
|
|
|
func (r versionRequirement) isBetweenRequirement() bool {
|
|
return r.minVersion != nil && r.maxVersion != nil
|
|
}
|
|
|
|
func (r versionRequirement) isMinRequirement() bool {
|
|
return r.minVersion != nil && r.maxVersion == nil
|
|
}
|
|
|
|
func (r versionRequirement) isMaxRequirement() bool {
|
|
return r.minVersion == nil && r.maxVersion != nil
|
|
}
|
|
|
|
const controllerVersionErrorMessage = "Controller version does not meet requirements"
|
|
|
|
func (v controllerVersionValidator) requireVersionForPath(req versionRequirement, attrPath path.Path, config tfsdk.Config) diag.Diagnostics {
|
|
diags := diag.Diagnostics{}
|
|
var val attr.Value
|
|
diags.Append(config.GetAttribute(context.Background(), attrPath, &val)...)
|
|
if diags.HasError() {
|
|
return diags
|
|
}
|
|
if !types.IsDefined(val) {
|
|
return diags
|
|
}
|
|
diags.Append(v.requireVersion(req, &attrPath)...)
|
|
return diags
|
|
}
|
|
|
|
// requireVersion checks if the controller version meets the constraints
|
|
func (v controllerVersionValidator) requireVersion(req versionRequirement, attrPath *path.Path) diag.Diagnostics {
|
|
diags := diag.Diagnostics{}
|
|
if v.client == nil || v.client.Version == nil {
|
|
diags.AddError("Controller version not available", "Provider was not initialized properly. UniFi client or controller version is not available")
|
|
return diags
|
|
}
|
|
|
|
controllerVersion := v.client.Version
|
|
errorBuilder := strings.Builder{}
|
|
if attrPath != nil {
|
|
errorBuilder.WriteString(fmt.Sprintf("%s is not supported. ", attrPath.String()))
|
|
}
|
|
errorBuilder.WriteString(fmt.Sprintf("Controller version %s", controllerVersion))
|
|
failed := false
|
|
|
|
if req.isBetweenRequirement() && (controllerVersion.LessThan(req.minVersion) || controllerVersion.GreaterThan(req.maxVersion)) {
|
|
failed = true
|
|
errorBuilder.WriteString(fmt.Sprintf(" is not between required %s and %s", req.minVersion, req.maxVersion))
|
|
} else if req.isMinRequirement() && controllerVersion.LessThan(req.minVersion) {
|
|
failed = true
|
|
errorBuilder.WriteString(fmt.Sprintf(" is less than minimum required version %s", req.minVersion))
|
|
} else if req.isMaxRequirement() && controllerVersion.GreaterThan(req.maxVersion) {
|
|
failed = true
|
|
errorBuilder.WriteString(fmt.Sprintf(" is greater than maximum required version %s", req.maxVersion))
|
|
}
|
|
if failed {
|
|
diags.AddError(controllerVersionErrorMessage, errorBuilder.String())
|
|
}
|
|
return diags
|
|
}
|