Skip to content

Time out policy #4

Open
wants to merge 1 commit into
base: tf-upgrade
Choose a base branch
from
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
33 changes: 33 additions & 0 deletions .terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions .tflint.hcl
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
config {
module = true
force = false
module = true
force = false
disabled_by_default = false

# ignore_module = {
# "terraform-aws-modules/vpc/aws" = true
# "terraform-aws-modules/security-group/aws" = true
# }
# ignore_module = {
# "terraform-aws-modules/vpc/aws" = true
# "terraform-aws-modules/security-group/aws" = true
# }

# varfile = ["example1.tfvars", "example2.tfvars"]
# variables = ["foo=bar", "bar=[\"baz\"]"]
# varfile = ["example1.tfvars", "example2.tfvars"]
# variables = ["foo=bar", "bar=[\"baz\"]"]
}

rule "aws_instance_invalid_type" {
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@

* 2.2.2 -- 2024-07-29
- only process image_config if enabled (default)

* 2.2.3 -- 2025-03-27
- add lifecycle time_out policy to expire images older than 365 days (default)
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ Currently, a destroy of the images (null\_resources) does **NOT** remove the rep

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.0 |
| <a name="provider_null"></a> [null](#provider\_null) | >= 1.0 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.93.0 |
| <a name="provider_null"></a> [null](#provider\_null) | 3.2.3 |

## Modules

Expand All @@ -223,6 +223,7 @@ No modules.
| [aws_ecr_lifecycle_policy.images_all](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_lifecycle_policy) | resource |
| [aws_ecr_lifecycle_policy.patterns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_lifecycle_policy) | resource |
| [aws_ecr_lifecycle_policy.prefixes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_lifecycle_policy) | resource |
| [aws_ecr_lifecycle_policy.time_out](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_lifecycle_policy) | resource |
| [aws_ecr_repository.apps_repos](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository) | resource |
| [aws_ecr_repository.image_repos](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository) | resource |
| [null_resource.copy_images](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
Expand All @@ -235,6 +236,7 @@ No modules.
| [aws_ecr_lifecycle_policy_document.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecr_lifecycle_policy_document) | data source |
| [aws_ecr_lifecycle_policy_document.patterns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecr_lifecycle_policy_document) | data source |
| [aws_ecr_lifecycle_policy_document.prefixes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecr_lifecycle_policy_document) | data source |
| [aws_ecr_lifecycle_policy_document.time_out_lifecycle](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecr_lifecycle_policy_document) | data source |
| [aws_iam_account_alias.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_account_alias) | data source |
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |

Expand All @@ -251,13 +253,14 @@ No modules.
| <a name="input_enable_lifecycle_policy"></a> [enable\_lifecycle\_policy](#input\_enable\_lifecycle\_policy) | Flag to enable/disable ECR lifecycle policy. If enabled, default is 5 most recent images (count) | `bool` | `false` | no |
| <a name="input_enable_lifecycle_policy_image_config"></a> [enable\_lifecycle\_policy\_image\_config](#input\_enable\_lifecycle\_policy\_image\_config) | Flag to enable/disable ECR lifecycle policy for images in the image\_config. If enabled, it will keep lifecycle\_policy\_keep\_count (default: 5) images | `bool` | `true` | no |
| <a name="input_force_delete"></a> [force\_delete](#input\_force\_delete) | Flag to force delete of a repository even if contains images (warning!) | `bool` | `false` | no |
| <a name="input_image_config"></a> [image\_config](#input\_image\_config) | List of image configuration objects to copy from SOURCE to DESTINATION | <pre>list(object({<br> name = string,<br> tag = string,<br> dest_path = string,<br> source_registry = string,<br> source_image = string,<br> source_tag = string,<br> enabled = bool,<br> }))</pre> | `[]` | no |
| <a name="input_image_config"></a> [image\_config](#input\_image\_config) | List of image configuration objects to copy from SOURCE to DESTINATION | <pre>list(object({<br/> name = string,<br/> tag = string,<br/> dest_path = string,<br/> source_registry = string,<br/> source_image = string,<br/> source_tag = string,<br/> enabled = bool,<br/> }))</pre> | `[]` | no |
| <a name="input_lifecycle_days"></a> [lifecycle\_days](#input\_lifecycle\_days) | number of days after which we automatically expire images | `string` | `365` | no |
| <a name="input_lifecycle_policy_all"></a> [lifecycle\_policy\_all](#input\_lifecycle\_policy\_all) | Flag to enable the same default policy (any, count of 5) if true | `bool` | `false` | no |
| <a name="input_lifecycle_policy_default"></a> [lifecycle\_policy\_default](#input\_lifecycle\_policy\_default) | Object with settings for selecting repositories to apply a policy for 'any'. Select repo list and number of images to keep (default: 5). | <pre>object({<br> repos = list(string)<br> count = optional(number, 5)<br> })</pre> | <pre>{<br> "count": 5,<br> "repos": []<br>}</pre> | no |
| <a name="input_lifecycle_policy_explicit"></a> [lifecycle\_policy\_explicit](#input\_lifecycle\_policy\_explicit) | Object with settings for selecting repositories to apply a policy for an explicit policy. Select repo list and number of images to keep (default: 5), and a policy defined using `data.aws_ecr_lifecycle_policy_document.{name}.json'` | <pre>object({<br> repos = list(string)<br> policy = string<br> })</pre> | <pre>{<br> "policy": null,<br> "repos": []<br>}</pre> | no |
| <a name="input_lifecycle_policy_default"></a> [lifecycle\_policy\_default](#input\_lifecycle\_policy\_default) | Object with settings for selecting repositories to apply a policy for 'any'. Select repo list and number of images to keep (default: 5). | <pre>object({<br/> repos = list(string)<br/> count = optional(number, 5)<br/> })</pre> | <pre>{<br/> "count": 5,<br/> "repos": []<br/>}</pre> | no |
| <a name="input_lifecycle_policy_explicit"></a> [lifecycle\_policy\_explicit](#input\_lifecycle\_policy\_explicit) | Object with settings for selecting repositories to apply a policy for an explicit policy. Select repo list and number of images to keep (default: 5), and a policy defined using `data.aws_ecr_lifecycle_policy_document.{name}.json'` | <pre>object({<br/> repos = list(string)<br/> policy = string<br/> })</pre> | <pre>{<br/> "policy": null,<br/> "repos": []<br/>}</pre> | no |
| <a name="input_lifecycle_policy_keep_count"></a> [lifecycle\_policy\_keep\_count](#input\_lifecycle\_policy\_keep\_count) | Number of images to keep when not specified per type of policy (default: 5) | `number` | `5` | no |
| <a name="input_lifecycle_policy_pattern"></a> [lifecycle\_policy\_pattern](#input\_lifecycle\_policy\_pattern) | Object with settings for selecting repositories to apply a policy for 'pattern'. Select repo list and number of images to keep (default: 5), and a list of patterns (will create one rule per pattern). | <pre>object({<br> count = optional(number, 5)<br> repos = list(string)<br> values = list(string)<br> })</pre> | <pre>{<br> "count": 5,<br> "repos": [],<br> "values": []<br>}</pre> | no |
| <a name="input_lifecycle_policy_prefix"></a> [lifecycle\_policy\_prefix](#input\_lifecycle\_policy\_prefix) | Object with settings for selecting repositories to apply a policy for 'prefix'. Select repo list and number of images to keep (default: 5), and a list of prefixes (will create one rule per prefix). | <pre>object({<br> count = optional(number, 5)<br> repos = list(string)<br> values = list(string)<br> })</pre> | <pre>{<br> "count": 5,<br> "repos": [],<br> "values": []<br>}</pre> | no |
| <a name="input_lifecycle_policy_pattern"></a> [lifecycle\_policy\_pattern](#input\_lifecycle\_policy\_pattern) | Object with settings for selecting repositories to apply a policy for 'pattern'. Select repo list and number of images to keep (default: 5), and a list of patterns (will create one rule per pattern). | <pre>object({<br/> count = optional(number, 5)<br/> repos = list(string)<br/> values = list(string)<br/> })</pre> | <pre>{<br/> "count": 5,<br/> "repos": [],<br/> "values": []<br/>}</pre> | no |
| <a name="input_lifecycle_policy_prefix"></a> [lifecycle\_policy\_prefix](#input\_lifecycle\_policy\_prefix) | Object with settings for selecting repositories to apply a policy for 'prefix'. Select repo list and number of images to keep (default: 5), and a list of prefixes (will create one rule per prefix). | <pre>object({<br/> count = optional(number, 5)<br/> repos = list(string)<br/> values = list(string)<br/> })</pre> | <pre>{<br/> "count": 5,<br/> "repos": [],<br/> "values": []<br/>}</pre> | no |
| <a name="input_override_prefixes"></a> [override\_prefixes](#input\_override\_prefixes) | Override built-in prefixes by component. This should be used primarily for common infrastructure things | `map(string)` | `{}` | no |
| <a name="input_profile"></a> [profile](#input\_profile) | AWS Profile Name, used generating key rotation file | `string` | n/a | yes |
| <a name="input_region"></a> [region](#input\_region) | Region in which to create the ECR repositories (default of current region) | `string` | `null` | no |
Expand Down
24 changes: 21 additions & 3 deletions ecr-lifecycle.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
locals {
default_count = var.lifecycle_policy_keep_count

default_count = var.lifecycle_policy_keep_count
default_lifecycle_days = var.lifecycle_days
lifecycle_policy_specific_repos = compact(distinct(concat(
try(var.lifecycle_policy_default.repos, []),
try(var.lifecycle_policy_prefix.repos, []),
Expand All @@ -21,6 +21,18 @@ data "aws_ecr_lifecycle_policy_document" "any" {
}
}

data "aws_ecr_lifecycle_policy_document" "time_out_lifecycle" {
rule {
priority = 9
description = format("expire images older than %v", try(var.lifecycle_days, local.default_lifecycle_days))
selection {
tag_status = "any"
count_type = "sinceImagePushed"
count_unit = "days"
count_number = var.lifecycle_days
}
}
}

data "aws_ecr_lifecycle_policy_document" "default" {
count = length(var.lifecycle_policy_default.repos) > 0 ? 1 : 0
Expand Down Expand Up @@ -92,7 +104,7 @@ data "aws_ecr_lifecycle_policy_document" "patterns" {

# set policies
resource "aws_ecr_lifecycle_policy" "all" {
for_each = var.lifecycle_policy_all ? { for k, v in aws_ecr_repository.apps_repos : k => v if ! contains(local.lifecycle_policy_specific_repos, k) } : {}
for_each = var.lifecycle_policy_all ? { for k, v in aws_ecr_repository.apps_repos : k => v if !contains(local.lifecycle_policy_specific_repos, k) } : {}
repository = each.value.name
policy = data.aws_ecr_lifecycle_policy_document.any.json
}
Expand All @@ -103,6 +115,12 @@ resource "aws_ecr_lifecycle_policy" "images_all" {
policy = data.aws_ecr_lifecycle_policy_document.any.json
}

resource "aws_ecr_lifecycle_policy" "time_out" {
for_each = var.lifecycle_policy_all ? { for k, v in aws_ecr_repository.apps_repos : k => v if !contains(local.lifecycle_policy_specific_repos, k) } : {}
repository = each.value.name
policy = data.aws_ecr_lifecycle_policy_document.any.json
}

resource "aws_ecr_lifecycle_policy" "default" {
for_each = toset(try(var.lifecycle_policy_default.repos, []))
repository = aws_ecr_repository.apps_repos[each.key].name
Expand Down
1 change: 1 addition & 0 deletions examples/lifecycle-policy-eks-cluster/images.tf
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module "images" {
lifecycle_policy_all = true
enable_lifecycle_policy_image_config = true
lifecycle_policy_keep_count = 5
lifecycle_days = 365
image_config = local.image_config
tags = merge(
local.base_tags,
Expand Down
6 changes: 6 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,9 @@ variable "force_delete" {
type = bool
default = false
}

variable "lifecycle_days" {
description = "number of days after which we automatically expire images"
type = string
default = 365
}