0

I'm trying to create a module for Sagemaker endpoints. There's an optional object variable called async_inference_config. If you omit it, the endpoint being deployed is synchronous, but if you include it, the endpoint deployed is asynchronous. To satisfy both of these usecases, the async_inference_config needs to be an optional block.

I am unsure of how to make this block optional though.
Any guidance would be greatly appreciated. See example below of structure of the optional parameter.

Example:

resource "aws_sagemaker_endpoint_configuration" "sagemaker_endpoint_configuration" {
  count = var.create ? 1 : 0

  name = var.endpoint_configuration_name
  production_variants {
    instance_type          = var.instance_type
    initial_instance_count = var.instance_count
    model_name             = var.model_name
    variant_name           = var.variant_name
  }
  async_inference_config {
    output_config {
      s3_output_path = var.s3_output_path
    }
    client_config {
      max_concurrent_invocations_per_instance = var.max_concurrent_invocations_per_instance
    }
  }
  lifecycle {
    create_before_destroy = true
    ignore_changes        = ["name"]
  }

  tags = var.tags

  depends_on = [aws_sagemaker_model.sagemaker_model]
}

Update: What I tried based on the below suggestion, which seemed to work

dynamic "async_inference_config" {
    for_each = var.async_inference_config == null ? [] : [true]
    content {
      output_config {
        s3_output_path = lookup(var.async_inference_config, "s3_output_path", null)
      }
      client_config {
        max_concurrent_invocations_per_instance = lookup(var.async_inference_config, "max_concurrent_invocations_per_instance", null)
      }
    }
  }

1 Answer 1

2

You could use a dynamic block [1] in combination with for_each meta-argument [2]. It would look something like:

dynamic "async_inference_config" {
    for_each = var.s3_output_path != null && var.max_concurrent_invocations_per_instance != null ? [1] : []
    content {
    output_config {
      s3_output_path = var.s3_output_path
    }
    client_config {
      max_concurrent_invocations_per_instance = var.max_concurrent_invocations_per_instance
    }
  }
}

Of course, you could come up with a different variable, say enable_async_inference_config (probalby of type bool) and base the for_each on that, e.g.:

dynamic "async_inference_config" {
    for_each = var.enable_async_inference_config ? [1] : []
    content {
    output_config {
      s3_output_path = var.s3_output_path
    }
    client_config {
      max_concurrent_invocations_per_instance = var.max_concurrent_invocations_per_instance
    }
  }
}

[1] https://www.terraform.io/language/expressions/dynamic-blocks

[2] https://www.terraform.io/language/meta-arguments/for_each

Sign up to request clarification or add additional context in comments.

13 Comments

I'm getting an error: │ The argument "async_inference_config.0.output_config.0.s3_output_path" is required, but no definition was found. I set the s3_output_path as null in the variables.tf
Which method did you go for, the one with a new variable or the one with multiple variables in for_each?
I tried both. I adapted your suggestion and used lookups. Added an update in the original post. Not sure if that's best practice though. I'm a terraform novice.
If I were to choose, I would go with the second approach. Which combination of parameters caused the error?
Both approaches complained of the same error. Was saying I needed to make the s3_output_path non null and a string greater than length 1
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.