Skip to content

Commit 82c2f82

Browse files
feat: Enabling public ECR support (#4)
* Enabling public ECR support * terraform-docs: automated action * Updating readme for public ECR usage * fixing terraform fmt for CI * fixing terraform fmt for CI * fixing the end of line error for ci --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent eed95ab commit 82c2f82

File tree

7 files changed

+147
-33
lines changed

7 files changed

+147
-33
lines changed

README.md

+42-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ AWS ECR Module which creates
77
- ECR policy
88

99
## Usage
10+
### Private Repository
1011
```hcl
1112
module "ecr" {
1213
source = "mattyait/ecr/aws"
@@ -24,26 +25,60 @@ module "ecr" {
2425
max_tagged_image_count = 50
2526
protected_tags = ["latest"]
2627
27-
tags = {
28+
tags = {
2829
Environment = "demo"
2930
Created_By = "Terraform"
3031
}
3132
}
3233
```
3334

35+
### Public Repository
36+
```
37+
module "public_ecr" {
38+
source = "../"
39+
repository_type = "public"
40+
image_names = [
41+
"test",
42+
"test1",
43+
]
44+
45+
public_repository_catalog_data = [
46+
{
47+
description = "Docker container Description test repo"
48+
about_text = "About Text test"
49+
usage_text = "Usage Text test"
50+
operating_systems = ["Linux"]
51+
architectures = ["x86"]
52+
},
53+
{
54+
description = "Docker container Description test1 repo"
55+
about_text = "About Text test1"
56+
usage_text = "Usage Text test1"
57+
operating_systems = ["Alpine"]
58+
architectures = ["x86"]
59+
}
60+
]
61+
62+
tags = {
63+
Environment = "demo"
64+
Created_By = "Terraform"
65+
}
66+
}
67+
```
68+
3469
<!-- BEGIN_TF_DOCS -->
3570
## Requirements
3671

3772
| Name | Version |
3873
|------|---------|
3974
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >=1.0.3 |
40-
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 4.31.0 |
75+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 5.31.0 |
4176

4277
## Providers
4378

4479
| Name | Version |
4580
|------|---------|
46-
| <a name="provider_aws"></a> [aws](#provider\_aws) | ~> 4.31.0 |
81+
| <a name="provider_aws"></a> [aws](#provider\_aws) | ~> 5.31.0 |
4782

4883
## Modules
4984

@@ -56,6 +91,7 @@ No modules.
5691
| [aws_ecr_lifecycle_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_lifecycle_policy) | resource |
5792
| [aws_ecr_repository.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository) | resource |
5893
| [aws_ecr_repository_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository_policy) | resource |
94+
| [aws_ecrpublic_repository.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecrpublic_repository) | resource |
5995
| [aws_kms_alias.kms_key_alias](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource |
6096
| [aws_kms_key.kms_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource |
6197
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
@@ -74,15 +110,17 @@ No modules.
74110
| <a name="input_max_untagged_image_count"></a> [max\_untagged\_image\_count](#input\_max\_untagged\_image\_count) | The maximum number of untagged images that you want to retain in repository. | `number` | `1` | no |
75111
| <a name="input_only_pull_accounts"></a> [only\_pull\_accounts](#input\_only\_pull\_accounts) | AWS accounts which pull only. | `list(string)` | `[]` | no |
76112
| <a name="input_protected_tags"></a> [protected\_tags](#input\_protected\_tags) | Name of image tags prefixes that should not be destroyed. | `list(string)` | <pre>[<br> "latest"<br>]</pre> | no |
113+
| <a name="input_public_repository_catalog_data"></a> [public\_repository\_catalog\_data](#input\_public\_repository\_catalog\_data) | Catalog data configuration for the public repository | `any` | `{}` | no |
77114
| <a name="input_push_and_pull_accounts"></a> [push\_and\_pull\_accounts](#input\_push\_and\_pull\_accounts) | AWS accounts which push and pull. | `list(string)` | `[]` | no |
115+
| <a name="input_repository_type"></a> [repository\_type](#input\_repository\_type) | The type of repository to create(public or private) | `string` | `"private"` | no |
78116
| <a name="input_scan_on_push"></a> [scan\_on\_push](#input\_scan\_on\_push) | Whether images should automatically be scanned on push or not. | `bool` | `false` | no |
79117
| <a name="input_tags"></a> [tags](#input\_tags) | The tags for the resources | `map(any)` | `{}` | no |
80118

81119
## Outputs
82120

83121
| Name | Description |
84122
|------|-------------|
85-
| <a name="output_ecr_repository_arn"></a> [ecr\_repository\_arn](#output\_ecr\_repository\_arn) | Full ARN of the repository. |
123+
| <a name="output_ecr_repository_arn"></a> [ecr\_repository\_arn](#output\_ecr\_repository\_arn) | Full ARN of the repository |
86124
| <a name="output_ecr_repository_name"></a> [ecr\_repository\_name](#output\_ecr\_repository\_name) | Name of first repository created |
87125
| <a name="output_ecr_repository_registry_id"></a> [ecr\_repository\_registry\_id](#output\_ecr\_repository\_registry\_id) | The registry ID where the repository was created. |
88126
| <a name="output_ecr_repository_url"></a> [ecr\_repository\_url](#output\_ecr\_repository\_url) | URL of first repository created |

example/main.tf

+35-4
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@ terraform {
33
required_providers {
44
aws = {
55
source = "hashicorp/aws"
6-
version = "~> 4.31.0"
6+
version = "~> 5.31.0"
77
}
88
}
99
}
1010

1111
provider "aws" {
12-
region = "ap-southeast-2"
12+
region = "us-east-1"
1313
}
1414

1515
module "ecr" {
1616
source = "../"
1717

1818
image_names = [
19-
"test",
20-
"test1",
19+
"test_private",
20+
"test1_private",
2121
]
2222
scan_on_push = true
2323
image_tag_mutability = "IMMUTABLE"
@@ -53,3 +53,34 @@ module "ecr_with_kms" {
5353
Created_By = "Terraform"
5454
}
5555
}
56+
57+
module "public_ecr" {
58+
source = "../"
59+
repository_type = "public"
60+
image_names = [
61+
"test",
62+
"test1",
63+
]
64+
65+
public_repository_catalog_data = [
66+
{
67+
description = "Docker container Description test repo"
68+
about_text = "About Text test"
69+
usage_text = "Usage Text test"
70+
operating_systems = ["Linux"]
71+
architectures = ["x86"]
72+
},
73+
{
74+
description = "Docker container Description test1 repo"
75+
about_text = "About Text test1"
76+
usage_text = "Usage Text test1"
77+
operating_systems = ["Alpine"]
78+
architectures = ["x86"]
79+
}
80+
]
81+
82+
tags = {
83+
Environment = "demo"
84+
Created_By = "Terraform"
85+
}
86+
}

example/outputs.tf

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
1-
output "ecr_repository_arn" {
2-
value = module.ecr.ecr_repository_arn
3-
description = "Full ARN of the repository."
1+
output "public_ecr_repository_url_map" {
2+
value = try(module.public_ecr.repository_url_map, null)
3+
description = "Returning the ecr repo url as map"
44
}
55

6-
output "ecr_repository_name" {
7-
value = module.ecr.ecr_repository_name
8-
description = "Name of first repository created"
6+
output "public_repository_arn_map" {
7+
value = try(module.public_ecr.repository_arn_map, null)
8+
description = "Returning the ecr repo arn as map"
9+
}
10+
11+
output "private_ecr_repository_url_map" {
12+
value = try(module.ecr.repository_url_map, null)
13+
description = "Returning the ecr repo url as map"
14+
}
15+
16+
output "private_repository_arn_map" {
17+
value = try(module.ecr.repository_arn_map, null)
18+
description = "Returning the ecr repo arn as map"
919
}

main.tf

+32-8
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ locals {
55
kms_key = var.encryption_type == "KMS" && var.kms_key == null ? aws_kms_key.kms_key[0].arn : var.kms_key
66
}
77
]
8-
}
9-
locals {
108
image_names = length(var.image_names) > 0 ? var.image_names : []
9+
10+
create_private_repository = var.repository_type == "private"
11+
create_public_repository = var.repository_type == "public"
1112
}
1213

14+
1315
locals {
1416
untagged_image_rule = [{
1517
rulePriority = length(var.protected_tags) + 1
@@ -62,19 +64,19 @@ locals {
6264
}
6365

6466
resource "aws_kms_key" "kms_key" {
65-
count = var.encryption_type == "KMS" && var.kms_key == null ? 1 : 0
67+
count = (local.create_private_repository && var.encryption_type == "KMS" && var.kms_key == null) ? 1 : 0
6668
description = "ECR KMS key for ECR"
6769
tags = var.tags
6870
}
6971

7072
resource "aws_kms_alias" "kms_key_alias" {
71-
count = var.encryption_type == "KMS" && var.kms_key == null ? 1 : 0
73+
count = (local.create_private_repository && var.encryption_type == "KMS" && var.kms_key == null) ? 1 : 0
7274
name = "alias/ecrkey"
7375
target_key_id = aws_kms_key.kms_key[0].key_id
7476
}
7577

7678
resource "aws_ecr_repository" "this" {
77-
for_each = toset(local.image_names)
79+
for_each = local.create_private_repository ? toset(local.image_names) : []
7880
name = each.value
7981
image_tag_mutability = var.image_tag_mutability
8082

@@ -94,7 +96,7 @@ resource "aws_ecr_repository" "this" {
9496
}
9597

9698
resource "aws_ecr_repository_policy" "this" {
97-
for_each = toset(local.image_names)
99+
for_each = local.create_private_repository ? toset(local.image_names) : []
98100
repository = aws_ecr_repository.this[each.value].name
99101
policy = data.aws_iam_policy_document.push_and_pull.json
100102
}
@@ -118,7 +120,7 @@ data "aws_iam_policy_document" "only_pull" {
118120

119121
# Allows specific accounts to push and pull images
120122
data "aws_iam_policy_document" "push_and_pull" {
121-
source_json = data.aws_iam_policy_document.only_pull.json
123+
source_policy_documents = [data.aws_iam_policy_document.only_pull.json]
122124

123125
statement {
124126
sid = "ElasticContainerRegistryPushAndPull"
@@ -139,7 +141,7 @@ data "aws_iam_policy_document" "push_and_pull" {
139141
}
140142

141143
resource "aws_ecr_lifecycle_policy" "this" {
142-
for_each = toset(local.image_names)
144+
for_each = local.create_private_repository ? toset(local.image_names) : []
143145
repository = aws_ecr_repository.this[each.value].name
144146
policy = jsonencode({
145147
rules = concat(local.protected_tag_rules, local.untagged_image_rule, local.remove_old_image_rule)
@@ -149,3 +151,25 @@ resource "aws_ecr_lifecycle_policy" "this" {
149151

150152

151153
data "aws_caller_identity" "current" {}
154+
155+
156+
157+
resource "aws_ecrpublic_repository" "this" {
158+
for_each = local.create_public_repository ? toset(local.image_names) : []
159+
160+
repository_name = each.value
161+
162+
dynamic "catalog_data" {
163+
for_each = length(var.public_repository_catalog_data) > 0 ? [var.public_repository_catalog_data] : []
164+
content {
165+
about_text = try(catalog_data.value[index(local.image_names, each.value)].about_text, null)
166+
architectures = try(catalog_data.value[index(local.image_names, each.value)].architectures, null)
167+
description = try(catalog_data.value[index(local.image_names, each.value)].description, null)
168+
logo_image_blob = try(catalog_data.value[index(local.image_names, each.value)].logo_image_blob, null)
169+
operating_systems = try(catalog_data.value[index(local.image_names, each.value)].operating_systems, null)
170+
usage_text = try(catalog_data.value[index(local.image_names, each.value)].usage_text, null)
171+
}
172+
}
173+
174+
tags = var.tags
175+
}

outputs.tf

+9-10
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,35 @@
1-
21
output "ecr_repository_arn" {
3-
value = aws_ecr_repository.this[local.image_names[0]].arn
4-
description = "Full ARN of the repository."
2+
description = "Full ARN of the repository"
3+
value = try(aws_ecr_repository.this[local.image_names[0]].arn, aws_ecrpublic_repository.this[local.image_names[0]].arn, null)
54
}
65

76
output "ecr_repository_name" {
8-
value = aws_ecr_repository.this[local.image_names[0]].name
7+
value = try(aws_ecr_repository.this[local.image_names[0]].name, aws_ecrpublic_repository.this[local.image_names[0]].name, null)
98
description = "Name of first repository created"
109
}
1110

1211
output "ecr_repository_registry_id" {
13-
value = aws_ecr_repository.this[local.image_names[0]].registry_id
12+
value = try(aws_ecr_repository.this[local.image_names[0]].registry_id, aws_ecrpublic_repository.this[local.image_names[0]].registry_id, null)
1413
description = "The registry ID where the repository was created."
1514
}
1615

1716
output "ecr_repository_url" {
18-
value = aws_ecr_repository.this[local.image_names[0]].repository_url
17+
value = try(aws_ecr_repository.this[local.image_names[0]].repository_url, aws_ecrpublic_repository.this[local.image_names[0]].repository_url, null)
1918
description = "URL of first repository created"
2019
}
2120

2221
output "repository_url_map" {
2322
value = zipmap(
24-
values(aws_ecr_repository.this)[*].name,
25-
values(aws_ecr_repository.this)[*].repository_url
23+
concat(values(aws_ecr_repository.this)[*].name, values(aws_ecrpublic_repository.this)[*].repository_name),
24+
concat(values(aws_ecr_repository.this)[*].repository_url, values(aws_ecrpublic_repository.this)[*].repository_uri)
2625
)
2726
description = "Map of repository names to repository URLs"
2827
}
2928

3029
output "repository_arn_map" {
3130
value = zipmap(
32-
values(aws_ecr_repository.this)[*].name,
33-
values(aws_ecr_repository.this)[*].arn
31+
concat(values(aws_ecr_repository.this)[*].name, values(aws_ecrpublic_repository.this)[*].repository_name),
32+
concat(values(aws_ecr_repository.this)[*].arn, values(aws_ecrpublic_repository.this)[*].arn)
3433
)
3534
description = "Map of repository names to repository ARNs"
3635
}

variables.tf

+12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
variable "repository_type" {
2+
description = "The type of repository to create(public or private)"
3+
type = string
4+
default = "private"
5+
}
6+
17
variable "image_names" {
28
type = list(string)
39
default = []
@@ -64,3 +70,9 @@ variable "tags" {
6470
type = map(any)
6571
default = {}
6672
}
73+
74+
variable "public_repository_catalog_data" {
75+
description = "Catalog data configuration for the public repository"
76+
type = any
77+
default = {}
78+
}

versions.tf

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ terraform {
33
required_providers {
44
aws = {
55
source = "hashicorp/aws"
6-
version = "~> 4.31.0"
6+
version = "~> 5.31.0"
77
}
88
}
99
}

0 commit comments

Comments
 (0)