mkabatek
mkabatek

Reputation: 1276

Getting Elasticache endpoint using pulumi Typescript

Using Pulumi I'm attempting to get the primary endpoint from an elasticache cluster so I can pass it as an environment variable to a fargate service on aws. For some reason the same process that works for RDS does not work on ElastiCache.

pulumi version
v3.23.0
"@pulumi/aws": "^4.36.0",
"@pulumi/awsx": "^0.32.0",
"@pulumi/pulumi": "^3.23.0",

The following works perfectly for RDS:

    super("backend:portalInfrastructure:rds", name, {}, opts)

    let securityGroupIds = cluster.securityGroups.map((g:any) => g.id)

    let dbSubnets = new aws.rds.SubnetGroup(`${name}-rds-subnets-${ENV_LOWER}`, {
      subnetIds: vpc.publicSubnetIds,
    })

    //Extra dash on the name here because pulumi doesn't add one for RDS
    let db = new aws.rds.Instance(`${name}-postgres-${ENV_LOWER}-`, {
      engine: 'postgres',
      instanceClass: 'db.t3.micro',
      allocatedStorage: 20,
      dbSubnetGroupName: dbSubnets.id,
      vpcSecurityGroupIds: securityGroupIds,
      // TODO only needs to be publicly accessible
      // to run migrations from external host
      publiclyAccessible: true,
      ...DB_CONN,
      tags: {
        'env':ENV_LOWER
      },

      skipFinalSnapshot: true
    })

    this.DBSetupOutput = {
      dbhost : db.endpoint.apply(e => e.split(":")[0]),
      db: db
    }

    // For dependency tracking, register output properties for this component
    this.registerOutputs({
      DBSetupOutput: this.DBSetupOutput
    })

However when I try this for ElastiCache/Redis:

    super("backend:portalInfrastructure:redis", name, {}, opts)

    let securityGroupIds = cluster.securityGroups.map((g:any) => g.id)
    
    let redisSubnets = new aws.elasticache.SubnetGroup(`${name}-redis-subnets-${ENV_LOWER}`, {
      subnetIds: vpc.publicSubnetIds,
    })

    let redis = new aws.elasticache.Cluster(`${name}-redis-${ENV_LOWER}`, {
      engine: "redis",
      engineVersion: "3.2.10",
      nodeType: "cache.t3.micro",
      numCacheNodes: 1,
      parameterGroupName: "default.redis3.2",
      port: 6379,
      subnetGroupName: redisSubnets.id,
      securityGroupIds: securityGroupIds
    }, {parent: this});

    redis.clusterAddress.apply(address => {
      console.log(address)
    })

    this.RedisSetupOutput = {
      redishost : redis.clusterAddress.apply(a => a),
      redis: redis
    }

    // For dependency tracking, register output properties for this component
    this.registerOutputs({
      RedisSetupOutput: this.RedisSetupOutput
    })

I get the following output for my variable redishost

"Calling [toString] on an [Output<T>] is not supported.\n\nTo get the value of an Output<T> as an Output<string> consider either:\n1: o.apply(v => `prefix${v}suffix`)\n2: pulumi.interpolate `prefix${v}suffix`\n\nSee https://pulumi.io/help/outputs for more details.\nThis function may throw in a future version of @pulumi/pulumi."

I don't understand because I am calling apply to the pulumi output. The same thing happens when trying to get ElastiCache clusterAddress or cacheNodes. If anyone understand how to get the ElastiCache primary endpoint, or can tell me what I'm doing wrong here it would be greatly appreciated.

Upvotes: 3

Views: 442

Answers (1)

jaxxstorm
jaxxstorm

Reputation: 13301

You are creating a redis elasticache cluster. If you read the docs for elasticache, it states the clusterAddress is only populated for a memcache cluster. See here

What you actually need to use is the cacheNodes output, like so:

this.RedisSetupOutput = {
  redishost : redis.cacheNodes
  redis: redis
}

This returns an array of addressed, you can narrow it down by specifying one fo the outputs from the array:

this.RedisSetupOutput = {
  redishost : redis.cacheNodes[0].address
  redis: redis
}

Upvotes: 1

Related Questions