Hi everyone, I'm investigating whether pulumi is s...
# getting-started
t
Hi everyone, I'm investigating whether pulumi is suitable for us. I'm starting simple: create a number of nodes on Linode, and then add them to a firewall. I'm creating the nodes like this:
Copy code
let instances = []
const numNodes = 2

for (let n = 0; n < numNodes; n++) {
    // Create a Linode resource (Linode Instance)
    const instance = new linode.Instance(`foo-${n}`, {
        type: "g6-nanode-1",
        region: "eu-central",
        image: 'linode/ubuntu22.04',
        label: `foo-${n}`,
        group: 'foo',
        tags: ["test"],
        privateIp: true,
        interfaces: [{purpose: 'public'}, {purpose: 'vlan', label: 'acc-swarm', ipamAddress: '192.0.2.0/24'}],
    });

    instances.push(instance)
}
Then I create a firewall instance:
Copy code
const accSwarmFirewall = new linode.Firewall("acc-swarm", {
    label: 'acc_swarm',
    inbounds: [ ... ],
    inboundPolicy: 'DROP',
    outbounds: [ ... ],
    outboundPolicy: "ACCEPT",
    linodes: [instances[0].id, instances[1].id]
})
This does what you'd expect: the firewall is assigned to both instances. But of course I don't want to hard-code the number of instances again in that firewall declaration. I've tried many things, for example:
pulumi.all(instances).apply(i=>i.id)
. This way when I change
numNodes
to 3, I don't get any errors, but the new node is not added to the firewall. Or this:
pulumi.all(instances.map(i => i.id.apply(id=>parseInt(id))))
, guided by TypeScript type information (apparently
instance.id
is a
string
, but the firewall expects a list of numbers), but then I get errors like this:
Copy code
pulumi:pulumi:Stack (foo-dev):
    panic: interface conversion: interface {} is string, not int
    goroutine 105 [running]:
    <http://github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.HashInt({0x291b0a0|github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.HashInt({0x291b0a0>?, 0x31acd50?})
        /home/runner/go/pkg/mod/github.com/pulumi/terraform-plugin-sdk/v2@v2.0.0-20220824175045-450992f2f5b9/helper/schema/set.go:24 +0x55
    <http://github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/sdk-v2.v2Schema.SetHash({0x0?}|github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/sdk-v2.v2Schema.SetHash({0x0?}>, {0x291b0a0, 0x31acd50})
        /home/runner/go/pkg/mod/github.com/pulumi/pulumi-terraform-bridge/v3@v3.28.1/pkg/tfshim/sdk-v2/schema.go:176 +0x43
    <http://github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge.visitPropertyValue({0xc003be0b20|github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge.visitPropertyValue({0xc003be0b20>, 0x7}, {0xc003b019d0, 0x7}, {{0x28c7ba0?, 0xc003b2ac18?}}, {0x31dd8b8?, 0xc0000b72c0}, 0x0, 0x0, ...)
        /home/runner/go/pkg/mod/github.com/pulumi/pulumi-terraform-bridge/v3@v3.28.1/pkg/tfbridge/diff.go:114 +0x812
    <http://github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge.doIgnoreChanges({0x31d1070|github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge.doIgnoreChanges({0x31d1070>, 0xc00048d080}, 0xc003b45f10?, 0x31b5c00?, 0xc003b35d40?, {0x0, 0x0, 0xc000682820?}, {0x31d3b78, 0xc000634a00})
        /home/runner/go/pkg/mod/github.com/pulumi/pulumi-terraform-bridge/v3@v3.28.1/pkg/tfbridge/diff.go:260 +0x3ce
    <http://github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge.(*Provider).Diff(0xc000386fc0|github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge.(*Provider).Diff(0xc000386fc0>, {0x31cbc88?, 0xc003b346c0?}, 0xc000ba09a0)
        /home/runner/go/pkg/mod/github.com/pulumi/pulumi-terraform-bridge/v3@v3.28.1/pkg/tfbridge/provider.go:762 +0x608
    <http://github.com/pulumi/pulumi/sdk/v3/proto/go._ResourceProvider_Diff_Handler.func1({0x31cbc88|github.com/pulumi/pulumi/sdk/v3/proto/go._ResourceProvider_Diff_Handler.func1({0x31cbc88>, 0xc003b346c0}, {0x2bb6760?, 0xc000ba09a0})
        /home/runner/go/pkg/mod/github.com/pulumi/pulumi/sdk/v3@v3.38.0/proto/go/provider.pb.go:3707 +0x78
    <http://github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc.OpenTracingServerInterceptor.func1({0x31cbc88|github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc.OpenTracingServerInterceptor.func1({0x31cbc88>, 0xc003b342a0}, {0x2bb6760, 0xc000ba09a0}, 0xc003b28880, 0xc003b2a300)
        /home/runner/go/pkg/mod/github.com/grpc-ecosystem/grpc-opentracing@v0.0.0-20180507213350-8e809c8a8645/go/otgrpc/server.go:57 +0x3f9
    <http://github.com/pulumi/pulumi/sdk/v3/proto/go._ResourceProvider_Diff_Handler({0x2c7fb80|github.com/pulumi/pulumi/sdk/v3/proto/go._ResourceProvider_Diff_Handler({0x2c7fb80>?, 0xc000386fc0}, {0x31cbc88, 0xc003b342a0}, 0xc000ba0930, 0xc000a641e0)
        /home/runner/go/pkg/mod/github.com/pulumi/pulumi/sdk/v3@v3.38.0/proto/go/provider.pb.go:3709 +0x138
    <http://google.golang.org/grpc.(*Server).processUnaryRPC(0xc000a6a000|google.golang.org/grpc.(*Server).processUnaryRPC(0xc000a6a000>, {0x31d4240, 0xc000102b60}, 0xc003b079e0, 0xc000a58ab0, 0x4233608, 0x0)
        /home/runner/go/pkg/mod/google.golang.org/grpc@v1.48.0/server.go:1295 +0xb2b
    <http://google.golang.org/grpc.(*Server).handleStream(0xc000a6a000|google.golang.org/grpc.(*Server).handleStream(0xc000a6a000>, {0x31d4240, 0xc000102b60}, 0xc003b079e0, 0x0)
        /home/runner/go/pkg/mod/google.golang.org/grpc@v1.48.0/server.go:1636 +0xa2f
    <http://google.golang.org/grpc.(*Server).serveStreams.func1.2()|google.golang.org/grpc.(*Server).serveStreams.func1.2()>
        /home/runner/go/pkg/mod/google.golang.org/grpc@v1.48.0/server.go:932 +0x98
    created by <http://google.golang.org/grpc.(*Server).serveStreams.func1|google.golang.org/grpc.(*Server).serveStreams.func1>
        /home/runner/go/pkg/mod/google.golang.org/grpc@v1.48.0/server.go:930 +0x28a
I'm not sure what I'm missing here. Is there anyone who can shed some light on this? Thanks a lot!!
e
I don't think you need pulumi.all for the instances array, it's just a plain array. So probably something like:
instances.map(i => i.id.apply(id=>parseInt(id)))
t
Thanks Fraser, but unfortunately that gives the same error about
interface {} is string, not int
...
e
linodes:  [instances[0].id, instances[1].id]
works? The equivilant map for that is just:
linodes: instances.map(i => i.id)
t
Yes, that's what I thought as well, but same error :(
e
that's very strange 😐 I'd raise an issue at https://github.com/pulumi/pulumi-linode about this, especially given that's a panic in the provider itself.
t
Ok Fraser, I'll do that, thanks for looking into this with me!
e
No worries, sorry the obvious thing didn't just work.
t
Hmm just now I noticed that the
map
method does work when initially creating the resources from scratch, but not when updating it after increasing the number of nodes. Is that maybe a clue?
e
probably, suggests that the typescript code is correct and it really is a provider bug in the Update method.
Is it crashing at preview or update time?
t
preview
e
Maybe a bit risky but could you run an update with
--skip-preview
and see if that works?
t
Nice, that works indeed 🙂
e
Ha, then yes definitely a provider bug. It's not handling unknown values at preview time correctly.
t
Indeed! Thanks for narrowing it down, that should make the issue easier to solve!