Skip to content
Merged
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
164 changes: 155 additions & 9 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion examples/pull-through-cache/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,4 @@ terraform destroy
## Cost Considerations

- Storage costs apply to cached images
- Use lifecycle policies to manage storage costs
- Use lifecycle policies to manage storage costs
2 changes: 1 addition & 1 deletion modules/pull-through-cache/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,4 @@ module "pull_through_cache" {
| Name | Description |
|------|-------------|
| pull_through_cache_rules | List of pull-through cache rules |
| pull_through_cache_role_arn | The ARN of the IAM role used for pull-through cache operations |
| pull_through_cache_role_arn | The ARN of the IAM role used for pull-through cache operations |
58 changes: 29 additions & 29 deletions scripts/migrate-to-foreach.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Migration Script: Count to For_Each Pattern Migration
# terraform-aws-ecr module v0.27.x -> v0.28.x+
#
# This script helps migrate terraform state from count-based resources
# This script helps migrate terraform state from count-based resources
# to for_each-based resources in the terraform-aws-ecr module.
#
# Usage: ./migrate-to-foreach.sh [module_name]
Expand Down Expand Up @@ -50,7 +50,7 @@ safe_state_mv() {
local from="$1"
local to="$2"
local description="$3"

if resource_exists "$from"; then
log_info "Migrating: $description"
if terraform state mv "$from" "$to"; then
Expand All @@ -68,20 +68,20 @@ safe_state_mv() {
main() {
log_info "Starting terraform-aws-ecr migration from count to for_each patterns"
log_info "Module name: $MODULE_NAME"

# Step 1: Validate prerequisites
log_info "Checking prerequisites..."

if ! command -v terraform &> /dev/null; then
log_error "Terraform not found. Please install Terraform."
exit 1
fi

if ! terraform version | grep -E "Terraform v(1\.|[2-9]\.)"; then
log_error "Terraform 1.0+ required. Please upgrade Terraform."
exit 1
fi

# Step 2: Create state backup
log_info "Creating state backup: $BACKUP_FILE"
if terraform state pull > "$BACKUP_FILE"; then
Expand All @@ -90,7 +90,7 @@ main() {
log_error "Failed to create state backup"
exit 1
fi

# Step 3: Validate current state
log_info "Validating current state..."
if ! terraform plan -detailed-exitcode > /dev/null 2>&1; then
Expand All @@ -102,101 +102,101 @@ main() {
exit 0
fi
fi

# Step 4: Execute migrations
log_info "Starting resource migrations..."

# CloudWatch Monitoring Resources
log_info "Migrating CloudWatch monitoring resources..."
safe_state_mv "module.${MODULE_NAME}.aws_cloudwatch_metric_alarm.repository_storage_usage[0]" \
"module.${MODULE_NAME}.aws_cloudwatch_metric_alarm.monitoring[\"storage_usage\"]" \
"Storage usage alarm"

safe_state_mv "module.${MODULE_NAME}.aws_cloudwatch_metric_alarm.api_call_volume[0]" \
"module.${MODULE_NAME}.aws_cloudwatch_metric_alarm.monitoring[\"api_call_volume\"]" \
"API call volume alarm"

safe_state_mv "module.${MODULE_NAME}.aws_cloudwatch_metric_alarm.image_push_count[0]" \
"module.${MODULE_NAME}.aws_cloudwatch_metric_alarm.monitoring[\"image_push_count\"]" \
"Image push count alarm"

safe_state_mv "module.${MODULE_NAME}.aws_cloudwatch_metric_alarm.image_pull_count[0]" \
"module.${MODULE_NAME}.aws_cloudwatch_metric_alarm.monitoring[\"image_pull_count\"]" \
"Image pull count alarm"

safe_state_mv "module.${MODULE_NAME}.aws_cloudwatch_metric_alarm.security_findings[0]" \
"module.${MODULE_NAME}.aws_cloudwatch_metric_alarm.monitoring[\"security_findings\"]" \
"Security findings alarm"

# SNS Resources
log_info "Migrating SNS resources..."
safe_state_mv "module.${MODULE_NAME}.aws_sns_topic.ecr_monitoring[0]" \
"module.${MODULE_NAME}.aws_sns_topic.ecr_monitoring[\"ecr_monitoring\"]" \
"SNS topic"

# SNS Subscriptions (check up to 10 subscriptions)
log_info "Migrating SNS subscriptions..."
for i in {0..9}; do
safe_state_mv "module.${MODULE_NAME}.aws_sns_topic_subscription.ecr_monitoring_email[$i]" \
"module.${MODULE_NAME}.aws_sns_topic_subscription.ecr_monitoring_email[\"subscription-$i\"]" \
"SNS subscription $i"
done

# Auxiliary Resources
log_info "Migrating auxiliary resources..."

# KMS Module
safe_state_mv "module.${MODULE_NAME}.module.kms[0]" \
"module.${MODULE_NAME}.module.kms[\"kms\"]" \
"KMS module"

# Logging Resources
safe_state_mv "module.${MODULE_NAME}.aws_cloudwatch_log_group.ecr_logs[0]" \
"module.${MODULE_NAME}.aws_cloudwatch_log_group.ecr_logs[\"log_group\"]" \
"CloudWatch log group"

safe_state_mv "module.${MODULE_NAME}.aws_iam_role.ecr_logging[0]" \
"module.${MODULE_NAME}.aws_iam_role.ecr_logging[\"iam_role\"]" \
"IAM logging role"

# Replication Configuration
safe_state_mv "module.${MODULE_NAME}.aws_ecr_replication_configuration.replication[0]" \
"module.${MODULE_NAME}.aws_ecr_replication_configuration.replication[\"replication\"]" \
"Replication configuration"
# Registry Scanning Configuration

# Registry Scanning Configuration
safe_state_mv "module.${MODULE_NAME}.aws_ecr_registry_scanning_configuration.scanning[0]" \
"module.${MODULE_NAME}.aws_ecr_registry_scanning_configuration.scanning[\"scanning\"]" \
"Registry scanning configuration"

# Pull-Through Cache Module
safe_state_mv "module.${MODULE_NAME}.module.pull_through_cache[0]" \
"module.${MODULE_NAME}.module.pull_through_cache[\"cache\"]" \
"Pull-through cache module"

# Step 5: Validate migration
log_info "Validating migration..."

if terraform plan -detailed-exitcode > /dev/null 2>&1; then
log_success "Migration completed successfully! No resource changes detected."
else
log_warning "Migration completed, but terraform plan shows changes."
log_info "This may be normal if you've updated module version or configuration."
log_info "Run 'terraform plan' to review the changes."
fi

# Step 6: Show summary
log_info "Migration Summary:"
log_info "- Backup created: $BACKUP_FILE"
log_info "- Module migrated: $MODULE_NAME"
log_info "- Migration completed: $(date)"

log_success "Migration completed successfully!"
log_info "Next steps:"
log_info "1. Run 'terraform plan' to review any configuration changes"
log_info "2. Run 'terraform apply' if needed"
log_info "3. Update your module version to 0.28.x+ in your configuration"

# Cleanup suggestion
echo
read -p "Keep state backup file $BACKUP_FILE? (Y/n): " -n 1 -r
Expand Down Expand Up @@ -271,4 +271,4 @@ case "${1:-}" in
*)
main
;;
esac
esac
8 changes: 4 additions & 4 deletions scripts/terraform-move-commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# Storage usage alarm
terraform state mv 'module.ecr.aws_cloudwatch_metric_alarm.repository_storage_usage[0]' 'module.ecr.aws_cloudwatch_metric_alarm.monitoring["storage_usage"]'

# API call volume alarm
# API call volume alarm
terraform state mv 'module.ecr.aws_cloudwatch_metric_alarm.api_call_volume[0]' 'module.ecr.aws_cloudwatch_metric_alarm.monitoring["api_call_volume"]'

# Image push count alarm
Expand Down Expand Up @@ -50,7 +50,7 @@ terraform state mv 'module.ecr.aws_sns_topic_subscription.ecr_monitoring_email[2
terraform state mv 'module.ecr.module.kms[0]' 'module.ecr.module.kms["kms"]'

# =============================================================================
# Logging Resources
# Logging Resources
# =============================================================================
# Only run these if var.enable_logging = true

Expand Down Expand Up @@ -125,5 +125,5 @@ terraform state mv 'module.ecr.module.pull_through_cache[0]' 'module.ecr.module.
# Example for module named "app1_ecr":
# terraform state mv 'module.app1_ecr.aws_cloudwatch_metric_alarm.repository_storage_usage[0]' 'module.app1_ecr.aws_cloudwatch_metric_alarm.monitoring["storage_usage"]'

# Example for module named "app2_ecr":
# terraform state mv 'module.app2_ecr.aws_cloudwatch_metric_alarm.repository_storage_usage[0]' 'module.app2_ecr.aws_cloudwatch_metric_alarm.monitoring["storage_usage"]'
# Example for module named "app2_ecr":
# terraform state mv 'module.app2_ecr.aws_cloudwatch_metric_alarm.repository_storage_usage[0]' 'module.app2_ecr.aws_cloudwatch_metric_alarm.monitoring["storage_usage"]'
56 changes: 28 additions & 28 deletions scripts/validate-migration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ resource_exists() {
check_old_resources() {
local resource_type="$1"
local description="$2"

log_check "Checking for old $description resources..."

local old_resources=$(terraform state list | grep "$resource_type\[" || true)

if [[ -z "$old_resources" ]]; then
log_success "No old $description resources found"
else
Expand All @@ -77,12 +77,12 @@ check_new_resources() {
local resource_pattern="$1"
local description="$2"
local expected_count="$3"

log_check "Checking for new $description resources..."

local new_resources=$(terraform state list | grep "$resource_pattern" || true)
local actual_count=$(echo "$new_resources" | grep -v '^$' | wc -l)

if [[ $actual_count -gt 0 ]]; then
log_success "Found $actual_count new $description resource(s)"
if [[ -n "$expected_count" && $actual_count -ne $expected_count ]]; then
Expand All @@ -97,7 +97,7 @@ check_new_resources() {
# Validate terraform configuration
validate_terraform() {
log_check "Validating Terraform configuration..."

if terraform validate > /dev/null 2>&1; then
log_success "Terraform configuration is valid"
else
Expand All @@ -109,10 +109,10 @@ validate_terraform() {
# Check terraform plan
check_terraform_plan() {
log_check "Checking Terraform plan for unexpected changes..."

local plan_output=$(terraform plan -detailed-exitcode 2>&1)
local exit_code=$?

case $exit_code in
0)
log_success "No changes detected - migration successful!"
Expand All @@ -133,26 +133,26 @@ main() {
log_info "Starting migration validation for terraform-aws-ecr module"
log_info "Module name: $MODULE_NAME"
log_info "Timestamp: $(date)"

# Prerequisites check
log_info "Checking prerequisites..."

if ! command -v terraform &> /dev/null; then
log_error "Terraform not found. Please install Terraform."
exit 1
fi

if ! terraform state list > /dev/null 2>&1; then
log_error "No Terraform state found. Ensure you're in the correct directory."
exit 1
fi

# Validate Terraform configuration
validate_terraform

# Check for old count-based resources (should be gone)
log_info "Checking for old count-based resources..."

check_old_resources "module\.${MODULE_NAME}\.aws_cloudwatch_metric_alarm\.repository_storage_usage\[" "storage usage alarm"
check_old_resources "module\.${MODULE_NAME}\.aws_cloudwatch_metric_alarm\.api_call_volume\[" "API call volume alarm"
check_old_resources "module\.${MODULE_NAME}\.aws_cloudwatch_metric_alarm\.image_push_count\[" "image push count alarm"
Expand All @@ -166,10 +166,10 @@ main() {
check_old_resources "module\.${MODULE_NAME}\.aws_ecr_replication_configuration\.replication\[" "replication configuration"
check_old_resources "module\.${MODULE_NAME}\.aws_ecr_registry_scanning_configuration\.scanning\[" "registry scanning configuration"
check_old_resources "module\.${MODULE_NAME}\.module\.pull_through_cache\[" "pull-through cache module"

# Check for new for_each-based resources
log_info "Checking for new for_each-based resources..."

check_new_resources "module\.${MODULE_NAME}\.aws_cloudwatch_metric_alarm\.monitoring\[" "CloudWatch alarms" "5"
check_new_resources "module\.${MODULE_NAME}\.aws_sns_topic\.ecr_monitoring\[" "SNS topics" "1"
check_new_resources "module\.${MODULE_NAME}\.aws_sns_topic_subscription\.ecr_monitoring_email\[" "SNS subscriptions"
Expand All @@ -179,10 +179,10 @@ main() {
check_new_resources "module\.${MODULE_NAME}\.aws_ecr_replication_configuration\.replication\[" "replication configurations" "1"
check_new_resources "module\.${MODULE_NAME}\.aws_ecr_registry_scanning_configuration\.scanning\[" "registry scanning configurations" "1"
check_new_resources "module\.${MODULE_NAME}\.module\.pull_through_cache\[" "pull-through cache modules" "1"

# Check resource addressing patterns
log_info "Validating resource addressing patterns..."

# Check CloudWatch alarms use correct keys
local alarm_resources=$(terraform state list | grep "module\.${MODULE_NAME}\.aws_cloudwatch_metric_alarm\.monitoring\[" || true)
if [[ -n "$alarm_resources" ]]; then
Expand All @@ -196,36 +196,36 @@ main() {
fi
done
fi

# Check SNS topic uses correct key
if resource_exists "module.${MODULE_NAME}.aws_sns_topic.ecr_monitoring[\"ecr_monitoring\"]"; then
log_success "SNS topic uses correct for_each key: ecr_monitoring"
fi

# Check module keys
local module_keys=("kms" "cache")
for key in "${module_keys[@]}"; do
local kms_resource="module.${MODULE_NAME}.module.kms[\"$key\"]"
local cache_resource="module.${MODULE_NAME}.module.pull_through_cache[\"$key\"]"

if resource_exists "$kms_resource"; then
log_success "KMS module uses correct for_each key: $key"
fi

if resource_exists "$cache_resource"; then
log_success "Pull-through cache module uses correct for_each key: $key"
fi
done

# Final terraform plan check
check_terraform_plan

# Summary
log_info "Validation Summary:"
log_info "- Total checks: $TOTAL_CHECKS"
log_success "- Passed: $PASSED_CHECKS"
log_error "- Failed: $FAILED_CHECKS"

if [[ $FAILED_CHECKS -eq 0 ]]; then
log_success "🎉 Migration validation completed successfully!"
log_info "Your terraform-aws-ecr module has been successfully migrated to for_each patterns."
Expand All @@ -235,7 +235,7 @@ main() {
log_info "You may need to run additional 'terraform state mv' commands."
exit 1
fi

# Additional recommendations
echo
log_info "Post-migration recommendations:"
Expand Down Expand Up @@ -292,4 +292,4 @@ case "${1:-}" in
*)
main
;;
esac
esac
Loading
Loading