https://pulumi.com logo
#general
Title
# general
b

bored-table-20691

02/03/2022, 11:20 PM
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

02/03/2022, 11:26 PM
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

02/03/2022, 11:28 PM
This is my Go code to do the first part of the conversion:
Copy code
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

02/03/2022, 11:32 PM
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

02/03/2022, 11:37 PM
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

02/03/2022, 11:39 PM
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:
Copy code
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

02/03/2022, 11:42 PM
@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

02/03/2022, 11:45 PM
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

02/03/2022, 11:46 PM
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

02/03/2022, 11:48 PM
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

02/03/2022, 11:49 PM
huh, til what the ctx.Export is for
b

bored-table-20691

02/03/2022, 11:50 PM
@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.
16 Views