diff --git a/pkg/helpers/wrapper.go b/pkg/helpers/wrapper.go index bb5d0afa..a5c0dd11 100644 --- a/pkg/helpers/wrapper.go +++ b/pkg/helpers/wrapper.go @@ -40,6 +40,19 @@ func GetP[T any](d ResourceData, key string) *T { return nil } +// Get Pointer value from resource data, if castable to generic type +func GetStringP(d ResourceData, key string) *string { + fallback := "" + rv, ok := d.GetOk(key) + if !ok { + return &fallback + } + if tt, ok := rv.(string); ok { + return new(strings.TrimSpace(tt)) + } + return &fallback +} + // Similar to `GetP` however also casts to an int32 as that is what the API prefers func GetIntP(d ResourceData, key string) *int32 { rv, ok := d.GetOk(key) diff --git a/pkg/provider/resource_application.go b/pkg/provider/resource_application.go index 42942920..cc24beb4 100644 --- a/pkg/provider/resource_application.go +++ b/pkg/provider/resource_application.go @@ -87,9 +87,9 @@ func resourceApplicationSchemaToModel(d *schema.ResourceData) *api.ApplicationRe Provider: *api.NewNullableInt32(helpers.GetIntP(d, ("protocol_provider"))), OpenInNewTab: new(d.Get("open_in_new_tab").(bool)), PolicyEngineMode: api.PolicyEngineMode(d.Get("policy_engine_mode").(string)).Ptr(), - Group: helpers.GetP[string](d, "group"), - MetaIcon: helpers.GetP[string](d, "meta_icon"), - MetaLaunchUrl: helpers.GetP[string](d, "meta_launch_url"), + Group: helpers.GetStringP(d, "group"), + MetaIcon: helpers.GetStringP(d, "meta_icon"), + MetaLaunchUrl: helpers.GetStringP(d, "meta_launch_url"), MetaDescription: helpers.GetP[string](d, "meta_description"), MetaPublisher: helpers.GetP[string](d, "meta_publisher"), } @@ -98,6 +98,7 @@ func resourceApplicationSchemaToModel(d *schema.ResourceData) *api.ApplicationRe for _, bp := range d.Get("backchannel_providers").([]any) { m.BackchannelProviders = append(m.BackchannelProviders, int32(bp.(int))) } + return &m } diff --git a/pkg/provider/resource_application_test.go b/pkg/provider/resource_application_test.go index cb3507d4..76675d6c 100644 --- a/pkg/provider/resource_application_test.go +++ b/pkg/provider/resource_application_test.go @@ -17,19 +17,36 @@ func TestAccResourceApplication(t *testing.T) { ProviderFactories: providerFactories, Steps: []resource.TestStep{ { - Config: testAccResourceApplicationSimple(rName), + Config: testAccResourceApplicationSimple(rName, "icon", "https://example.com", "testgroup"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("authentik_application.name", "name", rName), + resource.TestCheckResourceAttr("authentik_application.name", "slug", rName), + resource.TestCheckResourceAttr("authentik_application.name", "protocol_provider", "0"), + resource.TestCheckResourceAttr("authentik_application.name", "meta_launch_url", "https://example.com"), + resource.TestCheckResourceAttr("authentik_application.name", "meta_icon", "http://localhost/icon"), + resource.TestCheckResourceAttr("authentik_application.name", "meta_description", ""), + resource.TestCheckResourceAttr("authentik_application.name", "meta_publisher", ""), + resource.TestCheckResourceAttr("authentik_application.name", "group", "testgroup"), + resource.TestCheckResourceAttr("authentik_application.name", "policy_engine_mode", string(api.POLICYENGINEMODE_ANY)), + ), + }, + // Verify that updating the app will remove the icon and launch url + { + Config: testAccResourceApplicationSimple(rName, "", "", ""), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("authentik_application.name", "name", rName), resource.TestCheckResourceAttr("authentik_application.name", "slug", rName), resource.TestCheckResourceAttr("authentik_application.name", "protocol_provider", "0"), resource.TestCheckResourceAttr("authentik_application.name", "meta_launch_url", ""), + resource.TestCheckResourceAttr("authentik_application.name", "meta_icon", ""), resource.TestCheckResourceAttr("authentik_application.name", "meta_description", ""), resource.TestCheckResourceAttr("authentik_application.name", "meta_publisher", ""), + resource.TestCheckResourceAttr("authentik_application.name", "group", ""), resource.TestCheckResourceAttr("authentik_application.name", "policy_engine_mode", string(api.POLICYENGINEMODE_ANY)), ), }, { - Config: testAccResourceApplicationSimple(rName + "test"), + Config: testAccResourceApplicationSimple(rName+"test", "icon", "", ""), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("authentik_application.name", "name", rName+"test"), resource.TestCheckResourceAttr("authentik_application.name", "slug", rName+"test"), @@ -41,14 +58,14 @@ func TestAccResourceApplication(t *testing.T) { ), }, { - Config: testAccResourceApplicationSimple(rName + "test+"), + Config: testAccResourceApplicationSimple(rName+"test+", "icon", "", ""), ExpectError: regexp.MustCompile("consisting of letters, numbers, underscores or hyphens"), }, }, }) } -func testAccResourceApplicationSimple(name string) string { +func testAccResourceApplicationSimple(name string, icon string, launchUrl string, group string) string { return fmt.Sprintf(` data "authentik_flow" "default-authentication-flow" { slug = "default-authentication-flow" @@ -74,8 +91,10 @@ resource "authentik_provider_ldap" "name" { resource "authentik_application" "name" { name = "%[1]s" slug = "%[1]s" - meta_icon = "http://localhost/%[1]s" + meta_icon = "http://localhost/%[2]s" + meta_launch_url = "%[3]s" backchannel_providers = [authentik_provider_ldap.name.id] + group = "%[4]s" } -`, name) +`, name, icon, launchUrl, group) }