From 7440febd101afa764d437213164cf3683f2e4a1f Mon Sep 17 00:00:00 2001 From: Mateusz Filipowicz Date: Fri, 14 Mar 2025 07:19:45 +0100 Subject: [PATCH] feat: add support for UniFi Switch (USW) settings with `unifi_setting_usw` resource (#53) --- .../acctest/resource_setting_usw_test.go | 47 +++++++++++ internal/provider/provider_v2.go | 1 + .../provider/settings/resource_setting_usw.go | 83 +++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 internal/provider/acctest/resource_setting_usw_test.go create mode 100644 internal/provider/settings/resource_setting_usw.go diff --git a/internal/provider/acctest/resource_setting_usw_test.go b/internal/provider/acctest/resource_setting_usw_test.go new file mode 100644 index 0000000..7a410d8 --- /dev/null +++ b/internal/provider/acctest/resource_setting_usw_test.go @@ -0,0 +1,47 @@ +package acctest + +import ( + "fmt" + pt "github.com/filipowm/terraform-provider-unifi/internal/provider/testing" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "sync" + "testing" +) + +var settingUswLock = &sync.Mutex{} + +func TestAccSettingUsw(t *testing.T) { + AcceptanceTest(t, AcceptanceTestCase{ + Lock: settingUswLock, + Steps: []resource.TestStep{ + { + Config: testAccSettingUswConfig(true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("unifi_setting_usw.test", "id"), + resource.TestCheckResourceAttr("unifi_setting_usw.test", "site", "default"), + resource.TestCheckResourceAttr("unifi_setting_usw.test", "dhcp_snoop", "true"), + ), + ConfigPlanChecks: pt.CheckResourceActions("unifi_setting_usw.test", plancheck.ResourceActionCreate), + }, + pt.ImportStepWithSite("unifi_setting_usw.test"), + { + Config: testAccSettingUswConfig(false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("unifi_setting_usw.test", "id"), + resource.TestCheckResourceAttr("unifi_setting_usw.test", "site", "default"), + resource.TestCheckResourceAttr("unifi_setting_usw.test", "dhcp_snoop", "false"), + ), + ConfigPlanChecks: pt.CheckResourceActions("unifi_setting_usw.test", plancheck.ResourceActionUpdate), + }, + }, + }) +} + +func testAccSettingUswConfig(dhcpSnoop bool) string { + return fmt.Sprintf(` +resource "unifi_setting_usw" "test" { + dhcp_snoop = %t +} +`, dhcpSnoop) +} diff --git a/internal/provider/provider_v2.go b/internal/provider/provider_v2.go index ebbf9ff..ca8eb38 100644 --- a/internal/provider/provider_v2.go +++ b/internal/provider/provider_v2.go @@ -187,6 +187,7 @@ func (p *unifiProvider) Resources(_ context.Context) []func() resource.Resource settings.NewSslInspectionResource, settings.NewTeleportResource, settings.NewUsgResource, + settings.NewUswResource, } } diff --git a/internal/provider/settings/resource_setting_usw.go b/internal/provider/settings/resource_setting_usw.go new file mode 100644 index 0000000..952e1ab --- /dev/null +++ b/internal/provider/settings/resource_setting_usw.go @@ -0,0 +1,83 @@ +package settings + +import ( + "context" + + "github.com/filipowm/go-unifi/unifi" + "github.com/filipowm/terraform-provider-unifi/internal/provider/base" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +type uswModel struct { + base.Model + DHCPSnoop types.Bool `tfsdk:"dhcp_snoop"` +} + +func (d *uswModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnostics) { + diags := diag.Diagnostics{} + + model := &unifi.SettingUsw{ + ID: d.ID.ValueString(), + DHCPSnoop: d.DHCPSnoop.ValueBool(), + } + + return model, diags +} + +func (d *uswModel) Merge(ctx context.Context, other interface{}) diag.Diagnostics { + diags := diag.Diagnostics{} + + model, ok := other.(*unifi.SettingUsw) + if !ok { + diags.AddError("Cannot merge", "Cannot merge type that is not *unifi.SettingUsw") + return diags + } + + d.ID = types.StringValue(model.ID) + d.DHCPSnoop = types.BoolValue(model.DHCPSnoop) + + return diags +} + +var ( + _ base.ResourceModel = &uswModel{} + _ resource.Resource = &uswResource{} + _ resource.ResourceWithConfigure = &uswResource{} + _ resource.ResourceWithImportState = &uswResource{} +) + +type uswResource struct { + *base.GenericResource[*uswModel] +} + +func (r *uswResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + 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(), + "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, + }, + }, + } +} + +func NewUswResource() resource.Resource { + r := &uswResource{} + r.GenericResource = NewSettingResource( + "unifi_setting_usw", + func() *uswModel { return &uswModel{} }, + func(ctx context.Context, client *base.Client, site string) (interface{}, error) { + return client.GetSettingUsw(ctx, site) + }, + func(ctx context.Context, client *base.Client, site string, body interface{}) (interface{}, error) { + return client.UpdateSettingUsw(ctx, site, body.(*unifi.SettingUsw)) + }, + ) + return r +}