b

    bored-table-20691

    7 months ago
    Is there a way (especially in Go) to export an array of values (say array of strings) from one stack and import it into another without hating your decision? Both the casting to
    StringArrayOutput
    in and of itself is difficult, and working with
    StringArrayOutput
    in the code (e.g. if you want to iterate over it to create something for each element) is just very very painful.
    l

    little-cartoon-10569

    7 months ago
    Would it be easier to export it as a key-value map? I have no idea about the golang-related complexities. It's not hard either way in TS.
    b

    bored-table-20691

    7 months ago
    This is my Go code to do the first part of the conversion:
    func GetStringArrayOutput(ref *pulumi.StackReference, key string) pulumi.StringArrayOutput {
    	output := ref.GetOutput(pulumi.String(key))
    	return output.ApplyT(func(input interface{}) []string {
    		vals := make([]string, len(input.([]interface{})))
    		for idx, val := range input.([]interface{}) {
    			vals[idx] = val.(string)
    		}
    		return vals
    	}).(pulumi.StringArrayOutput)
    }
    I think a map would actually be even worse 🙂
    @little-cartoon-10569 how are you iterating over the output? Say I wanted to create a new resource per item in the output, what do you do? To actually iterate, you’d need to do an
    Apply
    , but then I try and avoid creating resources in
    Apply
    . The other option is to call the
    Index(i)
    method, but there’s no way to know the length (unless you also export that). This is the kind of stuff I mean
    l

    little-cartoon-10569

    7 months ago
    Creating resources based on results of Outputs is something I always avoid. And unfortunately, exporting the length doesn't help the issue, since the exported value is also in an Output.
    You can either move the values from stack references to config (ick), or redesign something. It's (almost?) always possible. You really, really want to avoid mistakes like awsx.ec2's VPC subnets issue. It's awful.
    But it is an example of the problem you're talking about. You configure the number of subnets as a parameter, it creates a variable number of subnets, and as a result, you can only access your subnets inside an Output. It's a really good reason to not use awsx.
    b

    bored-table-20691

    7 months ago
    Ah yes, you’re right on the length in - I tried to do exactly that, ran into that issue, and gave up 😄
    Yeah, we don’t use
    awsx
    (because it’s not available for Go as the main reason 🙂 ), but what you said is exactly the type of thing I am thinking about. An example is I want to create some R53 records in my infrastructure stack, and then I want some downstream stack to be able to leverage those and create something based on them (e.g. a cert or something). It’s hard because of these types of issues, and usually requires a lot of gymnastics in order to avoid.
    p

    proud-angle-89904

    7 months ago
    can you not simply work with an array of elements? I’m a total newbie, so i’m probably misunderstanding your question, but this is how i’m making a firewall per linode node:
    func Firewall(ctx *pulumi.Context, instances []*linode.Instance, region string) (*linode.Firewall, error) {
    	var linodes pulumi.IntArray
    	for _, instance := range instances {
    		instanceId := instance.ID().ToStringOutput().ApplyT(parseString()).(pulumi.IntInput)
    		linodes = append(linodes, instanceId)
    	}
    	var wall, err = linode.NewFirewall(ctx, "Firewall", &linode.FirewallArgs{
    		Label: pulumi.String("Firewall"),
    		Tags: pulumi.StringArray{
    			pulumi.String("test"),
    		},
    		InboundPolicy:  pulumi.String("DROP"),
    		OutboundPolicy: pulumi.String("DROP"),
    		Linodes: linodes,
    	})
    ...
    b

    bored-table-20691

    7 months ago
    @proud-angle-89904 it’s a good question. The issue is that it’s exported from one stack (i.e.
    ctx.Export("my-key", someStringArrayOutput)
    And when you import it on the other side, it’ll be a
    pulumi.AnyOutput
    and you have to do some casting magic to get it to be
    pulumi.StringArrayOutput
    In your example, your
    instances
    array is actually a real array/slice, so you can iterate over it. And even your
    linodes
    is a
    []<http://pulumi.Int|pulumi.Int>
    (just typedef’ed to
    IntArray
    ).
    l

    little-cartoon-10569

    7 months ago
    If feasible, put the R53 and dependent resources in the same project. Maybe even in the same ComponentResource?
    Sidestep the issue.
    A new CertifiedARecord component resource sounds perfect 🙂
    Then you'll need a CertifiedCNameRecord... 🙂
    b

    bored-table-20691

    7 months ago
    Right, but that only really works if it’s in the same project (i.e. in the same stack), no? In this case, that’s not really feasible - I need to create something once and reference many times.
    l

    little-cartoon-10569

    7 months ago
    Not necessarily. You can export your ReallyImportantRecordId (not an array: they're important, so you must know all them in advance, so you can export them all individually), then in the other project, you can use
    Record.get()
    inside your component resource's constructor. Then you'll have a real (but read-only) instance of the Record.
    p

    proud-angle-89904

    7 months ago
    huh, til what the ctx.Export is for
    b

    bored-table-20691

    7 months ago
    @little-cartoon-10569 that’s fair, if you know them all in advance 🙂 In my case, I don’t, they come from the config. Anyway, I do get what you’re saying, which boils down to “this is going to be painful unless you avoid this problem altogether”, which is very fair.