pulumi / pulumi-awsx

AWS infrastructure best practices in component form!
https://www.pulumi.com/docs/guides/crosswalk/aws/
Apache License 2.0
218 stars 105 forks source link

FargateService keeps telling me to define a container, and I have. #820

Open jaxxstorm opened 2 years ago

jaxxstorm commented 2 years ago

What happened?

const svc = new awsx.ecs.FargateService("cal", {
    cluster: cluster.id,
    tags: tags,
    networkConfiguration: {
        assignPublicIp: true,
        subnets: publicSubnets,
        securityGroups: [ appSg.id ]
    },
    taskDefinitionArgs: {
        container: { // containter is definitely defined
            image: "nginx",
            essential: true,
            portMappings: [{
                containerPort: 80,
                targetGroup: loadbalancer.targetGroup,
            }]
        }
    }
})
Diagnostics:
  pulumi:pulumi:Stack (cal-app-production):
    error: Error: failed to register new resource cal [awsx:ecs:FargateService]: 2 UNKNOWN: Exactly one of [container] or [containers] must be provided
        at Object.registerResource (/Users/lbriggs/src/git/jaxxstorm/calendar/app/node_modules/@pulumi/runtime/resource.ts:295:27)
        at new Resource (/Users/lbriggs/src/git/jaxxstorm/calendar/app/node_modules/@pulumi/resource.ts:393:13)
        at new ComponentResource (/Users/lbriggs/src/git/jaxxstorm/calendar/app/node_modules/@pulumi/resource.ts:881:9)
        at new FargateService (/Users/lbriggs/src/git/jaxxstorm/calendar/app/node_modules/@pulumi/ecs/fargateService.ts:78:9)
        at Object.<anonymous> (/Users/lbriggs/src/git/jaxxstorm/calendar/app/index.ts:118:13)
        at Module._compile (internal/modules/cjs/loader.js:1137:30)
        at Module.m._compile (/Users/lbriggs/src/git/jaxxstorm/calendar/app/node_modules/ts-node/src/index.ts:439:23)
        at Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
        at Object.require.extensions.<computed> [as .ts] (/Users/lbriggs/src/git/jaxxstorm/calendar/app/node_modules/ts-node/src/index.ts:442:12)
        at Module.load (internal/modules/cjs/loader.js:985:32)

    Error: Exactly one of [container] or [containers] must be provided: Error: Exactly one of [container] or [containers] must be provided
        at normalizeFargateTaskDefinitionContainers (/Users/lbriggs/.pulumi/plugins/ecs/fargateTaskDefinition.ts:120:15)
        at new FargateTaskDefinition (/Users/lbriggs/.pulumi/plugins/ecs/fargateTaskDefinition.ts:60:28)
        at new FargateService (/Users/lbriggs/.pulumi/plugins/ecs/fargateService.ts:55:30)
        at awsx:ecs:FargateService (/Users/lbriggs/.pulumi/plugins/resources.ts:26:45)
        at construct (/Users/lbriggs/.pulumi/plugins/resources.ts:56:12)
        at Provider.construct (/Users/lbriggs/.pulumi/plugins/index.ts:43:35)
        at Server.<anonymous> (/Users/lbriggs/.pulumi/plugins/resource-awsx-v1.0.0-beta.1/node_modules/@pulumi/provider/server.ts:322:48)
        at Generator.next (<anonymous>)
        at fulfilled (/Users/lbriggs/.pulumi/plugins/resource-awsx-v1.0.0-beta.1/node_modules/@pulumi/pulumi/provider/server.js:18:58)
        at processTicksAndRejections (internal/process/task_queues.js:97:5)

Steps to reproduce

Use the above code

Expected Behavior

I can define a fargate service

Actual Behavior

I cannot

Versions used

CLI          
Version      3.31.0
Go Version   go1.18.1
Go Compiler  gc

Plugins
NAME        VERSION
aws         5.3.0
awsx        1.0.0-beta.1
cloudflare  4.6.0
docker      3.2.0
nodejs      unknown

Host     
OS       darwin
Version  12.3.1
Arch     x86_64

This project is written in nodejs (/Users/lbriggs/.nvm/versions/node/v12.18.4/bin/node v12.18.4)

Current Stack: lbrlabs/production

TYPE                                                 URN
pulumi:pulumi:Stack                                  urn:pulumi:production::cal-app::pulumi:pulumi:Stack::cal-app-production
jaxxstorm:index:ApplicationLoadBalancer              urn:pulumi:production::cal-app::jaxxstorm:index:ApplicationLoadBalancer::cal
jaxxstorm:index:WebListener                          urn:pulumi:production::cal-app::jaxxstorm:index:WebListener::cal
pulumi:providers:cloudflare                          urn:pulumi:production::cal-app::pulumi:providers:cloudflare::default_4_6_0
pulumi:providers:pulumi                              urn:pulumi:production::cal-app::pulumi:providers:pulumi::default
pulumi:providers:aws                                 urn:pulumi:production::cal-app::pulumi:providers:aws::default_5_3_0
aws:ecs/cluster:Cluster                              urn:pulumi:production::cal-app::aws:ecs/cluster:Cluster::cal
pulumi:pulumi:StackReference                         urn:pulumi:production::cal-app::pulumi:pulumi:StackReference::lbrlabs/cal-vpc/production
aws:lb/targetGroup:TargetGroup                       urn:pulumi:production::cal-app::jaxxstorm:index:ApplicationLoadBalancer$aws:lb/targetGroup:TargetGroup::cal
aws:ec2/securityGroup:SecurityGroup                  urn:pulumi:production::cal-app::aws:ec2/securityGroup:SecurityGroup::cal-lb
aws:lb/loadBalancer:LoadBalancer                     urn:pulumi:production::cal-app::jaxxstorm:index:ApplicationLoadBalancer$aws:lb/loadBalancer:LoadBalancer::cal
aws:lb/listener:Listener                             urn:pulumi:production::cal-app::jaxxstorm:index:WebListener$aws:lb/listener:Listener::cal-http
cloudflare:index/record:Record                       urn:pulumi:production::cal-app::cloudflare:index/record:Record::cal
aws:ec2/securityGroup:SecurityGroup                  urn:pulumi:production::cal-app::aws:ec2/securityGroup:SecurityGroup::cal-app
aws:acm/certificate:Certificate                      urn:pulumi:production::cal-app::aws:acm/certificate:Certificate::cal-cert
cloudflare:index/record:Record                       urn:pulumi:production::cal-app::cloudflare:index/record:Record::cal-cert
aws:acm/certificateValidation:CertificateValidation  urn:pulumi:production::cal-app::aws:acm/certificateValidation:CertificateValidation::cal-validation
aws:lb/listener:Listener                             urn:pulumi:production::cal-app::jaxxstorm:index:WebListener$aws:lb/listener:Listener::cal-https

Found no pending operations associated with lbrlabs/production

Backend        
Name           pulumi.com
URL            https://app.pulumi.com/jaxxstorm
User           jaxxstorm
Organizations  jaxxstorm, lbrlabs, team-ce, demo, pulumi

NAME                VERSION
@pulumi/pulumi      3.31.0
@types/node         14.18.16
@pulumi/aws         5.3.0
@pulumi/awsx        1.0.0-beta.1
@pulumi/cloudflare  4.6.0

Pulumi locates its logs in /var/folders/1y/s9gz0_l10hb2y8mtknj45stc0000gn/T/ by default

Additional context

No response

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).

jaxxstorm commented 2 years ago

This appears to be related to portMappings. I'm defining my own targetGroup.

If I do the following:

const svc = new awsx.ecs.FargateService("cal", {
    cluster: cluster.id,
    tags: tags,
    networkConfiguration: {
        assignPublicIp: true,
        subnets: publicSubnets,
        securityGroups: [ appSg.id ]
    },
    taskDefinitionArgs: {
        container: {
            image: "nginx",
            essential: true,
            // portMappings: [{
            //     containerPort: 80,
            //     targetGroup: loadbalancer.targetGroup,
            // }]
        }
    }
})

It works successfully.

fieldfoxWim commented 2 years ago

Hi @jaxxstorm

I also stumbled on this error, when there is an error in the container config it just ignores the container.

Looking at your snippet using awsx I would expect loadbalancer.defaultTargetGroup instead of loadbalancer.targetGroup

cheers Wim

wizardfiction commented 2 years ago

@jaxxstorm Is there any sort of update on this? I am experiencing the issue when I provide an aws.lb.TargetGroup resource in the portMappings block of an awsx.ecs.EC2Service.

I am defining a custom TargetGroup, rather than grabbing defaultTargetGroup off of an awsx alb.

In fact, I'm not using awsx for any of the LB resources (alb, target groups, listeners, listener rules, etc)

wizardfiction commented 2 years ago

I'm doing the same thing successfully on an awsx.ecs.FargateService, except I'm passing the custom TargetGroup via a StackReference.

wizardfiction commented 2 years ago

Just confirmed that my EC2Service also works when the target group is provided via StackReference

robinsummerhill commented 1 year ago

I am seeing the same issue when passing a custom TargetGroup in the portMappings config for a awsx.ecs.FargateService.

ixti commented 1 year ago

I've been seeing this issue too, and if you add multiple containers you will get even more funny message, anyway I was able to solve it by:

loadbalancer.defaultTargetGroup.apply(targetGroup => {
  new awsx.ecs.FargateService("cal", {
    // ...
    taskDefinitionArgs: {
      container: {
        // ...
        portMappings: [{ targetGroup }]
      }
    }
  });
})

Although, I've changed that to:

new awsx.ecs.FargateService("cal", {
  // ...
  taskDefinitionArgs: {
    container: {
      // ...
      portMappings: [{ targetGroup: loadbalancer.defaultTargetGroup }]
    }
  }
}, {
  dependsOn: [loadBalancer.defaultTargetGroup]
});

I use defaultTargetGroup as I let awsx create it, you can use any aws.lb.TargetGroup instance I believe.

php-workx commented 1 year ago

I think the type definition of the targetGroup property is (unnecessarily) specific. The only two attributes it really needs are the LB's arn and port. Until this becomes a bit more flexible, you can use ...

new awsx.ecs.FargateService("cal", {
  // ...
  taskDefinitionArgs: {
    container: {
      // ...
      portMappings: [
        {
          targetGroup: { arn: loadbalancer.arn, port: loadbalancer.port } as any,
        }
      ],
    },
    // ...
  },  
})
don41382 commented 1 year ago

We had the same issue. Using a custom target group in portMappings was followed by the this error:

UNKNOWN: Exactly one of [container] or [containers] must be provided

But we found a workaround! After wrapping the new TargetGroup in a pulumi.Output.create the problem was fixed. I am still not sure why:

const targetGroup = pulumi.Output.create(new aws.alb.TargetGroup(`custom-tg`, {
  port: 80,
  protocol: 'HTTP',
  vpcId: evaluateVpcId,
  targetType: 'ip',
}))
lbkulinski commented 1 year ago

I'm currently running into this issue when using the Using AWS Elastic Container Service example. Seems like it still isn't fixed?

strcrzy commented 1 year ago

this is still a problem, though wrapping the targetGroup in an output is an effective workaround

lukehoban commented 1 year ago

This appears to be due to the underlying https://github.com/pulumi/pulumi/issues/13802 in the core platform. I believe it will need to be fixed there.

geovannimp commented 11 months ago

For me the problem was sharing the same package.json between my app and pulumi. After adding the pulumi package.json to the folder where my pulumi files are, the problem disappeared.

lily-es commented 7 months ago

I believe I have run into a related issue. We are successfully able to use a custom targetGroup, but the object is mangled in the stack.

{
  "containerDefinitions": [
    {
      "portMappings": [
        {
          "containerPort": 3000,
          "protocol": "tcp",
          "targetGroup": {
            "__pulumiResource": true,
            "__pulumiType": "aws:lb/targetGroup:TargetGroup",
            "__transformations": [],
            "__name": "tg-grafana-prod",
            "__providers": {},
            "__protect": false,
            "__version": "6.9.0",
            "__aliases": [
              "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi."
            ],
            "urn": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "id": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "connectionTermination": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "deregistrationDelay": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "healthCheck": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "ipAddressType": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "lambdaMultiValueHeadersEnabled": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "loadBalancingAlgorithmType": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "loadBalancingCrossZoneEnabled": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "name": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "namePrefix": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "port": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "preserveClientIp": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "protocol": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "protocolVersion": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "proxyProtocolV2": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "slowStart": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "stickiness": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "tags": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "targetFailovers": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "targetHealthStates": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "targetType": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "vpcId": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "arn": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "arnSuffix": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "tagsAll": "Calling [toJSON] on an [Output<T>] is not supported.\\n\\nTo get the value of an Output as a JSON value or JSON string consider either:\\n    1: o.apply(v => v.toJSON())\\n    2: o.apply(v => JSON.stringify(v))\\n\\nSee https://www.pulumi.com/docs/concepts/inputs-outputs for more details.\\nThis function may throw in a future version of @pulumi/pulumi.",
            "__pulumiCustomResource": true
          },
          "hostPort": 3000
        }
      ]
    }
  ]
}

This seems to also be what happens when you wrap the targetGroup in a pulumi.Output.create(). Although, this is not what we do. We pass the target group through a function argument as so:

interface CreateContainerArgs {
    targetGroup: aws.lb.TargetGroup
}

function createService(args: CreateContainerArgs) {
    new awsx.ecs.FargateService("test", {
        // ...
        taskDefinitionArgs: {
            container: {
                // ...
                portMappings: [
                    {
                        targetGroup: args.targetGroup,
                    }
                ],
            },
            // ...
        },
    })
}

Both result in the same mangled stack shown above