Search code examples
amazon-web-servicesamazon-s3terraformterraform-provider-aws

terraform error when creating list of s3 buckets: Inappropriate value for attribute "bucket": string required


I need to create multiple buckets in terraform with the same attributes (versioning, ownership, etc.) and don't want to copy the same text repeatedly. I also need to add and delete buckets occasionally. I tried using the below code:

# Create some buckets with the same attributes                                     
                                                                                       
locals {                                                                           
  buckets = {                                                                      
    bucket-a = "bucket-a-unique-name"                                              
    bucket-b = "bucket-b-unique-name"                                              
    bucket-c = "bucket-c-unique-name"                                              
  }                                                                                
}                                                                                  
                                                                                       
# Create the buckets                                                               
resource "aws_s3_bucket" "bucket_list" {                                           
  for_each = local.buckets                                                         
                                                                                       
  bucket = "name-is-${each.value}"                                                 
}                                                                                  

The above work works to create three buckets with the specified names:

  • name-is-bucket-a-unique-name
  • name-is-bucket-b-unique-name
  • name-is-bucket-c-unique-name

Now, I want to add versioning to each bucket, and this is where I ran into trouble:

resource "aws_s3_bucket_versioning" "versioning" {                                 
  for_each = local.buckets                                                         
                                                                                       
  bucket = aws_s3_bucket.bucket_list[each.key]                                     
                                                                                       
  versioning_configuration {                                                       
    status = "Enabled"                                                             
  }                                                                                
}  

error message:

│ Error: Incorrect attribute value type │ │ on buckets.tf line 77, in resource "aws_s3_bucket_versioning" "versioning": │ 77: bucket = aws_s3_bucket.bucket_list[each.key] │ ├──────────────── │ │ aws_s3_bucket.bucket_list is object with 3 attributes │ │ each.key is "bucket-a" │ │ Inappropriate value for attribute "bucket": string required. ╵

I know I need to refer to each specific bucket for the versioning resource, but I'm at a loss for how to do that.

I tried using the count meta argument and accomplished what I wanted, but when I later wanted to add or delete buckets no longer needed and I modified the count all of my resources are recreated. My AWS provider version is 4.6.7. Terraform version is 1.5.3.

Is there a solution for my error message or an alternative way I should approach this?


Solution

  • You need to reference the correct attribute of the resource or use resource chaining with for_each. The first example is using the id attribute of the bucket resource:

    locals {                                                                           
      buckets = {                                                                      
        bucket-a = "bucket-a-unique-name"                                              
        bucket-b = "bucket-b-unique-name"                                              
        bucket-c = "bucket-c-unique-name"                                              
      }                                                                                
    }                                                                                  
                                                                                       
    # Create the buckets                                                               
    resource "aws_s3_bucket" "bucket_list" {                                           
      for_each = local.buckets                                                         
                                                                                       
      bucket = "name-is-${each.value}"                                                 
    }                                                                                  
    
    resource "aws_s3_bucket_versioning" "versioning" {                                 
      for_each = local.buckets                                                         
                                                                                       
      bucket = aws_s3_bucket.bucket_list[each.key].id # here you reference the bucket ID attribute                               
                                                                                       
      versioning_configuration {                                                       
        status = "Enabled"                                                             
      }                                                                                
    }
    

    The second option would be to use resource chaining with for_each:

    locals {                                                                           
      buckets = {                                                                      
        bucket-a = "bucket-a-unique-name"                                              
        bucket-b = "bucket-b-unique-name"                                              
        bucket-c = "bucket-c-unique-name"                                              
      }                                                                                
    }                                                                                  
                                                                                       
    # Create the buckets                                                               
    resource "aws_s3_bucket" "bucket_list" {                                           
      for_each = local.buckets                                                         
                                                                                       
      bucket = "name-is-${each.value}"                                                 
    }                                                                                  
    
    resource "aws_s3_bucket_versioning" "versioning" {                                 
      for_each = aws_s3_bucket.bucket_list                                                         
                                                                                       
      bucket = each.value.id                               
                                                                                       
      versioning_configuration {                                                       
        status = "Enabled"                                                             
      }                                                                                
    }