provider

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 28, 2026 License: Apache-2.0 Imports: 35 Imported by: 0

Documentation

Overview

Package provider implements the Terrifi Terraform provider for managing Ubiquiti UniFi network infrastructure.

Architecture overview:

Terraform Plugin Framework is HashiCorp's modern SDK for building providers. A provider has three responsibilities:

  1. Schema — declare what configuration the provider block accepts (URL, credentials, etc.)
  2. Configure — use that config to create an authenticated API client
  3. Resources/DataSources — return the list of resource types this provider manages

The framework calls these methods in order: Schema → Configure → then CRUD methods on individual resources as needed. The Configure method stores the authenticated client in resp.ResourceData, and each resource retrieves it in its own Configure method.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New() provider.Provider

New creates a new provider instance. The framework calls this factory function for each Terraform operation, so providers should be cheap to create.

func NewClientDeviceResource

func NewClientDeviceResource() resource.Resource

func NewClientGroupResource

func NewClientGroupResource() resource.Resource

func NewDNSRecordResource

func NewDNSRecordResource() resource.Resource

NewDNSRecordResource is the factory function registered in provider.Resources(). The framework calls this to create a new instance for each resource block in the config.

func NewFirewallPolicyResource

func NewFirewallPolicyResource() resource.Resource

func NewFirewallZoneResource

func NewFirewallZoneResource() resource.Resource

func NewNetworkResource

func NewNetworkResource() resource.Resource

func NewWLANResource

func NewWLANResource() resource.Resource

Types

type Client

type Client struct {
	*ui.ApiClient
	Site    string
	BaseURL string
	APIPath string // API path prefix, e.g. "/proxy/network" for UniFi OS, empty for legacy
	APIKey  string // Stored separately because the SDK's apiKey field is private
	HTTP    *retryablehttp.Client
	// contains filtered or unexported fields
}

Client wraps the go-unifi API client with site information. The go-unifi SDK (github.com/ubiquiti-community/go-unifi) provides typed Go structs and CRUD methods for every UniFi API endpoint. We wrap it to carry the default site name alongside the API client so resources can fall back to it.

func NewClient

func NewClient(ctx context.Context, cfg ClientConfig) (*Client, error)

NewClient creates an authenticated UniFi API client from the given config. It handles HTTP client setup, TLS configuration, authentication (API key or username/password), and API path discovery.

TODO(go-unifi): The SDK's New() constructor creates its own internal HTTP client and does not expose it or the CSRF token. Because we need to make custom HTTP requests for v2/v1 endpoints that bypass the SDK (firewall zones, firewall policies, client devices), we create a separate retryablehttp.Client and perform an independent login to obtain our own session cookie + CSRF token. If the SDK ever exposes a Do() method or the CSRF token, this dual-login approach can be eliminated.

func (*Client) CreateClientDevice

func (c *Client) CreateClientDevice(ctx context.Context, site string, d *unifi.Client) (*unifi.Client, error)

CreateClientDevice creates a client device entry via the v1 REST API, bypassing the SDK to control boolean serialization.

func (*Client) CreateFirewallPolicy

func (c *Client) CreateFirewallPolicy(ctx context.Context, site string, d *unifi.FirewallPolicy) (*unifi.FirewallPolicy, error)

CreateFirewallPolicy creates a firewall policy via the v2 API, bypassing the SDK to control boolean serialization.

func (*Client) CreateFirewallZone

func (c *Client) CreateFirewallZone(ctx context.Context, site string, d *unifi.FirewallZone) (*unifi.FirewallZone, error)

CreateFirewallZone creates a firewall zone via the v2 API, bypassing the SDK to avoid bug #1 (default_zone serialization).

func (*Client) DeleteClientDevice

func (c *Client) DeleteClientDevice(ctx context.Context, site string, id string) error

DeleteClientDevice deletes a client device via the v1 REST API.

func (*Client) DeleteFirewallPolicy

func (c *Client) DeleteFirewallPolicy(ctx context.Context, site string, id string) error

DeleteFirewallPolicy deletes a firewall policy via the v2 API, bypassing the SDK to handle 204 No Content responses.

func (*Client) DeleteFirewallZone

func (c *Client) DeleteFirewallZone(ctx context.Context, site string, id string) error

DeleteFirewallZone deletes a firewall zone via the v2 API, bypassing the SDK to avoid bug #3 (204 No Content treated as error).

func (*Client) GetClientDevice

func (c *Client) GetClientDevice(ctx context.Context, site string, id string) (*unifi.Client, error)

GetClientDevice reads a client device via the SDK's getClient (GET has no body serialization issue).

func (*Client) GetClientDeviceByMAC

func (c *Client) GetClientDeviceByMAC(ctx context.Context, site string, mac string) (*unifi.Client, error)

GetClientDeviceByMAC looks up a client device by MAC address. This is needed when the controller auto-cleans a user record (common for non-connected MACs) but the MAC still exists in the client table with a different ID.

func (*Client) GetFirewallPolicy

func (c *Client) GetFirewallPolicy(ctx context.Context, site string, id string) (*unifi.FirewallPolicy, error)

TODO(go-unifi): GetFirewallPolicy uses a custom implementation because the SDK's generated FirewallPolicySource/Destination struct defines `port` as *int64, but the v2 API returns `port` as a JSON string (e.g. "443"). The SDK fails to unmarshal this. When the SDK fixes the port field type (or adds a custom unmarshaler), this can be replaced with c.ApiClient.GetFirewallPolicy().

func (*Client) ListClientDevices

func (c *Client) ListClientDevices(ctx context.Context, site string) ([]unifi.Client, error)

ListClientDevices returns all configured client devices for the given site.

func (*Client) ListFirewallPolicies

func (c *Client) ListFirewallPolicies(ctx context.Context, site string) ([]*unifi.FirewallPolicy, error)

ListFirewallPolicies returns all firewall policies for the given site. Reuses the same workaround as GetFirewallPolicy (custom response struct with string port field).

func (*Client) SiteOrDefault

func (c *Client) SiteOrDefault(site types.String) string

SiteOrDefault returns the given site if non-empty, otherwise falls back to the provider's default site. Every resource calls this to resolve which site to operate on, since the site attribute is optional on individual resources.

func (*Client) UpdateClientDevice

func (c *Client) UpdateClientDevice(ctx context.Context, site string, d *unifi.Client) (*unifi.Client, error)

UpdateClientDevice updates a client device entry via the v1 REST API, bypassing the SDK to control boolean serialization.

func (*Client) UpdateFirewallPolicy

func (c *Client) UpdateFirewallPolicy(ctx context.Context, site string, d *unifi.FirewallPolicy) (*unifi.FirewallPolicy, error)

UpdateFirewallPolicy updates a firewall policy via the v2 API, bypassing the SDK to include _id in the PUT body and control boolean serialization.

func (*Client) UpdateFirewallZone

func (c *Client) UpdateFirewallZone(ctx context.Context, site string, d *unifi.FirewallZone) (*unifi.FirewallZone, error)

UpdateFirewallZone updates a firewall zone via the v2 API, bypassing the SDK to avoid bugs #1 (default_zone) and #2 (_id in PUT body).

type ClientConfig

type ClientConfig struct {
	APIURL        string
	Username      string
	Password      string
	APIKey        string
	Site          string
	AllowInsecure bool
}

ClientConfig holds the configuration needed to create an authenticated UniFi API client. It can be populated from Terraform attributes, env vars, or both (via ClientConfigFromEnv).

func ClientConfigFromEnv

func ClientConfigFromEnv() ClientConfig

ClientConfigFromEnv reads UniFi connection configuration from environment variables. This is the same set of env vars that the Terraform provider reads.

type Logger

type Logger struct {
	// contains filtered or unexported fields
}

Logger adapts the go-retryablehttp LeveledLogger interface to Terraform's tflog system.

go-retryablehttp (the HTTP client library we use) wants to log things like retry attempts, request timing, etc. Rather than printing to stderr, we route these through tflog so they appear in Terraform's structured log output (visible with TF_LOG=DEBUG).

The LeveledLogger interface expects methods like Error(msg, key, val, key, val...) where keys and values alternate. We convert those to a map for tflog.

func NewLogger

func NewLogger(ctx context.Context) *Logger

func (*Logger) Debug

func (l *Logger) Debug(msg string, keysAndValues ...any)

func (*Logger) Error

func (l *Logger) Error(msg string, keysAndValues ...any)

func (*Logger) Info

func (l *Logger) Info(msg string, keysAndValues ...any)

func (*Logger) Warn

func (l *Logger) Warn(msg string, keysAndValues ...any)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL