Thread
#typescript
    p

    prehistoric-london-9917

    4 months ago
    Hi All- hoping you can help me out. I’m a bit stumped. I’ve updated some dependencies to:
    "@pulumi/aws": "^5",
    "@pulumi/awsx": "^0.40",
    And something that used to work (a while back) now doesn’t, and I can’t figure out how to update my code to make it work again. I have an
    awsx.ec2.Vpc
    (notice it’s the CrossWalk VPC), and I’m trying to map the private subnet CIDR blocks so I can use them in a security group ingress rule. This code used to work.
    privateCidrBlocks
    resolves to
    Promise<pulumi.Output<string | undefined>[]>
    and
    cidrBlocks
    now expects
    pulumi.Input<pulumi.Input<string>[]>
    . I’d love a suggestion for how to get the CIDR blocks from the
    vpc.privateSubnets
    into a format that I can feed into the
    cidrBlocks
    input for the security group ingress. Any ideas?
    c

    clever-sunset-76585

    4 months ago
    And something that used to work (a while back) now doesn’t, and I can’t figure out how to update my code to make it work again.
    What is not working? Are you getting type errors?
    r

    rhythmic-whale-48997

    4 months ago
    Can't you just use something like this?
    const privateCidrBlocks = vpc.getSubnetsIds('private');
    
    
    const storageSG = new aws.ec2.SecurityGroup('storage', {
      description: 'Allow private subnet access to EFS',
      vpcId: vpc.id,
      ingress: [
        {
          cidrBlocks: privateCidrBlocks,
          fromPort: 2049,
          toPort: 2049,
          protocol: 'tcp'
        }
      ]
    });
    c

    clever-sunset-76585

    4 months ago
    @rhythmic-whale-48997 that would just get the subnet IDs and not the CIDR blocks of those subnets, no?
    r

    rhythmic-whale-48997

    4 months ago
    F**ck, my bad. I just tried to run your code and it created a security group with 2 inbound rules for 2 private subnets that I have in my VPC. Are you sure that this doesn't work? 😅
    p

    prehistoric-london-9917

    4 months ago
    Sadly, not for me, getting type errors.
    Diagnostics:
      pulumi:pulumi:Stack (demo_cluster-demo_cluster_sandbox):
        error: Running program '/Users/matthew.riedel/Source/devex/demo_cluster' failed with an unhandled exception:
        TSError: ⨯ Unable to compile TypeScript:
        index.ts(182,56): error TS2345: Argument of type '{ description: string; vpcId: pulumi.Output<string>; ingress: { cidrBlocks: Promise<pulumi.Output<string | undefined>[]>; fromPort: number; toPort: number; protocol: string; }[]; }' is not assignable to parameter of type 'SecurityGroupArgs'.
          Types of property 'ingress' are incompatible.
            Type '{ cidrBlocks: Promise<Output<string | undefined>[]>; fromPort: number; toPort: number; protocol: string; }[]' is not assignable to type 'Input<SecurityGroupIngress>[] | Promise<Input<SecurityGroupIngress>[]> | OutputInstance<Input<SecurityGroupIngress>[]> | undefined'.
              Type '{ cidrBlocks: Promise<Output<string | undefined>[]>; fromPort: number; toPort: number; protocol: string; }[]' is not assignable to type 'Input<SecurityGroupIngress>[]'.
                Type '{ cidrBlocks: Promise<pulumi.Output<string | undefined>[]>; fromPort: number; toPort: number; protocol: string; }' is not assignable to type 'Input<SecurityGroupIngress>'.
                  Type '{ cidrBlocks: Promise<pulumi.Output<string | undefined>[]>; fromPort: number; toPort: number; protocol: string; }' is not assignable to type 'SecurityGroupIngress'.
                    Types of property 'cidrBlocks' are incompatible.
                      Type 'Promise<Output<string | undefined>[]>' is not assignable to type 'Input<string>[] | Promise<Input<string>[]> | OutputInstance<Input<string>[]> | undefined'.
                        Type 'Promise<Output<string | undefined>[]>' is not assignable to type 'Promise<Input<string>[]>'.
                          Type 'Output<string | undefined>[]' is not assignable to type 'Input<string>[]'.
                            Type 'Output<string | undefined>' is not assignable to type 'Input<string>'.
                              Type 'OutputInstance<string | undefined>' is not assignable to type 'Input<string>'.
                                Type 'OutputInstance<string | undefined>' is not assignable to type 'OutputInstance<string>'.
                                  Type 'string | undefined' is not assignable to type 'string'.
                                    Type 'undefined' is not assignable to type 'string'.
        index.ts(216,46): error TS2345: Argument of type '{ description: string; vpcId: pulumi.Output<string>; ingress: { cidrBlocks: Promise<pulumi.Output<string | undefined>[]>; fromPort: number; toPort: number; protocol: string; }[]; }' is not assignable to parameter of type 'SecurityGroupArgs'.
          Types of property 'ingress' are incompatible.
            Type '{ cidrBlocks: Promise<Output<string | undefined>[]>; fromPort: number; toPort: number; protocol: string; }[]' is not assignable to type 'Input<SecurityGroupIngress>[] | Promise<Input<SecurityGroupIngress>[]> | OutputInstance<Input<SecurityGroupIngress>[]> | undefined'.
              Type '{ cidrBlocks: Promise<Output<string | undefined>[]>; fromPort: number; toPort: number; protocol: string; }[]' is not assignable to type 'Input<SecurityGroupIngress>[]'.
                Type '{ cidrBlocks: Promise<pulumi.Output<string | undefined>[]>; fromPort: number; toPort: number; protocol: string; }' is not assignable to type 'Input<SecurityGroupIngress>'.
                  Type '{ cidrBlocks: Promise<pulumi.Output<string | undefined>[]>; fromPort: number; toPort: number; protocol: string; }' is not assignable to type 'SecurityGroupIngress'.
                    Types of property 'cidrBlocks' are incompatible.
                      Type 'Promise<Output<string | undefined>[]>' is not assignable to type 'Input<string>[] | Promise<Input<string>[]> | OutputInstance<Input<string>[]> | undefined'.
                        Type 'Promise<Output<string | undefined>[]>' is not assignable to type 'Promise<Input<string>[]>'.
    
            at createTSError (/Users/matthew.riedel/Source/devex/demo_cluster/node_modules/ts-node/src/index.ts:261:12)
            at getOutput (/Users/matthew.riedel/Source/devex/demo_cluster/node_modules/ts-node/src/index.ts:367:40)
            at Object.compile (/Users/matthew.riedel/Source/devex/demo_cluster/node_modules/ts-node/src/index.ts:558:11)
            at Module.m._compile (/Users/matthew.riedel/Source/devex/demo_cluster/node_modules/ts-node/src/index.ts:439:43)
            at Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
            at Object.require.extensions.<computed> [as .ts] (/Users/matthew.riedel/Source/devex/demo_cluster/node_modules/ts-node/src/index.ts:442:12)
            at Module.load (node:internal/modules/cjs/loader:981:32)
            at Function.Module._load (node:internal/modules/cjs/loader:822:12)
            at Module.require (node:internal/modules/cjs/loader:1005:19)
            at require (node:internal/modules/cjs/helpers:102:18)
    l

    little-cartoon-10569

    4 months ago
    Your code is working for me. However, for me, privateCidrBlocks is resolving to type
    Promise<pulumi.Output<string>[]>
    which is why I'm not getting that error. I can force the error by switching to this artificial code:
    const privateCidrBlocks = vpc.privateSubnets
        .then(subnets => subnets.map(subnet =>
              subnet.subnet.cidrBlock.length ? subnet.subnet.cidrBlock
                                             : undefined));
    Is there any way that you could be translating cidrBlock to an
    Output<string | undefined>
    instead of the
    Output<string>
    that it originally was? There's nothing in your example code that I can see..
    p

    prehistoric-london-9917

    4 months ago
    thanks @little-cartoon-10569 - the code I have is what I pasted in.. What versions of @pulumi/pulumi, @pulumi/awsx are you using?
    l

    little-cartoon-10569

    4 months ago
    "devDependencies": {
        "@pulumi/aws": "5.3.0",
        "@pulumi/awsx": "^0.40.0",
        "@pulumi/cloudinit": "*",
        "@pulumi/pulumi": "3.30.0",
        "@pulumi/random": "4.5.0",
        "@pulumi/docker": "^3.2.0",
        "@pulumi/tls": "^4.3.0",
    ...
    Anything I should change and try again?
    p

    prehistoric-london-9917

    4 months ago
    Hmm. looks close to mine:
    "@pulumi/aws": "^5",
            "@pulumi/awsx": "^0.40",
            "@pulumi/eks": "^0.40",
            "@pulumi/kubernetes": "^3.1.2",
            "@pulumi/kubernetesx": "^0.1.6",
            "@pulumi/pulumi": "^3.0.0",
            "@pulumi/random": "^4.1.1",
            "ts-retry": "^2.3.3"
    That resolved, for me, to:
    "@pulumi/aws@^5", "@pulumi/aws@^5.1.2":
      version "5.4.0"
    "@pulumi/awsx@^0.40":
      version "0.40.0"
    "@pulumi/eks@^0.40":
      version "0.40.0"
    "@pulumi/kubernetes@^3.0.0", "@pulumi/kubernetes@^3.1.2":
      version "3.19.0"
    "@pulumi/kubernetesx@^0.1.6":
      version "0.1.6"
    "@pulumi/pulumi@^3.0.0":
      version "3.32.1"
    So, pretty close to yours. 🤔 Maybe the old “blow away the node modules folder and re-run yarn” trick will fix it.
    l

    little-cartoon-10569

    4 months ago
    Oh yes, downloading the internet fixes everything... except DNS.
    p

    prehistoric-london-9917

    4 months ago
    lol
    otherwise I’m still stumped.. It’s just testing, so for now I got around it with
    cidrBlocks: [vpc.vpc.cidrBlock]
    - but obviously not ideal
    l

    little-cartoon-10569

    4 months ago
    Is your IDE (VSCode?) showing the error, or just Pulumi runtime? If you're seeing it in the IDE, then following the code into the libraries (ctrl-click, F12, whatever..) might take you into an unexpected version of the code, where transitive dependencies are your problem. There's no peerDependencies at play in Pulumi since it's all devDepenedencies, so different versions of the same code can happen, and cause this sort of problem...
    I know that the next version of awsx will break this code, so maybe you're depending on something that's sneakily depending on that next version?
    p

    prehistoric-london-9917

    4 months ago
    Is your IDE (VSCode?) showing the error,
    I’m seeing it in WebStorm &
    pulumi up
    fails with the same error. The output above was from
    pulumi up
    .
    There’s no peerDependencies at play in Pulumi since it’s all devDepenedencies
    Interesting - I didn’t install
    @pulumi/*
    as dev dependencies. Should I have?
    "dependencies": {
    "@pulumi/aws": "^5",
    "@pulumi/awsx": "^0.40",
    "@pulumi/eks": "^0.40",
    "@pulumi/kubernetes": "^3.1.2",
    "@pulumi/kubernetesx": "^0.1.6",
    "@pulumi/pulumi": "^3.0.0",
    "@pulumi/random": "^4.1.1",
    "ts-retry": "^2.3.3"
    l

    little-cartoon-10569

    4 months ago
    No, only devDependencies are needed, unless you have an automation-api app, but all dependencies are devDependencies too. You can though, and it will reduce the size of any packages you build (if any).
    Everything runs at "build" time, as far as node is concerned.
    For example, one of my clients' exposes all their stack references via interfaces defined in the project. Which means they have
    @pulumi/pulumi
    as in
    dependencies
    (for the StackReference stuff), but everything else is in
    devDependencies
    (since none of the "deployment" code is packaged and made available to other projects).
    p

    prehistoric-london-9917

    4 months ago
    Good to know- we’re starting to build automation API apps 😄
    This particular stack isn’t using that yet, though..
    l

    little-cartoon-10569

    4 months ago
    Then you can safely change it if you want to, but it's not necessary.
    p

    prehistoric-london-9917

    4 months ago
    Hi @little-cartoon-10569 - finally have time to circle back to this. I’m trying to figure out how you’re getting:
    Promise<pulumi.Output<string>[]>
    and I’m getting
    Promise<pulumi.Output<string | undefined>[]>
    vpc.privateSubnets
    ultimately boils down to a list of
    aws.ec2.Subnet
    types, and based on the definition, it seems
    cidrBlock
    might be undefined. So that kind of explains what I’m seeing - it’s an array of pulumi.Outputs that might be a string or undefined. Did you do anything to assert that
    cidrBlock
    would be defined?
    Also:
    I know that the next version of awsx will break this code, so maybe you’re depending on something that’s sneakily depending on that next version?
    Are you able to elaborate on that a little more? Is there something I could be doing here to prepare for this change?
    l

    little-cartoon-10569

    4 months ago
    No, I think it's just that awsx 1 is in the pipeline. I don't know what will change, maybe a look at the repo will help?
    My aws/ec2/subnet.d.ts has this:
    /**
         * The CIDR block for the subnet.
         */
        readonly cidrBlock: pulumi.Output<string>;
    Looks like 4.33.1 is the latest to have this shape code.
    I think that if you're requiring that all your subnets have IPv4 CIDR blocks, then you can just add an assert:
    const privateCidrBlocks = vpc.privateSubnets.then(subnets => subnets.map(subnet => subnet.subnet.cidrBlock!));
    p

    prehistoric-london-9917

    4 months ago
    I tried the assert, but my IDE still complained about that (didn’t actually try with a
    pulumi up
    , though). Went for maximum effort 😉
    function getCidrBlocks(): Promise<pulumi.Output<string>[]> {
      return vpc.privateSubnetIds.then(ids => {
        return ids.map(id => id.apply(i => pulumi.output(aws.ec2.getSubnet({id: i})).cidrBlock));
      });
    }
    
    const storageSG = new aws.ec2.SecurityGroup('storage', {
      description: 'Allow private subnet access to EFS',
      vpcId: vpc.id,
      ingress: [
        {
          cidrBlocks: getCidrBlocks(),
          fromPort: 2049,
          toPort: 2049,
          protocol: 'tcp'
        }
      ]
    });
    seems to be working. Would be nice if
    awsx.ec2.Vpc
    had a
    getCidrBlocks
    method for this. I reckon this will be a fairly common use case?
    I should make that generic and allow passing in a subnet type.
    In case this helps anyone else.