Configuring stack
Stacktape is an Infrastructure as a Code tool, building on top of the many advantages of this approach.
For people coming from a world of ClickOps (clicking in a GUI to create resources), this might seem inconvenient.
This is why most of the Stacktape configuration can also be done using an interactive config editor (GUI). You will learn more about it on the next page.
1. Configure resources
Resources are defined within the resources
section of the template.
Every resource must have a unique name within the template. You can only use alphanumeric for the resource names.
Every Stacktape resource translates to multiple underlying AWS CloudFormation resources.
Example web service configuration:
Copy
resources:webService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: ./src/server.tsresources:cpu: 0.5memory: 2048
2. Configure packaging
For compute resources (the ones that run your code), you must configure how they will be packaged. Stacktape supports multiple packaging methods.
Stacktape has built-in, content-aware hashing mechanism, that will only build and re-deploy your workloads if the application code or its dependencies have changed.
2.1 Packaging containers
2.1.1 Stacktape image buildpack
For Node.js application, Stacktape buildpack is probably the fastest and most efficient build tool out there. It creates smallest possible images that only contain the code necessary for your application to work.
Note that if your application also need other files (such as graphql schema file) in order to run, please explicitly
specify them using includeFiles
.
Stacktape image buildpacks offer a heavily optimized way to package your applications directly from source code. You configure the entryfile of your application, and Stacktape will figure out how to create a Docker image out of it, including all of the application dependencies.
Currently supported languages are: Javascript, Typescript, Python, Java and Go.
Copy
resources:webService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: ./src/server.ts
2.1.2 External buildpack
You can use any of the builders supported by pack.
For example, you can use builder paketobuildpacks/builder-jammy-base
, which will automatically detect which
paketo buildpack to use.
You can also use heroku builder heroku/builder:22
, which will automatically detect which
heroku buildpack to use.
Copy
resources:webService:type: web-serviceproperties:packaging:type: external-buildpackproperties:builder: heroku/builder:22sourceDirectoryPath: ./
2.1.3 Custom Dockerfile
You can also use your own Dockerfile.
Copy
resources:webService:type: web-serviceproperties:packaging:type: custom-dockerfileproperties:# All "COPY" instruction in the Dockerfile will be resolved relatively to this directorybuildContextPath: ./# Path to the Dockerfile (relative to buildContextPath)dockerfilePath: ./Dockerfile
2.1.4 Prebuilt image
You can also use your own prebuilt image from the docker repository.
Copy
resources:webService:type: web-serviceproperties:packaging:type: prebuilt-imageproperties:# The format is {registryUri}/{repositoryName}:{tag}image: repoUri/repoName:tag
2.2 Packaging lambda functions
2.2.1 Stacktape lambda buildpack
Stacktape can also automatically and very efficiently package your lambda functions (with all of their dependencies).
Currently supported languages are: Javascript, Typescript, Python, Java and Go.
Copy
resources:webService:type: web-serviceproperties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: ./src/my-lambda.ts
2.2.2 Custom artifact
If you build your lambda functions on your own, simply point Stacktape to the pre-built lambda artifact.
Copy
resources:webService:type: web-serviceproperties:packaging:type: custom-artifactproperties:packagePath: ./my-artifact.zip
3. Connect resources
Some Stacktape resources can be connected to other resources to allow interaction between them. Connecting resources does 2 things:
- Injects environment variables required for connecting to a resource. The name of the injected environment variables is
formed as CONSTANT_CASE resource name, prefixed by
STP
- When needed, required IAM and security group permissions are automatically added to allow communication between resources.
For example, you can connect your Web service to a SQL database.
This will:
- inject environment variables
STP_MAIN_DATABASES_CONNECTION_STRING
,STP_MAIN_DATABASES_HOST
andSTP_MAIN_DATABASES_PORT
to the environment of webService
Copy
resources:webService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: ./src/server.tsresources:cpu: 0.5memory: 2048connectTo:- mainDatabasemainDatabase:type: relational-databaseproperties: ...more-properties...
Or to connect a lambda function to a DynamoDb table. This will:
- inject environment variables
STP_DYNAMO_DB_NAME
andSTP_DYNAMO_DB_ARN
to the environment of myLambda function - add get / put / update / delete / scan / query IAM permissions to the myLambda function
Copy
resources:myLambda:type: functionproperties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: ./src/my-lambda.tsconnectTo:- dynamoDbdynamoDb:type: dynamo-db-tableproperties:primaryKey:partitionKey:name: idtype: string
4. Configure scripts and hooks
4.1 Scripts
Scripts are used to specify and execute your custom scripts and commands. Scripts can be used for anything from testing and building your application to performing database migrations. Specifying a script in the Stacktape config can be beneficial for multiple reasons:
- scripts will be easily reusable by all members of your team,
- scripts can be executed automatically within lifecycle hooks (before/after deploy/delete etc.) or manually using script:run command,
- you can use
connectTo
property to easily inject environment variables needed for connecting to resources of your stack, - you can leverage bastion scripts and bastion tunneling to access resources which are only accessible within VPC.
Copy
scripts:buildWeb:type: local-scriptproperties:executeCommand: npx gatsby buildresources:webBucket:type: hosting-bucketproperties:uploadDirectoryPath: ./publichostingContentType: gatsby-static-website
To learn more, refer to this dedicated page about scripts.
4.2 Hooks
- Hooks allow you to execute a custom command or script before or after stacktape command is executed.
- Example use cases:
- build, validate, or lint your application before deployment
- run unit tests on your application before deployment
- execute database migration after deployment
- cleanup database before delete
The following snippet shows an example script that executes database schema migration. The script is listed in the
afterDeploy
hooks to execute migration after each deployment.
Copy
scripts:migrateDb:type: local-scriptproperties:executeCommand: npx prisma db pushconnectTo:- mainDatabasehooks:afterDeploy:- scriptName: migrateDbresources:mainDatabase:type: relational-databaseproperties:credentials:masterUserName: admin_usermasterUserPassword: $Secret('my-pass')engine:type: postgresproperties:primaryInstance:instanceSize: db.t4g.microversion: "15.5"
To learn more, refer to this dedicated page about hooks.
5. Extend using CloudFormation
You can use the cloudformationResources
section to extend your Stacktape template with AWS Cloudformation resources.
This enables you to easily configure, manage, and interconnect Cloudformation resources with other resources in your
stack. As a result, you can leverage the full power of AWS in a single unit configuration.
Copy
# stacktape resourcesresources:myLambda:type: functionproperties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: ./src/my-lambda.tsenvironment:name: MONITOR_ARN# passing value from Cloudformation resourcevalue: $CfResourceParam('AnomalyServiceMonitor', 'MonitorArn')# Cloudformation resourcescloudformationResources:AnomalyServiceMonitor:Type: "AWS::CE::AnomalyMonitor"Properties:MonitorName: "MonitorName"MonitorType: "DIMENSIONAL"MonitorDimension: "SERVICE"# {stop-highlights}
6. Override properties
Stacktape runs on top of Cloudformation. To make your life easier, Stacktape abstracts the complexities of Cloudformation configurations and only exposes the essential parts that you need to set up your application in AWS.
However, when needed, Stacktape allows you to override the underlying Cloudformation resources to tweak and adjust low level configurations to your needs.
In the following example, we are overriding (setting) Description
property of underlying Cloudformation
AWS::Lambda::Function
resource.
Copy
resources:myFunction:type: functionproperties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: path/to/my/lambda.tsoverrides:MyFunctionFunction:Description: "My overriden lambda function description"
7. Add dynamic behavior
7.1 - Using directives
Directives can be used to add dynamic behavior to your templates. To learn more about directives, refer to directives docs.
7.1.1 - Built-in directives
Built-in directives are available for use within all of the Stacktape config files without any extra configuration.
For example, you can use built-in directives to set domain names for your web services dynamically.
Copy
resources:myHttpApi:type: http-api-gatewayproperties:customDomains:# When deploying to stage "staging", the domain will be "staging-api.mydomain.com"- domainName: $Format('{}-{}', $Stage(), 'api.mydomain.com')
7.1.2 Custom directives
You can use custom directives to further customize your templates. The following example shows how to adjust database instance size based on stage (environment).
- Write the directive code
Copy
export const getDbInstanceSize = (stage: string) => {if (stage === "production") {return "db.m5.xlarge";}return "db.t2.micro";};
- Register the directive
Copy
directives:- name: getDbInstanceSizefilePath: directives.ts:getDbInstanceSize
- Use the directive
Copy
resources:myDatabase:type: relational-databaseproperties:engine:type: postgresproperties:primaryInstance:instanceSize: $getDbInstanceSize($Stage())...more properties...
7.2 Using Javascript/Typescript configs
Besides YAML
, you can write your configuration in Javascript
and Typescript
.
If you also want to have type safety for your configurations, install @stacktape/sdk
.
Copy
npm install --dev @stacktape/sdk
For javascript files, you can use it in the following way:
Copy
/** @type {import('@stacktape/sdk').StacktapeConfig} */const config = {// your config};export default config;
For typescript files:
Copy
import { StacktapeConfig } from "@stacktape/sdk";const config: StacktapeConfig = {// your config};export default config;
You can also access other stack parameters, if you export a getConfig
function.
The function receives an object containing stack parameters and must return a valid Stacktape configuration.
The following example shows how to adjust container resources based on stage (environment).
Copy
import type { GetConfigFunction } from '@stacktape/sdk';export const getConfig: GetConfigFunction = ({ stage }) => {return {resources: {webService: {type: "web-service",properties: {resources: {cpu: stage === 'production' ? 0.5 : 2,memory: stage === 'production' ? 512 : 4096}...more properties...},}}};