diff --git a/README.md b/README.md index aaacc37..a5fe12b 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,9 @@ The following providers are used by this module: The following resources are used by this module: - [azapi_resource.container_app](https://registry.terraform.io/providers/Azure/azapi/1.9.0/docs/resources/resource) (resource) +- [azurerm_management_lock.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/management_lock) (resource) - [azurerm_resource_group_template_deployment.telemetry](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group_template_deployment) (resource) +- [azurerm_role_assignment.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) (resource) - [random_id.telem](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) (resource) - [azurerm_resource_group.rg](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) (data source) @@ -58,20 +60,14 @@ The following resources are used by this module: The following input variables are required: -### [container\_app\_environment\_resource\_id](#input\_container\_app\_environment\_resource\_id) - -Description: Resource ID of environment. - -Type: `string` - -### [container\_apps](#input\_container\_apps) +### [container\_app](#input\_container\_app) Description: Specifies the container apps in the managed environment. Type: ```hcl -list(object({ +object({ name = string revision_mode = optional(string, "Single") @@ -255,9 +251,15 @@ list(object({ storageType = string }))) }) - })) + }) ``` +### [container\_app\_environment\_resource\_id](#input\_container\_app\_environment\_resource\_id) + +Description: Resource ID of environment. + +Type: `string` + ### [name](#input\_name) Description: Name for the resource. @@ -292,6 +294,42 @@ Type: `string` Default: `null` +### [lock](#input\_lock) + +Description: The lock level to apply to the Container App. Default is `None`. Possible values are `None`, `CanNotDelete`, and `ReadOnly`. + +Type: + +```hcl +object({ + name = optional(string, null) + kind = optional(string, "None") + + }) +``` + +Default: `{}` + +### [role\_assignments](#input\_role\_assignments) + +Description: required AVM interfaces + +Type: + +```hcl +map(object({ + role_definition_id_or_name = string + principal_id = string + description = optional(string, null) + skip_service_principal_aad_check = optional(bool, true) + condition = optional(string, null) + condition_version = optional(string, "2.0") + delegated_managed_identity_resource_id = optional(string) + })) +``` + +Default: `{}` + ### [tags](#input\_tags) Description: Custom tags to apply to the resource. diff --git a/examples-not-working/dapr/README.md b/examples/dapr/README.md similarity index 80% rename from examples-not-working/dapr/README.md rename to examples/dapr/README.md index dfae813..91bcfa3 100644 --- a/examples-not-working/dapr/README.md +++ b/examples/dapr/README.md @@ -61,15 +61,15 @@ resource "azapi_resource" "managed_environment" { } # This is the module call -module "container-app" { +module "node-app" { source = "../../" # source = "Azure/avm--/azurerm" - name = replace(azurerm_resource_group.this.name, "rg-", "ca-") # TODO remove workaround pending PR - https://github.com/Azure/terraform-azurerm-naming/pull/103 + name = replace(azurerm_resource_group.this.name, "rg-", "ca-nodeapp-") # TODO remove workaround pending PR - https://github.com/Azure/terraform-azurerm-naming/pull/103 resource_group_name = azurerm_resource_group.this.name container_app_environment_resource_id = azapi_resource.managed_environment.id workload_profile_name = "" - container_apps = [{ + container_app = { name = "nodeapp" configuration = { ingress = { @@ -101,30 +101,40 @@ module "container-app" { maxReplicas = 1 } } - }, - { - name = "pythonapp" - configuration = { - dapr = { - enabled = true - appId = "pythonapp" - } + } +} + +module "python-app" { + source = "../../" + # source = "Azure/avm--/azurerm" + name = replace(azurerm_resource_group.this.name, "rg-", "ca-pythonapp-") # TODO remove workaround pending PR - https://github.com/Azure/terraform-azurerm-naming/pull/103 + resource_group_name = azurerm_resource_group.this.name + container_app_environment_resource_id = azapi_resource.managed_environment.id + + workload_profile_name = "" + container_app = { + name = "pythonapp" + configuration = { + dapr = { + enabled = true + appId = "pythonapp" } - template = { - containers = [{ - image = "dapriosamples/hello-k8s-python:latest" - name = "hello-k8s-python" - resources = { - cpu = 0.5 - memory = "1.0Gi" - } - }] - scale = { - minReplicas = 1 - maxReplicas = 1 + } + template = { + containers = [{ + image = "dapriosamples/hello-k8s-python:latest" + name = "hello-k8s-python" + resources = { + cpu = 0.5 + memory = "1.0Gi" } + }] + scale = { + minReplicas = 1 + maxReplicas = 1 } - }] + } + } } ``` @@ -181,17 +191,23 @@ No outputs. The following Modules are called: -### [container-app](#module\_container-app) +### [naming](#module\_naming) + +Source: Azure/naming/azurerm + +Version: 0.3.0 + +### [node-app](#module\_node-app) Source: ../../ Version: -### [naming](#module\_naming) +### [python-app](#module\_python-app) -Source: Azure/naming/azurerm +Source: ../../ -Version: 0.3.0 +Version: ## Data Collection diff --git a/examples-not-working/dapr/_footer.md b/examples/dapr/_footer.md similarity index 100% rename from examples-not-working/dapr/_footer.md rename to examples/dapr/_footer.md diff --git a/examples-not-working/dapr/_header.md b/examples/dapr/_header.md similarity index 100% rename from examples-not-working/dapr/_header.md rename to examples/dapr/_header.md diff --git a/examples-not-working/dapr/main.tf b/examples/dapr/main.tf similarity index 69% rename from examples-not-working/dapr/main.tf rename to examples/dapr/main.tf index bf76a88..f7021d0 100644 --- a/examples-not-working/dapr/main.tf +++ b/examples/dapr/main.tf @@ -55,15 +55,15 @@ resource "azapi_resource" "managed_environment" { } # This is the module call -module "container-app" { +module "node-app" { source = "../../" # source = "Azure/avm--/azurerm" - name = replace(azurerm_resource_group.this.name, "rg-", "ca-") # TODO remove workaround pending PR - https://github.com/Azure/terraform-azurerm-naming/pull/103 + name = replace(azurerm_resource_group.this.name, "rg-", "ca-nodeapp-") # TODO remove workaround pending PR - https://github.com/Azure/terraform-azurerm-naming/pull/103 resource_group_name = azurerm_resource_group.this.name container_app_environment_resource_id = azapi_resource.managed_environment.id workload_profile_name = "" - container_apps = [{ + container_app = { name = "nodeapp" configuration = { ingress = { @@ -95,28 +95,38 @@ module "container-app" { maxReplicas = 1 } } - }, - { - name = "pythonapp" - configuration = { - dapr = { - enabled = true - appId = "pythonapp" - } + } +} + +module "python-app" { + source = "../../" + # source = "Azure/avm--/azurerm" + name = replace(azurerm_resource_group.this.name, "rg-", "ca-pythonapp-") # TODO remove workaround pending PR - https://github.com/Azure/terraform-azurerm-naming/pull/103 + resource_group_name = azurerm_resource_group.this.name + container_app_environment_resource_id = azapi_resource.managed_environment.id + + workload_profile_name = "" + container_app = { + name = "pythonapp" + configuration = { + dapr = { + enabled = true + appId = "pythonapp" } - template = { - containers = [{ - image = "dapriosamples/hello-k8s-python:latest" - name = "hello-k8s-python" - resources = { - cpu = 0.5 - memory = "1.0Gi" - } - }] - scale = { - minReplicas = 1 - maxReplicas = 1 + } + template = { + containers = [{ + image = "dapriosamples/hello-k8s-python:latest" + name = "hello-k8s-python" + resources = { + cpu = 0.5 + memory = "1.0Gi" } + }] + scale = { + minReplicas = 1 + maxReplicas = 1 } - }] + } + } } diff --git a/examples/default/README.md b/examples/default/README.md index 3656660..6fa773d 100644 --- a/examples/default/README.md +++ b/examples/default/README.md @@ -56,7 +56,7 @@ module "container_app" { container_app_environment_resource_id = azurerm_container_app_environment.this.id workload_profile_name = "Consumption" - container_apps = [{ + container_app = { name = "helloworld" configuration = { ingress = { @@ -77,8 +77,7 @@ module "container_app" { maxReplicas = 1 } } - } - ] + } } ``` diff --git a/examples/default/main.tf b/examples/default/main.tf index 76d67e5..8b03f06 100644 --- a/examples/default/main.tf +++ b/examples/default/main.tf @@ -50,7 +50,7 @@ module "container_app" { container_app_environment_resource_id = azurerm_container_app_environment.this.id workload_profile_name = "Consumption" - container_apps = [{ + container_app = { name = "helloworld" configuration = { ingress = { @@ -71,6 +71,5 @@ module "container_app" { maxReplicas = 1 } } - } - ] + } } diff --git a/locals.tf b/locals.tf index 0eba510..1804b01 100644 --- a/locals.tf +++ b/locals.tf @@ -1,3 +1,4 @@ locals { - location = var.location != null ? var.location : data.azurerm_resource_group.rg.location + location = var.location != null ? var.location : data.azurerm_resource_group.rg.location + role_definition_resource_substring = "/providers/Microsoft.Authorization/roleDefinitions" } diff --git a/main.tf b/main.tf index 7382eb2..0a2bd9b 100644 --- a/main.tf +++ b/main.tf @@ -3,7 +3,6 @@ data "azurerm_resource_group" "rg" { } resource "azapi_resource" "container_app" { - for_each = { for app in var.container_apps : app.name => app } type = "Microsoft.App/containerApps@2023-05-01" schema_validation_enabled = false name = var.name @@ -18,16 +17,16 @@ resource "azapi_resource" "container_app" { body = jsonencode({ properties = { configuration = { - activeRevisionsMode = try(each.value.revision_mode, "Single") - dapr = try(each.value.dapr, null) - ingress = try(each.value.ingress, null) - maxInactiveRevisions = try(each.value.maxInactiveRevisions, null) - registries = try(each.value.registries, null) - secrets = try(each.value.secrets, null) - service = try(each.value.service, null) + activeRevisionsMode = try(var.container_app.revision_mode, "Single") + dapr = try(var.container_app.dapr, null) + ingress = try(var.container_app.ingress, null) + maxInactiveRevisions = try(var.container_app.maxInactiveRevisions, null) + registries = try(var.container_app.registries, null) + secrets = try(var.container_app.secrets, null) + service = try(var.container_app.service, null) } environmentId = var.container_app_environment_resource_id - template = each.value.template + template = var.container_app.template workloadProfileName = var.workload_profile_name } }) @@ -35,21 +34,21 @@ resource "azapi_resource" "container_app" { response_export_values = ["identity"] } -# resource "azurerm_management_lock" "this" { -# count = var.lock.kind != "None" ? 1 : 0 -# name = coalesce(var.lock.name, "lock-${var.name}") -# scope = azapi_resource.container_app.id -# lock_level = var.lock.kind -# } +resource "azurerm_management_lock" "this" { + count = var.lock.kind != "None" ? 1 : 0 + name = coalesce(var.lock.name, "lock-${var.name}") + scope = azapi_resource.container_app.id + lock_level = var.lock.kind +} -# resource "azurerm_role_assignment" "this" { -# for_each = var.role_assignments -# scope = azapi_resource.container_app.id -# role_definition_id = strcontains(lower(each.value.role_definition_id_or_name), lower(local.role_definition_resource_substring)) ? each.value.role_definition_id_or_name : null -# role_definition_name = strcontains(lower(each.value.role_definition_id_or_name), lower(local.role_definition_resource_substring)) ? null : each.value.role_definition_id_or_name -# principal_id = each.value.principal_id -# condition = each.value.condition -# condition_version = each.value.condition_version -# skip_service_principal_aad_check = each.value.skip_service_principal_aad_check -# delegated_managed_identity_resource_id = each.value.delegated_managed_identity_resource_id -# } +resource "azurerm_role_assignment" "this" { + for_each = var.role_assignments + scope = azapi_resource.container_app.id + role_definition_id = strcontains(lower(each.value.role_definition_id_or_name), lower(local.role_definition_resource_substring)) ? each.value.role_definition_id_or_name : null + role_definition_name = strcontains(lower(each.value.role_definition_id_or_name), lower(local.role_definition_resource_substring)) ? null : each.value.role_definition_id_or_name + principal_id = each.value.principal_id + condition = each.value.condition + condition_version = each.value.condition_version + skip_service_principal_aad_check = each.value.skip_service_principal_aad_check + delegated_managed_identity_resource_id = each.value.delegated_managed_identity_resource_id +} diff --git a/variables.containerapps.tf b/variables.containerapps.tf index 297cd6b..64ef4ab 100644 --- a/variables.containerapps.tf +++ b/variables.containerapps.tf @@ -32,9 +32,9 @@ variable "workload_profile_name" { default = null } -variable "container_apps" { +variable "container_app" { description = "Specifies the container apps in the managed environment." - type = list(object({ + type = object({ name = string revision_mode = optional(string, "Single") @@ -218,5 +218,5 @@ variable "container_apps" { storageType = string }))) }) - })) + }) } diff --git a/variables.tf b/variables.tf index e61c6fc..d2f9508 100644 --- a/variables.tf +++ b/variables.tf @@ -16,54 +16,31 @@ variable "resource_group_name" { //required AVM interfaces +variable "role_assignments" { + type = map(object({ + role_definition_id_or_name = string + principal_id = string + description = optional(string, null) + skip_service_principal_aad_check = optional(bool, true) + condition = optional(string, null) + condition_version = optional(string, "2.0") + delegated_managed_identity_resource_id = optional(string) + })) + default = {} +} -# variable "diagnostic_settings" { -# type = map(object({ -# name = optional(string, null) -# log_categories_and_groups = optional(set(string), ["allLogs"]) -# metric_categories = optional(set(string), ["AllMetrics"]) -# log_analytics_destination_type = optional(string, "Dedicated") -# workspace_resource_id = optional(string, null) -# storage_account_resource_id = optional(string, null) -# event_hub_authorization_rule_resource_id = optional(string, null) -# event_hub_name = optional(string, null) -# marketplace_partner_resource_id = optional(string, null) -# })) -# default = {} -# nullable = false - -# validation { -# condition = alltrue([for _, v in var.diagnostic_settings : contains(["Dedicated", "AzureDiagnostics"], v.log_analytics_destination_type)]) -# error_message = "Log analytics destination type must be one of: 'Dedicated', 'AzureDiagnostics'." -# } -# } - - -# variable "role_assignments" { -# type = map(object({ -# role_definition_id_or_name = string -# principal_id = string -# description = optional(string, null) -# skip_service_principal_aad_check = optional(bool, true) -# condition = optional(string, null) -# condition_version = optional(string, "2.0") -# delegated_managed_identity_resource_id = optional(string) -# })) -# default = {} -# } - -# variable "lock" { -# type = object({ -# name = optional(string, null) -# kind = optional(string, "None") +variable "lock" { + type = object({ + name = optional(string, null) + kind = optional(string, "None") -# }) -# description = "The lock level to apply to the Container App. Default is `None`. Possible values are `None`, `CanNotDelete`, and `ReadOnly`." -# default = {} -# nullable = false -# validation { -# condition = contains(["CanNotDelete", "ReadOnly", "None"], var.lock.kind) -# error_message = "The lock level must be one of: 'None', 'CanNotDelete', or 'ReadOnly'." -# } -# } + }) + description = "The lock level to apply to the Container App. Default is `None`. Possible values are `None`, `CanNotDelete`, and `ReadOnly`." + default = {} + nullable = false + validation { + condition = contains(["CanNotDelete", "ReadOnly", "None"], var.lock.kind) + error_message = "The lock level must be one of: 'None', 'CanNotDelete', or 'ReadOnly'." + } +}