Files
terraform-provider-unifi/internal/provider/provider_v2.go
Mateusz Filipowicz 8b5ed14d8d feat: add NTP setting resource support with unifi_setting_ntp resource (#36)
* feat: add NTP setting resource support with `unifi_setting_ntp` resource

* linting

* fix missing method

* add missing validators
2025-03-02 01:10:41 +01:00

191 lines
6.1 KiB
Go

package provider
import (
"context"
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
"github.com/filipowm/terraform-provider-unifi/internal/provider/dns"
"github.com/filipowm/terraform-provider-unifi/internal/provider/settings"
"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"
"github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/provider/schema"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
)
func NewV2(version string) func() provider.Provider {
return func() provider.Provider {
return &unifiProvider{
version: version,
}
}
}
var (
_ provider.Provider = &unifiProvider{}
)
type unifiProvider struct {
version string
}
type unifiProviderModel struct {
Username types.String `tfsdk:"username"`
Password types.String `tfsdk:"password"`
APIKey types.String `tfsdk:"api_key"`
APIUrl types.String `tfsdk:"api_url"`
Site types.String `tfsdk:"site"`
Insecure types.Bool `tfsdk:"allow_insecure"`
}
func (p *unifiProvider) Metadata(_ context.Context, _ provider.MetadataRequest, resp *provider.MetadataResponse) {
resp.TypeName = "unifi"
resp.Version = p.version
}
func (p *unifiProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"username": schema.StringAttribute{
MarkdownDescription: ProviderUsernameDescription,
Optional: true,
},
"password": schema.StringAttribute{
MarkdownDescription: ProviderPasswordDescription,
Optional: true,
Sensitive: true,
},
"api_key": schema.StringAttribute{
MarkdownDescription: ProviderAPIKeyDescription,
Optional: true,
Sensitive: true,
},
"api_url": schema.StringAttribute{
MarkdownDescription: ProviderAPIURLDescription,
Validators: []validator.String{
stringvalidator.LengthAtLeast(1), // workaround for `required: true`, because it fails on doc generation due to incorrectly detected difference between v1 and v2
validators.HTTPSUrl(),
},
Optional: true,
},
"site": schema.StringAttribute{
MarkdownDescription: ProviderSiteDescription,
Optional: true,
},
"allow_insecure": schema.BoolAttribute{
MarkdownDescription: ProviderAllowInsecureDescription,
Optional: true,
},
},
}
}
func (p *unifiProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
tflog.Info(ctx, "Configuring Unifi provider...")
// Retrieve provider data from the configuration
var cfg unifiProviderModel
diags := req.Config.Get(ctx, &cfg)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
// If practitioner provided a configuration value for any of the
// attributes, it must be a known value.
if cfg.APIUrl.IsUnknown() {
resp.Diagnostics.AddAttributeError(
path.Root("api_url"),
"Unknown UniFi Controller API URL",
"The provider cannot create the UniFi Controller API client as there is an unknown configuration value "+
"for the API endpoint. Either target apply the source of the value first, set the value statically in "+
"the configuration, or use the UNIFI_API environment variable.",
)
}
if resp.Diagnostics.HasError() {
return
}
// Default values to environment variables, but override
// with Terraform configuration value if set.
// Check environment variables
username := utils.GetAnyStringEnv("UNIFI_USERNAME")
password := utils.GetAnyStringEnv("UNIFI_PASSWORD")
apiKey := utils.GetAnyStringEnv("UNIFI_API_KEY")
apiUrl := utils.GetAnyStringEnv("UNIFI_API")
site := utils.GetAnyStringEnv("UNIFI_SITE")
insecure := utils.GetAnyBoolEnv("UNIFI_INSECURE")
if !cfg.Username.IsNull() {
username = cfg.Username.ValueString()
}
if !cfg.Password.IsNull() {
password = cfg.Password.ValueString()
}
if !cfg.APIKey.IsNull() {
apiKey = cfg.APIKey.ValueString()
}
if !cfg.APIUrl.IsNull() {
apiUrl = cfg.APIUrl.ValueString()
}
if !cfg.Site.IsNull() {
site = cfg.Site.ValueString()
}
if !cfg.Insecure.IsNull() {
insecure = cfg.Insecure.ValueBool()
}
if apiKey != "" && (username != "" || password != "") {
resp.Diagnostics.AddAttributeError(path.Root("api_key"), "Two authentication methods configured", "Only one of `username`/`password` or `api_key` can be set")
} else if apiKey == "" && (username == "" || password == "") {
resp.Diagnostics.AddAttributeError(path.Root("api_key"), "Missing UniFi API credentials", "Either `username`/`password` or `api_key` must be set")
}
if apiUrl == "" {
resp.Diagnostics.AddAttributeError(path.Root("api_url"), "Missing UniFi API URL", "The `api_url` attribute must be set")
}
if resp.Diagnostics.HasError() {
return
}
if site == "" {
site = "default" // set default site if not provided
}
c, err := base.NewClient(&base.ClientConfig{
Username: username,
Password: password,
ApiKey: apiKey,
Url: apiUrl,
Site: site,
Insecure: insecure,
})
if err != nil {
resp.Diagnostics.AddError("Failed to create UniFi client", err.Error())
return
}
resp.ResourceData = c
resp.DataSourceData = c
}
func (p *unifiProvider) Resources(_ context.Context) []func() resource.Resource {
return []func() resource.Resource{
dns.NewDnsRecordResource,
settings.NewAutoSpeedtestResource,
settings.NewCountryResource,
settings.NewLocaleResource,
settings.NewMagicSiteToSiteVpnResource,
settings.NewNtpResource,
}
}
func (p *unifiProvider) DataSources(_ context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{
dns.NewDnsRecordsDatasource,
dns.NewDnsRecordDatasource,
}
}