Good evening brains trust!
I have been struggling for many hours on something I thought would be quite trivial - using CDKTF, how to conditionally create Azure resources depending on environment variables that are only known at runtime.
I synthesize my Terraform JSON once, then use this to deploy to several different Azure resource groups (with different environment variables). Most of the time the resources are all created across each resource group, but sometimes there will be differences. I would like to avoid generating differing synthesized Terraform JSON for each deployment if possible. I thought I should be able to conditionally create a resource at run-time depending on the environment variables used, but I can’t seem to get it - hoping someone smarter than me can point me in the right direction.
Below is a minimal example of what I am talking about. Thank you in advance for any help you can provide.
main.ts:
import type { Construct } from ‘constructs’
import { App, Fn, TerraformStack, TerraformVariable } from ‘cdktf’
import { AzurermProvider } from ‘@cdktf/provider-azurerm/lib/provider’
import { RoleAssignment } from ‘@cdktf/provider-azurerm/lib/role-assignment’
import { StorageAccount } from ‘@cdktf/provider-azurerm/lib/storage-account’class MyStack extends TerraformStack {
constructor(scope: Construct, id: string) {
super(scope, id)//get environment variables
//these aren’t known when cdktf synth is ran
const envAbbrev = new TerraformVariable(this, ‘ENV_ABBREV’, {
type: ‘string’,
sensitive: false
})
const resourceGroupName = new TerraformVariable(this, ‘RESOURCE_GROUP_NAME’, {
type: ‘string’,
sensitive: false
})//configure provider
new AzurermProvider(this, ‘AzureRm’, {
features: {},
clientId: ‘1234567890’,
clientSecret: ‘1234567890’,
tenantId: ‘1234567890’,
subscriptionId: ‘1234567890’
})//how can I conditionally create a resource (e.g. storage account like below) depending on an
//environment variable that is not known at build stage
const st = new StorageAccount(this, ‘st’, {
name:storagename${envAbbrev.value}
,
// “name”: “storagename${var.ENV_ABBREV}” in synthesised cdk.tf.json
resourceGroupName: resourceGroupName.value,
// “resource_group_name”: “${var.RESOURCE_GROUP_NAME}” in synthesised cdk.tf.json
location: ‘australiaeast’,
accountTier: ‘Standard’,
accountReplicationType: ‘LRS’,//I thought that in order to do logic that involves run-time environment variables you have to use Terraform functions, but
//this doesn’t work - in the synthesised cdk.tf.json it doesn’t include the var token, instead
//computing to: “count”: “${false ? 1 : 0}”
count: Fn.conditional(envAbbrev.value === ‘tst’, 1, 0)
})//how can I conditionally create resources that relate to the conditionally created resource above,
//(e.g. role assignment for storage account)
new RoleAssignment(this, ‘stra-sp’, {//additionally, if using count, st will now be an array? but is not typed as such - what is the ‘cdktf’ pattern
//to reference a resource created like this?
scope: st.id,roleDefinitionName: 'Storage Blob Data Contributor', principalId: '1234567890', principalType: 'ServicePrincipal' })
}
}const app = new App({ skipValidation: true })
new MyStack(app, ‘myApp’)
app.synth()