diff --git a/internal/services/containerapps/container_app_resource_test.go b/internal/services/containerapps/container_app_resource_test.go index 546cdd3e3bc8..9111530ae3cf 100644 --- a/internal/services/containerapps/container_app_resource_test.go +++ b/internal/services/containerapps/container_app_resource_test.go @@ -143,6 +143,21 @@ func TestAccContainerAppResource_complete(t *testing.T) { }) } +func TestAccContainerAppResource_completeWithNoDaprAppPort(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_container_app", "test") + r := ContainerAppResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.completeWithNoDaprAppPort(data, "rev1"), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + func TestAccContainerAppResource_completeWithVNet(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_container_app", "test") r := ContainerAppResource{} @@ -195,6 +210,28 @@ func TestAccContainerAppResource_completeUpdate(t *testing.T) { }) } +func TestAccContainerAppResource_removeDaprAppPort(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_container_app", "test") + r := ContainerAppResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.complete(data, "rev1"), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.completeUpdate_withNoDaprAppPort(data, "rev2"), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).Key("dapr.0.app_port").HasValue("0"), + ), + }, + data.ImportStep(), + }) +} + func TestAccContainerAppResource_secretRemoveShouldFail(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_container_app", "test") r := ContainerAppResource{} @@ -472,6 +509,101 @@ resource "azurerm_container_app" "test" { `, r.templatePlusExtras(data), data.RandomInteger, revisionSuffix) } +func (r ContainerAppResource) completeWithNoDaprAppPort(data acceptance.TestData, revisionSuffix string) string { + return fmt.Sprintf(` +%s + +resource "azurerm_container_app" "test" { + name = "acctest-capp-%[2]d" + resource_group_name = azurerm_resource_group.test.name + container_app_environment_id = azurerm_container_app_environment.test.id + revision_mode = "Single" + + template { + container { + name = "acctest-cont-%[2]d" + image = "jackofallops/azure-containerapps-python-acctest:v0.0.1" + cpu = 0.25 + memory = "0.5Gi" + + readiness_probe { + transport = "HTTP" + port = 5000 + } + + liveness_probe { + transport = "HTTP" + port = 5000 + path = "/health" + + header { + name = "Cache-Control" + value = "no-cache" + } + + initial_delay = 5 + interval_seconds = 20 + timeout = 2 + failure_count_threshold = 1 + } + + startup_probe { + transport = "TCP" + port = 5000 + } + + volume_mounts { + name = azurerm_container_app_environment_storage.test.name + path = "/tmp/testdata" + } + } + + volume { + name = azurerm_container_app_environment_storage.test.name + storage_type = "AzureFile" + storage_name = azurerm_container_app_environment_storage.test.name + } + + min_replicas = 2 + max_replicas = 3 + + revision_suffix = "%[3]s" + } + + ingress { + allow_insecure_connections = true + external_enabled = true + target_port = 5000 + transport = "http" + traffic_weight { + latest_revision = true + percentage = 100 + } + } + + registry { + server = azurerm_container_registry.test.login_server + username = azurerm_container_registry.test.admin_username + password_secret_name = "registry-password" + } + + secret { + name = "registry-password" + value = azurerm_container_registry.test.admin_password + } + + dapr { + app_id = "acctest-cont-%[2]d" + } + + tags = { + foo = "Bar" + accTest = "1" + } +} +`, r.templatePlusExtras(data), data.RandomInteger, revisionSuffix) +} + func (r ContainerAppResource) completeWithVnet(data acceptance.TestData, revisionSuffix string) string { return fmt.Sprintf(` %s @@ -914,6 +1046,123 @@ resource "azurerm_container_app" "test" { `, r.templatePlusExtras(data), data.RandomInteger, revisionSuffix) } +func (r ContainerAppResource) completeUpdate_withNoDaprAppPort(data acceptance.TestData, revisionSuffix string) string { + return fmt.Sprintf(` +%s + +resource "azurerm_container_app" "test" { + name = "acctest-capp-%[2]d" + resource_group_name = azurerm_resource_group.test.name + container_app_environment_id = azurerm_container_app_environment.test.id + revision_mode = "Multiple" + + template { + container { + name = "acctest-cont-%[2]d" + image = "jackofallops/azure-containerapps-python-acctest:v0.0.1" + + cpu = 0.5 + memory = "1Gi" + + readiness_probe { + transport = "HTTP" + port = 5000 + path = "/uptime" + timeout = 2 + failure_count_threshold = 1 + success_count_threshold = 1 + + header { + name = "Cache-Control" + value = "no-cache" + } + } + + liveness_probe { + transport = "HTTP" + port = 5000 + path = "/health" + + header { + name = "Cache-Control" + value = "no-cache" + } + + initial_delay = 5 + timeout = 2 + failure_count_threshold = 3 + } + + startup_probe { + transport = "TCP" + port = 5000 + timeout = 5 + failure_count_threshold = 1 + } + + volume_mounts { + name = azurerm_container_app_environment_storage.test.name + path = "/tmp/testdata" + } + } + + volume { + name = azurerm_container_app_environment_storage.test.name + storage_type = "AzureFile" + storage_name = azurerm_container_app_environment_storage.test.name + } + + min_replicas = 1 + max_replicas = 4 + + revision_suffix = "%[3]s" + } + + ingress { + allow_insecure_connections = true + external_enabled = true + target_port = 5000 + transport = "auto" + + traffic_weight { + latest_revision = true + percentage = 20 + } + + traffic_weight { + revision_suffix = "rev1" + percentage = 80 + } + } + + registry { + server = azurerm_container_registry.test.login_server + username = azurerm_container_registry.test.admin_username + password_secret_name = "registry-password" + } + + secret { + name = "registry-password" + value = azurerm_container_registry.test.admin_password + } + + secret { + name = "rick" + value = "morty" + } + + dapr { + app_id = "acctest-cont-%[2]d" + } + + tags = { + foo = "Bar" + accTest = "1" + } +} +`, r.templatePlusExtras(data), data.RandomInteger, revisionSuffix) +} + func (ContainerAppResource) template(data acceptance.TestData) string { return ContainerAppEnvironmentResource{}.basic(data) } diff --git a/internal/services/containerapps/helpers/container_apps.go b/internal/services/containerapps/helpers/container_apps.go index b103c43a6c38..fddd7a1e2f34 100644 --- a/internal/services/containerapps/helpers/container_apps.go +++ b/internal/services/containerapps/helpers/container_apps.go @@ -404,7 +404,7 @@ func ContainerDaprSchema() *pluginsdk.Schema { "app_port": { Type: pluginsdk.TypeInt, - Required: true, + Optional: true, Description: "The port which the application is listening on. This is the same as the `ingress` port.", }, diff --git a/website/docs/r/container_app.html.markdown b/website/docs/r/container_app.html.markdown index 763b57778247..6a83b01ee17a 100644 --- a/website/docs/r/container_app.html.markdown +++ b/website/docs/r/container_app.html.markdown @@ -307,7 +307,7 @@ A `dapr` block supports the following: * `app_id` - (Required) The Dapr Application Identifier. -* `app_port` - (Required) The port which the application is listening on. This is the same as the `ingress` port. +* `app_port` - (Optional) The port which the application is listening on. This is the same as the `ingress` port. * `app_protocol` - (Optional) The protocol for the app. Possible values include `http` and `grpc`. Defaults to `http`.