Terrarform cdk condition based on attributes

Hello , I am attempting to assign a value to the ‘userData’ attribute while incorporating conditions that determine the specific value to be assigned. I aim to express these conditions in the same line as the assignment statement:
userData: conditional(Op.neq(platform,“windows”),linuxScripts,windowsScripts ) ,
these are my vars :
const windowsScripts= fs.readFileSync(‘…/scripts/user-data.ps1’,‘utf-8’) ;
const linuxScripts=fs.readFileSync(‘…/scripts/user-data.sh’,‘utf-8’) ;

and i got “Type ‘ConditionalExpression’ is not assignable to type ‘string’”.

And in order to solve this i was trying to use addOverride and conditions : instance.addOverride(“user_data”,conditional(Op.neq(platform,“windows”),linuxScripts,windowsScripts )).
And of course non of them works .

Hi @ramzi-af :wave:

You could try to wrap the conditional(...) in Token.asString() which would tell CDKTF to treat the result of conditional() as a string.

– Ansgar

@ansgarm Thank you, but a new error has occurred :
my code :
// Resources

     const  instance=new Instance(this, "instance", {
      ebsOptimized:true,
      iamInstanceProfile:iam.outputs["SystemsInstanceProfileName"],
      ami :"image", 
      instanceType: "t2.micro",
      keyName:env.outputs["AdminKeyPair"] , 
      vpcSecurityGroupIds
:locals.expression["security_groups"] ,
      subnetId:Token.asString(conditional(Op.neq(subnet.value,null),subnet.value,locals.expression["subnet"])) , 
      rootBlockDevice:{
        volumeSize: commonVars.rootVolumeSize.value
      },
      userData:  Token.asString(conditional(Op.neq(platform.value,"linux"),windowsScripts  ,linuxScripts)), 
      tags:generic_tags
      
    }).

Error description


Error: Invalid reference
                     │ 
                     │   on cdk.tf.json line 76, in resource.aws_instance.instance (instance):
                     │   76:         "subnet_id": "${(var.subnet != undefined) ? var.subnet : undefined}",
                     │ 
                     │ A reference to a resource type must be followed by at least one attribute
                     │ access, specifying the resource name.

Thank you very much @ansgarm, I appreciate your help.

@ansgarm
It seems like I’m missing something ,
Firstly, when comparing subnet.value with null, it should be compared with Token.asNull(). Secondly, it seems that the datasource is being accessed incorrectly by using env.outputs[“AdminKeyPair”].
The correct version will look like this :


    // Resources
    const instance = new Instance(this, "instance", {
      ebsOptimized: true,
      iamInstanceProfile: iam.outputs["SystemsInstanceProfileName"],
      ami: "image",
      instanceType: "t2.micro", 
      //"AdminKeyPair"
      //How  to work with datasources 
      keyName: Fn.lookup(env.getStringMapAttribute("outputs"), "AdminKeyPair", Token.nullValue()), //is  there any thing better  than this
      vpcSecurityGroupIds: locals.expression["security_groups"],
      subnetId: Token.asString(
        conditional(
          Op.neq(
            commonVars.subnet.value,
            Token.nullValue()
          ),
          commonVars.subnet.value, env.getStringAttribute("outputs[\"DefaultSubnet\"],")
        )
      ),
      rootBlockDevice: {
        volumeSize: commonVars.rootVolumeSize.value
      },
      userData: Token.asString(
        conditional(
          Op.neq(commonVars.platform.value, "linux"),
          Fn.file(powershell.path),
          Fn.file(linux.path)
        )
      ),
      tags: generic_tags,

    })

but is there a more effective way to access data sources than the current method?