context
View SourceThe Context
is a foundational piece of Stackattack. It provides a consistent way to name, tag, and organize your infrastructure resources while avoiding name collisions between resources.
What is a context?
Section titled “What is a context?”A Context is an object that encapsulates:
- Resource naming patterns - Consistent prefixes and naming conventions
- Tags - Common tags applied to all resources
- Hierarchical organization - Ability to create nested contexts for different parts of your infrastructure
The reasoning for having a context is quite simple: it allows you to abstract groups of resources into functions without name collisions. For example, without a context, if you write a function like the following:
import * as aws from '@pulumi/aws';import * as pulumi from '@pulumi/pulumi';
interface DnsRecordArgs { name: pulumi.Input<string>; zoneId: pulumi.Input<string>; ip: pulumi.Input<string>;}
function dnsRecord({ name, zoneId, ip }: DnsRecordArgs) { return new aws.route53.Record("record", { name, zoneId, type: "A", ttl: 300, records: [ip] });}
It will not work to use it multiple times in a single stack, for example:
const zoneId = aws.route53.getZoneOutput({ name: "mydomain.com" }).id;const ip1 = "71.112.12.111";const ip2 = "32.112.43.22";
const record1 = dnsRecord({ name: "server1.mydomain.com", zoneId, ip: ip1 });const record2 = dnsRecord({ name: "server2.mydomain", zoneId, ip: ip2 });
This code will fail when you run pulumi up
, because you end up with two aws.route53.Record
resources with the name “record”. You can mitigate this by, for example, passing a prefix to dnsRecord
, but stackattack’s context
provides a simple, clean way to do this in a consistent manner.
Using a context, the function might look like:
function dnsRecord(ctx: saws.Context, { name, zoneId, ip }: DnsRecordArgs) { return new aws.route53.Record(ctx.id(), { name, zoneId, type: "A", ttl: 300, records: [ip] });}
And your stack could look like:
import * as saws from '@stackattack/aws';
const ctx = saws.context();
const zoneId = aws.route53.getZoneOutput({ name: "mydomain.com" }).id;const ip1 = "71.112.12.111";const ip2 = "32.112.43.22";
const record1 = dnsRecord(ctx.prefix("record-1"), { name: "server1.mydomain.com", zoneId, ip: ip1 });const record2 = dnsRecord(ctx.prefix("record-2"), { name: "server2.mydomain", zoneId, ip: ip2 });
This illustrates a key point—contexts are not a Stackattack-specific abstraction! The concept is still useful even if you’re writing Pulumi code that doesn’t use Stackattack components at all.
Creating a Context
Section titled “Creating a Context”For typical usage, you should simply instantiate a context without any arguments:
import * as saws from "@stackattack/aws";
const ctx = saws.context();
By default, this context will generate a prefix and default tags based on your project and stack name. This approach works well because your resources will be clearly distinguishable by name in the AWS console, and the tags will make it easy to distinguish what stack and project resources belong to.
If you have more specific needs, you can create a context with a custom prefix and/or tags:
const ctx = saws.context({ prefix: "my-app", tags: { Environment: "production", Team: "platform", Project: "web-service" }});
Using Contexts
Section titled “Using Contexts”Every Stackattack component takes a Context as its first parameter:
const storage = saws.bucket(ctx, { versioned: true,});
const vpc = saws.vpc(ctx);
You can create nested contexts for different parts of your infrastructure:
const ctx = saws.context();
// Each will have appropriate naming: my-app-storage-*, my-app-database-*const s3 = saws.bucket(ctx.prefix("storage"), { versioned: true });const db = saws.database(ctx.prefix("database"), { network: vpc.network("private"), engine: "postgres" });
NOTE: all Stackattack components add default prefixes to the context you pass in by default, so it’s never necessary to use .prefix
unless you’re creating multiple instances of a single component with the same context. All components also take noPrefix: true
to disable to default prefixing behavior.
Adding Tags
Section titled “Adding Tags”You can add additional tags to a context:
const baseCtx = saws.context();
const prodCtx = baseCtx.withTags({ Environment: "production", CostCenter: "engineering"});
context
Section titled “context”Creates a new Context for consistent resource naming and tagging.
function context(opts?: ContextOpts): Context
Parameters
Section titled “Parameters”opts?
(ContextOpts
) - Optional configuration for prefix and tags
Returns
Section titled “Returns”- (
Context
) - Creates a new Context for consistent resource naming and tagging.
Functions
Section titled “Functions”defaultContextPrefix
Section titled “defaultContextPrefix”Generates a default prefix based on the current project and stack. Defaults to <project>-<stack>
, unless stack
begins with project
(e.g. project is named api
and stack is named api-prod
), in which case the default will just be stack
function defaultContextPrefix(): string
Returns
Section titled “Returns”- (
string
) - Generates a default prefix based on the current project and stack. Defaults to<project>-<stack>
, unlessstack
begins withproject
(e.g. project is namedapi
and stack is namedapi-prod
), in which case the default will just bestack
defaultContextTags
Section titled “defaultContextTags”Generates a default set of context tags based on the current project and stack, plus a Source: "pulumi"
tag.
function defaultContextTags(): Record<string, string>
Returns
Section titled “Returns”- (
Record<string, string>
) - Generates a default set of context tags based on the current project and stack, plus aSource: "pulumi"
tag.
Interfaces
Section titled “Interfaces”Context
Section titled “Context”Core context interface for resource naming and tagging in AWS infrastructure.
Properties
Section titled “Properties”id
((value?: string) => string
) - Generates a resource ID by combining the context prefix with an optional valueprefix
((value: string) =>
Context
) - Creates a new Context with an extended prefixtags
((others?: Record<string, string>) => Record<string, string>
) - Returns merged tags combining context tags with optional additional tagswithTags
((others: Record<string, string>) =>
Context
) - Creates a new Context with additional tags merged in
ContextOpts
Section titled “ContextOpts”Configuration options for creating a Context.
Properties
Section titled “Properties”prefix?
(null | string
) - Optional prefix for resource naming (defaults to project-stack combination). Defaults to<project>-<stack>
, unlessstack
begins withproject
(e.g. project is namedapi
and stack is namedapi-prod
), in which case the default will just bestack
tags?
(Record<string, string>
) - Optional tags to apply to all resources created with this context. Defaults to{ Source: "pulumi", Project: <project>, Stack: <stack> }