Skip to main content

file() Directive

The file() directive allows you to include the contents of external JSON or YAML files directly into your stackql_manifest.yml property values. This is particularly useful for modularizing large or reusable configuration blocks like IAM policy statements, role definitions, or any complex nested structures.

Syntax

file(relative/path/to/file.json)

The argument is a file path relative to the resources/ directory of your stack (the same base path used for .iql resource query files).

Supported file formats

ExtensionFormat
.jsonParsed as JSON
.yml, .yamlParsed as YAML
Other/noneTries JSON first, falls back to YAML

How it works

When the manifest is loaded, the file() directive is resolved before any template variable substitution occurs. The referenced file is read and parsed, and the resulting value (object, array, or scalar) replaces the file() string in the manifest value tree.

note

Because file() directives are resolved at manifest load time (before template rendering), the included files should contain static data only. Template variables like {{ stack_name }} in property values surrounding the file() directive will still be rendered as normal.

Usage

Including individual items in a list

You can use file() as individual items within a YAML sequence. Each directive is replaced by the parsed contents of the referenced file.

stackql_manifest.yml
resources:
- name: aws/iam/cross_account_role
file: aws/iam/iam_role.iql
props:
- name: policies
value:
- PolicyDocument:
Statement:
- file(aws/iam/policies/ec2_permissions.json)
- file(aws/iam/policies/iam_service_linked_role.json)
Version: '2012-10-17'
PolicyName: "{{ stack_name }}-{{ stack_env }}-policy"

Where resources/aws/iam/policies/ec2_permissions.json contains a single policy statement object:

resources/aws/iam/policies/ec2_permissions.json
{
"Sid": "Stmt1403287045000",
"Effect": "Allow",
"Action": [
"ec2:AllocateAddress",
"ec2:AssociateDhcpOptions",
"ec2:AssociateIamInstanceProfile",
"ec2:AssociateRouteTable",
"ec2:AttachInternetGateway",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:CreateSecurityGroup",
"ec2:CreateSubnet",
"ec2:CreateTags",
"ec2:CreateVpc",
"ec2:DeleteSecurityGroup",
"ec2:DeleteSubnet",
"ec2:DeleteVpc",
"ec2:DescribeInstances",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeVpcs",
"ec2:RunInstances",
"ec2:TerminateInstances"
],
"Resource": ["*"]
}

And resources/aws/iam/policies/iam_service_linked_role.json:

resources/aws/iam/policies/iam_service_linked_role.json
{
"Effect": "Allow",
"Action": [
"iam:CreateServiceLinkedRole",
"iam:PutRolePolicy"
],
"Resource": [
"arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot"
],
"Condition": {
"StringLike": {
"iam:AWSServiceName": "spot.amazonaws.com"
}
}
}

Replacing an entire value with a file

You can also use file() to replace an entire value, such as a complete list of statements:

stackql_manifest.yml
resources:
- name: aws/iam/cross_account_role
file: aws/iam/iam_role.iql
props:
- name: policies
value:
- PolicyDocument:
Statement: file(aws/iam/policies/cross_account_statements.json)
Version: '2012-10-17'
PolicyName: "{{ stack_name }}-{{ stack_env }}-policy"

Where resources/aws/iam/policies/cross_account_statements.json is a JSON array:

resources/aws/iam/policies/cross_account_statements.json
[
{
"Sid": "Stmt1403287045000",
"Effect": "Allow",
"Action": ["ec2:AllocateAddress", "ec2:CreateVpc", "ec2:DeleteVpc"],
"Resource": ["*"]
},
{
"Effect": "Allow",
"Action": ["iam:CreateServiceLinkedRole", "iam:PutRolePolicy"],
"Resource": ["arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot"],
"Condition": {
"StringLike": {
"iam:AWSServiceName": "spot.amazonaws.com"
}
}
}
]

Using YAML files

YAML files can be used instead of JSON, which can be more readable for some configurations:

stackql_manifest.yml
resources:
- name: aws/iam/metastore_access_role
file: aws/iam/iam_role.iql
props:
- name: policies
value:
- PolicyName: MetastoreS3Policy
PolicyDocument:
Version: '2012-10-17'
Statement: file(aws/iam/policies/metastore_statements.yaml)
resources/aws/iam/policies/metastore_statements.yaml
- Effect: Allow
Action:
- "s3:GetObject"
- "s3:PutObject"
- "s3:DeleteObject"
- "s3:ListBucket"
- "s3:GetBucketLocation"
Resource:
- "arn:aws:s3:::my-metastore-bucket/*"
- "arn:aws:s3:::my-metastore-bucket"
- Effect: Allow
Action:
- "sts:AssumeRole"
Resource:
- "arn:aws:iam::123456789012:role/my-metastore-role"

Using in globals

The file() directive also works in global variable values:

stackql_manifest.yml
globals:
- name: default_tags
value: file(common/default_tags.json)

Subdirectory organization

File paths can include subdirectories, making it easy to organize included files alongside your resource query files:

my-stack/
stackql_manifest.yml
resources/
aws/
iam/
iam_role.iql
policies/
ec2_permissions.json
iam_service_linked_role.json
metastore_statements.yaml
s3/
s3_bucket.iql

Nested file() directives

Included files can themselves contain file() directives, which will be resolved recursively. This allows you to compose configurations from multiple reusable fragments:

resources/aws/iam/policies/combined_policy.yaml
Version: '2012-10-17'
Statement:
- file(aws/iam/policies/base_permissions.json)
- file(aws/iam/policies/extra_permissions.json)

Error handling

If a file() directive references a file that does not exist or contains invalid JSON/YAML, the manifest will fail to load with a descriptive error message indicating the problematic file path and the nature of the error.