# What is Takomo?

Takomo helps you organize, parameterize and deploy CloudFormation stacks across multiple regions and accounts. It works equally well with smaller deployments consisting of just a few stacks and larger multi-account environments.

Takomo was inspired by Cloudreach’s excellent [Sceptre](https://sceptre.cloudreach.com/), a CloudFormation wrapper tool built with Python, and [Terraform](https://www.terraform.io/) created by Hashicorp.

## Motivation

[AWS CloudFormation](https://aws.amazon.com/cloudformation/) is a great tool to manage AWS infrastructure, but as a low-level tool, it's not sufficient alone to manage deployments spanning multiple regions and accounts. Many tools do a good job generating and deploying CloudFormation templates but lack crucial features to handle large-scale deployments.

Takomo was created to overcome challenges that arise when managing a complex AWS infrastructure with inter-stack dependencies across multiple accounts and regions.

## How Takomo works?

You specify the stacks you want to manage with Takomo in configuration files. Each file contains information about the stack, including stack name, regions, values for parameters and tags, and which template file to use.

When you run a command, Takomo starts by reading the configuration files and building a plan showing the changes it is about to execute. Once you have reviewed the plan, you can decide to cancel or proceed with the deployment. During the operation, Takomo prints stack events so you can see what is happening. Once the operation completes, Takomo presents you with a summary of changes and possible errors.

Takomo doesn't store the infrastructure's state or operations it has executed anywhere. It relies solely on the configuration files' information to match locally defined stacks with the ones found in the target accounts.

## Features

Here are Takomo's key features.

### Stack configuration

Provide configuration to your CloudFormation stacks including, input parameters, tags, region, timeouts and more. Use outputs from other stacks as input parameters to your stacks, even if the source stacks reside in different accounts or regions.

### Stack deployment

Quickly deploy all of your stacks at once or choose to deploy only a subset. Takomo understands inter-stack dependencies and deploys stacks in the correct order and parallel when possible.

### Generate IAM policies

Takomo helps you follow the principle of least privilege by providing you with a [command to generate IAM policies](/command-line-usage/generate-iam-policies) based on actions performed during your previous deployments.

### Resolve parameter values at deployment time

Avoid hard coding of parameter values to configuration files by using parameter resolvers that provide parameter values at deployment time.

Takomo comes with these built-in resolvers that resolve parameter values from:

* [Stack outputs](/parameter-resolvers/built-in-parameter-resolvers#stack-output-resolver) - use outputs from other stacks &#x20;
* [File contents](/parameter-resolvers/built-in-parameter-resolvers#file-contents-resolver) - read contents of a file
* [Shell command output](/parameter-resolvers/built-in-parameter-resolvers#command-resolver) - execute a shell command and use its output&#x20;
* [Hook output](/parameter-resolvers/built-in-parameter-resolvers#hook-output-resolver) - use value exposed by a lifecycle hook
* [SSM parameter](/parameter-resolvers/built-in-parameter-resolvers#ssm-parameter-resolver) - read value from an SSM parameter&#x20;

It's really easy to [implement your own custom resolvers](/parameter-resolvers/custom-parameter-resolvers), too!

### Dynamic templates files

Take advantage of [dynamic Handlebars templating](/variables/introduction) and avoid repetitive configuration and copy-pasting in CloudFormation templates.

### **Safe**

Avoid mistakes by reviewing changes to the configuration before deployment. Take advantage of safety features that prevent deployments to the wrong environments and accounts:

* [Enable stack termination protection](/stack-properties/termination-protection)
* [Ensure stacks are deployed only to allowed accounts](/stack-properties/account-ids)

### **Extensible**

Plug in your own JavaScript code to extend the core features. You can implement your own:

* [Parameter resolvers](/parameter-resolvers/custom-parameter-resolvers) to resolve stack parameter values at deployment time
* [Hooks](/hooks/custom-hooks) to run code at different deployment stages
* [Joi validation schemas](/validation-schemas/custom-validation-schemas) to validate your configuration
* [Handlebars helpers](/variables/helpers) to run custom code when processing configuration&#x20;

### **Continuous Integration**

Easily integrate Takomo to your CI pipeline.

### AWS organization management

Manage organizational units, member accounts, and policies of your AWS organization. You can also easily configure and deploy CloudFormation stacks to all of your accounts or choose to deploy to accounts that belong to a specified organizational unit.

* [Go to Takomo's organization management documentation](https://organizations.takomo.io)


# Installation

## System requirements

Sorry to say this, but currently, Takomo doesn't work on Windows, so you need to have Linux or Mac. Takomo is built with Node.js and requires Node.js v14.4.0 or later.

## Install as a project dependency

The recommended way to install Takomo is to add it as a development dependency in your project's package.json.

Initialize a new project if needed:

```
npm init -y
```

Add Takomo as a development dependency:

```
npm install -D takomo 
```

Verify installation:

```
npx tkm --version
```

## Global installation

You can, of course, use global installation, too.

```
npm install -g takomo
```

Verify installation:

```
tkm --version
```


# Quick start

This quick start guide will show you how to install and configure Takomo and deploy some basic infrastructure.

## AWS credentials

During this tutorial, you'll deploy some stacks, so you need an AWS account where you can safely try things out.

Create an IAM user with administrator permissions.

Next, create access keys for the IAM user and configure them to your **\~/.aws/credentials** file. Let's name our profile as **takomo-quick-start**.

```bash
[takomo-quick-start]
aws_access_key_id = ENTER_YOUR_ACCESS_KEY_ID_HERE
aws_secret_access_key = ENTER_YOUR_SECRET_ACCESS_KEY_HERE
```

## Project initialization <a href="#project-initialization" id="project-initialization"></a>

We'll start by creating a new directory for your Takomo project:

```
mkdir takomo-quick-start
```

From now on, we'll call the **takomo-quick-start** directory as project's root directory.

Change to the root directory and initialize a new NPM project:

```bash
cd takomo-quick-start
npm init -y
```

Add Takomo as a development dependency:

```bash
npm install -D takomo 
```

Initialize a new Takomo project:

```bash
npx tkm init --create-samples --project quick-start --regions eu-west-1
```

From the command output you can see what directories and files were created. You might want to take a look at the files, there isn't much to see =).

## Deploy stacks

Now that you have the project initialized, it's time to deploy the stacks. Go ahead and run the following command:

```bash
npx tkm stacks deploy --profile takomo-quick-start
```

Takomo will present you a deployment plan. Review it and continue when you are ready. Once the deployment completes, you can see a summary of what just happened.

## Clean up

You can remove the created stacks by running the following command:

```bash
npx tkm stacks undeploy --profile takomo-quick-start
```

You'll see a plan showing what will happen next. Review the plan and proceed. After the operation you'll see a summary.&#x20;


# Tutorial

Now that we have the introduction out of the way, it's time to learn how to use Takomo. The best way to learn is by doing, so let's get our hands dirty and deploy some stacks.

## What are we going to build?

Let's do something more interesting than just a trivial single stack example. Let's create a setup where we have a DynamoDB table, a VPC without internet access, a lambda function inside the VPC, and a VPC endpoint to DynamoDB to make it possible for the lambda function to access the DynamoDB table.

To make our configuration resemble a real-life use case, we'll create two separate environments: **dev** and **prod**.

Finally, we choose to deploy our stacks to the **eu-west-1** region.

## AWS credentials

During this tutorial, you'll deploy some stacks, so you need an AWS account where you can safely try things out.

Create an IAM user with administrator permissions.

Next, create access keys for the IAM user and configure them to your **\~/.aws/credentials** file. Let's name our profile as **takomo-tutorial**.

{% code title="\~/.aws/credentials" %}

```bash
[takomo-tutorial]
aws_access_key_id = ENTER_YOUR_ACCESS_KEY_ID_HERE
aws_secret_access_key = ENTER_YOUR_SECRET_ACCESS_KEY_HERE
```

{% endcode %}

## Project initialization

We'll start by creating a new directory for your Takomo project:

```bash
mkdir takomo-tutorial
```

From now on, we'll call the **takomo-tutorial** directory as project's root directory.

Change to the root directory and initialize a new NPM project:

```bash
cd takomo-tutorial
npm init -y
```

Add Takomo as a development dependency:

```bash
npm install -D takomo 
```

## Project file structure

Make sure you are in the project root directory and create two other directories under it:

```bash
mkdir stacks
mkdir templates
```

The stacks directory will contain all configuration files for your stacks, and the templates directory is where you'll place template files for the stacks.

## Stack groups

Takomo lets you organize stacks into directories under the stacks directory to group them by the environment, region, or other criteria. These directories are called stack groups. You can use them to provide configuration shared by the stacks that belong under the same stack group.

You can also nest stack groups to build tree-like hierarchies. You identify stack groups by their path, which is the file path to the stack group's directory from the stacks directory.

Let's group our stacks first by the environment and then by region. To do that, create directories under the stacks directory like so:

```bash
mkdir -p stacks/dev/eu-west-1
mkdir -p stacks/prod/eu-west-1
```

Now, you should have the following files in place:

```bash
.
├─ stacks
│  ├─ dev
│  │  └─ eu-west-1
│  └─ prod
│     └─ eu-west-1
├─ templates
└─ package.json
```

## DynamoDB stack

It's time to start adding configuration for our stacks. We begin by creating a template file for the DynamoDB table. Go ahead and create a new file for it:

```bash
touch templates/dynamodb.yml
```

Add the following contents to it:

{% code title="templates/dynamodb.yml" %}

```yaml
Parameters:
  Environment:
    Type: String
    Description: Application environment
    AllowedValues:
      - dev
      - prod

Resources:
  Table:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: !Sub my-table-${Environment}
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH

Outputs:
  TableName:
    Value: !Ref Table
  TableArn:
    Value: !GetAtt Table.Arn  
```

{% endcode %}

The template is simple; it has a single parameter for the environment used as a suffix of the DynamoDB table name.

Let's then add configuration for the dev environment's DynamoDB stack.

```bash
touch stacks/dev/eu-west-1/dynamodb.yml
```

Add the following contents to it:

{% code title="stacks/dev/eu-west-1/dynamodb.yml" %}

```yaml
regions: eu-west-1
template: dynamodb.yml
parameters:
  Environment: dev
```

{% endcode %}

In the stack configuration file, you can find three important properties.

We instruct Takomo to deploy the stack to the eu-west-1 region using the `regions` property. It's in plural form because you can deploy a single stack to multiple regions, and therefore the `regions` property accepts a single region or a list of regions.

The `template` property takes a file path relative to the templates directory and specifies which template file Takomo uses when it deploys the stack.

Finally, we provide values for the stack parameters using the `parameters` property.

You should now have the following files in place:

```bash
.
├─ stacks
│  ├─ dev
│  │  └─ eu-west-1
│  │     └─ dynamodb.yml
│  └─ prod
│     └─ eu-west-1
├─ templates
│  └─ dynamodb.yml
└─ package.json
```

## First deploy

Alright then, we are now ready to deploy our first stack. Make sure you are in the project's root directory and run the following command:

```bash
npx tkm stacks deploy --profile takomo-tutorial
```

You should see the deployment plan, and from it that you're about to deploy the DynamoDB stack.

The line printed in green displays the stack's path, which should be **/dev/eu-west-1/dynamodb.yml/eu-west-1**. The stack path is sort-of a file path to the stack's configuration file under the stacks directory and is used to identify stacks.

From the deployment plan, you can also see the stack's name, which is **dev-eu-west-1-dynamodb**. We can specify the stack name ourselves by using the `name` property, but as we didn't do that, Takomo generated the name for us from the stack path.

Choose *"continue, but let me review changes to each stack"*

You should see a stack-specific deployment plan showing changes about to be performed to the DynamoDB stack.

Choose *"continue to deploy the stack, then let me review the remaining stacks"*

The deployment should take a few seconds, and after it, you should see a deployment summary.

## VPC stack

Let's proceed to the VPC stack. Create a template for it:

```bash
touch templates/vpc.yml
```

Add the following contents to it:

{% code title="templates/vpc.yml" %}

```yaml
Parameters:
  Environment:
    Type: String
    Description: Application environment
    AllowedValues:
      - dev
      - prod
  VpcCidr:
    Type: String
    Description: VPC CIDR block

Resources:
  Vpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidr
  Subnet:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Ref VpcCidr
      VpcId: !Ref Vpc
  RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc
  RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref Subnet
      RouteTableId: !Ref RouteTable

Outputs:
  VpcId:
    Value: !Ref Vpc
  RouteTableIds:
    Value: !Ref RouteTable
  SubnetIds:
    Value: !Ref Subnet

```

{% endcode %}

Then, create the stack configuration file:

```bash
touch stacks/dev/eu-west-1/vpc.yml
```

Add the following contents to it:

{% code title="stacks/dev/eu-west-1/vpc.yml" %}

```yaml
regions: eu-west-1
template: vpc.yml
parameters:
  Environment: dev
  VpcCidr: 10.0.0.0/26
```

{% endcode %}

You should now have the following files in place:

```bash
.
├─ stacks
│  ├─ dev
│  │  └─ eu-west-1
│  │     ├─ dynamodb.yml
│  │     └─ vpc.yml
│  └─ prod
│     └─ eu-west-1
├─ templates
│  ├─ dynamodb.yml
│  └─ vpc.yml
└─ package.json
```

## Listing stacks

Let's quickly check what stacks we have configured and what's their current status:

```bash
npx tkm stacks list --profile takomo-tutorial
```

You should see two stacks: the DynamoDB stack we already deployed and the VPC stack that is still waiting for deployment.

## Second deploy

Rerun the deploy command to get also the VPC stack deployed:

```bash
npx tkm stacks deploy --profile takomo-tutorial
```

This time the deployment plan shows you both of the stacks. The DynamoDB stack already exists, and it is about to be updated. The VPC stack, on the other hand, doesn't exist yet, so Takomo needs to create it.

Choose *"continue, but let me review changes to each stack"*

The DynamoDB stack contains no changes and you don't need to confirm its deployment. Instead, you'll see the plan for the VPC stack.

Review the changes and choose *"continue to deploy the stack, then let me review the remaining stacks"*.

Like earlier, the deployment takes just a short amount of time, and you'll see the summary once it completes.

## Shared configuration

At this point, we notice that we have specified the same properties in multiple configuration files. Both of our stacks belong to the dev environment and reside in the eu-west-1 region.

Earlier, we learned that we can use stack groups to provide common configuration for multiple stacks. You provide configuration for a stack group by placing a **config.yml** file in its directory. Stacks that belong to the stack group inherit the stack group's configuration.

Let's start by creating configuration for the **/dev** stack group.

Create the configuration file:

```bash
touch stacks/dev/config.yml
```

Add the following contents to it:

{% code title="stacks/dev/config.yml" %}

```yaml
data:
  environment: dev
```

{% endcode %}

We specified the environment under the **data** property. It's an object that can contain arbitrary values.

Then, create another file for the **/dev/eu-west-1** stack group:

```yaml
touch stacks/dev/eu-west-1/config.yml
```

Add the following contents to it:

{% code title="stacks/dev/eu-west-1/config.yml" %}

```yaml
regions: eu-west-1
```

{% endcode %}

We can now remove the `regions` properties from our stack configuration files. We also need to modify the way we give value for the Environment parameter.

Update the stack configuration files to look like this:

{% code title="stacks/dev/eu-west-1/dynamodb.yml" %}

```yaml
template: dynamodb.yml
parameters:
  Environment: {{ stackGroup.data.environment }}
```

{% endcode %}

{% code title="stacks/dev/eu-west-1/vpc.yml" %}

```yaml
template: vpc.yml
parameters:
  Environment: {{ stackGroup.data.environment }}
  VpcCidr: 10.0.0.0/26
```

{% endcode %}

Notice how we refer to the values specified in the stack group.

You should now have the following files in place,:

```bash
.
├─ stacks
│  ├─ dev
│  │  ├─ config.yml
│  │  └─ eu-west-1
│  │     ├─ config.yml
│  │     ├─ dynamodb.yml
│  │     └─ vpc.yml
│  └─ prod
│     └─ eu-west-1
├─ templates
│  ├─ dynamodb.yml
│  └─ vpc.yml
└─ package.json
```

Our little configuration restructuring didn't actually change configurations of the stacks. We can verify that by deploying the stacks again. There shouldn't be any updates to the stacks.

```bash
npx tkm stacks deploy --profile takomo-tutorial
```

## VPC endpoints stack

Next, we'll add a stack for the VPC endpoint that makes it possible to use DynamoDB from the VPC without Internet access.

Create a new template file:

```bash
touch templates/vpc-endpoints.yml
```

Add the following contents to it:

{% code title="templates/vpc-endpoints.yml" %}

```yaml
Parameters:
  Environment:
    Type: String
    Description: Application environment
    AllowedValues:
      - dev
      - prod
  VpcId:
    Type: AWS::EC2::VPC::Id
    Description: Id of the VPC where the endpoints should be created
  RouteTableIds:
    Type: CommaDelimitedList
    Description: Ids of the route tables where the endpoints should be attached

Resources:
  DynamoDbVpcEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      RouteTableIds: !Ref RouteTableIds
      ServiceName: !Sub com.amazonaws.${AWS::Region}.dynamodb
      VpcEndpointType: Gateway
      VpcId: !Ref VpcId
```

{% endcode %}

Then, create the stack configuration file:

```yaml
touch stacks/dev/eu-west-1/vpc-endpoints.yml
```

Add the following contents to it:

{% code title="stacks/dev/eu-west-1/vpc-endpoints.yml" %}

```yaml
template: vpc-endpoints.yml
parameters:
  Environment: {{ stackGroup.data.environment }}
  VpcId:
    resolver: stack-output
    stack: vpc.yml
    output: VpcId
  RouteTableIds:
    resolver: stack-output
    stack: vpc.yml
    output: RouteTableIds
```

{% endcode %}

The parameters in this stack use a new kind of syntax. Previously, we have used static values for our parameters, but here we are using parameter resolvers that resolve the parameter values at deployment time.

Resolver of type **stack-output** reads the value for a parameter from another stack's outputs. In this case, we read values from the VPC stack's outputs.

You should now have the following files in place:

```bash
.
├─ stacks
│  ├─ dev
│  │  ├─ config.yml
│  │  └─ eu-west-1
│  │     ├─ config.yml
│  │     ├─ dynamodb.yml
│  │     ├─ vpc.yml
│  │     └─ vpc-endpoints.yml
│  └─ prod
│     └─ eu-west-1
├─ templates
│  ├─ dynamodb.yml
│  ├─ vpc.yml
│  └─ vpc-endpoints.yml
└─ package.json
```

It's again time to deploy our changes, but this time, let's do something different. Instead of deploying all stacks, let's deploy just the VPC endpoints stack. To achieve that, you need to give the path of the stack you want to deploy to the deploy stacks command:

```bash
npx tkm stacks deploy \
  /dev/eu-west-1/vpc-endpoints.yml \
  --profile takomo-tutorial
```

When you review the deployment plan, you notice something that you might find unexpected. You chose to deploy only the VPC endpoints stack, but the deployment plan indicates that Takomo will deploy the VPC stack as well.

This is because the VPC endpoints stack uses the VPC stack's outputs as inputs to its parameters, making the VPC endpoint stack dependent on the VPC stack. When building the deployment plan, Takomo takes relations between the stacks into account and ensures that it deploys the stacks in the correct order.

## Lambda function stack

The infrastructure for the dev environment is almost complete. We still need to add the Lambda function that accesses the DynamoDB table through the VPC endpoint.

Let's start by creating a file that holds the Lambda function body:

```bash
mkdir partials
touch partials/lambda.js
```

Add the following contents to it:

{% code title="partials/lambda.js" %}

```javascript
const AWS = require("aws-sdk")
const dynamo = new AWS.DynamoDB.DocumentClient()

exports.handler = async (event, context) => {
  console.log("EVENT: \n" + JSON.stringify(event, null, 2))
  await dynamo.put({
    TableName: process.env.TABLE_NAME,
    Item: {
      id: Date.now().toString()
    }  
  }).promise()
  
  const { Count } = await dynamo.scan({ TableName: process.env.TABLE_NAME }).promise()
  return Count
}
```

{% endcode %}

Create a new template file:

```bash
touch templates/lambda.yml
```

Add the following contents to it:

{% code title="templates/lambda.yml" %}

```yaml
Parameters:
  Environment:
    Type: String
    Description: Application environment
    AllowedValues:
      - dev
      - prod
  VpcId:
    Type: AWS::EC2::VPC::Id
    Description: Id of the VPC where the endpoints should be created
  SubnetIds:
    Type: CommaDelimitedList
    Description: Ids of the subnets where the function should be created
  TableName:
    Type: String
    Description: Name of the DynamoDB table
  TableArn:
    Type: String
    Description: ARN of the DynamoDB table

Resources:
  FunctionSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: !Sub tutorial-function-${Environment}
      VpcId: !Ref VpcId
      
  FunctionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole     
      Policies:
        - PolicyName: DynamoDB
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - dynamodb:PutItem
                  - dynamodb:Scan
                Resource: !Ref TableArn
                      
  Function:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub tutorial-function-${Environment}
      Handler: index.handler
      MemorySize: 128
      Role: !GetAtt FunctionRole.Arn
      Runtime: nodejs12.x
      Timeout: 10
      Environment:
        Variables:
          TABLE_NAME: !Ref TableName
      VpcConfig:
        SecurityGroupIds:
          - !Ref FunctionSecurityGroup
        SubnetIds: !Ref SubnetIds
      Code:
        ZipFile: |
          {{> lambda.js }}
```

{% endcode %}

Notice how the lambda code is included in the template file (line 69).

Then, create the stack configuration file:

```yaml
touch stacks/dev/eu-west-1/lambda.yml
```

Add the following contents to it:

{% code title="stacks/dev/eu-west-1/lambda.yml" %}

```yaml
template: lambda.yml
parameters:
  Environment: {{ stackGroup.data.environment }}
  VpcId:
    resolver: stack-output
    stack: vpc.yml
    output: VpcId
  SubnetIds:
    resolver: stack-output
    stack: vpc.yml
    output: SubnetIds
  TableName:
    resolver: stack-output
    stack: dynamodb.yml
    output: TableName
  TableArn:
    resolver: stack-output
    stack: dynamodb.yml
    output: TableArn
```

{% endcode %}

You should now have the following files in place:

```bash
.
├─ stacks
│  ├─ dev
│  │  ├─ config.yml
│  │  └─ eu-west-1
│  │     ├─ config.yml
│  │     ├─ dynamodb.yml
│  │     ├─ lambda.yml
│  │     ├─ vpc.yml
│  │     └─ vpc-endpoints.yml
│  └─ prod
│     └─ eu-west-1
├─ templates
│  ├─ dynamodb.yml
│  ├─ vpc.yml
│  └─ vpc-endpoints.yml
└─ package.json
```

It's time to deploy the stacks again to get the lambda function stack created.

```bash
npx tkm stacks deploy --profile takomo-tutorial
```

## Testing

We now have everything ready for the development environment, and it's time to test the lambda function.

If you have the AWS CLI installed, you can test the function from command-line:

```bash
aws lambda invoke \
  --region eu-west-1 \
  --function-name tutorial-function-dev \
  --profile takomo-tutorial \
  response.txt
```

The lambda returns the number of items in the DynamoDB table, so each invocation should increase the number in **response.txt** by one.

You can also invoke the function from AWS management console.

## Production environment

Now that we have the dev environment ready, it's time to set up the prod environment.

Create shared configuration for the prod environment.

```yaml
touch stacks/prod/config.yml
```

Add the following contents to it:

{% code title="stacks/prod/config.yml" %}

```yaml
data:
  environment: prod
```

{% endcode %}

Then, create configuration shared by all stacks located in the eu-west-1 region.

```yaml
touch stacks/prod/eu-west-1/config.yml
```

Add the following contents to it:

{% code title="stacks/prod/eu-west-1/config.yml" %}

```yaml
regions: eu-west-1
```

{% endcode %}

Next, create configuration files for the stacks.

```yaml
touch stacks/prod/eu-west-1/dynamodb.yml
touch stacks/prod/eu-west-1/lambda.yml
touch stacks/prod/eu-west-1/vpc.yml
touch stacks/prod/eu-west-1/vpc-endpoints.yml
```

Then, add the following contents to them:

{% code title="stacks/prod/eu-west-1/dynamodb.yml" %}

```yaml
template: dynamodb.yml
parameters:
  Environment: {{ stackGroup.data.environment }}
```

{% endcode %}

{% code title="stacks/prod/eu-west-1/lambda.yml" %}

```yaml
template: lambda.yml
parameters:
  Environment: {{ stackGroup.data.environment }}
  VpcId:
    resolver: stack-output
    stack: vpc.yml
    output: VpcId
  SubnetIds:
    resolver: stack-output
    stack: vpc.yml
    output: SubnetIds
  TableName:
    resolver: stack-output
    stack: dynamodb.yml
    output: TableName
  TableArn:
    resolver: stack-output
    stack: dynamodb.yml
    output: TableArn
```

{% endcode %}

{% code title="stacks/prod/eu-west-1/vpc.yml" %}

```yaml
template: vpc.yml
parameters:
  Environment: {{ stackGroup.data.environment }}
  VpcCidr: 10.0.0.64/26
```

{% endcode %}

{% code title="stacks/prod/eu-west-1/vpc-endpoints.yml" %}

```yaml
template: vpc-endpoints.yml
parameters:
  Environment: {{ stackGroup.data.environment }}
  VpcId:
    resolver: stack-output
    stack: vpc.yml
    output: VpcId
  RouteTableIds:
    resolver: stack-output
    stack: vpc.yml
    output: RouteTableIds
```

{% endcode %}

Your file structure should now look like this:

```bash
.
├─ stacks
│  ├─ dev
│  │  ├─ config.yml
│  │  └─ eu-west-1
│  │     ├─ config.yml
│  │     ├─ dynamodb.yml
│  │     ├─ lambda.yml
│  │     ├─ vpc.yml
│  │     └─ vpc-endpoints.yml
│  └─ prod
│     ├─ config.yml
│     └─ eu-west-1
│        ├─ config.yml
│        ├─ dynamodb.yml
│        ├─ lambda.yml
│        ├─ vpc.yml
│        └─ vpc-endpoints.yml
├─ templates
│  ├─ dynamodb.yml
│  ├─ vpc.yml
│  └─ vpc-endpoints.yml
└─ package.json
```

Let's quickly check how our stacks look like now:

```bash
npx tkm stacks list --profile takomo-tutorial
```

You should see four more stacks in addition to the existing dev stacks.

Deploy the stacks like earlier but this time use `-y` option to skip the plan review and confirm step.

```bash
npx tkm stacks deploy --profile takomo-tutorial -y
```

## Clean up

You have reached the end of this tutorial. Hopefully, you now have a better understanding of how to configure and deploy CloudFormation stacks with Takomo.

To remove the stacks you have created, run the next command:

```bash
npx tkm stacks undeploy --profile takomo-tutorial
```


# AWS credentials

To do anything with Takomo, you need to have valid AWS credentials configured. Under the hood, Takomo uses AWS JavaScript SDK to acquire the credentials. Take a look at [the SDK's documentation](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-node.html) to learn the ways you can configure credentials.

## Using profile

The easiest way to provide credentials when running Takomo on your local computer is to configure a profile in the **\~/.aws/credentials** file and then either export the profile name in `AWS_PROFILE` environment variable or pass it on with the `--profile` command-line option.

#### Example

Configure a profile in the **\~/.aws/credentials** file:

{% code title="\~/.aws/credentials" %}

```yaml
[my-profile]
aws_access_key_id=<YOUR ACCESS KEY ID>
aws_secret_access_key=<YOUR SECRET ACCESS KEY>
```

{% endcode %}

You can then provide the profile in an environment variable:

```bash
AWS_PROFILE=my-profile tkm stacks deploy
```

Or, you can use the `--profile` command line option:

```bash
tkm stacks deploy --profile my-profile
```

## Assuming roles

If you have an IAM user in one account that you use to assume roles from the same or other accounts, you can configure the access keys for the user in the credentials file and then create separate profiles for each of the roles.

#### Example

Configure a profile and roles in the credentials file.&#x20;

{% code title="\~/.aws/credentials" %}

```yaml
[manager]
aws_access_key_id=<YOUR ACCESS KEY ID>
aws_secret_access_key=<YOUR SECRET ACCESS KEY>

[account-a-admin]
role_arn=arn:aws:iam::123456789012:role/admin
source_profile=manager

[account-b-readonly]
role_arn=arn:aws:iam::210987654321:role/readonly
source_profile=manager
```

{% endcode %}

Now, when you run a command with **account-a-admin** profile, AWS SDK uses the access keys you have configured for the **manager** profile to assume the **arn:aws:iam::123456789012:role/admin** IAM role referenced by the **account-a-admin** profile.

```bash
tkm stacks deploy --profile account-a-admin
```

## Assuming roles that require MFA

You can specify in an IAM role's trust policy that the user must provide an MFA token to assume it. Then, to assume the role, you need to configure your IAM user's MFA device with `mfa_serial` property in the role's profile like so:

{% code title="\~/.aws/credentials" %}

```yaml
[manager]
aws_access_key_id=<YOUR ACCESS KEY ID>
aws_secret_access_key=<YOUR SECRET ACCESS KEY>

[account-a-admin]
role_arn=arn:aws:iam::123456789012:role/admin
source_profile=manager
mfa_serial=arn:aws:iam::224466880011:mfa/username
```

{% endcode %}

When you run a command, Takomo will ask you the MFA code.

```bash
tkm stacks deploy --profile account-admin
```


# Directory structure

Takomo project's directory structure looks like this.

```bash
.
├─ stacks
├─ templates
├─ helpers
├─ partials
├─ resolvers
├─ hooks
├─ schemas
├─ deployment
├─ config-sets
└─ organization
```

There are two mandatory directories: **stacks** and **templates**. The stacks directory will contain all configuration files for your stacks, and the templates directory is where you'll place template files for the stacks.

You can find the purpose of each directory from the table below.

| Directory    | Description                                                                                                                                                                                                                                                              |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| stacks       | Configuration files for stacks. You can create subdirectories to organize stacks and to provide common configuration. Takomo treats each subdirectory as a stack group, You can provide configuration for a stack group by placing a config.yml file into its directory. |
| templates    | CloudFormation template files that can be referenced from the stack configuration files. You can use subdirectories to organize template files.                                                                                                                          |
| helpers      | Custom Handlebars helpers. You can use helpers in stack configuration and template files.                                                                                                                                                                                |
| partials     | Handlebars partial files. You can include partial files in stack configuration and template files.                                                                                                                                                                       |
| resolvers    | Custom resolvers.                                                                                                                                                                                                                                                        |
| hooks        | Custom hooks.                                                                                                                                                                                                                                                            |
| schemas      | Custom Joi schemas.                                                                                                                                                                                                                                                      |
| deployment   | Configuration for [deployment targets](broken://pages/-MXR3PIS38_5jTTCimTt).                                                                                                                                                                                             |
| organization | Configuration for [AWS organization management](https://organizations.takomo.io).                                                                                                                                                                                        |
| config-sets  | Config sets                                                                                                                                                                                                                                                              |


# Stacks and stack groups

You create a configuration file in the **stacks** directory for each stack you want to manage with Takomo. Configuration files are in **YAML** format and should contain the configuration needed to deploy the corresponding stacks.

{% hint style="info" %}
Takomo uses **.yml** file extension with YAML files.
{% endhint %}

## Stack groups for common configuration

You can create more directories under the stacks directory to group stacks by application environment, region, or another criterion. Takomo treats these directories as stack groups. You can use them to provide common configurations for stacks that belong to the stack groups by placing a config.yml file into the stack group's directory. Individual stacks can override parts or all of the configurations they inherit from their stack group.

You can also nest stack groups to create a tree-like hierarchy where child stack groups inherit configuration from their parent. Like the stacks, they can override the configuration they inherit.

The stacks directory itself is the root stack group, and the configuration defined in its config.yml file gets inherited for all other stack groups and every stack in the project.

## Identifying stacks and stack groups

You identify stack groups and stacks by their path, which is basically like a file path in Linux filesystem where the stacks directory is the filesystem root.

We learned earlier the stacks directory is the root stack group. Its path is **/.** Other stack groups' path is the absolute file path to the stack group's directory from the stacks directory.

The stack paths follow this same logic with one important difference. A stack's path is the absolute file path to its configuration file from the stacks directory, appended with a region specifier that is a forward slash followed by the stack's region. You may omit the region specifier if the stack has only one region.

{% hint style="info" %}
A stack can have one or more regions. The regions are defined in the stack's configuration file, which means more than one CloudFormation stack can be created from a single stack configuration file.
{% endhint %}

## Command path

A common name for both stack and stack group paths is the **command path**. The command path is used in many places in Takomo's configuration files and is accepted as input arguments by many CLI commands. Wherever a command path is required, you can always use either a stack or stack group path.

## Example project

Here is an example of how a Takomo project could look like.

```bash
.
├─ stacks
│  ├─ config.yml
│  ├─ dev
│  │  ├─ config.yml
│  │  ├─ application.yml
│  │  └─ vpc.yml
│  └─ prod
│     ├─ application.yml
│     └─ vpc.yml
└─ templates
   ├─ application-template.yml
   └─ vpc-template.yml
```

In the **stacks** directory, there is a **config.yml** file that contains configurations shared with all stack groups and stacks.

There are two stack groups for application environments: **dev** and **prod.** Each environment consists of two stacks: **application.yml** and **vpc.yml**. The dev environment also has its own config.yml file with configurations shared only with its stacks.

Let's say that in the root config.yml file, we specify that we want to use region eu-west-1, and that we override this for the dev environment by setting a different region, us-east-1, in its config.yml file.

The templates directory contains CloudFormation template files for the stacks.

This table shows the paths for each stack and stack group found from the example project.

| File                 | Path                            |
| -------------------- | ------------------------------- |
| the stacks directory | /                               |
| dev                  | /dev                            |
| dev/application.yml  | /dev/application.yml/us-east-1  |
| dev/vpc.yml          | /dev/vpc.yml/us-east-1          |
| prod                 | /prod                           |
| prod/application.yml | /prod/application.yml/eu-west-1 |
| prod/vpc.yml         | /prod/vpc.yml/eu-west-1         |


# Project configuration

You can configure project-wide settings in a **takomo.yml** file that you place in the project root directory.&#x20;

## Required Takomo version

You specify the required Takomo version with the `requiredVersion` property. It accepts a NPM [semver](https://www.npmjs.com/package/semver) compatible version range.

**Example**

Require Takomo version 3.4.0 or above:

{% code title="takomo.yml" %}

```yaml
requiredVersion: ">=3.4.0"
```

{% endcode %}

## Allowed regions

By default, the supported regions are hardcoded in Takomo's codebase. A new Takomo version is released whenever AWS launches new regions.

In case you need to use an older Takomo version that does not include some regions launched after its release, you may specify the missing regions yourself using this property.&#x20;

You can also use this property to list only the regions you intend to use to prevent deploys to any other region.

#### Example

Allow only these four regions:

{% code title="takomo.yml" %}

```yaml
regions:
  - us-east-1
  - eu-west-1
  - eu-central-1
  - eu-north-1 
```

{% endcode %}

## Feature flags

You can enable and disable certain Takomo features by specifying feature flags under the features property. Here are the available feature flags

| Feature flag              | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| deploymentTargetsUndeploy | <p>Set <strong>false</strong> to disable <a href="https://targets.takomo.io/command-line-usage/undeploy-targets">undeploy deployment targets</a> command.</p><p></p><p>You might want to disable this command to add an extra confirmation step to prevent removing targets unintentionally.</p><p></p><p>You can override this setting by giving <code>--feature deploymentTargetsUndeploy=true</code> option from command-line when executing <a href="https://targets.takomo.io/command-line-usage/undeploy-targets">undeploy deployment targets</a> command.</p> |
| deploymentTargetsTearDown | <p>Set false to disable <a href="https://targets.takomo.io/command-line-usage/tear-down-targets">tear down deployment targets</a> command.<br></p><p>You might want to disable this command to add an extra confirmation step to prevent removing targets unintentionally.</p><p></p><p>You can override this setting by giving <code>--feature deploymentTargetsTearDown=true</code> option from command-line when executing <a href="https://targets.takomo.io/command-line-usage/tear-down-targets">tear down deployment targets</a> command.</p>                 |

#### Example

Disable undeploy deployment targets command:

{% code title="takomo.yml" %}

```yaml
features:
  deploymentTargetsUndeploy: false
```

{% endcode %}

## Extending project configuration

You can make a Takomo project configuration file to inherit configuration from another file. Inheriting configuration becomes useful, for example, when you have a monorepo containing multiple Takomo projects, each having its own configuration and sharing some common properties with others. You can place the common properties in a parent file that others then inherit.

You use the `extends` property to make a project configuration file inherit configuration from another file:

{% code title="takomo.yml" %}

```yaml
extends: ../my-parent-config.yml
```

{% endcode %}


# Name

Each CloudFormation stack must have a name that is unique within the stack's region. Takomo uses stack names to match stacks found from the local configuration with the target accounts' stacks.

You can give a name for a stack using the `name` property.

#### Example

Specifying a name:

```
name: vpc
```

## Default value

If you omit the name, Takomo will generate the name using the following logic:

1. Take the stack path and remove the leading forward slash
2. Remove the region specifier from the end of the stack path
3. Replace the remaining forward slashes with hyphens
4. If the `project` property is specified, prepend it to the name

For example, if your stack's path is **/dev/eu-west-1/vpc.yml/eu-west-1**, its generated name will be **dev-eu-west-1-vpc**.

## Where to define

The `name` property can be defined only in stack configuration files.

## Requirements

The `name` property must satisfy these requirements:

* Must be a string
* Must match regex `^[a-zA-Z0-9][-a-zA-Z0-9]*$`
* Have a minimum length of 1
* Have a maximum length 128

## Renaming stacks

You can't rename stacks. If you change the name of an existing stack, Takomo will use the new name to find a corresponding stack from the target account. As Takomo does not keep track of the stacks it has deployed, it can't know that the stack still exists with the old name.


# Regions

You specify the regions where to deploy a stack using the `regions` property. You can give a single region or a list of regions. Each stack must have at least one region.

#### Examples

Specifying a single region:

```yaml
regions: eu-west-1
```

Specifying multiple regions:

```yaml
regions:
  - eu-central-1
  - eu-north-1
  - us-east-1
```

## Where to define

The `regions` property can be defined in stack and stack group configuration files. If specified in a stack group, the stack group's children and stacks inherit the value. Stack groups and stacks can override the value they have inherited from their parent.

## Requirements

The `regions` property must satisfy these requirements:

* Must be a string or a list of strings
* Must be valid region

## Changing the regions

You can't change the stack's region. If you change the region of an existing stack, Takomo will look for a corresponding stack from the new region. As Takomo does not keep track of the stacks it has deployed, it can't know that the stack still exists in the old region.

You can always add new regions for a stack.


# Template

You put CloudFormation template files for stacks in the templates directory or its subdirectories.

For each stack, you specify the template file to use with the `template` property. It accepts a relative file path to the template file in the templates directory.

If you don't specify the template, Takomo looks for a template file using the relative file path to the current stack configuration file from the stacks directory.

{% hint style="info" %}
Takomo supports both of the standard CloudFormation template file formats, i.e., JSON and YAML.
{% endhint %}

#### Example

Say, we have the following project.

```bash
.
├─ stacks
│  └─ application.yml
└─ templates
   └─ application-template.yml
```

In **application.yml** stack configuration file you can define the `template` property like so:

{% code title="stacks/application.yml" %}

```yaml
template: application-template.yml
```

{% endcode %}

If you would omit the `template` property, Takomo would fallback to the default behaviour and look for a template file by name **application.yml** from the templates directory.

## Inline template body

You can also inline the template body in a stack configuration file.

#### Example

```yaml
template:
  inline: |
    Resources:
      VPC:
        Type: AWS::EC2::VPC
        Properties:
          CidrBlock: 10.0.0.0/16
  
```

## Disabling dynamic template

By default, Takomo processes each template file with [Handlebars](https://handlebarsjs.com/) templating engine. You can turn off this dynamic template processing by providing the template configuration with an object with two properties: `filename` and `dynamic`. The former specifies the relative file path to the template file in the templates directory., and the latter is an optional boolean to enable or disable dynamic processing.

#### Example

Use the object notation to disable dynamic template:

```yaml
template:
  filename: networking.yml
  dynamic: false
```

## Where to define

The `template` property can be defined only in stack configuration files.

## Requirements

The `template` property must satisfy these requirements:

* Must be a string or an object


# Template bucket

By default, the maximum size for a CloudFormation template file is **51,200 bytes**. Using larger template files, up to **460,800 bytes**, requires that you upload them to an S3 bucket before deployment.

You use the `templateBucket` property to instruct Takomo to upload template files to a specific S3 bucket before the deployment. The bucket must exist.

The `templateBucket` property is an object with two properties: `name` and `keyPrefix`. The former is required and used to specify the bucket's name, and the latter is optional and specifies the object key prefix under which Takomo uploads the templates files.

#### Examples

Specifying a template bucket with a key prefix:

```yaml
templateBucket:
  name: my-bucket
  keyPrefix: template-files/
```

Specifying a template bucket with just a name:

```yaml
templateBucket:
  name: hello-bucket
```

## Where to define

The `templateBucket` property can be defined in stack and stack group configuration files. If specified in a stack group, the stack group's children and stacks inherit the value. Stack groups and stacks can override the value they have inherited from their parent.

## Requirements

The `templateBucket` property must satisfy these requirements:

* Name must be a valid S3 bucket name
* Key prefix must be a valid S3 object key prefix


# Command role

When you execute a Takomo command, the AWS credentials present in the current terminal session dictate the target AWS account. We call these credentials **the default credentials**.

Should you want to target a different account, you can specify an IAM role that Takomo should assume using the default credentials and then use it to execute the commands to the account where the role is bound. We call this role **the command role**, and you can specify it with the `commandRole` property, which accepts an IAM role ARN.

{% hint style="warning" %}
The command role must not require MFA authentication.
{% endhint %}

#### Example

Specify a command role:

```yaml
arn:aws:iam::123456789012:role/deployer-role
```

## Where to define

The `capabilities` property can be defined in stack and stack group configuration files. If specified in a stack group, the stack group's children and stacks inherit the value. Stack groups and stacks can override the value they have inherited from their parent.

## Requirements

The `commandRole` property must satisfy these requirements:

* Must be a valid IAM role ARN


# Account ids

Working simultaneously with multiple accounts usually requires switching between many credentials or IAM roles. This poses a real risk of accidentally deploying infrastructure to the wrong account.

You can mitigate this risk with the `accountIds` property, which lets you define a list of allowed accounts to deploy a stack. It accepts a single account id or a list of account ids.

#### Examples

A single allowed account:

```yaml
accountIds: "123456789012"
```

A list of allowed accounts:

```yaml
accountIds:
  - "876272828282"
  - "763273627326"
```

## Where to define

The `accountIds` property can be defined in stack and stack group configuration files. If specified in a stack group, the stack group's children and stacks inherit the value. Stack groups and stacks can override the value they have inherited from their parent.

## Requirements

The `accountIds` property must satisfy these requirements:

* Must be a string or a list of strings
* Account ids must be valid AWS account ids


# Depends

It’s a good practice to split the infrastructure into multiple stacks that group related resources together. Naturally, there will be dependencies between the stacks.

For example, one stack creates a VPC with subnets, and another stack creates some resources into those subnets. The stacks need to be created and updated in a certain order to ensure that the dependencies can be satisfied. For example, you need to have the subnets ready before you can create other resources into them.

You specify the stacks that a stack depends on by using the `depends` property which accepts a single stack path or a list of stack paths.

#### Examples

A single dependency:

```yaml
depends: /dev/vpc.yml
```

A single dependency with region:

```yaml
depends: /dev/vpc.yml/eu-west-1
```

Multiple dependencies:

```yaml
depends:
  - /dev/vpc.yml
  - /dev/security-groups.yml
```

Using a relative stack path:

```yaml
depends: ../../common/logs.yml
```

## Where to define

The `depends` property can be defined only in stack configuration files.

## Requirements

The `depends` property must satisfy these requirements:

* Must be a string or a list of strings
* Must contain valid stack paths


# Parameters

You use the `parameter` property to define input parameters for a stack. It's an object of key-value pairs where the keys are parameter names, and the values are configuration for the corresponding parameter values.

The value configuration can be a single static value, an object, or a list of the two types mentioned above. You must use the object configuration when the parameter requires additional configuration, or you want Takomo to resolve its value at deployment time.

## Simple static parameters

The simplest way to specify the value for a parameter is to hard code the value to the stack configuration file.

#### Examples

A single static value for a parameter named **VpcId**:

```yaml
parameters:
  VpcId: vpc-06e4ab6c6c
```

A list of values for a parameter named **CidrBlocks**:

```yaml
parameters:
  CidrBlocks:
    - 10.0.0.0/26
    - 10.0.0.64/26
```

## Static parameters with object notation

You can provide configuration for static parameters using the object notation which allows you to use additional properties in the configuration. When using the object notation you give the parameter value in `value` property:

#### Example

A single static parameter using the object notation:

```yaml
parameters:
  VpcId:
    value: vpc-06e4ab6c6c
```

## Immutable parameters

You can mark parameters as immutable if you want to make sure their values are not updated. Many CloudFormation resources have properties that don't support updating after creation, and making them immutable in stack configuration helps prevent failures during deployment.

A parameter can't be marked as immutable if it has **NoEcho** set to true in the CloudFormation template file. There is no way to find out the current value for NoEcho parameters and therefore Takomo can't detect if their value is about to be changed.

#### Example

A static immutable value for a parameter named **VpcId**:

```yaml
parameters:
  VpcId:
    value: vpc-06e4ab6c6c
    immutable: true
```

## Dynamic parameters

In many cases, it's not wise or even possible to hard code all parameter values. When you need to assign parameter values dynamically at deployment time, you can use parameter resolvers. There are a few built-in parameter resolvers, and you can also implement your own.

You use the `resolver` property to specify which parameter resolver to use to resolve the value for a parameter.

Below, you can find some examples of built-in parameter resolvers. You can read more about parameter resolvers from [here](/parameter-resolvers/built-in-parameter-resolvers).

#### Examples

If you have two stacks configured within the same Takomo project, you can use the stack-output resolver to read the first stack's output value and use it as a parameter value in the second stack.

```yaml
parameters:
  VpcId:
    resolver: stack-output
    stack: /vpc.yml
    output: vpcId
```

If the stacks are not configured within the same Takomo project, you need to use the external-stack-output resolver.

```yaml
parameters:
  VpcId:
    resolver: external-stack-output
    stack: vpc-stack
    output: vpcId
    region: eu-west-1
    commandRole: arn:aws:iam::123456789012:role/deployer
```

## Where to define

The `parameters` property can be defined only in stack configuration files.

## Requirements

The `parameters` property must satisfy these requirements:

* Parameter name must be a string
* Parameter name must match regex `^[a-zA-Z0-9]*$`

## See also

* [Built-in parameter resolvers](/parameter-resolvers/built-in-parameter-resolvers)
* [Implementing custom parameter resolvers](/parameter-resolvers/custom-parameter-resolvers)


# Tags

You specify stack tags with the `tags` property. CloudFormation automatically adds the tags to each resource in the stack that supports tagging.

#### Examples

Setting tags:

```yaml
tags:
  foo: bar
  code: 123
  backups: true
```

## Where to define

The `tags` property can be defined in stack and stack group configuration files. If specified in a stack group, the stack group's children and stacks inherit the value. Stack groups and stacks can add new tags and overwrite individual tags they inherited from their parent by specifying a new value with the same key.

## Requirements

The `tags` property must satisfy these requirements:

* Each tag key must be a string
* Each tag value must be a string, a number or a boolean


# Inherit tags

By default, stacks and stack groups inherit tags from their parent stack group. You can disable this behaviour by setting `inheritTags` to false.

#### Examples

Disable inheriting of tags.

```yaml
inheritTags: false
```

## Where to define

The `inheritTags` property can be defined in stack and stack group configuration files. Disabling tag inheritance in a stack group configuration affects only to the stack group itself and not stacks and stack groups that belong under it.

## Requirements

The `inheritTags` property must satisfy these requirements:

* Must be a boolean


# Termination protection

You can enable termination protection for a stack with the `terminationProtection` property.

#### Example

Enabling termination protection:

```yaml
terminationProtection: true
```

## Default value

Termination protection is not enabled by default.

## Where to define

The `terminationProtection` property can be defined in stack and stack group configuration files. If specified in a stack group, the stack group's children and stacks inherit the value. Stack groups and stacks can override the value they have inherited from their parent.

## Requirements

The `terminationProtection` property must satisfy these requirements:

* Must be a boolean


# Timeout

You specify a timeout in seconds for stack create and update operations by using the `timeout` property. Takomo cancels the operation if it takes longer than what you have specified in the `timeout` property. You can't set a timeout for the delete operation. Use 0 to disable the timeout.

You set the timeout for both create and update operations by specifying a single integer. You can also set a separate timeout for create and update operations by using an object with `create` and `update` properties.

#### Examples

Timeout of 180 seconds for both create and update:

```yaml
timeout: 180
```

Timeout of 300 seconds for create and no timeout for update:

```yaml
timeout:
  create: 300
```

Separate timeouts for create and update:

```yaml
timeout:
  create: 300
  update: 120
```

## Where to define

The `timeout` property can be defined in stack and stack group configuration files. If specified in a stack group, the stack group's children and stacks inherit the value. Stack groups and stacks can override the value they have inherited from their parent.

## Requirements

The `timeout` property must satisfy these requirements:

* Must be an integer greater or equal to 0


# Capabilities

You specify stack capabilities with the `capabilities` property.

#### Examples

A single capability:

```yaml
capabilities: CAPABILITY_IAM
```

A list of capabilities

```yaml
capabilities:
  - CAPABILITY_IAM
  - CAPABILITY_NAMED_IAM
```

Disable all capabilities:

```yaml
capabilities: []
```

## Default value

By default, all capabilities are enabled.

## Where to define

The `capabilities` property can be defined in stack and stack group configuration files. If specified in a stack group, the stack group's children and stacks inherit the value. Stack groups and stacks can override the value they have inherited from their parent.

## Requirements

The `capabilities` property must satisfy these requirements:

* Must be a string or a list of strings
* Allowed values are:
  * CAPABILITY\_IAM
  * CAPABILITY\_NAMED\_IAM
  * CAPABILITY\_AUTO\_EXPAND


# Stack policy

You specify a stack policy with the `stackPolicy` property. It accepts a string or an object.

#### Examples

Setting a stack policy as a string:

```yaml
stackPolicy: |
  {
    "Statement": [
      {
        "Effect": "Allow",
        "NotAction": "Update:Delete",
        "Principal": "*",
        "Resource": "*"
      }
    ]
  }
```

Setting a stack policy as an object:

```yaml
stackPolicy:
  Statement:
    - Effect: Allow
      NotAction: Update:Delete
      Principal: "*"
      Resource: "*"
```

## Stack policy during update

You specify a stack policy to use during stack update with the `stackPolicyDuringUpdate` property. It works the same way as the `stackPolicy` property.

#### Examples

Setting a stack policy to use during the stack update as an object:

```yaml
stackPolicyDuringUpdate:
  Statement:
    - Effect: Allow
      Action: Update:*
      Principal: "*"
      Resource: "*"
```

## Deleting stack policy

CloudFormation doesn't support removing of a stack policy once it has been created. As a workaround, when you remove the stack policy from the stack configuration, Takomo updates the policy with the allow all policy shown below, which is essentially equivalent to not having a stack policy attached at all.

{% code title="allow all stack policy" %}

```yaml
{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "Update:*",
      "Principal": "*",
      "Resource": "*"
    }
  ]
}
```

{% endcode %}

## Where to define

The `stackPolicy` and `stackPolicyDuringUpdate` properties can be defined in stack and stack group configuration files. If specified in a stack group, the stack group's children and stacks inherit the value. Stack groups and stacks can overwrite the policies they inherited from their parent.

## Requirements

The `stackPolicy` property must satisfy these requirements:

* Must be a valid JSON document&#x20;


# Ignore

You can exclude stacks and stack groups from the configuration with the `ignore` property.

#### Examples

Setting the `ignore` property:

```yaml
ignore: true
```

## Where to define

The `ignore` property can be defined in stack and stack group configuration files. If specified in a stack group, the stack group's children and stacks inherit the value. If you set a stack group as ignored, its children or stacks can't set the ignore property back to false.

## Requirements

The `ignore` property must satisfy these requirements:

* Must be a boolean


# Obsolete

You can exclude stacks from configuration by marking them as obsolete with the `obsolete` property. Obsolete stacks can be removed with [prune stacks](/command-line-usage/prune-stacks) command.&#x20;

Obsolete stacks can't have dependents that are not obsolete themselves.

#### Examples

Setting the `obsolete` property:

```yaml
obsolete: true
```

## Where to define

The `obsolete` property can be defined in stack and stack group configuration files. If specified in a stack group, the stack group's children and stacks inherit the value but can also override it.

## Requirements

The `obsolete` property must satisfy these requirements:

* Must be a boolean


# Hooks

You use the `hooks` property to specify actions Takomo should execute at different stages of deploy and undeploy commands. The `hooks` property accepts a list of hook configuration objects. A hook configuration object has the following properties:

* `name` - Name of the hook
* `type` - Type of the hook
* `operation` - Operations during which the hook should be executed
  * Supported operations are:
    * create
    * update
    * delete
  * Accepts a single operation or a list of operations
  * By default, a hook is executed on every operation&#x20;
* `stage` - Stages during which the hook should be executed
  * Supported values are:
    * before
    * after
  * Accepts a single stage or a list of stages
  * By default, a hook is executed on every stage
* `status` - Statuses during which the hook should be executed
  * Available on when stage is after
  * Supported values are:
    * success - The operation succeeded
    * failed - The operation failed
    * cancelled - The operation was cancelled
  * By default, a hook is executed on every status

Takomo executes hooks in the order that you have defined them in the configuration files. If one hook fails, the whole stack operation with any remaining hooks is aborted and deemed a failure.

#### Examples

A cmd hook that is executed after a successful stack creation:

```yaml
hooks:
  - name: executed-after-successful-create
    type: cmd
    operation: create
    stage: after
    status: success
    command: echo 'success'
```

A cmd hook that is executed after all create and update operations:

```yaml
hooks:
  - name: my-hook
    type: cmd
    operation:
      - create
      - update
    stage: after
    command: echo 'hello'
```

## Where to define

The `hooks` property can be defined in stack and stack group configuration files. If specified in a stack group, the stack group's children and stacks inherit the value. The hooks defined by stack groups and stacks are appended to the list of hooks they inherit from their parent.

## Requirements

The `hooks` property must satisfy these requirements:

* Must be a list of objects

## See also

* [Built-in hooks](/hooks/built-in-hooks)
* [Implementing custom hooks](/hooks/custom-hooks)


# Data

You can define custom properties by using the `data` property. The properties specified in a stack group configuration are available in its children's and stack's configuration files and stack templates files.

#### Example

If you specify data in a stack configuration file like this:

```yaml
data:
  subnets:
    - subnet-ccbbb18ac981dc554e
    - subnet-969b3de3fa0a275d9b
    - subnet-7609598000b229fcb3
  environment:
    name: dev
    code: 123
```

Then, you can refer to the properties in the stack template file like so:

```yaml
Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      Tags:
        - Key: Environment
          Value: {{ stack.data.environment.name }}
        - Key: Code
          Value: {{ stack.data.environment.code }}
```

## Where to define

The `data` property can be defined in stack and stack group configuration files. If specified in a stack group, the stack group's children and stacks inherit the value. Takomo merges the properties defined by stack groups and stacks to the properties they inherit from their parents.

## Requirements

The `data` property must satisfy these requirements:

* Must be an object


# Schemas

You can use custom Joi validation schemas to validate the following parts of stack configuration:

* stack data
* stack tags
* stack parameters
* stack name

You use the `schemas` property to specify which schemas Takomo should use for validation.

#### Example

In this example we have specified to use **myDataSchema** schema to validate data configuration. For tags, we have two schemas: **commonTags** and **environmentTag**.

```yaml
schemas:
  data: myDataSchema
  tags:
    - commonTags
    - name: environmentTag
      allowedValues:
        - dev
        - test
        - prod
```

The implementation of **myDataSchema** schema provider could look like this:

```javascript
schemas/data.js

module.exports = {
  name: "myDataSchema",
  init: ({ joi }) => joi.object({
    owner: joi.string().email(),
    costCenter: joi.number().required()
  }) 
}
```

The file exports an object with two properties `name` and `init`. The former specifies the schema's name used to refer to it from configuration files and the latter is a function that initializes the schema object.&#x20;

{% hint style="info" %}
Read more about custom validation schemas from [here](/validation-schemas/custom-validation-schemas).
{% endhint %}

The implementation of commonTags schema provider could look like this:

{% code title="schemas/common-tags.js" %}

```javascript
module.exports = {
  name: "commonTags",
  init: ({ joi }) => joi.object({
    project: joi.string().required()
  })
}
```

{% endcode %}

Finally, we have the implementation of environmentTag schema provider:

{% code title="schemas/environment-tag.js" %}

```javascript
module.exports = {
  name: "environmentTag",
  init: ({ joi, props }) => {
    return joi.object({
      environment: joi.string().valid(...props.allowedValues)
    })
  }
}
```

{% endcode %}

Unlike the other schema providers, its `init` function uses properties from the stack configuration file that are passed via the `props` argument.

## Where to define

The `schemas` property can be defined in stack and stack group configuration files. If specified in a stack group, the stack group's children and stacks inherit the value. The schemas defined by stack groups and stacks are appended to the list of schemas they inherit from their parent.

## Requirements

The `schemas` property must satisfy these requirements:

* Must be an object with the following optional properties: `data`, `tags`, `parameters` and `name`.


# Introduction

Sometimes static configuration files and templates are not enough to solve the real-life problems we might face. To help overcome those trickier challenges and avoid tedious and error-prone manual work, Takomo supports dynamic templating with [Handlebars](https://handlebarsjs.com/).

All standard Handlebars features are available, which means you can use loops, if-conditions, partial includes, helpers, and variables to streamline your configuration.

By default, Takomo processes all stack configuration, stack group configuration, and stack template files using Handlebars.&#x20;

{% hint style="info" %}
You can turn off dynamic processing of stack template files by setting `dynamic` to false under the stack's [template](/stack-properties/template) property.
{% endhint %}

## Understanding dynamic templating

It's essential to understand how dynamic templating works with Takomo. Takomo processes configuration files with Handlebars before parsing their content. The output produced by the processing needs to be a valid YAML document.

The YAML standard has some gotchas which may cause unexpected behaviour especially if you generate configuration files dynamically using Handlebars. It's helpful to set the logging level to trace when troubleshooting YAML-related problems.


# Handlebars syntax

Here's a short guide to Handlebars syntax. For more information, consult the official Handlebars [documentation](https://handlebarsjs.com/).

## Variables

You refer to variables like this:

```yaml
{{ variable_name }}
```

If the variable is an object with properties of its own, you can refer to them like so:

```yaml
{{ person.firstName }}
```

This is how you refer to a specific index of an array:

```yaml
{{ people.[0] }}
```

## Comments

You can use Handlebars comments in your files. Commented out sections won't show up in the final rendered output.

```yaml
{{! This comment will not show up in the output}}
```

If the content you want to comment out contains `}}` or other Handlebars tokens, you need to use different comment style:&#x20;

```yaml
{{!-- This comment may contain mustaches like }} --}}
```

## If-conditions

Here's an example of if-condition:

```yaml
{{#if some_variable}}
  this will be included in the output
{{/if}}
```

## Iterating over collections

This is how you iterate over a collection of items:

```yaml
{{#each securityGroupIds}}
  - {{this}}
{{/each}}
```


# Environment variables

System environment variables are exposed via the `env` variable.

#### Example

Here's an example how to print the `HOME` environment variable:

```yaml
Home dir is {{ env.HOME }}
```


# Command-line variables

You can pass variables from command line using `--var` and `--var-file` options. Both options can be used multiple times. Variables are exposed via `var` variable.

## Named variables

Use `--var` option to pass a single named variable from the command line.

#### Example

Provide a single variable named **myVariable** with value **hello**:

```bash
--var myVariable=hello
```

You can refer to the variable in configuration files like so:

```yaml
Resources:
  LogGroup:
    Type: AWS::Logs::LogGroup
    LogGroupName: {{ var.myVariable }}
```

## Variables from files

Use `--var-file` option to load variables from a file. If the file extension is **.json** or **.yml**, the file is first parsed into an object which is then stored to a variable. If the file extension is something else, the contents are just read into a variable.

The variable name can be omitted for **.yml** and **.json** files as long as the file contents can be deserialized to an object. The deserialized object is then stored to the top-level of variables.

#### Example - Read file contents to a variable

If the project directory contains a file named **commit.txt**, you can read its contents into a variable named **commitHash** like so:

```bash
--var-file commitHash=commit.txt
```

#### Example - Deserialize file contents to a variable

Here's an example how you would deserialize file contents to a variable. Suppose you have a file **/home/variables.yml** with valid YAML contents:

{% code title="/home/variables.yml" %}

```yaml
name: James
age: 55
permissions:
  - create
  - delete
  - update
```

{% endcode %}

You can deserialize its contents to a variable named **myVariable** like so:

```bash
--var-file person=/home/variables.yml
```

And then use the variable in the configuration like so:

```yaml
parameters:
  UserName: {{ var.person.name }}
  UserAge: {{ var.person.age }}
```

#### Example - Deserialize file contents to top-level variables

Say, you have a file **properties.json** with valid JSON contents:

{% code title="properties.json" %}

```yaml
{
  "color: "red",
  "foo": {
    "bar": true
  }
}
```

{% endcode %}

You can deserialize its contents to top-level of variables:

```bash
--var-file person=/home/variables.yml
```

And then use the variables in the configuration like so:

```yaml
parameters:
  Color: {{ var.color }}
  FooBarEnabled: {{ var.foo.bar }}
```

## Loading order and merging of variables

Variables from files are loaded first in the order they are defined, and then the named variables also in the definition order. Variables defined later will override previously loaded variables with the same name. Complex variables are merged recursively.

#### Example

Say, you have a JSON file that defines some basic settings:

{% code title="base.json" %}

```yaml
{
  "color": "blue",
  "width": 100,
  "settings": {
    "debug": true
  }
}
```

{% endcode %}

You also have another file that contains environment-specific settings:

{% code title="prod.json" %}

```yaml
{
  "settings": {
    "debug": false
  }
}
```

{% endcode %}

You can load both settings files and also override and extend the loaded configuration using named variables:

```bash
--var-file base.json \
  --var-file prod.json \
  --var color=yellow \
  --var height=200
```

The final merged variables object would look like this:

```yaml
{
  "color": "yellow",
  "width": 100,
  "height": 200,
  "settings": {
    "debug": false
  }
}
```


# Partials

Each file in the **partials** directory or its subdirectory can be used as Handlebars partial.

#### Example

If the **partials** directory contains a file named **my-partial.hbs**, you can include it as a partial in a configuration file like so:

```yaml
{{> my-partial.hbs }}
```


# Helpers


# Available variables

You can use variables in stack and stack group configuration files and stack template files. Each of them has a different set of variables available.

## Stack group configuration files

Here are variables available in stack group configuration files:

| Key                             | Type      | Description                                                                     |
| ------------------------------- | --------- | ------------------------------------------------------------------------------- |
| env                             | object    | Environment variables.                                                          |
| context                         | object    | An object containing context variables.                                         |
| context.projectDir              | string    | Current project directory.                                                      |
| stackGroup                      | object    | An object representing the current stack group.                                 |
| stackGroup.name                 | string    | Name of the stack group.                                                        |
| stackGroup.path                 | string    | Path of the stack group.                                                        |
| stackGroup.pathSegments         | string\[] | Path of the stack group split into an array using **/** as a separator.         |
| parent                          | object    | An object representing the parent stack group where the stack group belongs to. |
| parent.accountIds               | string\[] | Account ids of the parent stack group.                                          |
| parent.capabilities             | string\[] | Capabilities of the parent stack group.                                         |
| parent.commandRole              | string    | Command role of the parent stack group.                                         |
| parent.data                     | object    | Data object of the parent stack group.                                          |
| parent.isRoot                   | boolean   | Is the parent stack group the root.                                             |
| parent.name                     | string    | Name of the parent stack group.                                                 |
| parent.path                     | string    | Path of the parent stack group.                                                 |
| parent.pathSegments             | string\[] | Path of the parent stack group split into an array using **/** as a separator.  |
| parent.project                  | string    | Project of the parent stack group.                                              |
| parent.regions                  | string    | Regions of the parent stack group.                                              |
| parent.tags                     | object\[] | Stack tags of the parent stack group.                                           |
| parent.tags\[].key              | string    | Tag key.                                                                        |
| parent.tags\[].value            | string    | Tag value.                                                                      |
| parent.templateBucket           | object    | Template bucket configuration of the parent stack group.                        |
| parent.templateBucket.name      | string    | Name of the template bucket.                                                    |
| parent.templateBucket.keyPrefix | string    | Key prefix of the template bucket.                                              |
| parent.timeout                  | object    | Timeout configuration of the parent stack group.                                |
| parent.timeout.create           | number    | Create timeout in seconds.                                                      |
| parent.timeout.update           | number    | Update timeout in seconds.                                                      |
| var                             | object    | Variables from the command line.                                                |

## Stack configuration files

Here are variables available in stack configuration files:

| Key                                 | Type      | Description                                                                                     |
| ----------------------------------- | --------- | ----------------------------------------------------------------------------------------------- |
| context                             | object    | An object containing context variables.                                                         |
| context.projectDir                  | string    | Current project directory.                                                                      |
| env                                 | object    | Environment variables.                                                                          |
| stackGroup                          | object    | An object representing the stack group where the stack belongs to.                              |
| stackGroup.accountIds               | string\[] | Account ids of the stack group.                                                                 |
| stackGroup.capabilities             | string\[] | Capabilities of the stack group.                                                                |
| stackGroup.commandRole              | string    | Command role of the stack group.                                                                |
| stackGroup.data                     | object    | Data object of the stack group.                                                                 |
| stackGroup.isRoot                   | boolean   | Is the stack group the root.                                                                    |
| stackGroup.name                     | string    | Name of the stack group.                                                                        |
| stackGroup.path                     | string    | Path of the stack group.                                                                        |
| stackGroup.pathSegments             | string\[] | Path of the stack group split into an array using **/** as a separator.                         |
| stackGroup.project                  | string    | Project of the stack group.                                                                     |
| stackGroup.regions                  | string    | Regions of the stack group.                                                                     |
| stackGroup.tags                     | object\[] | Stack tags of the stack group.                                                                  |
| stackGroup.tags\[].key              | string    | Tag key.                                                                                        |
| stackGroup.tags\[].value            | string    | Tag value.                                                                                      |
| stackGroup.templateBucket           | object    | Template bucket configuration of the stack group.                                               |
| stackGroup.templateBucket.name      | string    | Name of the template bucket.                                                                    |
| stackGroup.templateBucket.keyPrefix | string    | Key prefix of the template bucket.                                                              |
| stackGroup.timeout                  | object    | Timeout configuration of the stack group.                                                       |
| stackGroup.timeout.create           | number    | Create timeout in seconds.                                                                      |
| stackGroup.timeout.update           | number    | Update timeout in seconds.                                                                      |
| stack                               | object    | An object representing the stack.                                                               |
| stack.configFile                    | object    | An object representing configuration file of the stack.                                         |
| stack.configFile.basename           | string    | Name of the stack configuration file including the file extension                               |
| stack.configFile.dirPath            | string    | File path to the directory containing the stack configuration file relative to stack directory. |
| stack.configFile.filePath           | string    | File path of the stack configuration file relative to stack directory.                          |
| stack.configFile.name               | string    | Name of the stack configuration file without the file extension.                                |
| stack.path                          | string    | Path of the stack without the region specified.                                                 |
| stack.pathSegments                  | string\[] | Path of the stack without the region specified split into an array using **/** as a separator.  |
| var                                 | object    | Variables from the command line.                                                                |

## Stack template files

Here are variables available in stack template files:

| Key                            | Type      | Description                                                                                                     |
| ------------------------------ | --------- | --------------------------------------------------------------------------------------------------------------- |
| context                        | object    | An object containing context variables.                                                                         |
| context.projectDir             | string    | Current project directory.                                                                                      |
| env                            | object    | Environment variables.                                                                                          |
| hooks                          | object    | An object containing values returned by hooks                                                                   |
| stack                          | object    | An object representing the current stack                                                                        |
| stack.accountIds               | string\[] | Account ids of the stack.                                                                                       |
| stack.commandRole              | string    | Command role of the stack.                                                                                      |
| stack.configFile               | object    | An object representing configuration file of the stack.                                                         |
| stack.configFile.basename      | string    | Name of the stack configuration file including the file extension                                               |
| stack.configFile.dirPath       | string    | File path to the directory containing the stack configuration file relative to stack directory.                 |
| stack.configFile.filePath      | string    | File path of the stack configuration file relative to stack directory.                                          |
| stack.configFile.name          | string    | Name of the stack configuration file without the file extension.                                                |
| stack.data                     | object    | Data object of the stack.                                                                                       |
| stack.depends                  | string\[] | Dependencies of the stack.                                                                                      |
| stack.name                     | string    | Name of the stack.                                                                                              |
| stack.path                     | string    | Path of the stack.                                                                                              |
| stack.pathSegments             | string\[] | Path of the stack split into an array using **/** as a separator.                                               |
| stack.parameters               | object\[] | Parameters of the stack                                                                                         |
| stack.parameters\[].key        | string    | Parameters key                                                                                                  |
| stack.parameters\[].value      | string    | Parameters value                                                                                                |
| stack.parametersMap            | object    | Stack parameters in an object where each key is a parameter key and value is the corresponding parameter value. |
| stack.project                  | string    | Project of the stack.                                                                                           |
| stack.region                   | string    | Region of the stack.                                                                                            |
| stack.tags                     | object\[] | Stack tags of the stack.                                                                                        |
| stack.tags\[].key              | string    | Tag key.                                                                                                        |
| stack.tags\[].value            | string    | Tag value.                                                                                                      |
| stack.template                 | string    | Template of the stack.                                                                                          |
| stack.templateBucket           | object    | Template bucket configuration of the stack.                                                                     |
| stack.templateBucket.name      | string    | Name of the template bucket.                                                                                    |
| stack.templateBucket.keyPrefix | string    | Key prefix of the template bucket.                                                                              |
| stack.timeout                  | object    | Timeout configuration of the stack.                                                                             |
| stack.timeout.create           | number    | Create timeout in seconds.                                                                                      |
| stack.timeout.update           | number    | Update timeout in seconds.                                                                                      |
| var                            | object    | Variables from the command line.                                                                                |


# Built-in parameter resolvers

You can use parameter resolvers to resolve values for stack parameters at deployment time. Takomo has a few built-in parameter resolvers, and you can also implement your own.

In a stack configuration, you choose which resolver to use by providing value to the `resolver` property. In addition to the resolver property, each resolver may have its own set of additional properties.

Here are the built-in parameter resolvers:

* [Stack output resolver](/parameter-resolvers/built-in-parameter-resolvers/stack-output-resolver)
* [External stack output resolver](/parameter-resolvers/built-in-parameter-resolvers/external-stack-output-resolver)
* [Command resolver](/parameter-resolvers/built-in-parameter-resolvers/command-resolver)
* [File contents resolver](/parameter-resolvers/built-in-parameter-resolvers/file-contents-resolver)
* [Hook output resolver](/parameter-resolvers/built-in-parameter-resolvers/hook-output-resolver)
* [SSM parameter resolver](/parameter-resolvers/built-in-parameter-resolvers/ssm-parameter-resolver)
* [Secret resolver](/parameter-resolvers/built-in-parameter-resolvers/secret-resolver)

## See also

* [Configuring parameter resolvers in stack configuration](/stack-properties/parameters#dynamic-parameters)
* [Implementing custom parameter resolvers](/parameter-resolvers/custom-parameter-resolvers)


# Stack output resolver

Stack output resolver reads the parameter value from a stack output of another stack configured within the same Takomo project. The source stack automatically becomes the target stack's dependency. Takomo reads the output value using the credentials associated with the source stack.

{% hint style="info" %}
If you need to read outputs of stacks that are not configured in the same Takomo project, you can use the [external stack output resolver](/parameter-resolvers/built-in-parameter-resolvers#external-stack-output-resolver).
{% endhint %}

### Properties

Here are the properties of the stack output resolver:

| Key          | Required | Type    | Description                                                                  |
| ------------ | -------- | ------- | ---------------------------------------------------------------------------- |
| resolver     | yes      | string  | Resolver name, this must be **stack-output**.                                |
| stack        | yes      | string  | Stack path of the source stack. Can be an absolute or a relative stack path. |
| output       | yes      | string  | Name of the stack output whose value is read.                                |
| confidential | no       | boolean | Conceal the resolved parameter value from logs, defaults to **false**        |
| immutable    | no       | boolean | Mark the parameter as immutable, defaults to **false**                       |

### Example

Say, we have two stacks: **vpc.yml** and **security-groups.yml**. The former creates a VPC and exposes its id in the stack outputs with a name **VpcId**, and the latter uses the VPC id to create some security groups.

The directory structure looks like this:

```bash
.
├─ stacks
│  ├─ vpc.yml
│  └─ security-groups.yml
└─ templates
   ├─ vpc.yml
   └─ security-groups.yml
```

In **security-groups.yml** stack configuration we use the **stack-output** resolver to read the value for the **VpcId** parameter like so:

{% code title="stacks/security-groups.yml" %}

```yaml
parameters:
  VpcId:
    resolver: stack-output
    stack: /vpc.yml
    output: MyVpcId
```

{% endcode %}


# External stack output resolver

The external stack output resolver reads the parameter value from a stack output of a stack. The source stack does not have to belong to the same Takomo project as the target stack.

### Properties

Here are the properties of the external stack output resolver:

| Key          | Required | Type    | Description                                                                                                                            |
| ------------ | -------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| resolver     | yes      | string  | Resolver name, this must be **external-stack-output**.                                                                                 |
| stack        | yes      | string  | Name of the source stack.                                                                                                              |
| output       | yes      | string  | Name of the stack output whose value is read.                                                                                          |
| region       | no       | string  | Region of the source stack. Region is optional. By default, the region of the target stack is used.                                    |
| commandRole  | no       | string  | IAM role used to access the stack output. Command role is optional. By default, credentials associated with the target stack are used. |
| confidential | no       | boolean | Conceal the resolved parameter value from logs, defaults to **false**                                                                  |
| immutable    | no       | boolean | Mark the parameter as immutable, defaults to **false**                                                                                 |

### Example

Say, we have two accounts: **123456789012** and **888888888888**.

The account **123456789012** has one stack: **src-bucket**. It is located in the **us-east-1** region and exposes the name of an application source bucket in a stack output named **SrcBucketName**. The **123456789012** account also has a read-only role that the **888888888888** account can assume.

The **888888888888** account has two stacks: **assets-bucket** and **build-infra**. The stacks are located in the **us-east-1** and **eu-west-1** regions, respectively. The **assets-bucket** stack exposes the name of an assets bucket in a stack output named **AssetsBucket**.

Only the **build-infra** stack is managed in our Takomo project. The two other stacks are configured elsewhere. The **build-infra** stack has two parameters: **SrcBucket** and **AssetsBucket**. To get the values for them, we use the **external-stack-output** resolver to read the two other stacks' outputs.

The directory structure looks like this:

```bash
.
├─ stacks
│  └─ build-infra.yml
└─ templates
   └─ build-infra.yml
```

The configuration of **build-infra** stack looks like this:

{% code title="stacks/build-infra.yml" %}

```yaml
regions: us-east-1
parameters:
  SrcBucket:
    resolver: external-stack-output
    stack: src-bucket
    output: SrcBucketName
    commandRole: arn:aws:iam::123456789012:role/read-only
  AssetsBucket:
    resolver: external-stack-output
    stack: assets-bucket
    output: AssetsBucketName
    region: eu-west-1
```

{% endcode %}

For the **SrcBucket** parameter, we need to specify the **commandRole** property because the source stack is located in a different account. We don't need to specify the **region** because both stacks are located in the same region.

For the **AssetsBucket** parameter, we must specify the **region** but not the **commandRole** because the stacks are located in the same account but different regions.


# Command resolver

The command resolver executes a specified shell command and uses the command output as a parameter value.

### Properties

Here are the properties of the command resolver:

| Key                    | Required | Type    | Description                                                                                                                                                                              |
| ---------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| resolver               | yes      | string  | Resolver name, this must be **cmd**.                                                                                                                                                     |
| command                | yes      | string  | Shell command to execute.                                                                                                                                                                |
| confidential           | no       | boolean | Conceal the resolved parameter value from logs, defaults to **false**                                                                                                                    |
| immutable              | no       | boolean | Mark the parameter as immutable, defaults to **false**                                                                                                                                   |
| exposeStackCredentials | no       | boolean | Make the current stack's AWS credentials available for the shell command. Defaults to false. Added in Takomo v3.11.0.                                                                    |
| exposeStackRegion      | no       | boolean | Make the current stack's region available for the shell command. Defaults to false. Added in Takomo v3.11.0.                                                                             |
| capture                | no       | string  | Controls how to capture the output of the executed shell command. By default, all output is captured. To capture only the last line, set this to **last-line.** Added in Takomo v3.11.0. |

### Environment variables available in the shell command

The following environment variables are available in the shell command:

| Name                     | Description                                                                                                        |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------ |
| AWS\_ACCESS\_KEY\_ID     | If `exposeStackCredentials` is **true**, this will hold the access key id of credentials of the current stack.     |
| AWS\_SECRET\_ACCESS\_KEY | If `exposeStackCredentials` is **true**, this will hold the secret access key of credentials of the current stack. |
| AWS\_SESSION\_TOKEN      | If `exposeStackCredentials` is **true**, this will hold the session token of credentials of the current stack.     |
| AWS\_SECURITY\_TOKEN     | If `exposeStackCredentials` is **true**, this will hold the session token of credentials of the current stack.     |
| AWS\_DEFAULT\_REGION     | IF `exposeStackRegion` is **true**, this will hold the region of the current stack.                                |

### Example

Use contents of the **/home/password.txt** file as parameter value:

```yaml
parameters:
  Password:
    resolver: cmd
    command: cat /home/password.txt
```

##


# File contents resolver

The file contents resolver reads a file and uses the file contents as a parameter value.

### Properties

Here are the properties of the file contents resolver:

| Key          | Required | Type    | Description                                                                        |
| ------------ | -------- | ------- | ---------------------------------------------------------------------------------- |
| resolver     | yes      | string  | Resolver name, this must be **file-contents**.                                     |
| file         | yes      | string  | Path to file. Can be an absolute path or a path relative to the project directory. |
| confidential | no       | boolean | Conceal the resolved parameter value from logs, defaults to **false**              |
| immutable    | no       | boolean | Mark the parameter as immutable, defaults to **false**                             |

### Examples

Use contents of the **/tmp/commit.txt** file as parameter value:

```yaml
parameters:
  CommitHash:
    resolver: file-contents
    file: /tmp/commit.txt
```

Use a relative file path:

```yaml
parameters:
  Code:
    resolver: file-contents
    file: code.txt
```

##


# Hook output resolver

The hook output resolver reads parameter values from hook outputs.

### Properties

Here are the properties of the hook output resolver:

| Key          | Required | Type    | Description                                                           |
| ------------ | -------- | ------- | --------------------------------------------------------------------- |
| resolver     | yes      | string  | Resolver name, this must be **hook-output**.                          |
| hook         | yes      | string  | Name of the hook whose output should be read.                         |
| confidential | no       | boolean | Conceal the resolved parameter value from logs, defaults to **false** |
| immutable    | no       | boolean | Mark the parameter as immutable, defaults to **false**                |

### Examples

This stack configuration has a hook named **my-hook**, which runs before stack operations. It is a command hook and will store the output from the shell command to hook outputs from where the subsequent hooks and parameter resolvers can access it.

A hook output resolver reads the output of **my-hook** and sets it as the value of the **Greeting** parameter.

```yaml
parameters:
  Greeting:
    resolver: hook-output
    hook: my-hook
hooks:
  - name: my-hook
    type: cmd
    stage: before
    command: echo 'hello world'
```

##


# SSM parameter resolver

The SSM parameter resolver reads parameter values from SSM parameter store. The parameter can be encrypted.

### Properties

Here are the properties of the SSM parameter resolver:

| Key          | Required | Type    | Description                                                                                                                              |
| ------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| resolver     | yes      | string  | Resolver name, this must be **ssm**.                                                                                                     |
| name         | yes      | string  | Name of the SSM parameter.                                                                                                               |
| region       | no       | string  | Region where the SSM parameter resides. By default, Takomo uses the region of the stack where the parameter resolver is used.            |
| commandRole  | no       | string  | IAM role used to access the SSM parameter. Command role is optional. By default, credentials associated with the current stack are used. |
| confidential | no       | boolean | Conceal the resolved parameter value from logs, defaults to **false**                                                                    |
| immutable    | no       | boolean | Mark the parameter as immutable, defaults to **false**                                                                                   |

### Examples

Read value from an SSM parameter **/database/password** that resides in the same region as the current stack:

```yaml
parameters:
  Password:
    resolver: ssm
    name: /database/password
```

Read value from an SSM parameter **/database/username** that resides in eu-north-1 region:

```yaml
parameters:
  Username:
    resolver: ssm
    region: eu-north-1
    name: /database/username
```

Read value from an SSM parameter using custom IAM role:

```yaml
parameters:
  Password:
    resolver: ssm
    commandRole: arn:aws:iam::123456789012:role/read-only
    name: MyParam
```


# Secret resolver

The secret parameter resolver reads parameter values from secrets stored in Secrets Manager.

### Properties

Here are the properties of the secret parameter resolver:

| Key          | Required | Type    | Description                                                                                                                                            |
| ------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| resolver     | yes      | string  | Resolver name, this must be **secret**.                                                                                                                |
| secretId     | yes      | string  | Secret id.                                                                                                                                             |
| versionId    | no       | string  | Secret version id.                                                                                                                                     |
| versionStage | no       | string  | Secret version stage.                                                                                                                                  |
| commandRole  | no       | string  | IAM role used to access the secret from Secrets Manager. Command role is optional. By default, credentials associated with the current stack are used. |
| region       | no       | string  | Region where the secret resides. By default, Takomo uses the region of the stack where the parameter resolver is used.                                 |
| confidential | no       | boolean | Conceal the resolved parameter value from logs, defaults to **false**                                                                                  |
| immutable    | no       | boolean | Mark the parameter as immutable, defaults to **false**                                                                                                 |

### Examples

Read the parameter value from a secret with id "my-secret-password":&#x20;

```yaml
parameters:
  Password:
    resolver: secret
    secretId: my-secret-password
```

Read the parameter value from a secret in a different region:

```yaml
parameters:
  MyParam:
    resolver: secret
    secretId: my-secret-password
    region: eu-west-1
```

Read the parameter value from a different account

```yaml
parameters:
  MyParam:
    resolver: secret
    secretId: arn:aws:secretsmanager:us-west-2:123456789012:secret:MySecret
    commandRole: arn:aws:iam::123456789012:role/SecretReader
```


# Custom parameter resolvers

You can provide custom parameter resolvers by placing plain JavaScript files, with **.js** file extension, into the **resolvers** directory. Each file must export a parameter resolver provider object. Takomo uses the provider to initialize the actual parameter resolver.

{% hint style="info" %}
You can use all language features available in Node 14.4.0.
{% endhint %}

## Parameter Resolver Provider

The parameter resolver provider must implement the [ResolverProvider interface](https://takomo.io/api-docs/release/latest/interfaces/stacks_model_src.resolverprovider.html) which has the following properties:

* `name`
  * Name of the resolver used to refer to the resolver from stack configuration files.
  * Must be either a string or a synchronous function that returns a string.
  * Required.
* `init`
  * A function that initializes the resolver with properties given in a stack configuration file.
  * Can be either synchronous or asynchronous.
  * Must return an instantiated [parameter resolver](/parameter-resolvers/custom-parameter-resolvers#parameter-resolver) object.
  * Required.
* `schema`
  * An optional function that returns a [Joi](https://joi.dev/) schema that is used to validate configuration provided for the resolver from stack configuration files.
  * It takes one argument that is an object with the following properties:
    * `ctx` - [CommandContext](https://takomo.io/api-docs/release/latest/interfaces/core_src.commandcontext.html) object that provides access to project configuration
    * `joi` - Joi instance to create new validation constraints
    * `base` - A pre-initialized [Joi object schema](https://joi.dev/api/?v=17.4.0#object) that you can modify to provide your resolver's validation schema
  * You can return the pre-initialized schema from the schema function or use the Joi instance to create an entirely new schema. In most cases you should modify the base schema object as needed and then return it.

## Parameter Resolver

The parameter resolver must implement the [Resolver interface](https://takomo.io/api-docs/release/latest/interfaces/stacks_model_src.resolver.html) which consists of the following properties:

* `resolve`
  * A function that resolves the actual parameter value. The resolved value can be of any type and is converted to a string before it is passed to CloudFormation. If the value is an array, it is converted to a string by joining its values with a comma.
  * The resolve function is invoked with a single argument of type [ResolverInput](https://takomo.io/api-docs/release/latest/interfaces/stacks_model_src.resolverinput.html) that contains the following properties:
    * `ctx` - [CommandContext](https://takomo.io/api-docs/release/latest/interfaces/core_src.commandcontext.html) object that provides access to project configuration
    * `logger` - [Logger](https://takomo.io/api-docs/release/latest/interfaces/util_src.tkmlogger.html) instance.
    * `stack` - The [stack](https://takomo.io/api-docs/release/latest/interfaces/stacks_model_src.stack.html) where the parameter whose value is being resolved belongs to.
    * `listParameterIndex` - If the parameter whose value is being resolved is of type list, this will hold the index of the value in the list. The index begins from 0. This will be 0 if the parameter being resolved os not list.
    * `parameterName` - Name of the parameter whose value is being resolved.
    * `variables` - A mutable copy of the current command [variables](https://takomo.io/api-docs/release/latest/interfaces/stacks_model_src.stackoperationvariables.html) during the stack operation.
* `confidential`
  * A boolean or a synchronous function that returns a boolean value determining if the resolved parameter value should be concealed from log messages. The **confidential** property in a stack configuration file takes precedence over this value.
  * Optional, defaults to false.
* `dependencies`
  * A list of stack paths or a synchronous function that returns a list of stack paths of the stacks that the resolver depends on.
  * Optional, defaults to an empty list.
* `iamRoleArns`
  * A list of IAM role ARNs or a synchronous function that returns a list of IAM role ARNs needed to resolve the value.
  * Optional, defaults to an empty list.

## Examples

### Simple custom resolver

Here's an example of a simple custom parameter resolver that converts the value given in the parameter resolver configuration to uppercase. The parameter resolver schema requires that in the stack configuration file where the resolver is used, the resolver configuration must contain a value property of type string, and that its value must not have more than 50 characters.

Our file structure looks like this:

```bash
.
├─ stacks
│  └─ my-stack.yml
├─ resolvers
│  └─ uppercase.js
└─ templates
   └─ my-stack.yml
```

The parameter resolver provider defined in **resolvers/uppercase.js** looks like this:

{% code title="resolvers/uppercase.js" %}

```javascript
module.exports = {
  name: "uppercase",
  schema: ({joi, base}) => {
    return base.keys({
      value: joi.string().max(50).required()
    })
  },
  init: (props) => {
    return {
      confidential: true,
      dependencies: () => [],
      iamRoleArns: [],
      resolve: (input) => {
        input.logger.debug("Execute uppercase!");
        input.logger.debug(`Resolve value for parameter '${input.parameterName}'`);
        return props.value.toUpperCase();
      }
    }
  }
}
```

{% endcode %}

Our custom parameter resolver is used in the stack configuration like so:

{% code title="stacks/my-stack.yml" %}

```yaml
parameters:
  MyParameter:
    resolver: uppercase
    value: hello
```

{% endcode %}

When the stack is deployed, the value for **MyParameter** parameter is resolved using the **uppercase** custom parameter resolver. The actual value that is assigned to the parameter will be **"HELLO"**.

## Publishing resolvers to NPM

You can share your custom resolvers with others by publishing them to NPM. The published NPM package must export a [parameter resolver provider](/parameter-resolvers/custom-parameter-resolvers#parameter-resolver-provider) object.

#### Example

Here's an example of how to publish a simple custom resolver that returns the current timestamp. The project file structure looks like this:

```bash
.
├─ index.js
└─ package.json
```

The **index.js** file contains the parameter resolver provider:

{% code title="index.js" %}

```javascript
module.exports = {
  name: "timestamp",
  init: () => Date.now(),
}
```

{% endcode %}

The **package.json** file contains minimum configuration that is needed to publish the resolver to NPM:&#x20;

{% code title="package.json" %}

```yaml
{
  "name": "takomo-timestamp-resolver",
  "version": "0.0.1",
  "description": "My custom timestamp resolver",
  "files": [
    "index.js"
  ],
  "main": "index.js",
  "license": "MIT",
  "publishConfig": {
    "access": "public",
    "registry": "https://registry.npmjs.org/"
  }
}
```

{% endcode %}

Refer to official [NPM documentation](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry) for more information about publishing NPM packages.

## Using resolvers from NPM

To use custom resolvers published to NPM, you need to install the resolver's NPM package to your project and then register the resolver in your project's **takomo.yml** file.

#### Example

Let's see how we would include the timestamp resolver from the previous example to our own project.

First of all, we need to install and save the resolver package to our project's dependencies.:

```bash
npm install takomo-timestamp-resolver@0.0.1 --save-dev 
```

Then, we need to register the resolver to our Takomo project by modifying the **takomo.yml** file. There are three ways to register a resolver:

{% code title="takomo.yml" %}

```yaml
# Add resolvers section
resolvers:

  # 1) Use just the package name
  - takomo-timestamp-resolver

  # 2) Give the package name with 'package' property
  - package: takomo-timestamp-resolver

  # 3) Give the package name with 'package' property and
  #    override the resolver name with 'name' property.    
  - package: takomo-timestamp-resolver
    name: special-timestamp
```

{% endcode %}

When registering the resolver using option 1 or 2, Takomo registers the resolver using the name exposed by the resolver provider object - in this case that is **timestamp**.

It's possible that our project already has a resolver registered with the same name. Takomo requires that all resolver names are unique and will throw an error if more that one resolver has the same name. To work around this problem, you can use the third way to register a resolver, which let's you specify a new name for it. In our example, we have set the resolver name to be **special-timestamp**.

Once the resolver is registered, you can use it like any resolver. For more information, see the related [documentation](/stack-properties/parameters#dynamic-parameters).


# Built-in hooks

You can use hooks to execute actions at specific stages of stack deploy and undeploy operations. Takomo has two built-in hooks, and you can also implement your own.

In a stack configuration, you choose which type of hook to use by providing value to the `type` property. You also need to give a name for each hook. In addition to these two mandatory properties, each hook type may have its own set of additional properties.

## Command hook

The command hook executes the specified shell command.

### Properties

Here are the properties of the Command hook:

| Key                    | Required | Type    | Description                                                                                                                                                     |
| ---------------------- | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type                   | yes      | string  | Type of the hook, this must be **cmd**.                                                                                                                         |
| name                   | yes      | string  | Name of the hook.                                                                                                                                               |
| command                | yes      | string  | Shell command to execute.                                                                                                                                       |
| cwd                    | no       | string  | Path to the working directory from where the shell command is executed. Relative to the current project directory.                                              |
| exposeStackCredentials | no       | boolean | Make the current stack's AWS credentials available for the shell command. Defaults to false.                                                                    |
| exposeStackRegion      | no       | boolean | Make the current stack's region available for the shell command. Defaults to false.                                                                             |
| capture                | no       | string  | Controls how to capture the output of the executed shell command. By default, all output is captured. To capture only the last line, set this to **last-line.** |

### Environment variables available in the shell command

The following environment variables are available in the shell command:

| Name                     | Description                                                                                                                                                                                                                                                                                                |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| TKM\_COMMAND\_STAGE      | The current stack operation stage.                                                                                                                                                                                                                                                                         |
| TKM\_COMMAND\_OPERATION  | The current stack operation.                                                                                                                                                                                                                                                                               |
| TKM\_COMMAND\_STATUS     | The current stack operation status, not present in before stage                                                                                                                                                                                                                                            |
| AWS\_ACCESS\_KEY\_ID     | If `exposeStackCredentials` is **true**, this will hold the access key id of credentials of the current stack.                                                                                                                                                                                             |
| AWS\_SECRET\_ACCESS\_KEY | If `exposeStackCredentials` is **true**, this will hold the secret access key of credentials of the current stack.                                                                                                                                                                                         |
| AWS\_SESSION\_TOKEN      | If `exposeStackCredentials` is **true**, this will hold the session token of credentials of the current stack.                                                                                                                                                                                             |
| AWS\_SECURITY\_TOKEN     | If `exposeStackCredentials` is **true**, this will hold the session token of credentials of the current stack.                                                                                                                                                                                             |
| AWS\_DEFAULT\_REGION     | If `exposeStackRegion` is **true**, this will hold the region of the current stack.                                                                                                                                                                                                                        |
| TKM\_HOOK\_{hook-name}   | Values returned from previous hooks are exposed in environment variables where the {hook-name} placeholder is replaced with the hook's name. Hooks whose name has unsafe characters not compatible with a pattern /^\[a-zA-Z\_]+\[a-zA-Z0-&#x39;*\_*]\*$/ are not exposed and a warning is logged instead. |

Any output the hook prints to the stdout is captured and exposed to other hooks.

### Examples

A command hook that runs a simple shell command:

```yaml
- name: my-hook
  type: cmd
  command: echo 'hello world'
```

A command hook that exposes the current stack's AWS credentials to the shell command:

```yaml
- name: my-another-hook
  type: cmd
  exposeStackCredentials: true
  command: aws sts get-caller-identity
```

## Checksum hook

The checksum hook calculates a checksum from a specified directory. The checksum is calculated recursively, i.e. all files and directories under the specified directory are included in the checksum.

### Properties

Here are the properties of the Checksum hook:

| Key      | Required | Type   | Description                                                                                                                        |
| -------- | -------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| type     | yes      | string | Type of the hook, this must be **checksum**                                                                                        |
| name     | yes      | string | Name of the hook                                                                                                                   |
| dir      | yes      | string | Path to the directory from where the checksum should be calculated. The path can be absolute or relative to the project directory. |
| encoding | no       | string | Encoding used to encode the calculated checksum. Supported values are **base64** (default) and **hex**.                            |

### Examples

Calculate a checksum from a directory lambda/scripts located in the project directory.

```yaml
- name: my-checksum
  type: checksum
  dir: lambda/scripts
```

The same as above but using the hex encoding.

```yaml
- name: my-hex-checksum
  type: checksum
  dir: lambda/scripts
  encoding: hex
```

## See also

* [Configuring hooks in stack configuration](/stack-properties/hooks)


# Custom hooks

You can provide custom hooks by placing plain JavaScript files, with **.js** file extension, into the **hooks** directory. Each file must export a [hook provider object](/hooks/custom-hooks#hook-provider). Takomo uses the provider to initialize the actual hook.

{% hint style="info" %}
You can use all language features available in Node 14.4.0.
{% endhint %}

## Hook provider

Hook provider has the following properties:

| Key  | Required | Type     | Description                                                                                                                                                                                                                               |
| ---- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type | yes      | string   | Type of the hook                                                                                                                                                                                                                          |
| init | yes      | function | A function that initializes the hook with properties given in a stack group or stack configuration file. The function can be either synchronous or asynchronous, and must return an instantiated [hook object](/hooks/custom-hooks#hook). |

## Hook

Hook has the following properties:

| Key     | Required | Type     | Description                                                                                                                                                                                                                         |
| ------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| execute | yes      | function | A function that is invoked with [an hook input object](/hooks/custom-hooks#hook-input) when the hook is executed. The function can be synchronous or asynchronous and must return [a hook output](/hooks/custom-hooks#hook-output). |

## Hook Input

A hook input is an object that is passed to hook's execute function. It has the following properties:

| Key       | Required | Type   | Description                                                                                                                                                                                                                                                                                                                      |
| --------- | -------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| stage     | yes      | string | Current stack operation stage. Possible values are: before, after                                                                                                                                                                                                                                                                |
| operation | yes      | string | Current stack operation. Possible values are: create, update, delete                                                                                                                                                                                                                                                             |
| status    | yes      | string | <p>Current stack operation status. Possible values are: success, failed, cancelled<br><br>This is defined only when the stage is <strong>after</strong>.</p>                                                                                                                                                                     |
| variables | yes      | object | Mutable variables object containing command line and environment variables. The hook can modify existing variables and add new ones. After the hook is completed, the same variables object is passed to the subsequent hooks which can then access its contents. The variables are available also in the stack's template file. |
| ctx       | yes      | object | Command context object                                                                                                                                                                                                                                                                                                           |

## Hook Output

A hook output is a value returned from hook's execute function. It is used to determine if the hook execution was successful and to share data between hooks. It can be either a **boolean**, an **Error** which is always considered as failure, or a detailed object with the following properties:

| Key     | Required | Type    | Description                                                                                                             |
| ------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------- |
| success | yes      | boolean | A boolean determining if the hook execution was successful.                                                             |
| message | no       | string  | An informative message about the hook execution outcome.                                                                |
| value   | no       | any     | A value to be exposed to other hooks.                                                                                   |
| skip    | no       | boolean | A boolean determining if all the remaining hooks of the current stack and the stack operation itself should be skipped. |

## Example

This example hook prints some debug information to the console.

Our file structure looks like this:

```bash
.
├─ stacks
│  └─ my-stack.yml
├─ hooks
│  └─ debug.js
└─ templates
   └─ my-stack.yml
```

The hook provider defined in **hooks/debug.js** looks like this:

{% code title="hooks/debug.js" %}

```javascript
module.exports = {
  type: "debug",
  init: (props) => {
    console.log("Initialize debug hook")
    return {
      execute: (input) => {
        console.log("Execute debug hook!")
        console.log(`Stage:     ${input.stage}`)
        console.log(`Operation: ${input.operation}`)
        console.log(`Status:    ${input.status}`)
        console.log(JSON.stringify(props, null, 2))
        
        return {
          message: "OK",
          success: true,
          value: "Did some debugging"
        }
      }
    }
  }
}
```

{% endcode %}

Our custom hook is used in the stack configuration like so:

{% code title="stacks/my-stack.yml" %}

```yaml
hooks:
  - name: my-hook
    type: debug
```

{% endcode %}

When executed, the hook exposes string **"Did some debugging"** in the mutable variables object.


# Sharing data between hooks

Hooks can expose values to other hooks by returning a hook output object. Takomo stores the returned value with a hook's name in a mutable variables object that it then passes to the subsequent hooks. Takomo discards the mutable variables object after the stack operation completes, which means the exposed data is not visible to hooks executed in other stacks.

### Example

This example shows how you can share data between hooks.&#x20;

Our file structure looks like this:

```bash
.
├─ stacks
│  └─ my-stack.yml
├─ hooks
│  ├─ first.js 
│  └─ second.js
└─ templates
   └─ my-stack.yml
```

There are two custom hooks located in the hooks dir.

{% code title="hooks/first.js" %}

```javascript
module.exports = {
  type: "first",
  init: (props) => {
    return {
      execute: (input) => {
        return {
          message: "OK",
          success: true,
          value: "My greeting to the next hook"
        }
      }
    }
  }
}
```

{% endcode %}

The first hook returns a hook output object that contains a greeting to other hooks in the `value` property.

{% code title="hooks/second.js" %}

```javascript
module.exports = {
  type: "second",
  init: (props) => {
    return {
      execute: (input) => {
        const greeting = input.variables.hooks.firstHook
        // Do something with the greeting here...
        return true
      }
    }
  }
}
```

{% endcode %}

The second hook reads the greeting from the input argument.

And this is how you glue everything together in a stack configuration file:

```yaml
template: my-stack.yml
regions: eu-west-1
hooks:
  - name: firstHook
    type: first
  - name: secondHook
    type: second  
```

The `hooks` property defines two hooks, one of each type. Takomo executes the hooks in order they are defined.


# Custom validation schemas

You can use custom Joi validation schemas to validate your configuration.&#x20;

{% hint style="info" %}
Please read more about Joi from its [official documentation](https://joi.dev/api/?v=17.4.0).&#x20;
{% endhint %}

You provide custom validation schemas by placing plain JavaScript files, with **.js** file extension, into the **schemas** directory or its subdirectories. Each file must export a [schema provider object](/validation-schemas/custom-validation-schemas#schema-provider). Takomo uses the provider to initialize the actual schema.

{% hint style="info" %}
You can use all language features available in Node 14.4.0.
{% endhint %}

## Schema provider

Schema provider initializes a Joi validation schema. It has the following properties:

* `name`
  * Name of the resolver used to refer to the schema from configuration files. It can be either a string or a function that returns a string. The function must not be asynchronous.
  * Required.
* `init`
  * A function that initializes the Joi schema object with properties given in a configuration file that uses to the schema.
  * The function can be either synchronous or asynchronous, and must return an instantiated Joi schema.
  * It takes one argument that is an object with the following properties:
    * `ctx` - [CommandContext](https://takomo.io/api-docs/release/latest/interfaces/core_src.commandcontext.html) object that provides access to project configuration
    * `joi` - Joi instance to create new validation constraints
    * `props` - Properties from the configuration file
  * Required.
* `schema`
  * A function that return a Joi schema object used to validate the properties given to the **init** function.
  * It takes one argument that is an object with the following properties:
    * `ctx` - [CommandContext](https://takomo.io/api-docs/release/latest/interfaces/core_src.commandcontext.html) object that provides access to project configuration
    * `joi` - Joi instance to create new validation constraints
    * `base` - A pre-initialized [Joi object schema](https://joi.dev/api/?v=17.4.0#object) that you can modify to provide your resolver's validation schema
  * You can return the pre-initialized schema from the schema function or use the Joi instance to create an entirely new schema. In most cases you should modify the base schema object as needed and then return it.
  * Optional.

You can find more information from the [API documentation](https://takomo.io/api-docs/release/latest/interfaces/stacks_model_src.schemaprovider.html).

## Examples

Here are a few examples of custom schemas.

### Validation schema for stack tags

You can use the [schemas](/stack-properties/schemas) property to specify validation schemas for stack tag configuration. Tag configuration is an object whose keys are tag keys and values are value for the corresponding tags. Therefore you need to use Joi's object schema to validate your tag configurations.

First, you need to implement a schema provider. We name our tag schema as **my-tags** and specify two required properties: **environment** and **costCenter**. In other words, we require that every stack must always have these two tags.

{% code title="schemas/my-tags.js" %}

```javascript
module.exports = {
  name: "my-tags",
  init: ({ joi }) => joi.object({
    environment: joi.string().valid("dev", "test", "prod").required(),
    costCenter: joi.number().required()
  }).unknown(false)
} 
```

{% endcode %}

In stack configuration we specify that we want to validate stack tags using our custom schema like so:

```javascript
schemas:
  tags: my-tags
  
tags:
  environment: dev
  costCenter: 1234  
```


# Common options

Here are the options available for all commands (unless stated otherwise).

* [Assume yes to all questions](/command-line-usage/common-options#assume-yes-to-all-questions)
* [Display help](/command-line-usage/common-options#display-help)
* [Display Takomo version](/command-line-usage/common-options#display-takomo-version)
* [Enable confidential information logging](/command-line-usage/common-options#enable-confidential-information-logging)
* [Enable statistics](/command-line-usage/common-options#enable-statistics)
* [Feature flags](/command-line-usage/common-options#feature-flags)
* [Load AWS SDK config](/command-line-usage/common-options#load-aws-sdk-config)
* [Load environment variables from a file](/command-line-usage/common-options#load-environment-variables-from-a-file)
* [Set logging level](/command-line-usage/common-options#set-logging-level)
* [Set project dir](/command-line-usage/common-options#set-logging-level)
* [Set variables](/command-line-usage/common-options#set-variables)
* [Show command to generate IAM policies](/command-line-usage/common-options#show-command-to-generate-iam-policies)
* [Suppress all but the final output](/command-line-usage/common-options#suppress-all-but-the-final-output)
* [Use AWS profile](/command-line-usage/common-options#use-aws-profile)

## Assume yes to all questions

Pass `--yes` or `-y` option to answer yes to all questions.

## Display help

Pass `--help` option to display help. Command specific helps include also the minimum IAM permissions needed to run the command.

## Display Takomo version

Pass `--version` option to print version information.

## Enable confidential information logging

By default, environment variables and confidential parameter values are concealed from logs. Override this default by passing `--log-confidential-info`.

## Enable statistics

Use `--stats` option to print statistics information of the executed command.

## Feature flags

You can use `--feature <feature>=<boolean value>` option to enable and disable certain Takomo features.

Available feature flags:

* deploymentTargetsUndeploy - Set false to disable [undeploy deployment targets](https://targets.takomo.io/command-line-usage/undeploy-targets) command
* deploymentTargetsTearDown - Set false to disable [tear down deployment targets](https://targets.takomo.io/command-line-usage/tear-down-targets) command

## Load AWS SDK config

Use `--load-aws-sdk-config` to prefer loading credentials from configuration file over the credentials file. Passing this option will enable loading the profile from **\~/.aws/config** file.

## Load environment variables from a file

Use `--env-file <path-to-environment-variables-file>` to load environment variables from a file. The loaded variables override existing variables with the same name. This option can be used multiple times.

The environment variables must be defined in a format accepted by [dotenv](https://www.npmjs.com/package/dotenv), like so:

```
DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3
```

## Set logging level

Use `--log <level>` option to choose the logging level.

Supported values are:

* trace
* debug
* info (default)
* warn
* error
* none (suppress all logging)

## Set project dir

Use `--dir <directory>` or `-d <directory>` option to define the directory from where Takomo loads configuration.

## Set variables

Pass `--var` and `--var-file` options to provide variables that can be used in stack group and stack configuration files and stack templates. Both options can be used multiple times.

For more information, see [command-line variables](/variables/command-line-variables).

## Show command to generate IAM policies

Use `--show-generate-iam-policies` option to print instructions how to generate IAM policies needed to run the command.&#x20;

## Suppress all but the final output

Use `--quiet` or `-q` to suppress all logging and all but the final output. Useful when you want to write the command output to a file.

## Use AWS profile

Use `--profile <profile>` option to choose which AWS profile to use.

For more information, see [AWS credentials](/configuration/aws-credentials).


# Deploy stacks

Deploy stacks within the given command path.&#x20;

Takomo also deploys stacks that the stacks within the command path depend on, even if they are outside the given command path. Takomo arranges the stacks in deployment order by stack dependencies, ensuring that it deploys the stacks in the correct order and in parallel when possible.

Takomo deletes stacks whose creation have failed earlier and then recreates them. Such failed stacks can't be updated, and deleting them is the only possible operation.

## Usage

```bash
tkm stacks deploy [command-path] \
  [--ignore-dependencies] \
  [--interactive|-i] \
  [--expect-no-changes] \
  [--output <format>]
```

## Positional arguments

* `command-path`
  * Command path to select which stacks to deploy.
  * Optional, by default, Takomo deploys all stacks.

## Options

In addition to the [common options](/command-line-usage/common-options), this command has the following options.

* `--ignore-dependencies`
  * Ignore stack dependencies. By default, when a stack is deployed, its dependencies are deployed first, and then the stack itself. In some exceptional cases, you might want to deploy just one stack and skip its dependencies.
  * Bear in mind that this option is supported only when exactly one stack is deployed. Ignoring dependencies may lead into unexpected results, so you should use this option only in exceptional circumstances.
* `--interactive`, `-i`
  * Choose the command path using autocompleting search.
* `--expect-no-changes`
  * Fail the deployment if at least one stack has changes.
* `--output <format>`
  * Print the command result using this format
  * Supported values: `text`, `json`, `yaml`

## IAM permissions

These are the minimum IAM permissions required to run this command.

```yaml
# Minimum permissions. Additional permissions are needed to actually 
# modify resources defined in the CloudFormation templates.
Statement: 
  - Sid: CloudFormation
    Effect: Allow
    Action:
      - cloudformation:CancelUpdateStack
      - cloudformation:DescribeStackEvents
      - cloudformation:CreateStack
      - cloudformation:GetTemplate
      - cloudformation:DeleteStack
      - cloudformation:UpdateStack
      - cloudformation:CreateChangeSet
      - cloudformation:DescribeChangeSet
      - cloudformation:DeleteChangeSet
      - cloudformation:ValidateTemplate
      - cloudformation:DescribeStacks
      - cloudformation:GetTemplateSummary
      - cloudformation:UpdateTerminationProtection
    Resource: "*"
  
  # S3 permissions needed only if a template bucket is used.
  # Specify resource to restrict access to specific buckets.  
  - Sid: S3
    Effect: Allow
    Action:
      - s3:PutObject
    Resource: "*"
  
  # IAM permissions needed only if command roles are used  
  # Specify resource to restrict access to specific roles.  
  - Sid: IAM
    Effect: Allow
    Action:
      - sts:AssumeRole
    Resource: "*"
```

## Examples

Deploy all stacks:

```bash
tkm stacks deploy
```

Deploy stacks within the given command path:

```bash
tkm stacks deploy /prod
```

Deploy only **/dev/vpc.yml** stack and its dependencies:

```bash
tkm stacks deploy /dev/vpc.yml
```

The region part must be specified if the stack has more than one region and you want to deploy it to only one region.

```bash
tkm stacks deploy /dev/vpc.yml/eu-west-1
```

Deploy exactly one stack and skip its dependencies:

```bash
tkm stacks deploy /cloudtrail.yml --ignore-dependencies
```


# Undeploy stacks

Undeploy (remove) stacks within the given command path.&#x20;

Takomo also removes stacks that depend on the stacks within the command path, even if they are outside the given command path. Takomo arranges the stacks in removal order by stack dependencies, ensuring that it removes the stacks in the correct order and in parallel when possible.

## Usage

```bash
tkm stacks undeploy [command-path] \
  [--ignore-dependencies] \
  [--interactive|-i] \
  [--output <format>]
```

## Positional arguments

* `command-path`
  * Command path to select which stacks to undeploy.
  * Optional, by default, Takomo undeploys all stacks.

## Options

In addition to the [common options](/command-line-usage/common-options), this command has the following options.

* `--ignore-dependencies`
  * Ignore stack dependencies. By default, when a stack is removed, its dependants are removed first, and then the stack itself. In some exceptional cases, you might want to remove just one stack and skip its dependants.
  * Bear in mind that this option is supported only when exactly one stack is removed. Ignoring dependants may lead into unexpected results, so you should use this option only in exceptional circumstances.
* `--interactive`, `-i`
  * Choose the command path using autocompleting search.
* `--output <format>`
  * Print the command result using this format
  * Supported values: `text`, `json`, `yaml`

## IAM permissions

These are the minimum IAM permissions required to run this command.

```yaml
# Minimum permissions. Additional permissions are needed to actually 
# remove the resources defined in CloudFormation templates.
Statement: 
  - Sid: Stacks
    Effect: Allow
    Action:
      - cloudformation:DescribeStackEvents
      - cloudformation:DeleteStack
      - cloudformation:DescribeStacks
    Resource: "*"

  # IAM permissions needed only if command roles are used  
  # Specify resource to restrict access to specific roles.  
  - Sid: IAM
    Effect: Allow
    Action:
      - sts:AssumeRole
    Resource: "*" 
```

## Examples

Undeploy all stacks:

```
tkm stacks undeploy
```

Undeploy stacks within the given command path:

```
tkm stacks undeploy /dev
```

Undeploy only **/dev/vpc.yml** stack and its dependants:

```
tkm stacks undeploy /dev/vpc.yml
```

The region part must be specified if the stack has more than one region and you want to undeploy it from only one region.

```
tkm stacks undeploy /dev/vpc.yml/eu-west-1
```

Undeploy exactly one stack and skip its dependants:

```
tkm stacks undeploy /cloudtrail.yml --ignore-dependencies
```


# Prune stacks

Undeploy (remove) stacks marked as obsolete within the given command path.&#x20;

Takomo also removes obsolete stacks that depend on the obsolete stacks within the command path, even if they are outside the given command path. Takomo arranges the stacks in removal order by stack dependencies, ensuring that it removes the stacks in the correct order and in parallel when possible.

Obsolete stacks can't have dependent stacks that are not obsolete themselves.

## Usage

```bash
tkm stacks prune [command-path] \
  [--ignore-dependencies] \
  [--interactive|-i] \
  [--output <format>]
```

## Positional arguments

* `command-path`
  * Command path to select which stacks to prune.
  * Optional, by default, Takomo prunes all stacks.

## Options

In addition to the [common options](/command-line-usage/common-options), this command has the following options.

* `--ignore-dependencies`
  * Ignore stack dependencies. By default, when a stack is removed, its dependants are removed first, and then the stack itself. In some exceptional cases, you might want to remove just one stack and skip its dependants.
  * Bear in mind that this option is supported only when exactly one stack is removed. Ignoring dependants may lead into unexpected results, so you should use this option only in exceptional circumstances.
* `--interactive`, `-i`
  * Choose the command path using autocompleting search.
* `--output <format>`
  * Print the command result using this format
  * Supported values: `text`, `json`, `yaml`

## IAM permissions

These are the minimum IAM permissions required to run this command.

```yaml
# Minimum permissions. Additional permissions are needed to actually 
# remove the resources defined in CloudFormation templates.
Statement: 
  - Sid: Stacks
    Effect: Allow
    Action:
      - cloudformation:DescribeStackEvents
      - cloudformation:DeleteStack
      - cloudformation:DescribeStacks
    Resource: "*"

  # IAM permissions needed only if command roles are used  
  # Specify resource to restrict access to specific roles.  
  - Sid: IAM
    Effect: Allow
    Action:
      - sts:AssumeRole
    Resource: "*" 
```

## Examples

Prune all stacks:

```
tkm stacks prune
```

Prune stacks within the given command path:

```
tkm stacks prune /dev
```

Prune only **/dev/vpc.yml** stack and its dependants:

```
tkm stacks prune /dev/vpc.yml
```

The region part must be specified if the stack has more than one region and you want to prune it from only one region.

```
tkm stacks prune /dev/vpc.yml/eu-west-1
```

Prune exactly one stack and skip its dependants:

```
tkm stacks prune /cloudtrail.yml --ignore-dependencies
```


# List stacks

List stacks within the given command path.

## Usage

```bash
tkm stacks list [command-path] [--output <format>]
```

## Positional arguments

* `command-path`
  * Command path to select which stacks to list.
  * Optional, by default, Takomo lists all stacks.

## Options

In addition to the [common options](/command-line-usage/common-options), this command has the following options.

* `--output <format>`
  * Print the command result using this format
  * Supported values: `text`, `json`, `yaml`

## IAM permissions

These are the minimum IAM permissions required to run this command.

```yaml
Statement: 
  - Sid: Stacks
    Effect: Allow
    Action: cloudformation:DescribeStacks
    Resource: "*"

  # IAM permissions needed only if command roles are used.  
  # Specify Resource to restrict access to specific roles.  
  - Sid: IAM
    Effect: Allow
    Action: sts:AssumeRole
    Resource: "*" 
```

## Examples

List all stacks:

```
tkm stacks list
```

List stacks within the given command path:

```
tkm stacks list /prod
```


# Detect drift

Detect drift of stacks within the given command path.

## Usage

```bash
tkm stacks detect-drift [command-path]
```

## Positional arguments

* `command-path`
  * Command path to select from which stacks to detect drift.
  * Optional, by default, Takomo detects drift from all stacks.

## Options

In addition to the [common options](/command-line-usage/common-options), this command has no command-specific options.

## IAM permissions

These are the minimum IAM permissions required to run this command.

```yaml
Statement: 
  - Sid: Stacks
    Effect: Allow
    Action:
      - cloudformation:DescribeStacks
      - cloudformation:DetectStackDrift
      - cloudformation:DescribeStackDriftDetectionStatus
    Resource: "*"

  # IAM permissions needed only if command roles are used  
  # Specify resource to restrict access to specific roles.  
  - Sid: IAM
    Effect: Allow
    Action:
      - sts:AssumeRole
    Resource: "*"  
```

## Examples

Detect drift from all stacks:

```
tkm stacks detect-drift
```

Detect drift from stacks within the given command path:

```
tkm stacks detect-drift /prod
```


# Generate IAM policies

Generate IAM policies based on CloudTrail events occurred between the given start and end time, in the given regions, by the given identities.

{% hint style="warning" %}

#### Important

The IAM policies generated by this command are based on events found from CloudTrail at the time the command is executed. There are a few things to keep in mind when generating policies.

* You need to have CloudTrail enabled, preferably in all regions.
* The IAM policies generated by this command can contain invalid IAM actions because not all events logged in CloudTrail can be mapped directly to valid IAM actions. You should use the generated policies as a starting point for your own handcrafted and fine-tuned policies.
* Typically, the performed actions become visible in CloudTrail within 15 minutes. You should wait at least that time before running the command shown above to ensure the generated policies contain all actions. If you suspect that not all actions were included in the generated policy, you should 5 minutes more and then rerun the command.
  {% endhint %}

## Usage

```bash
tkm iam generate-policies \
  --start-time <start-time> \
  --end-time <end-time> \
  --identity <identity>... \
  --region <region>... \ 
  [--role-name <role-name>]
  
```

This command is intended to be run with option values generated after running some other command with `--show-generate-iam-policies` option. For example, to get the IAM policies needed to deploy a stack, you first need to run the deploy stack command with `--show-generate-iam-policies` option, and then run this command using instructions shown after the deploy stack command.

Here's a typical workflow to generate IAM policies needed to deploy some stacks:

1. Run the deploy stacks command with `--show-generate-iam-policies` option and full admin permissions (to ensure the operation doesn't fail due to insufficient permissions). This step should be executed on a non-production environment.
2. Copy the command to generate IAM policies shown in the deploy stacks command's output.
3. Wait at least 15 minutes to ensure all events from the previous command are found from CloudTrail.
4. Run the command you copied in step 2 with a role or user that is allowed to look up events from CloudTrail (see [minimum IAM policy for this command](/command-line-usage/generate-iam-policies#iam-permissions)).
5. The command prints the generated policies that you can use to craft the final policies. &#x20;

## Positional arguments

This command has no positional arguments.

## Options

In addition to the [common options](/command-line-usage/common-options), this command has the following options.

* `--start-time <start time>`
  * Include events from CloudTrail after this time.
  * Must be in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format, e.g. 2021-10-05T14:48:00.000Z.
  * Required.
* `--end-time <end time>`
  * Include events from CloudTrail before this time.
  * Must be in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format, e.g. 2021-10-05T16:48:00.000Z.
  * Required.
* `--identity <identity>`
  * Include events from CloudTrail by this identity.
  * You can use this option multiple times to specify more identities.
  * Must be a valid IAM identity ARN.
  * Optional.
* `--region <region>`
  * Include events from CloudTrail from this region.
  * You can use this option multiple times to specify more regions.
  * Optional.
* `--role-name <role>`
  * If you are generating policies from actions executed against multiple accounts, you need to provide a name of the IAM role for Takomo to assume from each account to collect the CloudTrail events.
  * Optional.

## IAM permissions

These are the minimum IAM permissions required to run this command.

```yaml
Statement: 
  - Sid: CloudTrail
    Effect: Allow
    Action: cloudtrail:LookupEvents
    Resource: "*"

  # IAM permissions needed only if policies are generated 
  # from multiple accounts. Specify the Resource to restrict 
  # access to specific roles.  
  - Sid: IAM
    Effect: Allow
    Action: sts:AssumeRole
    Resource: "*" 
```

## Examples

Generate policies for IAM user <john@example.com> based on actions executed in eu-west-1 and us-east-1 regions:

```
tkm iam generate-policies \
  --start-time 2021-05-02T16:45:54.169Z \
  --end-time 2021-05-02T16:45:54.462Z \
  --identity arn:aws:iam::123456789012:user/john@example.com \
  --region eu-west-1 \
  --region us-east-1
```


# Inspect stack configuration

Show stack configuration within the given command path.

## Usage

```bash
tkm stacks inspect configuration [command-path] \
  [--interactive|-i] \
  [--output <format>]
```

## Positional arguments

* `command-path`
  * Command path to select which stacks to include.
  * Optional, by default, Takomo lists all stacks.

## Options

In addition to the [common options](/command-line-usage/common-options), this command has the following options.

* `--interactive`, `-i`
  * Choose the command path using autocompleting search.
* `--output <format>`
  * Print the result from the command using this format
  * Supported values: `text`, `json`, `yaml`

## Examples

Show configuration of all stacks:

```
tkm stacks inspect configuration
```

Show configuration of stacks within the given command path:

```
tkm stacks inspect configuration /prod
```


# Inspect stack dependencies

Inspect dependencies between stacks within the given command path. Prints the dependency graph in a [DOT](https://en.wikipedia.org/wiki/DOT_\(graph_description_language\)) format which can be rendered using various tools like [this one](https://dreampuf.github.io/GraphvizOnline/).

## Usage

```bash
tkm stacks inspect dependency-graph [command-path]
```

## Positional arguments

* `command-path`
  * Command path to select which stacks to include.
  * Optional, by default, Takomo lists all stacks.

## Options

In addition to the [common options](/command-line-usage/common-options), this command has no command-specific options.

## Examples

Inspect dependencies from all stacks:

```
tkm stacks inspect dependency-graph
```

Inspect dependencies within the given command path:

```
tkm stacks inspect dependency-graph /prod
```


# Getting help

## Questions and assistance

If you need help or have general questions concerning Takomo, feel free to contact us at [Gitter](https://gitter.im/takomo-io/community) or start a [GitHub discussion](https://github.com/takomo-io/takomo/discussions).

## Bug reports and feature requests

Bug reports and feature requests are welcome via [GitHub issues](https://github.com/takomo-io/takomo/issues).


# Troubleshooting

Here are some tips to help you troubleshoot problems.

## Logging level

By setting the [logging level](/command-line-usage/common-options#set-logging-level) to **debug** or **trace**, you will see lots of useful information that might help you spot the problem. Logging level is set with `--log <level>` option which is available for all commands,

#### Example

This is how you set logging level to trace:

```bash
tkm stacks deploy --log trace
```

## Statistics

To understand how Takomo interacts with AWS APIs you can use `--stats` option to instruct Takomo to print various statistics after executing a command.

#### Example

This is how you enable statistics:

```bash
tkm <your command here> --stats
```


# Change log

## v3.39.1

Released on 2021/12/12, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.39.1))

### Bug fixes

* Fix a bug that caused stacks marked as obsolete to be included in undeploy stacks operation if they depended on stacks chosen to be included in the undeploy operation.&#x20;

## v3.39.0

Released on 2021/12/11, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.39.0))

### Features

**Prune obsolete stacks**

It's now easier to remove stacks that are no longer needed by marking them as obsolete and then executing the new [prune stacks command](/command-line-usage/prune-stacks) ([#327](https://github.com/takomo-io/takomo/issues/327)).

### Improvements

* Reviewing stacks to be deployed or undeployed now shows only the direct dependencies of the effected stacks. Previously, also transitive dependencies where shown, which caused the dependency list to become very long in larger projects with complex dependency graphs.&#x20;

## v3.38.1

Released on 2021/11/20, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.38.1))

This release includes only code refactoring and more tests.

## v3.38.0

Released on 2021/11/05, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.38.0))

### Features

**Secret parameter resolver**

With the new secret parameter resolver, you can use secrets stored in Secrets Manager as inputs for your CloudFormation stacks ([#317](https://github.com/takomo-io/takomo/issues/317)).

This is an example of how you could use the secret parameter resolver in a stack configuration file:

```yaml
parameters:
  DatabasePassword:
    resolver: secret
    secretId: my-password-secret
```

Read more from the [docs](/parameter-resolvers/built-in-parameter-resolvers/secret-resolver).

## v3.37.1

Released on 2021/11/03, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.37.1))

This release includes only code refactoring and more tests.

## v3.37.0

Released on 2021/10/14, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.37.0))

### Features

**Extending Takomo project configuration files**

It's now possible to make a Takomo project configuration file (takomo.yml) to inherit configuration from another file. Inheriting configuration becomes useful, for example, when you have a monorepo containing multiple Takomo projects, each having its own configuration and sharing some common properties with others. You can place the common properties in a parent file that others then inherit ([#316](#bug-fixes)).

You use the `extends` property to make a project configuration file inherit configuration from another file:

{% code title="takomo.yml" %}

```yaml
extends: ../takomo.parent.yml
```

{% endcode %}

## v3.36.0

Released on 2021/10/06, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.36.0))

### Features

**Load custom Handlebars helpers from additional directories**

You can now specify additional directories from where Takomo loads custom Handlebars helpers by providing one or more directory paths to the `helpersDir` property of Takomo project configuration. The paths can be either absolute or relative to the current project directory ([#276](https://github.com/takomo-io/takomo/issues/276)).

Read more from the [docs](/variables/helpers#loading-helpers-from-additional-directories).

## v3.35.2

Released on 2021/09/29, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.35.2))

### Bug fixes

* Fix a bug that caused the stacks deployment order to go wrong in some cases where there was inter-region dependencies between stacks, ([#312](https://github.com/takomo-io/takomo/issues/312)).

## v3.35.1

Released on 2021/09/26, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.35.1))

### Improvements

* Improve AWS API invocations and handling of concurrent operations

## v3.35.0

Released on 2021/09/21, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.35.0))

### Features

#### Expect no changes to stacks when deploying

You can now invoke [deploy stacks](/command-line-usage/deploy-stacks), [deploy targets](https://targets.takomo.io/command-line-usage/deploy-targets) and [bootstrap targets](https://targets.takomo.io/command-line-usage/bootstrap-targets) commands with `--expect-no-changes` option which causes the operation to fail if at least one of the targeted stacks would have changes. This is useful, for example, if you have made some clean-up to your local configuration and want to make sure that you have not unintentionally introduced some infrastructure changes ([#308](https://github.com/takomo-io/takomo/issues/308)).

### Bug fixes

* Fix loading of stacks when the target regions has more than 100 stacks ([#307](https://github.com/takomo-io/takomo/issues/307)).

## v3.34.1

Released on 2021/09/20, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.34.1))

### Improvements

* Previously, Takomo could not update a stack if its status was ROLLBACK\_FAILED. Now, if Takomo encounters stacks with ROLLBACK\_FAILED status, it attempts to delete the failed stack, and if that succeeds, proceeds to deploy the stack normally).

### Bug fixes

* Fix texts shown on confirm deployment targets operation prompt

## v3.34.0

Released on 2021/09/17, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.34.0))

### Improvements

* Previously, Takomo could not update a stack if its status was UPDATE\_ROLLBACK\_FAILED. Now, if Takomo encounters stacks with UPDATE\_ROLLBACK\_FAILED status, it attempts to continue rollback, and if that succeeds, proceeds to update the stack normally ([#302](https://github.com/takomo-io/takomo/issues/302)).

## v3.33.2

Released on 2021/09/15, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.33.2))

Small improvements.

## v3.33.1

Released on 2021/09/12, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.33.1))

### Features

#### New CLI command: list stacks in organization accounts

You can now use a new CLI command to list CloudFormation stacks from accounts that belong to your AWS organization.

List stacks from every account.

```bash
tkm org accounts list-stacks --config-set-type standard
```

List stacks from accounts that belong to the Root/Workload organizational unit.

```bash
tkm org accounts list-stacks ROOT/Workload --config-set-type standard
```

List all stacks from accounts 123456789012 and 210987654321

```bash
tkm org accounts list-stacks \
  -a 123456789012 210987654321 \
  --config-set-type standard
```

For more information, see the [documentation](https://organizations.takomo.io/command-line-usage/list-accounts-stacks).

#### Choose which config set and command path to use when deploying stacks to accounts

Two new options added to CLI commands that deploy or undeploy stacks from accounts that belong to your AWS organization.&#x20;

* `--config-set <config-set>`
  * Include only this config set.
* `--command-path <command-path>`
  * Include only this command path. Using this option requires that also `--config-set` is used.

These options are supported in the following commands:

* [Deploy accounts](https://organizations.takomo.io/command-line-usage/deploy-accounts)
* [Undeploy accounts](https://organizations.takomo.io/command-line-usage/undeploy-accounts)
* [Bootstrap accounts](https://organizations.takomo.io/command-line-usage/bootstrap-accounts)
* [Tear down accounts](https://organizations.takomo.io/command-line-usage/tear-down-accounts)

## v3.32.0

Released on 2021/08/26, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.30.0))

### Improvements

* Optimize deploying of stacks to minimize AWS API throttling that can occur in larger projects.

### Bug fixes

* Fix bug that prevented recreating failed stacks that have termination protection enabled ([#293](https://github.com/takomo-io/takomo/issues/293)).

## v3.31.2

Released on 2021/08/24, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.31.2))

### Improvements

* Optimize loading of currently existing stacks to speed up commands: deploy stacks and detect stack drift ([#288](https://github.com/takomo-io/takomo/issues/288)).&#x20;

## v3.31.1

Released on 2021/08/23, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.31.1))

### Improvements

* Optimize loading of currently existing stacks to speed up the list stacks operation in larger projects.

## v3.31.0

Released on 2021/08/17, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.31.0))

### Features

#### New configuration property: Infer deployment target's name from its configuration file name

A new property `inferDeploymentTargetNameFromFileName` is now available in the configuration of the filesystem deployment target repository used to load deployment targets from the local filesystem. You can use it to instruct Takomo to infer deployment target names from their configuration files' names. Read more from the [docs](https://targets.takomo.io/configuration/externalize-targets-configuration#infer-deployment-targets-names-from-names-of-their-config-files).

### Bug fixes

* Fix a bug that prevented stack groups to inherit custom validation schemas from their parent.  &#x20;

## v3.30.0

Released on 2021/08/16, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.30.0))

### Features

#### New configuration property: inheritTags

By default, stacks and stack groups inherit tags from their parent stack group. You can now disable this behaviour by setting `inheritTags` to false ([#282](https://github.com/takomo-io/takomo/issues/282)). Read more from the [docs](/stack-properties/inherit-tags).

## v3.29.0

Released on 2021/08/16, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.29.0))

### Features

#### New hook: Checksum hook

You can use this new hook to calculate checksums from directories in your project. For example, suppose you have a lambda function with its source code located in some directory. In that case, you can calculate a checksum from the directory and all files located under it and use it to skip the lambda deployment if the sources have not changed. Read more form the [docs](/hooks/built-in-hooks#checksum-hook).

### Bug fixes

* Fix a bug that caused stdout buffer to exceed when a shell command executed with the cmd resolver produced large amounts of output to the stdout ([#279](https://github.com/takomo-io/takomo/issues/279)).&#x20;

## v3.28.0

Released on 2021/08/15, ([GitHub](https://github.com/takomo-io/takomo/releases/tag/v3.28.0))

### Features

#### Skip stack deploy if a hook returns a skip signal

You can now implement a custom hook to decide whether the following stack operation should be skipped ([#254](https://github.com/takomo-io/takomo/issues/254)). For example, you might use this new feature to skip a stack update if your stack has a lambda function, but its source code has not changed.

To indicate that the following stack operation should be skipped, you need to return an output object from your hook that contains `skip: true`.

{% code title="hooks/my-skip-hook.js" %}

```javascript
const execute = (input) => {
  // Some logic that determines if the stack operations should be skipped
  const skipIsNeeded = isSkipNeeded() 

  return {
    skip: skipIsNeeded,
    success: true,
  }
}

// Hook provider that initializes the hook
module.exports = {
  type: "example",
  init: (props) => ({ execute })
}
```

{% endcode %}

Read [here](/hooks/custom-hooks) how to implement custom hooks.

### Bug fixes

* Fix a bug that caused stdout buffer to exceed when a shell command executed with the cmd hook produced large amounts of output to the stdout.&#x20;


