Hi all. I using Pulumi with the Go SDK and try to ...
# getting-started
b
Hi all. I using Pulumi with the Go SDK and try to understand how I can exactly use dependsOn. I am creating subnets in AWS and then want to use some of those to create a TGW attachment. For the latter, I need SubnetIds, which is an array of StringArrayInput. My problem is, the subnet resource only provides an ID of type pulumi.IDOutput. There's no straightforward way to convert this to a string right? What should I be using/doing instead here?
Ok, I figured it out myself. So,for anyone that might run in a similar problem: When creating a subnet, the resulting ID you get from subnet.ID() is a pulumi.IDOutput The SubnetIds necessary for the TGW attachment arguments are a pulumi.StringArrayInput I now found a helper function that does just this conversion:
Copy code
func IDOutputArrayToPulumiStringArrayOutput(IDoutputArray []pulumi.IDOutput) pulumi.StringArrayOutput {
	var outputs []interface{}
	for _, a := range IDoutputArray {
		outputs = append(outputs, a)
	}
	return pulumi.All(outputs...).ApplyT(func(vs []interface{}) []string {
		var results []string
		for _, v := range vs {
			results = append(results, string(v.(pulumi.ID)))
		}
		return results
	}).(pulumi.StringArrayOutput)
}
If theres a pulumi native way to handle these situations, that would be great to know
m
Unfortunately, type conversions in Go are tedious by nature. We have some helpers in the SDK, like
func ToStringArrayOutput(in []StringOutput)
but they don’t cover all cases. Here’s a deeper discussion if you’re interested.
s
I’m using this approach, which seems to work fine (
numOfAZs
is a count of how many AZs are in the specified region):
Copy code
// Create private subnets in the VPC
privSubnetIds := make([]pulumi.StringInput, numOfAZs)
for idx := 0; idx < numOfAZs; idx++ {
	subnetAddr := (idx * 32) + 16
	subnetCidrBlock := fmt.Sprintf("%s%d.0/22", netAddrMap[awsRegion], subnetAddr)
	subnet, err := ec2.NewSubnet(ctx, fmt.Sprintf("priv-subnet-%d", idx), &ec2.SubnetArgs{
		VpcId:               vpc.ID(),
		AvailabilityZone:    pulumi.String(azNames[idx]),
		CidrBlock:           pulumi.String(subnetCidrBlock),
		MapPublicIpOnLaunch: pulumi.Bool(false),
		Tags: pulumi.StringMap{
			"Name":    pulumi.Sprintf("%s-priv-%d", baseName, idx),
		},
	})
	if err != nil {
		log.Printf("error creating private subnet: %s", err.Error())
	}
	privSubnetIds[idx] = subnet.ID()
}
You can then use
privSubnetIds
where you need a list of subnet IDs, or you can specify a specific subnet using
privSubnetIds[i]
to pull out a specific subnet ID.
b
Thank you Scott, I will try and see if this works for me. Because your code also calculates the subnets, which our Terraform stack did with its own function before. Until now, I just resented to declaring the subnets explicitly in the config (which is fine), but creating them dynamically leads to less repetition
s
I’ve been looking for a better/smarter/more resilient way to handle the subnet calculations, but I haven’t gotten there yet. (BTW, I don’t use AWSX because I need a tad more flexibility than the high-level VPC component offers. However, it’s very useful for the vast majority of straightforward implementations.)
b
update on this: I spent the day and wrote my own Go implementation of the Terraform cidrsubnet function. Works just the same, takes a CIDR, number of additional bits and index of the subnet in the available range and returns it. Added unittests, so now I have a robust way of doing what I could before :)
s
Sweet! Have you published that code anywhere? 🙂
b
Since I worked on this during company hours and for my company, I am unsure if am allowed to share it (even if it's completely generic and has of course no reference to anything from my company). I will check that tomorrow and will get back to you! Would be happy to share if possible, to give something back to the community
s
Totally understand, no worries at all!