Global Context
Create context prompting questionnaires to be used within blueprint-created resources or standing alone in non-resourcely created terraforms.
Global Contexts are context-prompting questionnaires used to gather data from developers before provisioning a resource. Global Contexts are designed to gather and store insightful data related to the resource that will be generated. Some examples include:
What type of data will be stored in this infrastructure?
In which environment(s) will this infrastructure be deployed?
What application is this infrastructure associated with?
What is the email address of the person/team responsible for this infrastructure?

You can create your own Global Contexts and apply them to your Blueprint(s) so that they must be filled out before infrastructure is provisioned. Global Contexts can be defined with the following properties:
Single Choice
Multiple Choice
Text Field
Answers from .resourcely.yaml
.resourcely.yaml can provide answers to global context questions for the whole config root, or for individual enviornments. These answers apply to every resource in the config root or enviornment.
In the Create form, Resourcely will automatically fill in the answers to these global context questions. Users cannot change answers that came from .resourcely.yaml
.

Resource-level answers
When users answer Global Context Questions in the Create form, Resourcely stores the answers in your Terraform code. The answers are stored in a specific data structure, documented below, that minimizes repetition.
Developers can edit these answers outside of Resourcely. Answers can apply to any resource, even ones created outside Resourcely.
By default, Resourcely stores context answers in resourcely.tf
. If you move the answers to a different file, Resourcely will leave them where you put them.
The answers are structured like this:
# Each config root contains zero or one of these blocks. The name of the block must
# be resourcely_context_answers.
resource "terraform_data" "resourcely_context_answers" {
# input is a required property
# It must be an object.
input = {
# version is a required property.
# The only valid version is 1.
"version": 1,
# data is a required property.
# It must be a list of objects.
"data": [
# Each object represents a set of answers that apply to a set of resources.
# Values within the object must be a string or list of strings.
# A string and 1-item list are logically equivalent.
{
# $applies_to is required in each object.
# The value lists the resources (or resource) that these answers apply to.
"$applies_to": "resource.aws_instance.log_ingester",
# The rest of the data in the object represents answers.
# Each key is a global context question label.
# Each value is the answer to the global context question for the resources
# in $applies_to.
"is_customer_facing": "false"
},
# You can have as many objects as you need. Each object can answer a different
# set of questions (and provide different answers).
{
# The answers from this object apply to multiple resources.
"$applies_to": [
"resource.aws_s3_bucket.website_assets",
"resource.aws_s3_bucket_public_access_block.website_assets",
],
# This global context question was a multiple-choice question.
"team": ["frontend", "translation"],
}
]
}
}
Using Global Context Questions with Guardrails
Guardrails can reference the answers to global context questions when evaluating a resource. Writing Guardrails with Really describes this feature in detail. There are several best practices for creating and maintaining global context questions used by guardrails.
Here is an example guardrail that we'll use to talk about best practices.
GUARDRAIL "Bucket naming convention"
WHEN aws_s3_bucket AND CONTEXT is_customer_facing = "false"
REQUIRE bucket STARTS WITH CONTEXT team
This guardrail enforces a naming convention on S3 buckets, except when a customer could see the bucket's name (e.g. website buckets). It references two global context questions that might have different answers for each S3 bucket.
Question type
When a guardrail references a context answer in the WHEN clause, avoid using Text Field questions. In our example, is_customer_facing
should be a Single Choice question, with the choices true
and false
. If it were a Text Field, a spelling or capitalization error would trigger unwanted guardrail behavior.
The team
question, on the other hand, can be a Text Field with no drawbacks.
Blueprint categories
When a context-sensitive guardrail evaluates a resource, and the resource does not have an answer that the guardrail needs, it fails safe. Resourcely will request approval from the guardrail's approver group, the same as if the guardrail was violated.
Every Global Context Question is associated with a set of blueprints. This association is computed using the Question's categories and the Blueprint's categories. In our example, both Questions should include the Blob Storage category. Additionally, any Blueprint that creates an S3 bucket should include the Blob Storage category. This will ensure that all S3 buckets have an answer for is_customer_facing
and team
.
Note that answers from .resourcely.yaml apply to every resource in the config root, so they don't have the same concerns.
Changing a label
Guardrails reference global context questions by their label. This makes changing an existing label potentially dangerous.
Due to the fail-safe behavior described above, label changes can cause guardrails to request large numbers of approvals. Resourcely recommends against changing the labels of actively in-use questions.
Let's see what happens when we change the label of team
to org
.
Resourcely does not automatically update guardrails when a context question label changes. The next time a developer creates an S3 bucket through Resourcely, it will have an answer for org
, but not team
. The guardrail will fail-safe and request an approval.
Now let's assume we make corresponding changes to the guardrail:
REQUIRE bucket STARTS WITH CONTEXT org
This solves the problem for new buckets, but what about pre-existing buckets? Those have an answer for team
, but not org
. When a developer makes changes to a pre-existing bucket, the guardrail will fail-safe again!
You can solve both problems by using OPTIONAL CONTEXT
and referencing both labels:
REQUIRE bucket STARTS WITH OPTIONAL CONTEXT team OR bucket STARTS WITH CONTEXT org
Last updated