From f82bce6de0629f03626416c3274e82449ca39ced Mon Sep 17 00:00:00 2001 From: Mateusz Filipowicz Date: Tue, 11 Mar 2025 11:33:43 +0100 Subject: [PATCH] feat: add support for Deep Packet Inspection (DPI) settings with `unifi_setting_dpi` resource (#45) --- .../acctest/resource_setting_dpi_test.go | 70 +++++++++++++++ internal/provider/provider_v2.go | 2 +- .../provider/settings/resource_setting_dpi.go | 90 +++++++++++++++++++ 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 internal/provider/acctest/resource_setting_dpi_test.go create mode 100644 internal/provider/settings/resource_setting_dpi.go diff --git a/internal/provider/acctest/resource_setting_dpi_test.go b/internal/provider/acctest/resource_setting_dpi_test.go new file mode 100644 index 0000000..fd32cc4 --- /dev/null +++ b/internal/provider/acctest/resource_setting_dpi_test.go @@ -0,0 +1,70 @@ +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 settingDpiLock = &sync.Mutex{} + +func TestAccSettingDpi(t *testing.T) { + AcceptanceTest(t, AcceptanceTestCase{ + Lock: settingDpiLock, + Steps: []resource.TestStep{ + { + Config: testAccSettingDpiConfig(true, true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("unifi_setting_dpi.test", "id"), + resource.TestCheckResourceAttr("unifi_setting_dpi.test", "site", "default"), + resource.TestCheckResourceAttr("unifi_setting_dpi.test", "enabled", "true"), + resource.TestCheckResourceAttr("unifi_setting_dpi.test", "fingerprinting_enabled", "true"), + ), + ConfigPlanChecks: pt.CheckResourceActions("unifi_setting_dpi.test", plancheck.ResourceActionCreate), + }, + pt.ImportStepWithSite("unifi_setting_dpi.test"), + { + Config: testAccSettingDpiConfig(false, true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("unifi_setting_dpi.test", "id"), + resource.TestCheckResourceAttr("unifi_setting_dpi.test", "site", "default"), + resource.TestCheckResourceAttr("unifi_setting_dpi.test", "enabled", "false"), + resource.TestCheckResourceAttr("unifi_setting_dpi.test", "fingerprinting_enabled", "true"), + ), + ConfigPlanChecks: pt.CheckResourceActions("unifi_setting_dpi.test", plancheck.ResourceActionUpdate), + }, + { + Config: testAccSettingDpiConfig(false, false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("unifi_setting_dpi.test", "id"), + resource.TestCheckResourceAttr("unifi_setting_dpi.test", "site", "default"), + resource.TestCheckResourceAttr("unifi_setting_dpi.test", "enabled", "false"), + resource.TestCheckResourceAttr("unifi_setting_dpi.test", "fingerprinting_enabled", "false"), + ), + ConfigPlanChecks: pt.CheckResourceActions("unifi_setting_dpi.test", plancheck.ResourceActionUpdate), + }, + { + Config: testAccSettingDpiConfig(true, false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("unifi_setting_dpi.test", "id"), + resource.TestCheckResourceAttr("unifi_setting_dpi.test", "site", "default"), + resource.TestCheckResourceAttr("unifi_setting_dpi.test", "enabled", "true"), + resource.TestCheckResourceAttr("unifi_setting_dpi.test", "fingerprinting_enabled", "false"), + ), + ConfigPlanChecks: pt.CheckResourceActions("unifi_setting_dpi.test", plancheck.ResourceActionUpdate), + }, + }, + }) +} + +func testAccSettingDpiConfig(enabled, fingerprintingEnabled bool) string { + return fmt.Sprintf(` +resource "unifi_setting_dpi" "test" { + enabled = %t + fingerprinting_enabled = %t +} +`, enabled, fingerprintingEnabled) +} diff --git a/internal/provider/provider_v2.go b/internal/provider/provider_v2.go index efcd4e3..c15fe73 100644 --- a/internal/provider/provider_v2.go +++ b/internal/provider/provider_v2.go @@ -176,7 +176,7 @@ func (p *unifiProvider) Resources(_ context.Context) []func() resource.Resource dns.NewDnsRecordResource, settings.NewAutoSpeedtestResource, settings.NewCountryResource, - //settings.NewDpiResource, + settings.NewDpiResource, //settings.NewIpsResource, settings.NewLcmResource, settings.NewLocaleResource, diff --git a/internal/provider/settings/resource_setting_dpi.go b/internal/provider/settings/resource_setting_dpi.go new file mode 100644 index 0000000..4141241 --- /dev/null +++ b/internal/provider/settings/resource_setting_dpi.go @@ -0,0 +1,90 @@ +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 dpiModel struct { + base.Model + Enabled types.Bool `tfsdk:"enabled"` + FingerprintingEnabled types.Bool `tfsdk:"fingerprinting_enabled"` +} + +func (d *dpiModel) AsUnifiModel(_ context.Context) (interface{}, diag.Diagnostics) { + diags := diag.Diagnostics{} + + model := &unifi.SettingDpi{ + ID: d.ID.ValueString(), + Enabled: d.Enabled.ValueBool(), + FingerprintingEnabled: d.FingerprintingEnabled.ValueBool(), + } + + return model, diags +} + +func (d *dpiModel) Merge(_ context.Context, other interface{}) diag.Diagnostics { + diags := diag.Diagnostics{} + + model, ok := other.(*unifi.SettingDpi) + if !ok { + diags.AddError("Cannot merge", "Cannot merge type that is not *unifi.SettingDpi") + return diags + } + + d.ID = types.StringValue(model.ID) + d.Enabled = types.BoolValue(model.Enabled) + d.FingerprintingEnabled = types.BoolValue(model.FingerprintingEnabled) + + return diags +} + +var ( + _ base.ResourceModel = &dpiModel{} + _ resource.Resource = &dpiResource{} + _ resource.ResourceWithConfigure = &dpiResource{} + _ resource.ResourceWithImportState = &dpiResource{} +) + +type dpiResource struct { + *BaseSettingResource[*dpiModel] +} + +func (r *dpiResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + 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(), + "enabled": schema.BoolAttribute{ + MarkdownDescription: "Whether Deep Packet Inspection is enabled.", + Required: true, + }, + "fingerprinting_enabled": schema.BoolAttribute{ + MarkdownDescription: "Whether DPI fingerprinting is enabled. Fingerprinting allows the controller to identify applications and services based on traffic patterns.", + Required: true, + }, + }, + } +} + +func NewDpiResource() resource.Resource { + r := &dpiResource{} + r.BaseSettingResource = NewBaseSettingResource( + "unifi_setting_dpi", + func() *dpiModel { return &dpiModel{} }, + func(ctx context.Context, client *base.Client, site string) (interface{}, error) { + return client.GetSettingDpi(ctx, site) + }, + func(ctx context.Context, client *base.Client, site string, body interface{}) (interface{}, error) { + return client.UpdateSettingDpi(ctx, site, body.(*unifi.SettingDpi)) + }, + ) + return r +}