pulumi / pulumi-aws

An Amazon Web Services (AWS) Pulumi resource package, providing multi-language access to AWS
Apache License 2.0
442 stars 154 forks source link

Issue with endpoint output in the `aws.elasticache` package #2092

Closed throttlehead-dev closed 1 year ago

throttlehead-dev commented 2 years ago

What happened?

It seems that using endpoint outputs in other resources is completely broken with this package. I'm basically encountering the same problem as detailed in this stack overflow only with a ReplicationGroup: https://stackoverflow.com/questions/70900831/getting-elasticache-endpoint-using-pulumi-typescript

I've tried many different ways of resolving the output before passing it to my container task resource. Even the ironclad apply(t => t) method doesn't seem to work.

Steps to reproduce

The following code is a simplified version, but basically I have an ElasticCache component with the replication group being outputted:

export default class ElasticCache extends pulumi.ComponentResource {

    replicationGroup

    constructor(name: string, args: ElasticCacheArgs, opts?: pulumi.ResourceOptions) {

        super("pkg:index:ElasticCache", name, {}, opts);

        const password  = config.requireSecret("elastic_cache_password");

        const replicationGroup = new aws.elasticache.ReplicationGroup(`${args.env}-`+name, {
            automaticFailoverEnabled: true,
            description: `${args.env}-elastic-cache`,
            nodeType: args.elasticCacheNodeType,
            numberCacheClusters: args.elasticCacheNodes,
            parameterGroupName: args.elasticCacheGoupName,
            authToken: password,
            port: args.elasticCachePort,
            preferredCacheClusterAzs: args.availableZones,
            multiAzEnabled: true,
            transitEncryptionEnabled: true,
            atRestEncryptionEnabled: true,
            subnetGroupName: args.elasticCacheSubnetGroupName,
            securityGroupIds: [
                args.elasticCacheSecurityGroupId
            ],
            tags: {
                name: `${args.env}-ReplicationGroup`,
            }
        });

        this.replicationGroup = replicationGroup;
    }
}

This then gets passed into a WebServer component when I try to use the value in a task definitions environment:

const redisHost = args.redisHost.apply(redisHost => redisHost);

const taskDefinitionNginx = new aws.ecs.TaskDefinition("web-server-app-task",{
      ...,
      containerDefinitions: JSON.stringify([
          {
             ...
              "environment": [
                  ...
                  {
                      "name": "REDIS_HOST",
                      "value": redisHost
                  }
              ]
          }
      ])
});

Expected Behavior

The endpoint output to work correctly instead of putting a strange error output into my environment.

Actual Behavior

The task requiring that output is not waiting for the cache to be created. It immediatly applys updates to the container task while the redis cluster is still running.

There's then strange error output put in the environment:

Example:

REDIS_HOST | Calling [toJSON] on an [Output<T>] is not supported. To get the value of an Output as a JSON value or JSON string consider either: 1: o.apply(v => v.toJSON()) 2: o.apply(v => JSON.stringify(v)) See https://pulumi.io/help/outputs for more details. This function may throw in a future version of @pulumi/pulumi.

Versions used

CLI          
Version      3.37.2
Go Version   go1.17.12
Go Compiler  gc

Plugins
NAME    VERSION
aws     5.9.2
docker  3.2.0
nodejs  unknown

Host     
OS       ubuntu
Version  20.04
Arch     x86_64

This project is written in nodejs: executable='/home/jacob/.nvm/versions/node/v16.14.2/bin/node' version='v16.14.2'

Additional context

I'm not the only one who's encountered this:

https://stackoverflow.com/questions/70900831/getting-elasticache-endpoint-using-pulumi-typescript

I think its something with these outputs not being wrapped properly but I know little about Pulumi's underlying code. It's almost like they're missing whats actually supposed to be resolved here, or are possibly double wrapped.

Contributing

Vote on this issue by adding a 👍 reaction. To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).

pierskarsenbarg commented 2 years ago

Hi @throttlehead-dev

This line is what's tripping you up: const redisHost = args.redisHost.apply(redisHost => redisHost);

If you use IntelliSense, you'll see that even though you're using the apply() method, the resulting type is still an Output (if you look at the sentence in our docs on the Apply method you'll see this).

In your case, I'd advise using the pulumi.interpolate method so your code above will look something like this:

const taskDefinitionNginx = new aws.ecs.TaskDefinition("web-server-app-task",{
      ...,
      containerDefinitions: JSON.stringify([
          {
             ...
              "environment": [
                  ...
                  {
                      "name": "REDIS_HOST",
                      "value": pulumi.interpolate`${redisHost}`
                  }
              ]
          }
      ])
});

Give that a go, and let me know how you get on.

My somewhat esteemed colleague @jaxxstorm wrote an excellent blog post on Apply(), which is well worth a read.

stack72 commented 1 year ago

Going to close this issue out - we have not head back on it. Please do let us know if it hasn't worked and we can look at it again