Skip to content
Open
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
29 changes: 22 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,34 @@ No modules.

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_acr_admin_enabled"></a> [acr\_admin\_enabled](#input\_acr\_admin\_enabled) | Specifies whether the admin user is enabled. Defaults to false. | `string` | `"false"` | no |
| <a name="input_acr_name"></a> [acr\_name](#input\_acr\_name) | Specifies the name of the Container Registry. Changing this forces a new resource to be created. | `string` | n/a | yes |
| <a name="input_acr_tier"></a> [acr\_tier](#input\_acr\_tier) | The SKU name of the container registry. Possible values are Basic, Standard and Premium. Classic (which was previously Basic) is supported only for existing resources. | `string` | `"Basic"` | no |
| <a name="input_default_tags"></a> [default\_tags](#input\_default\_tags) | A map of default tags to assign to all resources, aiding in resource organization and cost tracking. | `map(string)` | n/a | yes |
| <a name="input_acr_admin_enabled"></a> [acr\_admin\_enabled](#input\_acr\_admin\_enabled) | Specifies whether the admin user is enabled for the Container Registry. | `bool` | `false` | no |
| <a name="input_acr_name"></a> [acr\_name](#input\_acr\_name) | The name of the Container Registry. Changing this forces a new resource to be created. | `string` | n/a | yes |
| <a name="input_acr_tier"></a> [acr\_tier](#input\_acr\_tier) | The SKU name of the Container Registry. Possible values are Basic, Standard, and Premium. | `string` | `"Basic"` | no |
| <a name="input_anonymous_pull_enabled"></a> [anonymous\_pull\_enabled](#input\_anonymous\_pull\_enabled) | Whether anonymous pull access is enabled for the Container Registry (Premium SKU only). | `bool` | `false` | no |
| <a name="input_data_endpoint_enabled"></a> [data\_endpoint\_enabled](#input\_data\_endpoint\_enabled) | Whether data endpoint is enabled for the Container Registry (Premium SKU only). | `bool` | `false` | no |
| <a name="input_default_tags"></a> [default\_tags](#input\_default\_tags) | A map of default tags to assign to all resources. | `map(string)` | n/a | yes |
| <a name="input_encryption"></a> [encryption](#input\_encryption) | Encryption configuration for the Container Registry (Premium SKU only). | <pre>object({<br/> key_vault_key_id = string<br/> identity_client_id = string<br/> })</pre> | `null` | no |
| <a name="input_environment"></a> [environment](#input\_environment) | The name of the environment to deploy resources into, such as 'dev', 'test', or 'prod'. | `string` | n/a | yes |
| <a name="input_resource_group_location"></a> [resource\_group\_location](#input\_resource\_group\_location) | The Azure region where the resource group is located. Changing this value will recreate the Container Registry. | `string` | n/a | yes |
| <a name="input_resource_group_name"></a> [resource\_group\_name](#input\_resource\_group\_name) | The name of the resource group in which the Container Registry will be created. Modifying this value will recreate the resource. | `string` | n/a | yes |
| <a name="input_export_policy_enabled"></a> [export\_policy\_enabled](#input\_export\_policy\_enabled) | Whether export policy is enabled for the Container Registry. | `bool` | `true` | no |
| <a name="input_georeplications"></a> [georeplications](#input\_georeplications) | A list of georeplication configurations for the Container Registry (Premium SKU only). | <pre>list(object({<br/> location = string<br/> zone_redundancy_enabled = bool<br/> regional_endpoint_enabled = bool<br/> tags = map(string)<br/> }))</pre> | `[]` | no |
| <a name="input_identity"></a> [identity](#input\_identity) | Identity configuration for the Container Registry. | <pre>object({<br/> type = string<br/> identity_ids = list(string)<br/> })</pre> | `null` | no |
| <a name="input_network_rule_bypass_option"></a> [network\_rule\_bypass\_option](#input\_network\_rule\_bypass\_option) | Specifies whether Azure Services can bypass network rules. Possible values are 'AzureServices' or 'None'. | `string` | `"AzureServices"` | no |
| <a name="input_network_rule_set"></a> [network\_rule\_set](#input\_network\_rule\_set) | Network rules for the Container Registry (Premium SKU only). | <pre>object({<br/> default_action = string<br/> ip_rules = list(string)<br/> })</pre> | `null` | no |
| <a name="input_public_network_access_enabled"></a> [public\_network\_access\_enabled](#input\_public\_network\_access\_enabled) | Whether public network access is allowed for the Container Registry. | `bool` | `true` | no |
| <a name="input_quarantine_policy_enabled"></a> [quarantine\_policy\_enabled](#input\_quarantine\_policy\_enabled) | Whether quarantine policy is enabled for the Container Registry. | `bool` | `false` | no |
| <a name="input_resource_group_location"></a> [resource\_group\_location](#input\_resource\_group\_location) | The Azure region where the resource group is located. | `string` | n/a | yes |
| <a name="input_resource_group_name"></a> [resource\_group\_name](#input\_resource\_group\_name) | The name of the resource group in which the Container Registry will be created. | `string` | n/a | yes |
| <a name="input_retention_policy"></a> [retention\_policy](#input\_retention\_policy) | Number of days to retain untagged manifests in the Container Registry (Premium SKU only). Set to null to disable. | `number` | `null` | no |
| <a name="input_trust_policy"></a> [trust\_policy](#input\_trust\_policy) | Trust policy for the Container Registry (Premium SKU only). | <pre>object({<br/> enabled = bool<br/> })</pre> | `null` | no |
| <a name="input_zone_redundancy_enabled"></a> [zone\_redundancy\_enabled](#input\_zone\_redundancy\_enabled) | Whether zone redundancy is enabled for the Container Registry (Premium SKU only). | `bool` | `false` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_admin_password"></a> [admin\_password](#output\_admin\_password) | The Password associated with the Container Registry Admin account - if the admin account is enabled. |
| <a name="output_admin_username"></a> [admin\_username](#output\_admin\_username) | The Username associated with the Container Registry Admin account - if the admin account is enabled. |
| <a name="output_data_endpoint_host_names"></a> [data\_endpoint\_host\_names](#output\_data\_endpoint\_host\_names) | A set of data endpoint hostnames associated with the Container Registry - if data endpoints are enabled. |
| <a name="output_id"></a> [id](#output\_id) | The ID of the Container Registry. |
| <a name="output_login_server"></a> [login\_server](#output\_login\_server) | The URL that can be used to log into the container registry. |
| <a name="output_identity"></a> [identity](#output\_identity) | The identity details of the Container Registry, including principal\_id and tenant\_id, if a managed identity is configured. |
| <a name="output_login_server"></a> [login\_server](#output\_login\_server) | The URL that can be used to log into the Container Registry. |
65 changes: 58 additions & 7 deletions acr.tf
Original file line number Diff line number Diff line change
@@ -1,8 +1,59 @@
resource "azurerm_container_registry" "main" {
name = "${var.environment}${var.acr_name}"
resource_group_name = data.azurerm_resource_group.main.name
location = data.azurerm_resource_group.main.location
sku = var.acr_tier
admin_enabled = var.acr_admin_enabled
tags = var.default_tags
}
name = var.acr_name
resource_group_name = data.azurerm_resource_group.main.name
location = var.resource_group_location
sku = var.acr_tier
admin_enabled = var.acr_admin_enabled
public_network_access_enabled = var.public_network_access_enabled
quarantine_policy_enabled = var.quarantine_policy_enabled
zone_redundancy_enabled = var.zone_redundancy_enabled
export_policy_enabled = var.export_policy_enabled
anonymous_pull_enabled = var.anonymous_pull_enabled
data_endpoint_enabled = var.data_endpoint_enabled
network_rule_bypass_option = var.network_rule_bypass_option
retention_policy_in_days = var.retention_policy != null ? var.retention_policy : null
trust_policy_enabled = var.trust_policy != null ? var.trust_policy.enabled : false

dynamic "georeplications" {
for_each = var.georeplications
content {
location = georeplications.value.location
zone_redundancy_enabled = georeplications.value.zone_redundancy_enabled
regional_endpoint_enabled = georeplications.value.regional_endpoint_enabled
tags = merge(var.default_tags, georeplications.value.tags)
}
}

dynamic "network_rule_set" {
for_each = var.network_rule_set != null ? [var.network_rule_set] : []
content {
default_action = network_rule_set.value.default_action

dynamic "ip_rule" {
for_each = network_rule_set.value.ip_rules
content {
action = "Allow"
ip_range = ip_rule.value
}
}
}
}

dynamic "identity" {
for_each = var.identity != null ? [var.identity] : []
content {
type = identity.value.type
identity_ids = identity.value.identity_ids
}
}

dynamic "encryption" {
for_each = var.encryption != null ? [var.encryption] : []
content {
key_vault_key_id = encryption.value.key_vault_key_id
identity_client_id = encryption.value.identity_client_id
}
}
Comment on lines +50 to +56
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Premium-only encryption block needs an SKU gate
encryption is accepted only on Premium registries. Protect the dynamic block so Basic/Standard deployments remain valid.

-for_each = var.encryption != null ? [var.encryption] : []
+for_each = var.acr_tier == "Premium" && var.encryption != null ? [var.encryption] : []
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
dynamic "encryption" {
for_each = var.encryption != null ? [var.encryption] : []
content {
key_vault_key_id = encryption.value.key_vault_key_id
identity_client_id = encryption.value.identity_client_id
}
}
dynamic "encryption" {
- for_each = var.encryption != null ? [var.encryption] : []
+ for_each = var.acr_tier == "Premium" && var.encryption != null ? [var.encryption] : []
content {
key_vault_key_id = encryption.value.key_vault_key_id
identity_client_id = encryption.value.identity_client_id
}
}
🤖 Prompt for AI Agents
In acr.tf around lines 58 to 64, the dynamic "encryption" block must be
conditionally included only for Premium SKU registries. Add a condition to check
if the SKU is Premium before including the encryption block, ensuring Basic and
Standard SKUs do not attempt to use encryption and cause deployment errors.


tags = var.default_tags
}
25 changes: 19 additions & 6 deletions output.tf
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
output "id" {
description = "The ID of the Container Registry."
value = azurerm_container_registry.main.id
sensitive = false
}

output "login_server" {
description = "The URL that can be used to log into the container registry."
description = "The URL that can be used to log into the Container Registry."
value = azurerm_container_registry.main.login_server
sensitive = false
}

output "admin_username" {
description = "The Username associated with the Container Registry Admin account - if the admin account is enabled."
value = azurerm_container_registry.main.admin_username
sensitive = true
value = azurerm_container_registry.main.admin_enabled ? azurerm_container_registry.main.admin_username : null
}

output "admin_password" {
description = "The Password associated with the Container Registry Admin account - if the admin account is enabled."
value = azurerm_container_registry.main.admin_password
value = azurerm_container_registry.main.admin_enabled ? azurerm_container_registry.main.admin_password : null
sensitive = true
}

output "data_endpoint_host_names" {
description = "A set of data endpoint hostnames associated with the Container Registry - if data endpoints are enabled."
value = azurerm_container_registry.main.data_endpoint_enabled ? azurerm_container_registry.main.data_endpoint_host_names : null
}

output "identity" {
description = "The identity details of the Container Registry, including principal_id and tenant_id, if a managed identity is configured."
value = azurerm_container_registry.main.identity != null ? {
principal_id = azurerm_container_registry.main.identity[0].principal_id
tenant_id = azurerm_container_registry.main.identity[0].tenant_id
} : null
}
73 changes: 73 additions & 0 deletions pipelines/.terraform-docs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
formatter: markdown
output:
file: README.md
mode: inject
sections:
show:
- header
- requirements
- providers
- inputs
- outputs
content: |
# Terraform Azure Container Registry Module

This Terraform module creates and manages an Azure Container Registry (ACR) with support for all configuration options available in the `azurerm_container_registry` resource for provider version 4.34.0.

## Usage

```hcl
module "acr" {
source = "./terraform-azure-container-registry"
acr_name = "mycontainerregistry123"
resource_group_name = "my-resource-group"
resource_group_location = "West Europe"
acr_tier = "Premium"
acr_admin_enabled = true
public_network_access_enabled = false
quarantine_policy_enabled = true
zone_redundancy_enabled = true
export_policy_enabled = false
anonymous_pull_enabled = true
data_endpoint_enabled = true
network_rule_bypass_option = "AzureServices"
retention_policy = 7
trust_policy = {
enabled = true
}
default_tags = {
Project = "MyProject"
Environment = "Production"
}
environment = "prod"
georeplications = [
{
location = "East US"
zone_redundancy_enabled = true
regional_endpoint_enabled = true
tags = { Environment = "prod" }
}
]
network_rule_set = {
default_action = "Deny"
ip_rules = ["203.0.113.0/24"]
}
identity = {
type = "SystemAssigned"
identity_ids = []
}
encryption = {
key_vault_key_id = "https://myvault.vault.azure.net/keys/mykey/1234567890abcdef"
identity_client_id = "<user-assigned-identity-client-id>"
}
}
```

## Notes

- The module supports all configuration options available in the `azurerm_container_registry` resource for provider version 4.34.0.
- Premium SKU is required for features like georeplication, network rules, retention policies, trust policies, and encryption.
- Ensure the resource group exists before deploying the module.
- Use the `default_tags` variable to enforce consistent tagging across resources.

© 2025 Think-Cube
8 changes: 4 additions & 4 deletions pipelines/azure-pipelines-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,16 @@ stages:
- script: |
# Variables
github_token="$(GITHUB_TOKEN)"
# Generate or update README.md
/tmp/terraform-docs markdown table . > README.md
# Generate or update README.md using .terraform-docs.yml
/tmp/terraform-docs markdown . --config .terraform-docs.yml

# Check if README.md has been updated or created and add to PR
if [ -f README.md ]; then
echo "README.md file generated/updated."
git config --global user.email "devops-bot@example.com"
git config --global user.name "DevOps Bot"
git add README.md
git commit -m "Update README.md with module documentation"
git commit -m "Update README.md with module documentation and example usage"

# Set remote URL with authentication token
git remote set-url origin https://$(GITHUB_TOKEN)@github.com/Think-Cube/terraform-azure-container-registry.git
Expand All @@ -81,4 +81,4 @@ stages:
echo "Failed to generate README.md"
exit 1
fi
displayName: 'Generate and Update README.md Documentation'
displayName: 'Generate and Update README.md Documentation'
Loading