Thread
#general
    p

    polite-napkin-90098

    5 months ago
    I'm continually struggling with Outputs and Inputs, which I think may be somewhat to do with being new to Golang, and typed languages in general. I used to write in perl, which is polymorphic, and when I use the ApplyT functions I seem to end up with a lot of type errors and panics which I don't understand. I'm going to explain these, with code examples in a thread and hopefully someone can demystify this for me.
    I have some code, which apparently I wrote, or at least copy from somewhere which works quite happily and looks like so:
    // because the node sg is wrapped up in some weird output nonsense we need to free it
    nsg := cluster.NodeSecurityGroup.ApplyT(func(nodesg *ec2.SecurityGroup) pulumi.StringOutput {
    	return nodesg.ID().ToStringOutput()
    }).ApplyT(func(id interface{}) string {
    	return id.(string)
    }).(pulumi.StringOutput)
    cluster
    is an EKS cluster created using eks.NewCluster what I think this code does is create a function called nodesg which takes a *ec2.SecurityGroup object as input and returns a pulumi.StringOutput object. That function returns the output of the ID() function fed into the ToStringOutput() function both of which are provided in the nodesg *ec2.SecurityGroup object which we were taking as an input. But then that seems to be nested with a second ApplyT which declares a function called id which takes an interface{} and returns a string, which I guess is taking the output of the nodesg function (which I thought was a pulumi.StringOutput, but I guess it's also an interface{}) and converting it to a string, which is then converted back to a pulumi.StringOutput but the last .() Am I right? Am I close? I'd appreciate any insight into what this code does as I really don't think I understand it.
    I then tried to copy this in order to do much the same thing with the InstanceRole so I can add more permissions to it. The code:
    // extract the role from the cluster output
    iRole := cluster.Core.ApplyT(func(irole *eks.CoreData) pulumi.StringOutput {
        return irole.InstanceRoles[0].Name
    })
    I've tried this, I've tried adding a second .ApplyT with the func(foo interface{}) string {... and I've tried having .(pulumi.StringOuput) after the last )
    None have worked and most have given me the error:
    Diagnostics:
      pulumi:pulumi:Stack (EKS-EKS-test):
        panic: applier must have 1 input parameter assignable from eks.CoreData
        goroutine 1 [running]:
        <http://github.com/pulumi/pulumi/sdk/v3/go/pulumi.makeContextful({0x1110880|github.com/pulumi/pulumi/sdk/v3/go/pulumi.makeContextful({0x1110880>, 0x14d7718}, {0x164b750, 0x145f9e0})
            /home/ubuntu/go/pkg/mod/github.com/pulumi/pulumi/sdk/v3@v3.24.1/go/pulumi/types.go:340 +0x4a6
        <http://github.com/pulumi/pulumi/sdk/v3/go/pulumi.(*OutputState).ApplyT(0xc0000d7490|github.com/pulumi/pulumi/sdk/v3/go/pulumi.(*OutputState).ApplyT(0xc0000d7490>, {0x1110880, 0x14d7718})
            /home/ubuntu/go/pkg/mod/github.com/pulumi/pulumi/sdk/v3@v3.24.1/go/pulumi/types.go:419 +0x5d
        main.main.func1(0xc00037db80)
            /home/ubuntu/docker/EKS/pulumi/main.go:411 +0x32b3
        <http://github.com/pulumi/pulumi/sdk/v3/go/pulumi.RunWithContext|github.com/pulumi/pulumi/sdk/v3/go/pulumi.RunWithContext>(0xc00037db80, 0x14d7720)
            /home/ubuntu/go/pkg/mod/github.com/pulumi/pulumi/sdk/v3@v3.24.1/go/pulumi/run.go:103 +0x199
        <http://github.com/pulumi/pulumi/sdk/v3/go/pulumi.RunErr(0x43efc5|github.com/pulumi/pulumi/sdk/v3/go/pulumi.RunErr(0x43efc5>, {0x0, 0x0, 0xc0000001a0})
            /home/ubuntu/go/pkg/mod/github.com/pulumi/pulumi/sdk/v3@v3.24.1/go/pulumi/run.go:84 +0x310
        <http://github.com/pulumi/pulumi/sdk/v3/go/pulumi.Run(0x0|github.com/pulumi/pulumi/sdk/v3/go/pulumi.Run(0x0>, {0x0, 0x10d0680, 0xc0000001a0})
            /home/ubuntu/go/pkg/mod/github.com/pulumi/pulumi/sdk/v3@v3.24.1/go/pulumi/run.go:41 +0x25
        main.main()
            /home/ubuntu/docker/EKS/pulumi/main.go:18 +0x27
        exit status 2
     
        error: an unhandled error occurred: program exited with non-zero exit code: 1
    Which I must confess confuses me further, but maybe it wants me to have one of the Input parameters used in my function, which I'll try next.
    If anyone has any helpful words of advice/explanation they will be gratefully received.
    l

    limited-rainbow-51650

    5 months ago
    Hello @polite-napkin-90098, while not an expert in Go, I want to verify something on your approach of Pulumi code, based on this comment:
    // because the node sg is wrapped up in some weird output nonsense we need to free it
    Question: do you expect to get a (free)
    string
    after using
    ApplyT
    callback which you would be able to use further in your application? The reason I’m asking this is that I have been bitten by this myself when I started using Pulumi. In an oversimplified way, you have to think as the language host (the runtime you use to write your infra code in, in your case Go) running your infra code, which talks to the Pulumi engine to instruct which resources need to be set up. By the time your code has run, none of your resources have been set up yet. The Pulumi engine takes the instructions, calculates a directed acyclic graph (DAG) and knows in which order it can set up these resources based on outputs of one resource being used as input to others. Think of an output as a bucket which will have a value in the future.
    ApplyT
    will invoke your call-back function at the time the value becomes available, but the result you return in your callback function, will be put again in an Output which you can pass around as inputs further in your code.
    p

    polite-napkin-90098

    5 months ago
    Thanks @limited-rainbow-51650 I am aware of the runtime nature of the ApplyT function and that it is providing a promise of a future value, i.e. the id of the security group in the working example and the name of the Role in the second non-working value. That's what I was referring to as 'nonsense' which I guess is somewhat uncharitable of me, but I may have been somewhat frustrated when I wrote that comment.
    l

    limited-rainbow-51650

    5 months ago
    Q2 regarding the line below:
    nsg := cluster.NodeSecurityGroup.ApplyT(...
    Where do you get
    NodeSecurityGroup
    from? I can’t find this as an output in the API docs of Cluster: • aws-classic: https://www.pulumi.com/registry/packages/aws/api-docs/eks/cluster/#outputs • aws-native: https://www.pulumi.com/registry/packages/aws-native/api-docs/eks/cluster/#outputs
    b

    bored-oyster-3147

    5 months ago
    I also struggle with golang but maybe this is relevant, it looks like the SecurityGroup type inherits from
    pulumi.CustomResourceState
    while the CoreDataOutput type inherits from
    pulumi.OutputState
    . Maybe I'm misunderstanding but given that
    eks
    is one of the combined providers, is one of those properties actually a Resource being forwarded from the inner component while the other is an Output?
    It looks like your apply function parameter is trying to take in an element of type eks.CoreData when that property is actually eks.CoreDataOutput . Again, I may be misreading the code it being golang lol Disregard I think this comment is me misunderstanding the way generics currently look in golang
    p

    polite-napkin-90098

    5 months ago
    Maybe I should stop struggling with golang and switch to Typescript.
    b

    bored-oyster-3147

    5 months ago
    hahaha well hopefully we can figure this out without you having to do that. It's probably something silly
    Hmm how about the fact that your
    ApplyT
    delegate returns a
    stringOutput
    ? Shouldn't your delegate return a non-output type, since the
    ApplyT
    method signature is essentially
    Output<Y> Apply<T>(Func<T, Y> delegate);
    . I think your first working example has some excessive
    ApplyT
    calls
    p

    polite-napkin-90098

    5 months ago
    I'm currently trying to modify that function and get it to return something else, but
    irole.InstanceRoles[0].Name
    seems to be a pulumi.StringOutput, although I could always change that.
    b

    bored-oyster-3147

    5 months ago
    Yea it's weird to me that in your working example:1. Your first apply turns a
    string
    into a
    stringOutput
    2. Your second apply turns in back into a
    string
    3. You turn the result back into a
    stringOutput
    Kinda confused by that snippet
    l

    limited-rainbow-51650

    5 months ago
    Same here.
    b

    bored-oyster-3147

    5 months ago
    Checkout this example in the docs: the inner delegate returns a non output type, and the result is turned into an output type - essentially doing the same thing as your first working example with a single ApplyT call.
    p

    polite-napkin-90098

    5 months ago
    Yeah, I can't say it makes sense to me. I suppose I could try changing it, by way of further example this is how to get the kubeconfig, using a similar method:
    kubeconfig := cluster.Kubeconfig.ApplyT(func(kc interface{}) string {
    			str, err :=json.Marshal(kc)
    			if err != nil {
    				panic(err)
    			}
    			return string(str)
    		}).(pulumi.StringOutput)
    I guess that's more straight forward with the ApplyT taking the interface kc and returning a string made by marshalling the json
    b

    bored-oyster-3147

    5 months ago
    Yea that is what I would expect that to look like.
    p

    polite-napkin-90098

    5 months ago
    I have something in my memory about it being because of the ID() function. I'll have a go at removing the second ApplyT in the other example, but I still don't understand the
    panic: applier must have 1 input parameter assignable from eks.CoreData
    error
    l

    limited-rainbow-51650

    5 months ago
    nsg := cluster.NodeSecurityGroup.ApplyT(func(nodesg *ec2.SecurityGroup) pulumi.StringOutput {
    	return nodesg.ID()
    }).(pulumi.StringOutput)
    In my head, I would simplify the first example to this. Don’t know if this is valid Go+Pulumi code though.
    b

    bored-oyster-3147

    5 months ago
    The second example you are having trouble with a maybe a little trickier because it is an output object with a nested property that you want to access. Is this possible?
    // extract the role from the cluster output
    iRole := cluster.Core.InstanceRoles.ApplyT(func(irole *whateverthistypeis) string {
        return irole[0].Name
    }).(pulumi.StringOutput)
    Or do the typings not permit you to access
    InstanceRoles
    without the apply? Again this is me having trouble reading golang type definitions lol
    p

    polite-napkin-90098

    5 months ago
    yeah that's what I was about to try. I'll let you know if it doesn't work
    I tried that, it said that InstanceRoles has no function or property ApplyT
    b

    bored-oyster-3147

    5 months ago
    ah because it is not an output. But you are able to access it at all though? That seems odd. I would instead expect it to say that
    Core has no function or property InstanceRoles
    if
    Core
    was an output
    p

    polite-napkin-90098

    5 months ago
    Ok when trying to remove the second ApplyT in the first example I get the error:
    /main.go:350:16: cannot use sg.CustomResourceState.ID() (type pulumi.IDOutput) as type pulumi.StringOutput in return argument
    so I think the second ApplyT is turning the pulumi.IDOutput into a pulumi.StringOutput
    b

    bored-oyster-3147

    5 months ago
    share the snippet that gave you that error?
    l

    limited-rainbow-51650

    5 months ago
    I guess that was the snippet I posted as simplification a few minutes ago.
    p

    polite-napkin-90098

    5 months ago
    // because the cluster sg is wrapped up in some weird output nonsense we need to free it
    sgid := cluster.NodeSecurityGroup.ApplyT(func(sg *ec2.SecurityGroup) pulumi.StringOutput {
           return sg.ID()
    }).(pulumi.StringOutput)
    l

    limited-rainbow-51650

    5 months ago
    Is this better?
    nsg := cluster.NodeSecurityGroup.ID().ApplyT(func(id interface{}) string {
    	return id.(string)
    }).(pulumi.StringOutput)
    p

    polite-napkin-90098

    5 months ago
    With the commented code removed
    b

    bored-oyster-3147

    5 months ago
    Yea I'm still confused by that ^. Because your ApplyT delegate is still returning an output value. You shouldn't be needing to deal with outputs inside of your ApplyT delegate, that's the whole point of the delegate - you are accessing a future value when it is available
    p

    polite-napkin-90098

    5 months ago
    Diagnostics:
      pulumi:pulumi:Stack (EKS-EKS-test):
        # EKS
        ./main.go:239:35: cluster.NodeSecurityGroup.ID undefined (type ec2.SecurityGroupOutput has no field or method ID)
        ./main.go:353:16: cannot use sg.CustomResourceState.ID() (type pulumi.IDOutput) as type string in return argument
    I'll see if I can find the docs/article where I copied this code from, but I think it's only for ID() which is why it is strnage.
    https://github.com/pulumi/pulumi/issues/4080 < I think this is relevant i.e "We can add
    AnyOutput
    to
    StringOutput
    or
    IDOutput
    to this list I believe as there's no easy way without applying another
    applier func
    to it"
    https://githubhot.com/index.php/repo/pulumi/pulumi-eks/issues/644< here you can see my code offered as a solution to this problem
    but this is all a Red Herring on the current issue, as eks.CoreData isn't giving us an IDOutput
    b

    bored-oyster-3147

    5 months ago
    Did you see that that issue references another issue, that references a PR that resolved that by supposedly adding some functions to make that easier? https://github.com/pulumi/pulumi/pull/6337
    p

    polite-napkin-90098

    5 months ago
    Yes, I did notice that but I haven't tried those functions yet.
    I'll have a look at them now.
    b

    bored-oyster-3147

    5 months ago
    You're correct that the issue with the
    CoreData
    delegate is that it is an Output<CoreData> type that is then giving you an Output<string> inside the delegate so we need one the pulumi golang guys to go over how or what you're supposed to return from that delegate in order to unwrap the inner output
    p

    polite-napkin-90098

    5 months ago
    Yes, that sounds about right. I'll keep fiddling with it and see if I can find the right incantation in the meantime
    b

    bored-oyster-3147

    5 months ago
    Checkout this function: https://github.com/pulumi/pulumi-eks/blob/d599a1b1f3650dba4c3dc4f560080e95ce6fb5b1/sdk/go/eks/pulumiTypes.go#L946 Can you do:
    // extract the role from the cluster output
    iRole := cluster.Core.InstanceRoles().ApplyT(func(irole []*iam.Role) string {
        return irole[0].Name
    }).(pulumi.StringOutput)
    p

    polite-napkin-90098

    5 months ago
    Sorry, got distracted by boring things like meetings. I'll give that a whirl
    That changes the error, first it complained that irole[0].Name was a pulmi.StringOutput and not a string so fixing the typing to:
    iRole := cluster.Core.InstanceRoles().ApplyT(func(irole []*iam.Role) pulumi.StringOutput{
      return irole[0].Name
    })
    I now get
    panic: interface conversion: pulumi.Output is pulumi.AnyOutput, not iam.RoleArrayOutput
    but I was expecting it to complain that InstanceRoles didn't have .ApplyT so that's new, and potentially useful
    b

    bored-oyster-3147

    5 months ago
    Is the role something you are creating or are you allowing the cluster to create it?
    p

    polite-napkin-90098

    5 months ago
    It is the one created by the EKS package, or maybe by the AWS api.
    I did try creating a role and passing that to the eks.NewCluster, but I never seemed to get the right bundle of permissions and my nodes never managed to join the cluster.
    I found out why I though I would get an error like:
    cluster.Core.InstanceRoles.ApplyT undefined (type func() iam.RoleArrayOutput has no field or method ApplyT)
    as that is what happens when when you leave the brackets out of
    cluster.Core.InstanceRoles.ApplyT
    and not
    cluster.Core.InstanceRoles().ApplyT
    b

    bored-oyster-3147

    5 months ago
    yes,
    CoreDataOutput
    type has no properties. It has functions only, that are used to access the properties of
    CoreData
    .
    p

    polite-napkin-90098

    5 months ago
    that makes sense
    b

    bored-oyster-3147

    5 months ago
    After you call
    InstanceRoles()
    you just have a standard
    iam.RoleArrayOutput
    that you should be able to use normally as you would use it from the iam provider. For instance you could use this function to get a specific index of the array. So maybe
    cluster.core.InstanceRoles().Index(0).ApplyT(func(irole *iam.Role) string { return irole.Name });
    or something like that.
    p

    polite-napkin-90098

    5 months ago
    ah yes, I was looking for that Index(0) function, thanks!
    although I need to make the 0 a
    pulumi.IntInput
    b

    bored-oyster-3147

    5 months ago
    you should be able to cast a constant to an input if it isn't inferred automatically. Since input types are just designed to accept either runtime values or output values
    p

    polite-napkin-90098

    5 months ago
    I don't seem to be able to make that happen. I've tried:
    var index pulumi.IntInput = pulumi.IntInput(0)
    iRole := cluster.Core.InstanceRoles().Index(index).ApplyT(func(irole *iam.Role) pulumi.StringOutput{
          return irole.Name
    })
    and some variations but I mostly get errors like
    pulumi:pulumi:Stack (EKS-EKS-test):
        # EKS
        ./main.go:411:46: cannot convert 0 (type int) to type pulumi.IntInput:
            int does not implement pulumi.IntInput (missing ElementType method)
    Which is the kind of thing which makes me long for polymorphism
    iRole := cluster.Core.InstanceRoles().Index(pulumi.IntInput(0)).ApplyT(func(irole *iam.Role) pulumi.StringOutput{
       return irole.Name
    })
    is a simpler form, but it gives the same error.
    b

    bored-oyster-3147

    5 months ago
    you're trying to use a type as a function I think... based on your previous samples doesn't casting in go look like
    0.(pulumi.IntInput)
    sorry you were closer, pulumi docs look like it is actually
    <http://pulumi.Int|pulumi.Int>(0)
    that you want
    p

    polite-napkin-90098

    5 months ago
    yeah I tried that but it results in
    # EKS
        ./main.go:411:49: cannot call non-function 0 (type float64)
        ./main.go:411:50: type pulumi.IntInput is not an expression
    Yeah so I also tried that, maybe getting to the conclusion the same time as you but that results in
    b

    bored-oyster-3147

    5 months ago
    look here: https://www.pulumi.com/docs/intro/concepts/inputs-outputs/#lifting A little down the page there is:
    cert.DomainValidationOptions.Index(<http://pulumi.Int|pulumi.Int>(0)).ResourceRecordValue().Elem(),
    p

    polite-napkin-90098

    5 months ago
    Diagnostics:
      pulumi:pulumi:Stack (EKS-EKS-test):
        error: an unhandled error occurred: program exited with non-zero exit code: 1
    
        panic: interface conversion: pulumi.Output is pulumi.AnyOutput, not iam.RoleArrayOutput
        goroutine 1 [running]:
        <http://github.com/pulumi/pulumi-eks/sdk/go/eks.CoreDataOutput.InstanceRoles({0xc00024c1e0})|github.com/pulumi/pulumi-eks/sdk/go/eks.CoreDataOutput.InstanceRoles({0xc00024c1e0})>
            /home/ubuntu/go/pkg/mod/github.com/pulumi/pulumi-eks/sdk@v0.36.0/go/eks/pulumiTypes.go:947 +0x54
        main.main.func1(0xc0000fa140)
            /home/ubuntu/docker/EKS/pulumi/main.go:411 +0x3265
        <http://github.com/pulumi/pulumi/sdk/v3/go/pulumi.RunWithContext|github.com/pulumi/pulumi/sdk/v3/go/pulumi.RunWithContext>(0xc0000fa140, 0x14d6720)
            /home/ubuntu/go/pkg/mod/github.com/pulumi/pulumi/sdk/v3@v3.24.1/go/pulumi/run.go:103 +0x199
        <http://github.com/pulumi/pulumi/sdk/v3/go/pulumi.RunErr(0x43efc5|github.com/pulumi/pulumi/sdk/v3/go/pulumi.RunErr(0x43efc5>, {0x0, 0x0, 0xc0000001a0})
            /home/ubuntu/go/pkg/mod/github.com/pulumi/pulumi/sdk/v3@v3.24.1/go/pulumi/run.go:84 +0x310
        <http://github.com/pulumi/pulumi/sdk/v3/go/pulumi.Run(0x0|github.com/pulumi/pulumi/sdk/v3/go/pulumi.Run(0x0>, {0x0, 0x10cf680, 0xc0000001a0})
            /home/ubuntu/go/pkg/mod/github.com/pulumi/pulumi/sdk/v3@v3.24.1/go/pulumi/run.go:41 +0x25
        main.main()
            /home/ubuntu/docker/EKS/pulumi/main.go:18 +0x27
        exit status 2
    But somehow seems closer
    So maybe this?
    iRole := cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).Name();
    I'm seeing a lot of
    Property()
    for things I think are properties in the golang sdk lol
    p

    polite-napkin-90098

    5 months ago
    That gives:
    ./main.go:411:61: cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).Name undefined (type iam.RoleOutput has no field or method Name)
    I think we need the ApplyT in there too.
    b

    bored-oyster-3147

    5 months ago
    But the
    ApplyT
    doesn't change the fact that Name is a
    pulumi.StringOutput
    inside the delegate so that isn't what we want
    We shouldn't have outputs inside our apply delegate.
    What does calling
    .Elem()
    on the result of
    .Index(<http://pulumi.Int|pulumi.Int>(0))
    give you for a type?
    p

    polite-napkin-90098

    5 months ago
    I tried:
    iRole := cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).Elem().ApplyT(func(irole *iam.Role) pulumi.StringOutput{
        return irole.Name
    })
    but that gives:
    error: an unhandled error occurred: program exited with non-zero exit code: 2
    
        # EKS
        ./main.go:411:61: cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).Elem undefined (type iam.RoleOutput has no field or method Elem)
    b

    bored-oyster-3147

    5 months ago
    @lemon-agent-27707 we need some golang expertise. It's something silly I'm missing. We've got a type of
    eks.Cluster
    We're trying to get the first element of the instance roles array on the
    eks.Cluster
    . Using
    cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0))
    gets us the first element of the
    RoleArrayOutput
    returned by
    InstanceRoles()
    . That first element is of type
    RoleOutput
    . How do you get the
    .Name
    property off of this element?
    p

    polite-napkin-90098

    5 months ago
    Thanks very much for all the help so far @bored-oyster-3147. I'm about to head home for the evening but will pick this up tomorrow.
    b

    bored-oyster-3147

    5 months ago
    Good luck. Sorry I suck at golang! lol
    l

    lemon-agent-27707

    5 months ago
    Looks like ya'll have tried lots of things. What was the issue with doing something like:
    cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).ApplyT(...
    Shouldn't need the
    Elem
    I don't think
    b

    bored-oyster-3147

    5 months ago
    Yea I realized after that golang has PtrOutput types and that is what that is for. The issue with the apply was that the
    .Name
    property was still a
    pulumi.StringOutput
    inside the apply
    l

    lemon-agent-27707

    5 months ago
    It makes sense that it would be an output.
    Role
    is a resource.
    I don't have an example handy. I wonder if you could do one apply that returns the
    Name
    output, and then a second apply on that result to manipulate the underlying value.
    something like:
    name := cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).ApplyT(...
    
    nameResult := name.Apply(...
    b

    bored-oyster-3147

    5 months ago
    Does it make sense that it is an output? Usually the resource itself isn't also an output. I would expect that it be
    Resource.PropertyOutput
    so you could
    Role.Name.Apply(...)
    but in this case it is
    ResourceOutput
    so you have to
    Role.Apply(...)
    which is very weird when he just wants to get the name and pass it around, he doesn't even want to manipulate the name. If it was just a resource he could just
    var roleName = Role.Name;
    and he would be fine, no apply necessary. But since the role itself is an output, that isn't possible since
    .Name
    isn't accessible. @polite-napkin-90098 did you try doing:
    iRole := cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).ApplyT(func(irole *iam.Role) pulumi.StringOutput {
      return irole[0].Name
    });
    p

    polite-napkin-90098

    5 months ago
    I'll get some fresh tea and give it a go.
    So if I use it as you wrote it, I get an error about *iam.Role not being indexable, due to the [0] after irole. If I drop that I get the
    panic: interface conversion: pulumi.Output is pulumi.AnyOutput, not iam.RoleArrayOutput
    error.
    iRole := cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).ApplyT(func(irole *iam.Role) pulumi.StringOutput{
                            return irole.Name
    })
    I've tried a few more variations, all with similar results to the above. Unless anyone knows how to actually do this I think my best path is to either try again in a different language, or maybe drop pulumi for something else like Terraform
    b

    bored-oyster-3147

    5 months ago
    Ok the square brackets were a typo on my part with the given example. The error above hopefully Evan can weigh on because that is the real issue, given that the above is what he was thinking would work
    p

    polite-napkin-90098

    5 months ago
    So I installed the CoC plugin for vim and now have VSCode style completion in golang. This then led me to find that I can do this:
    iRole := cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).ApplyT(func(irole *iam.Role) pulumi.StringOutput{
              return irole.Name.ToStringOutput
    })
    Which gives the error:
    ./main.go:412:21: cannot use irole.Name.ToStringOutput (type func() pulumi.StringOutput) as type pulumi.StringOutput in return argument
    which seems to be progress
    Hmm so I tried:
    iRole := cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).ApplyT(func(irole *iam.Role) pulumi.StringOutput{
                            return irole.Name.ToStringOutput()
                    }).ApplyT(func(iro interface{}) string {
                            return iro.(string)
                    }).(pulumi.StringOutput)
    Which is similar to the Security Group example I posted a couple of days ago in this thread. Unfortunately that errors with:
    Diagnostics:
      pulumi:pulumi:Stack (EKS-EKS-test):
        panic: interface conversion: pulumi.Output is pulumi.AnyOutput, not iam.RoleArrayOutput
        goroutine 1 [running]:
        <http://github.com/pulumi/pulumi-eks/sdk/go/eks.CoreDataOutput.InstanceRoles({0xc0002121e0})|github.com/pulumi/pulumi-eks/sdk/go/eks.CoreDataOutput.InstanceRoles({0xc0002121e0})>
            /home/ubuntu/go/pkg/mod/github.com/pulumi/pulumi-eks/sdk@v0.36.0/go/eks/pulumiTypes.go:947 +0x54
        main.main.func1(0xc0004b6000)
            /home/ubuntu/docker/EKS/pulumi/main.go:411 +0x32a5
        <http://github.com/pulumi/pulumi/sdk/v3/go/pulumi.RunWithContext|github.com/pulumi/pulumi/sdk/v3/go/pulumi.RunWithContext>(0xc0004b6000, 0x14d6af0)
            /home/ubuntu/go/pkg/mod/github.com/pulumi/pulumi/sdk/v3@v3.24.1/go/pulumi/run.go:103 +0x199
        <http://github.com/pulumi/pulumi/sdk/v3/go/pulumi.RunErr(0x43efc5|github.com/pulumi/pulumi/sdk/v3/go/pulumi.RunErr(0x43efc5>, {0x0, 0x0, 0xc0000001a0})
            /home/ubuntu/go/pkg/mod/github.com/pulumi/pulumi/sdk/v3@v3.24.1/go/pulumi/run.go:84 +0x310
        <http://github.com/pulumi/pulumi/sdk/v3/go/pulumi.Run(0x0|github.com/pulumi/pulumi/sdk/v3/go/pulumi.Run(0x0>, {0x0, 0x10cf720, 0xc0000001a0})
            /home/ubuntu/go/pkg/mod/github.com/pulumi/pulumi/sdk/v3@v3.24.1/go/pulumi/run.go:41 +0x25
        main.main()
            /home/ubuntu/docker/EKS/pulumi/main.go:18 +0x27
        exit status 2
    So there's still some kind of type confusion going on 😬
    b

    bored-oyster-3147

    5 months ago
    Does just your first .ApplyT work? why do you need the second one. Presumably you already have a
    StringOutput
    that you can pass around after the first. I mean this:
    iRole := cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).ApplyT(func(irole *iam.Role) pulumi.StringOutput {
        return irole.Name.ToStringOutput()
    })
    the fact that you have to
    .ToStringOutput()
    it at all implies that it is not in fact a string output inside the apply function so why the heck doesn't this work:
    iRole := cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).ApplyT(func(irole *iam.Role) string {
        return irole.Name
    }).(pulumi.StringOutput)
    I'm honestly really confused about this
    p

    polite-napkin-90098

    5 months ago
    I thought I had tried your first example before I added in the second ApplyT, but maybe I missed the () from the ToStringOutput() and got some other error. I get the same error
    panic: interface conversion: pulumi.Output is pulumi.AnyOutput, not iam.RoleArrayOutput
    for your first code block.
    I think I've tried the other one too, gimme a sec...
    yeah both of those give the same panic error.
    func (o CoreDataOutput) InstanceRoles() iam.RoleArrayOutput {
            return o.ApplyT(func(v CoreData) []*iam.Role { return v.InstanceRoles }).(iam.RoleArrayOutput)
    }
    This is the function in
    go/eks/pulumiTypes.go:947
    which is barfing. I guess the Index() is after a pulumi.AnyOutput and not a iam.RoleArrayOutput
    yeah and using my funky new vim plugin IntancesRoles() doesn't want to complete with .Index()
    iRole := cluster.Core.InstanceRoles().ApplyT(func(irole []*iam.Role) pulumi.StringOutput{
                            return irole[0].Name
                    }).(pulumi.StringOutput)
    This also gives the:
    panic: interface conversion: pulumi.Output is pulumi.AnyOutput, not iam.RoleArrayOutput
    I'm off to drink beer and enjoy my weekend. I'll pick this up on Mon
    Well I've tried a few more convolutions of this this morning, but I still can't make it work. I'm going to try typescript instead.
    b

    bored-oyster-3147

    5 months ago
    I'm sorry I can't be of more help. I'm frustrated by proxy, to be honest lol. Certainly doesn’t improve my opinion of golang
    p

    polite-napkin-90098

    5 months ago
    No worries, thanks for all your help. I too am liking golang significantly less after this. We'll see if typescript is less mind bending.
    l

    lemon-agent-27707

    5 months ago
    @polite-napkin-90098 sorry you're running into so many issues here. It looks like the last few issues you ran into might be related to a known bug working with
    StringOutput
    There is a workaround here that you might be able to try: https://github.com/pulumi/pulumi/issues/6073#issuecomment-809669645
    p

    polite-napkin-90098

    5 months ago
    Thanks Evan I'll take a look at that. I've found I tend to be quite good at finding bugs in things, which is a curse and a blessing 😉
    I had tried something similar to this a few days agohttps://pulumi-community.slack.com/archives/C84L4E3N1/p1649445617086939?thread_ts=1649258358.357719&amp;cid=C84L4E3N1 and following the example Evan linked I've tried:
    // extract the role from the cluster output
                    iRol, err := cluster.Core.InstanceRoles().ApplyT(func(irole []*iam.Role) pulumi.StringOutput{
                            return irole[0].Name.ToStringOutput()
                    }).(pulumi.AnyOutput), nil
                    if err != nil {
                            return err
                    }
                    iRole, err := iRol.ApplyT(func(iro interface{}) string {
                            return iro.(string)
                    }).(pulumi.StringOutput), nil
                    if err != nil {
                            return err
                    }
    But both of them give the
    panic: interface conversion: pulumi.Output is pulumi.AnyOutput, not iam.RoleArrayOutput
    which happens in the cluster.Core.InstanceRoles().ApplyT line. Perhaps I need to use the
    Index(<http://pulumi.Int|pulumi.Int>(0))
    and only pass the first role (there is only one in my case) into the ApplyT and then extract the pulumi.String from the pulumi.AnyOutput
    iRol, err := cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).ApplyT(func(irole *iam.Role) pulumi.StringOutput{
                            return irole.Name.ToStringOutput()
                    }).(pulumi.AnyOutput), nil
                    if err != nil {
                            return err
                    }
                    iRole, err := iRol.ApplyT(func(iro interface{}) string {
                            return iro.(string)
                    }).(pulumi.StringOutput), nil
                    if err != nil {
                            return err
                    }
    This gives the same error
    iRol, err := cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).ApplyT(func(irole *iam.Role) pulumi.StringOutput{
                            return irole.Name
                    }).(pulumi.AnyOutput), nil
    Also gives the interface conversion panic, and
    iRol, err := cluster.Core.InstanceRoles().Index(<http://pulumi.Int|pulumi.Int>(0)).ApplyT(func(irole *iam.Role) pulumi.StringOutput{
                            return pulumi.String(irole.Name).ToStringOutput()
                    }).(pulumi.AnyOutput), nil
    gives
    ./main.go:412:24: cannot convert irole.Name (type pulumi.StringOutput) to type pulumi.String
    which I guess makes sense. and proves that irole.Name is a pulumi.StringOutput
    But this is all making me think that golang is the wrong language for pulumi
    I've tried some more fiddling moving the ApplyT to earlier so it returns the CoreData object from the cluster and then get the Role Array inside that, but
    iRol, err := cluster.Core.ApplyT(func(irole *eks.CoreData) pulumi.StringOutput{
                            return irole.InstanceRoles[0].Name
                    }), nil
    or similar functions which return the []*iam.Role or just the zeroth *iam.Role result in
    panic: applier must have 1 input parameter assignable from eks.CoreData
    which is another error I'm struggling to understand and google just leads me tohttps://github.com/pulumi/pulumi-azure/issues/530 which doesn't help me much.
    For the sake of closure. I have switched to using Typescript. I haven't quite got to the point where my cluster is working with PVC provisioned from EFS, but it is certainly much less fiddly to write.
    b

    bored-oyster-3147

    5 months ago
    I'm glad you found something that works for you. Shame it was such a pain! I'm sure you experience with the TS sdk will be smoother
    p

    polite-napkin-90098

    5 months ago
    Maybe I should have researched the languages available some more before jumping in. But, imho, the best way to learn and or decide if you like a language is to try using it for something real. As a perl/csh/bash programmer all that mucking about with types was far too mind-bending for me. 😉
    b

    bored-oyster-3147

    5 months ago
    Ha well even as a primarily dotnet programmer I still havent completely wrapped my head around go syntax and typing. The lack of true generic support means things get weird quick.