Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_container_app_custom_domain - support the ability to use Azure Managed Certificates #25356

Merged
merged 3 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,15 @@ func (a ContainerAppCustomDomainResource) Arguments() map[string]*pluginsdk.Sche

"container_app_environment_certificate_id": {
Type: pluginsdk.TypeString,
Required: true,
Optional: true,
ForceNew: true,
RequiredWith: []string{"certificate_binding_type"},
ValidateFunc: managedenvironments.ValidateCertificateID,
},

"certificate_binding_type": {
Type: pluginsdk.TypeString,
Required: true,
Optional: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice(containerapps.PossibleValuesForBindingType(), false),
Description: "The Binding type. Possible values include `Disabled` and `SniEnabled`.",
Expand Down Expand Up @@ -106,9 +107,12 @@ func (a ContainerAppCustomDomainResource) Create() sdk.ResourceFunc {

id := parse.NewContainerAppCustomDomainId(containerAppId.SubscriptionId, containerAppId.ResourceGroupName, containerAppId.ContainerAppName, model.Name)

certificateId, err := managedenvironments.ParseCertificateID(model.CertificateId)
if err != nil {
return err
var certificateId *managedenvironments.CertificateId
if model.CertificateId != "" {
certificateId, err = managedenvironments.ParseCertificateID(model.CertificateId)
if err != nil {
return err
}
}

containerApp, err := client.Get(ctx, *containerAppId)
Expand Down Expand Up @@ -149,11 +153,17 @@ func (a ContainerAppCustomDomainResource) Create() sdk.ResourceFunc {
customDomains = *existingCustomDomains
}

customDomains = append(customDomains, containerapps.CustomDomain{
BindingType: pointer.To(containerapps.BindingType(model.BindingType)),
CertificateId: pointer.To(certificateId.ID()),
Name: model.Name,
})
customDomain := containerapps.CustomDomain{
Name: model.Name,
BindingType: pointer.To(containerapps.BindingTypeDisabled),
}

if certificateId != nil {
customDomain.CertificateId = pointer.To(certificateId.ID())
customDomain.BindingType = pointer.To(containerapps.BindingType(model.BindingType))
}

customDomains = append(customDomains, customDomain)

containerApp.Model.Properties.Configuration.Ingress.CustomDomains = pointer.To(customDomains)

Expand Down Expand Up @@ -200,11 +210,14 @@ func (a ContainerAppCustomDomainResource) Read() sdk.ResourceFunc {
found = true
state.Name = id.CustomDomainName
state.ContainerAppId = containerAppId.ID()
certId, err := managedenvironments.ParseCertificateIDInsensitively(pointer.From(v.CertificateId))
if err != nil {
return err
if pointer.From(v.CertificateId) != "" {
certId, err := managedenvironments.ParseCertificateIDInsensitively(pointer.From(v.CertificateId))
if err != nil {
return err
}
state.CertificateId = certId.ID()
}
state.CertificateId = certId.ID()

state.BindingType = string(pointer.From(v.BindingType))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,25 @@ func TestAccContainerAppCustomDomainResource_basic(t *testing.T) {
})
}

func TestAccContainerAppCustomDomainResource_managedCertificate(t *testing.T) {
if os.Getenv("ARM_TEST_DNS_ZONE") == "" || os.Getenv("ARM_TEST_DATA_RESOURCE_GROUP") == "" {
t.Skipf("Skipping as either ARM_TEST_DNS_ZONE or ARM_TEST_DATA_RESOURCE_GROUP is not set")
}

data := acceptance.BuildTestData(t, "azurerm_container_app_custom_domain", "test")
r := ContainerAppCustomDomainResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.managedCertificate(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccContainerAppCustomDomainResource_multiple(t *testing.T) {
if os.Getenv("ARM_TEST_DNS_ZONE") == "" || os.Getenv("ARM_TEST_DATA_RESOURCE_GROUP") == "" {
t.Skipf("Skipping as either ARM_TEST_DNS_ZONE or ARM_TEST_DATA_RESOURCE_GROUP is not set")
Expand Down Expand Up @@ -142,6 +161,27 @@ resource "azurerm_container_app_custom_domain" "test" {
certificate_binding_type = "SniEnabled"
}

`, r.template(data))
}

func (r ContainerAppCustomDomainResource) managedCertificate(data acceptance.TestData) string {
return fmt.Sprintf(`
provider azurerm {
features {}
}

%s

resource "azurerm_container_app_custom_domain" "test" {
name = trimprefix(azurerm_dns_txt_record.test.fqdn, "asuid.")
container_app_id = azurerm_container_app.test.id

lifecycle {
ignore_changes = [certificate_binding_type, container_app_environment_certificate_id]
}
}


`, r.template(data))
}

Expand Down
24 changes: 22 additions & 2 deletions website/docs/r/container_app_custom_domain.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,22 @@ resource "azurerm_container_app_custom_domain" "example" {

```

## Example Usage - Managed Certificate

```hcl
resource "azurerm_container_app_custom_domain" "example" {
name = trimprefix(azurerm_dns_txt_record.example.fqdn, "asuid.")
container_app_id = azurerm_container_app.example.id

lifecycle {
// When using an Azure created Managed Certificate these values must be added to ignore_changes to prevent resource recreation.
ignore_changes = [certificate_binding_type, container_app_environment_certificate_id]
}
}

```


## Arguments Reference

The following arguments are supported:
Expand All @@ -101,9 +117,13 @@ The following arguments are supported:

* `container_app_id` - (Required) The ID of the Container App to which this Custom Domain should be bound. Changing this forces a new resource to be created.

* `container_app_environment_certificate_id` - (Required) The ID of the Container App Environment Certificate to use. Changing this forces a new resource to be created.
* `container_app_environment_certificate_id` - (Optional) The ID of the Container App Environment Certificate to use. Changing this forces a new resource to be created.

-> **NOTE:** Omit this value if you wish to use an Azure Managed certificate. You must create the relevant DNS verification steps before this process will be successful.

* `certificate_binding_type` - (Optional) The Certificate Binding type. Possible values include `Disabled` and `SniEnabled`. Required with `container_app_environment_certificate_id`. Changing this forces a new resource to be created.

* `certificate_binding_type` - (Required) The Certificate Binding type. Possible values include `Disabled` and `SniEnabled`. Changing this forces a new resource to be created.
!> **NOTE:** If using an Azure Managed Certificate `container_app_environment_certificate_id` and `certificate_binding_type` should be added to `ignore_changes` to prevent resource recreation due to these values being modified asynchronously outside of Terraform.

## Timeouts

Expand Down
Loading