pulumi / pulumi-google-native

Apache License 2.0
71 stars 18 forks source link

Adding ephemeral IP results in: "Error 400: Updating 'networkInterface' is not supported" #680

Open aschleck opened 2 years ago

aschleck commented 2 years ago

What happened?

I created an instance without a public IP, and later tried to give it an ephemeral public IP. The update failed to apply.

Steps to reproduce

Start with

from pulumi_google_native.compute import v1 as compute

compute.Instance(
    name,
    hostname="purple",
    disks=[
        compute.AttachedDiskArgs(
            auto_delete=True,
            boot=True,
            initialize_params=compute.AttachedDiskInitializeParamsArgs(
                source_image="projects/ubuntu-os-cloud/global/images/ubuntu-2204-jammy-v20220810",
            ),
        )
    ],
    machine_type="e2-micro",
    zone=location,
    network_interfaces=[
        compute.NetworkInterfaceArgs(
            subnetwork=subnet.id,
        ),
    ],
)

then change network_interfaces to:

      network_interfaces=[
          compute.NetworkInterfaceArgs(
              access_configs=[compute.AccessConfigArgs()],
              subnetwork=subnet.id,
          ),
      ],

Expected Behavior

In the web UI I can add and remove ephemeral IPs from an instance, so I think this is supposed to work. From snooping the GQL request in the network tab it looks like the UpdateInstance API call might have some special variables but I am not sure if that's actually making the difference.

{
  "operationName": "UpdateInstance",
  "variables": {
    "instance": {
        ...
    },
    ...
    "networkInterfaceModels": [
      {
        "ephemeralIp": true,
        "ephemeralOldIp": false
      }
    ],
    ...
}

Actual Behavior

Do you want to perform this update? details
  pulumi:pulumi:Stack: (same)
    [urn=urn:pulumi:prod::machines::pulumi:pulumi:Stack::machines-prod]
    ~ google-native:compute/v1:Instance: (update)
        [id=https://www.googleapis.com/compute/v1/projects/thing/zones/us-west1-a/instances/purple-debede7]
        [urn=urn:pulumi:prod::machines::google-native:compute/v1:Instance::purple]
        [provider=urn:pulumi:prod::machines::pulumi:providers:google-native::default_0_25_0::8447cba3-acd2-46ff-8cd2-dc5f3c9ba986]
      ~ networkInterfaces: [
          ~ [0]: {
                  + accessConfigs: [
                  +     [0]: {}
                    ]
                }
        ]

...

Do you want to perform this update? yes
Updating (prod):
     Type                                  Name               Status                  Info
     pulumi:pulumi:Stack                   machines-prod      **failed**              1 error; 4 warnings
 ~   ├─ google-native:compute/v1:Instance  purple             **updating failed**     [diff: ~networkInterfaces]; 1 error

...

error: error sending request: googleapi: Error 400: Invalid value for field 'resource.networkInterfaces': ''. Updating 'networkInterface' is not supported., invalid: "https://www.googleapis.com/compute/v1/projects/thing/zones/us-west1-a/instances/purple-debede7" map[disks:[map[autoDelete:true boot:true initializeParams:map[sourceImage:projects/ubuntu-os-cloud/global/images/ubuntu-2204-jammy-v20220810]]] fingerprint:4dutfEnE1zI= hostname:purple labelFingerprint:42WmSpB8rSM=machineType:zones/us-west1-a/machineTypes/e2-micro

Output of pulumi about

CLI
Version      3.39.1
Go Version   go1.19
Go Compiler  gc

Plugins
NAME           VERSION
aws-native     0.24.0
google-native  0.25.0
python         unknown

Host
OS       ubuntu
Version  22.04
Arch     x86_64

This project is written in python: executable='<snip>' version='3.10.2
'

Current Stack: prod

TYPE                                        URN
pulumi:pulumi:Stack                         urn:pulumi:prod::machines::pulumi:pulumi:Stack::machines-prod
<snip>

Found no pending operations associated with prod

Backend
Name           bark
URL            <snip>
User           april
Organizations

Dependencies:
NAME                  VERSION
Mako                  1.2.1
pip                   22.0.3
pulumi-aws-native     0.24.0
pulumi-google-native  0.25.0
setuptools            60.9.3

Pulumi locates its logs in /tmp by default
warning: A new version of Pulumi is available. To upgrade from version '3.39.1' to '3.39.3', visit https://pulumi.com/docs/reference/install/ for manual instructions and release notes.

Additional context

Thank you for working on this project!

Contributing

Vote on this issue by adding a 👍 reaction. To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).

viveklak commented 2 years ago

Thanks for reporting the issue @aschleck. The compute API has a bunch of imperative operations defined for updates. In addition, it does have an update API which allows mutation of a small subset of resources. The heuristic used to generate this provider doesn't work well for resources with discrete imperative mutation APIs.

We have a couple of options here:

  1. Model all the imperative operations as we did in https://github.com/pulumi/pulumi-google-native/issues/124 for container resources. The pulumi-gcp provider supports this approach.
  2. Mark all properties not supported by the partial update API to trigger replacement. This is the model supported by config connector etc. using the DCL.
aschleck commented 2 years ago

Thank you for taking a look at this so quickly!

I am not sure if you're interested in my opinion, you of course have a lot more knowledge about the right thing to do here for your project than I have, but maybe I can say: we're looking to use pulumi-google-native/pulumi-gcp to provision both dedicated developer machines as well as shared cluster resources. In the particular case of this knob I was trying to attach a public IP to an instance that's more like a developer machine, so I am very wary of having to replace it outright (pets, as opposed to cattle.) From this perspective, if this project choose to not implement custom mutation support that other projects do support I will probably give up on this project. It's just too risky that we'll do something that triggers a painful replacement/reinstall/re-setup for someone that could otherwise be avoided.

I totally respect whatever choice you make but I hope my additional context makes sense.