Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions examples/python/documentation/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,50 @@
# SPDX-License-Identifier: MPL-2.0

from constructs import Construct
from cdktf import TerraformStack, App, TerraformVariable, Token
from cdktf import Op, TerraformStack, TerraformVariable, Token

# DOCS_BLOCK_START:functions-usage-example
from cdktf import Fn, TerraformOutput
from imports.aws.provider import AwsProvider
from imports.aws.data_aws_availability_zones import DataAwsAvailabilityZones
# DOCS_BLOCK_END:functions-usage-example
from imports.aws.instance import Instance


class FunctionsStack(TerraformStack):
def __init__(self, scope: Construct, id: str):
super().__init__(scope, id)
AwsProvider(self, "aws",
AwsProvider(self, "aws",
region="us-east-1"
)

# DOCS_BLOCK_START:functions-usage-example

zones = DataAwsAvailabilityZones(self, 'zones',
state="available",
)
state="available",
)

TerraformOutput(self, 'first-zone',
value=Fn.element(zones.names, 0)
)

# DOCS_BLOCK_END:functions-usage-example

# DOCS_BLOCK_START:functions-conditional
Instance(
self,
'web',
ami='ami-2757f631',
count=Token.as_number(
Fn.conditional(Op.eq(Token.as_any('terraform.workspace'), 'prod'), 2, 1)
),
instance_type='t2.micro',
)
# DOCS_BLOCK_END:functions-conditional

# INTERNAL NOTE: Due to an JSII bug, we have to pass the variable as a string_value in Python
# We can remove it, once https://github.com/aws/jsii/pull/4209 is released
# DOCS_BLOCK_START:functions-lookup
v = TerraformVariable(self, "complex-object",
type = 'object({users: list(object({name: string}))})',
type='object({users: list(object({name: string}))})',
)
TerraformOutput(self, 'users',
value=Fn.lookup(v.string_value, "users")
Expand All @@ -50,4 +63,3 @@ def __init__(self, scope: Construct, id: str):
value=Fn.raw_string('${TEMPLATE}')
)
# DOCS_BLOCK_END:functions-raw-string

23 changes: 20 additions & 3 deletions examples/typescript/documentation/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@ import { TerraformStack, TerraformVariable } from "cdktf";
import { Construct } from "constructs";
import { AwsProvider } from "@cdktf/provider-aws/lib/aws-provider";
// DOCS_BLOCK_END:functions
// DOCS_BLOCK_START:functions-conditional
import { Token } from "cdktf";
import { Instance } from "@cdktf/provider-aws/lib/instance";
// DOCS_BLOCK_END:functions-conditional
// DOCS_BLOCK_START:functions-conditional,operators,functions,functions-raw
import { Fn } from "cdktf";
// DOCS_BLOCK_END:functions-conditional,operators,functions,functions-raw
// DOCS_BLOCK_START:operators,functions,functions-raw
import { Fn, TerraformOutput } from "cdktf";
import { TerraformOutput } from "cdktf";
// DOCS_BLOCK_END:operators,functions,functions-raw
// DOCS_BLOCK_START:operators,functions-raw
// DOCS_BLOCK_START:functions-conditional,operators,functions-raw
import { Op } from "cdktf";
// DOCS_BLOCK_END:operators,functions-raw
// DOCS_BLOCK_END:functions-conditional,operators,functions-raw
// DOCS_BLOCK_START:functions-raw,functions
import { DataAwsAvailabilityZones } from "@cdktf/provider-aws/lib/data-aws-availability-zones";
// DOCS_BLOCK_END:functions-raw,functions
Expand All @@ -37,6 +44,16 @@ export class FunctionsStack extends TerraformStack {
});
// DOCS_BLOCK_END:functions

// DOCS_BLOCK_START:functions-conditional
new Instance(this, "web", {
ami: "ami-2757f631",
count: Token.asNumber(
Fn.conditional(Op.eq(Token.asAny("terraform.workspace"), "prod"), 2, 1),
),
instanceType: "t2.micro",
});
// DOCS_BLOCK_END:functions-conditional

// DOCS_BLOCK_START:functions-lookup
const v = new TerraformVariable(this, "complex_object", {
type: "object({users: list(object({name: string}))})",
Expand Down
34 changes: 26 additions & 8 deletions website/docs/cdktf/concepts/functions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ The `element` function gets the first element from the list of Availability Zone
import { TerraformStack, TerraformVariable } from "cdktf";
import { Construct } from "constructs";
import { AwsProvider } from "@cdktf/provider-aws/lib/aws-provider";
import { Fn, TerraformOutput } from "cdktf";
import { Fn } from "cdktf";
import { TerraformOutput } from "cdktf";
import { DataAwsAvailabilityZones } from "@cdktf/provider-aws/lib/data-aws-availability-zones";
export class FunctionsStack extends TerraformStack {
constructor(scope: Construct, id: string) {
Expand Down Expand Up @@ -79,15 +80,13 @@ import imports.aws.data_aws_availability_zones.DataAwsAvailabilityZonesConfig;
from cdktf import Fn, TerraformOutput
from imports.aws.provider import AwsProvider
from imports.aws.data_aws_availability_zones import DataAwsAvailabilityZones

zones = DataAwsAvailabilityZones(self, 'zones',
state="available",
)
state="available",
)

TerraformOutput(self, 'first-zone',
value=Fn.element(zones.names, 0)
)

```

```csharp
Expand Down Expand Up @@ -159,6 +158,15 @@ func NewFunctionsStack(scope constructs.Construct, name string) cdktf.TerraformS

## Special functions

### Conditional Expressions

The ternary [conditional expression](/terraform/language/expressions/conditionals) is supported in CDKTF as a function. Its first argument for the condition or predicate is usually an [operator](/terraform/cdktf/concepts/functions#operators) such as `Op.eq()` to ensure a runtime comparison. Programming language operators like `==` will be evaluated at synthesis time and the result hardcoded into the generated JSON or HCL. Depending on usage, output and inputs may need their [Token](/terraform/cdktf/concepts/tokens) types specified.

<!-- #NEXT_CODE_BLOCK_SOURCE:python examples/typescript/documentation#functions-conditional -->
<!-- #NEXT_CODE_BLOCK_SOURCE:python examples/python/documentation#functions-conditional -->

<CodeTabs></CodeTabs>

### Property Access Helpers

To access nested properties from untyped objects or other datasources that return a dynamic datatype, use the Terraform function `lookup` or, for nested access, the function "Fn.lookupNested()" which is a function offered by CDKTF that allows to avoid nesting `Fn.lookup` calls.
Expand All @@ -169,6 +177,8 @@ To access nested properties from untyped objects or other datasources that retur
<!-- #NEXT_CODE_BLOCK_SOURCE:csharp examples/csharp/documentation#functions-lookup -->
<!-- #NEXT_CODE_BLOCK_SOURCE:go examples/go/documentation#functions-lookup -->

<CodeTabs>

```ts
const v = new TerraformVariable(this, "complex_object", {
type: "object({users: list(object({name: string}))})",
Expand All @@ -181,7 +191,7 @@ new TerraformOutput(this, "first_user_name", {

```python
v = TerraformVariable(self, "complex-object",
type = 'object({users: list(object({name: string}))})',
type='object({users: list(object({name: string}))})',
)
TerraformOutput(self, 'users',
value=Fn.lookup(v.string_value, "users")
Expand Down Expand Up @@ -230,6 +240,8 @@ cdktf.NewTerraformOutput(stack, jsii.String("first-user-name"), &cdktf.Terraform
})
```

</CodeTabs>

### Raw string helper

Another helper function offered by CDKTF is `Fn.rawString` which can be used to escape raw strings that contain characters that CDKTF or Terraform would try to interpret otherwise.
Expand All @@ -240,6 +252,8 @@ Another helper function offered by CDKTF is `Fn.rawString` which can be used to
<!-- #NEXT_CODE_BLOCK_SOURCE:csharp examples/csharp/documentation#functions-raw-string -->
<!-- #NEXT_CODE_BLOCK_SOURCE:go examples/go/documentation#functions-raw-string -->

<CodeTabs>

```ts
new TerraformOutput(this, "quotes", {
value: Fn.rawString(`"b"`),
Expand Down Expand Up @@ -287,6 +301,8 @@ cdktf.NewTerraformOutput(stack, jsii.String("template"), &cdktf.TerraformOutputC
})
```

</CodeTabs>

## Operators

Use the `Op` object to include operators like `!`, `+`, and `-`.
Expand All @@ -298,7 +314,8 @@ Use the `Op` object to include operators like `!`, `+`, and `-`.
<CodeTabs>

```ts
import { Fn, TerraformOutput } from "cdktf";
import { Fn } from "cdktf";
import { TerraformOutput } from "cdktf";
import { Op } from "cdktf";

const zones = new DataAwsAvailabilityZones(this, "zones", {
Expand Down Expand Up @@ -360,7 +377,8 @@ It is also possible to use all built-in Terraform functions without using CDKTF'
<CodeTabs>

```ts
import { Fn, TerraformOutput } from "cdktf";
import { Fn } from "cdktf";
import { TerraformOutput } from "cdktf";
import { Op } from "cdktf";
import { DataAwsAvailabilityZones } from "@cdktf/provider-aws/lib/data-aws-availability-zones";

Expand Down
50 changes: 49 additions & 1 deletion website/docs/cdktf/concepts/tokens.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ You may need to use Tokens for:
- [Module outputs](/terraform/cdktf/concepts/modules) for boolean, string, lists, maps, and other complex types.
- Resource attributes (such as `id`).
- Terraform outputs based on resource attributes.
- Using Terraforms `null` type.
- Using Terraform's `null` type and [terraform.workspace](/terraform/language/state/workspaces#current-workspace-interpolation).

### Example

Expand Down Expand Up @@ -216,3 +216,51 @@ cdktf.Token_NullValue()
```

</CodeTabs>

### Using `terraform.workspace`

In the code below, the outer `Token.as_number()` avoids:

> TypeError: type of argument count must be one of (int, float, cdktf.TerraformCount, NoneType); got jsii.\_reference_map.InterfaceDynamicProxy instead

The inner `Token.as_any()` avoids generating extra quotes `"terraform.workspace"` and extra dollar signs `"$${terraform.workspace}"`.

<CodeTabs>
<!-- #NEXT_CODE_BLOCK_SOURCE:python examples/python/documentation#functions-conditional -->
<!-- #NEXT_CODE_BLOCK_SOURCE:ts examples/typescript/documentation#functions-conditional -->

```python
Instance(
self,
'web',
ami='ami-2757f631',
count=Token.as_number(
Fn.conditional(Op.eq(Token.as_any('terraform.workspace'), 'prod'), 2, 1)
),
instance_type='t2.micro',
)
```

```ts
import { Token } from "cdktf";
import { Instance } from "@cdktf/provider-aws/lib/instance";
import { Fn } from "cdktf";
import { Op } from "cdktf";
new Instance(this, "web", {
ami: "ami-2757f631",
count: Token.asNumber(
Fn.conditional(Op.eq(Token.asAny("terraform.workspace"), "prod"), 2, 1),
),
instanceType: "t2.micro",
});
```

```terraform
resource "aws_instance" "web" {
ami = "ami-2757f631"
count = (terraform.workspace == "prod") ? 2 : 1
instance_type = "t2.micro"
}
```

</CodeTabs>