Ludo
Ludo

Reputation: 5280

File not found when trying to use etag

I am trying to use etag when i update my bucket S3, but i get this error:

Error: Error in function call
   on config.tf line 48, in resource "aws_s3_bucket_object" "bucket_app":
   48:   etag = filemd5("${path.module}/${var.env}/app-config.json")
     |----------------
     | path.module is "."
     | var.env is "develop"
 Call to function "filemd5" failed: no file exists at develop/app-config.json.

However, this works fine:

resource "aws_s3_bucket_object" "bucket_app" {
  bucket = "${var.app}-${var.env}-app-assets"
  key    = "config.json"
  source = "${path.module}/${var.env}/app-config.json"

  // etag = filemd5("${path.module}/${var.env}/app-config.json")

  depends_on = [
    local_file.app_config_json
  ]
}

I am genereting the file this way:

resource "local_file" "app_config_json" {
  content  = local.app_config_json
  filename = "${path.module}/${var.env}/app-config.json"
}

I really don't get what i am doing wrong...

Upvotes: 3

Views: 4844

Answers (2)

Mike Dalrymple
Mike Dalrymple

Reputation: 1111

If you happen to arrive here and are using an archive_file Data Source, there is an exported attribute called output_md5. This seems to provide the same results that you would get from filemd5(data.archive_file.app_config_json.output_path).

Here is a full example:

data archive_file config {
  type        = "zip"
  output_path = "${path.module}/config.zip"
  source {
    filename = "config/template-configuration.json"
    content  = "some content"
  }
}

resource aws_s3_bucket_object config{
  bucket       = aws_s3_bucket.stacks.bucket
  key          = "config.zip"
  content_type = "application/zip"
  source       = data.archive_file.config.output_path
  etag         = data.archive_file.config.output_md5
}

Upvotes: 10

Martin Atkins
Martin Atkins

Reputation: 74209

All functions in Terraform run during the initial configuration processing, not during the graph walk. For all of the functions that read files on disk, that means that the files must be present on disk prior to running Terraform as part of the configuration itself -- usually, checked in to version control -- rather than being generated dynamically during the Terraform operation.

The documentation for [file], which filemd5 builds on, has the following to say about it:

This function can be used only with files that already exist on disk at the beginning of a Terraform run. Functions do not participate in the dependency graph, so this function cannot be used with files that are generated dynamically during a Terraform operation. We do not recommend using dynamic local files in Terraform configurations, but in rare situations where this is necessary you can use the local_file data source to read files while respecting resource dependencies.

As the documentation there suggests, the local_file data source provides a way to read a file into memory as a resource during the graph walk, although its result would still need to be passed to md5 to get the result you needed here.

Because you're creating the file with a local_file resource anyway, you can skip the need for the additional data resource and derive the MD5 hash directly from your local_file.app_config_json resource:

resource "aws_s3_bucket_object" "bucket_app" {
  bucket = "${var.app}-${var.env}-app-assets"
  key    = "config.json"
  source = local_file.app_config_json.filename
  etag   = md5(local_file.app_config_json.content)
}

Note that we don't need to use depends_on if we derive the configuration from attributes of the local_file.app_config_json resource, because Terraform can therefore already see that the dependency relationship exists.

Upvotes: 7

Related Questions