pulumi / pulumi-gcp

A Google Cloud Platform (GCP) Pulumi resource package, providing multi-language access to GCP
Apache License 2.0
178 stars 51 forks source link

GCE Instance import issues with attachedDisk #2096

Closed Josh-Ramirez closed 4 weeks ago

Josh-Ramirez commented 2 months ago

Describe what happened

Preview/up commands fail on imported GCE instances with attached disks specified using gcp.compute.AttachedDisk resource. The value of attachedDisks has been added to ignoreChanges and the value of gcp.compute.Instance.attachedDisks is an empty array ([]).

Value for unconfigurable attribute. Can't configure a value for "attached_disk.0.disk_encryption_key_sha256": its value will be decided automatically based on the result of applying this configuration.

Sample program

Import a VM that has attached disks:

pulumi import gcp:compute/instance:Instance default {{ project }}/{{ zone }}/{{ instance-name}}

Example Program:

  const definition = {
    project: "project-name",
    name: "instance-name",
    zone: "zone",
    attachedDisks: [],
    ....
    ....
  };

  const computeInstance = new gcp.compute.Instance(resourceName, definition, {
    ignoreChanges: ['bootDisk','attachedDisks'],
  });

Log output

Import Diagnostics:

Diagnostics:
  gcp:compute:Instance (<instance-name>):
    warning: Type checking failed: 
    warning: Unexpected type at field "metadata.__defaults":
               expected string type, got [] type
    warning: Type checking is still experimental. If you believe that a warning is incorrect,
    please let us know by creating an issue at https://github.com/pulumi/pulumi-terraform-bridge/issues.
    This will become a hard error in the future.
    warning: One or more imported inputs failed to validate. This is almost certainly a bug in the `gcp` provider. The import will still proceed, but you will need to edit the generated code after copying it into your program.
    warning: gcp:compute/instance:Instance resource '<instance-name>' has a problem: Value for unconfigurable attribute. Can't configure a value for "attached_disk.0.disk_encryption_key_sha256": its value will be decided automatically based on the result of applying this configuration.. Examine values at '<instance-name>.attachedDisks[0].diskEncryptionKeySha256'.
    warning: gcp:compute/instance:Instance resource '<instance-name>' has a problem: Value for unconfigurable attribute. Can't configure a value for "network_interface.0.ipv6_access_type": its value will be decided automatically based on the result of applying this configuration.. Examine values at '<instance-name>.networkInterfaces[0].ipv6AccessType'.
    warning: gcp:compute/instance:Instance resource '<instance-name>' has a problem: Value for unconfigurable attribute. Can't configure a value for "network_interface.0.name": its value will be decided automatically based on the result of applying this configuration.. Examine values at '<instance-name>.networkInterfaces[0].name'.
    warning: gcp:compute/instance:Instance resource '<instance-name>' has a problem: expected network_interface.0.nic_type to be one of ["GVNIC" "VIRTIO_NET"], got . Examine values at '<instance-name>.networkInterfaces[0].nicType'.

Preview Errors:

pulumi preview --stack <stack-name --diff
  pulumi:pulumi:Stack: (same)
    [urn=<urn>]
error: gcp:compute/instance:Instance resource '<instance-name>' has a problem: Value for unconfigurable attribute. Can't configure a value for "attached_disk.0.disk_encryption_key_sha256": its value will be decided automatically based on the result of applying this configuration.. Examine values at '<instance-name>.attachedDisks[0].diskEncryptionKeySha256'.
Resources:
    1 unchanged

Affected Resource(s)

gcp.compute.Instance
gcp.compute.AttachedDisk

Output of pulumi about

CLI          
Version      3.115.2
Go Version   go1.22.2
Go Compiler  gc

Plugins
KIND      NAME    VERSION
language  nodejs  unknown

Host     
OS       darwin
Version  14.5
Arch     arm64

This project is written in nodejs: executable='/opt/homebrew/opt/node@20/bin/node' version='v20.13.1'

Additional context

The documentation around gcp.compute.AttachDiskmakes mention to add attached_disk to ignoreChanges on the gcp.compute.Instance. After some trial and error, it appears it needs to be made on attachedDisks.

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).

guineveresaenger commented 2 months ago

Hi @Josh-Ramirez, thank you for filing this issue. Could you clarify a few things for us?

  1. When you import the gcp.compute.Instance, what is the code that gets generated?
  2. Specifically - does the code generate the attachedDisks: [] line, or are you adding that? What happens on preview if that line is missing?
  3. Can you let us know which version of the GCP provider you're using?

Thank you so much! This sounds like a potential import bug, and we'll take a look as soon as we can.

Josh-Ramirez commented 1 month ago

Hi @guineveresaenger, sorry for the delayed feedback.

The generated code looks something like what's below. However I am defining my resource like the first example because I would like to use gcp.compute.AttachedDisk to attach disks.

const <INSTANCE_NAME> = new gcp.compute.Instance("<INSTANCE_NAME>", {
    attachedDisks: [
        {
            deviceName: "persistent-disk-1",
            diskEncryptionKeyRaw: pulumi.secret(""),
            diskEncryptionKeySha256: "",
            kmsKeySelfLink: "",
            mode: "READ_WRITE",
            source: "https://www.googleapis.com/compute/v1/projects/<PROJECT_NAME>/zones/us-central1-a/disks/<INSTANCE_NAME>-1",
        },
        {
            deviceName: "persistent-disk-2",
            diskEncryptionKeyRaw: pulumi.secret(""),
            diskEncryptionKeySha256: "",
            kmsKeySelfLink: "",
            mode: "READ_WRITE",
            source: "https://www.googleapis.com/compute/v1/projects/<PROJECT_NAME>/zones/us-central1-a/disks/<INSTANCE_NAME>-3",
        },
        {
            deviceName: "persistent-disk-3",
            diskEncryptionKeyRaw: pulumi.secret(""),
            diskEncryptionKeySha256: "",
            kmsKeySelfLink: "",
            mode: "READ_WRITE",
            source: "https://www.googleapis.com/compute/v1/projects/<PROJECT_NAME>/zones/us-central1-a/disks/<INSTANCE_NAME>-2",
        },
    ],
    bootDisk: {
        deviceName: "persistent-disk-0",
        initializeParams: {
            image: "https://www.googleapis.com/compute/beta/projects/<IMAGE_PROJECT>/global/images/<IMAGE_NAME>",
            size: 100,
            type: "pd-standard",
        },
        source: "https://www.googleapis.com/compute/v1/projects/<PROJECT_NAME>/zones/us-central1-a/disks/<INSTANCE_NAME>",
    },
    hostname: "<INSTANCE_DNS_NAME>",
    machineType: "n2-standard-2",
    metadata: {
        "block-project-ssh-keys": "true",
        "startup-script": "",
    },
    name: "<INSTANCE_NAME>",
    networkInterfaces: [{
        accessConfigs: [],
        aliasIpRanges: [],
        internalIpv6PrefixLength: 0,
        ipv6AccessConfigs: [],
        ipv6AccessType: "",
        ipv6Address: "",
        name: "nic0",
        network: "https://www.googleapis.com/compute/v1/projects/<NETWORK_PROJECT_NAME>/global/networks/<SUBNETWORK_NAME>",
        networkAttachment: "",
        networkIp: "10.176.72.116",
        nicType: "",
        queueCount: 0,
        securityPolicy: "",
        stackType: "IPV4_ONLY",
        subnetwork: "https://www.googleapis.com/compute/v1/projects/<NETWORK_PROJECT_NAME>/regions/us-central1/subnetworks/<SUBNETWORK_NAME>",
        subnetworkProject: "<NETWORK_PROJECT_NAME>",
    }],
    project: "<PROJECT_NAME>",
    scheduling: {
        onHostMaintenance: "MIGRATE",
        provisioningModel: "STANDARD",
    },
    serviceAccount: {
        email: "project-service-account@<PROJECT_NAME>.iam.gserviceaccount.com",
        scopes: ["https://www.googleapis.com/auth/cloud-platform"],
    },
    tags: [
        "<PROJECT_NAME>-default-intra-allow",
        "route-usc1",
    ],
    zone: "us-central1-a",
}, {
    protect: true,
});

GCP Provider: 7.30.1

Additional Context: I prefer not to use gcp.compute.Instance.attachedDisk because index position matters towards management of the resource. We have use-cases where we may need to remove a disk in the middle of the array, which would detach and reattach all of the disks after the removed disk. Using gcp.compute.AttachedDisk provides more flexibility.

Thanks for taking a look!

VenelinMartinov commented 1 month ago

Thanks for engaging here @Josh-Ramirez, I have reproduced the problem locally and I see the issue.

The Value for unconfigurable attribute. error looks pretty bad as it prevents a user from importing the resource without manual state interventions. I am looking into why that is happening.


Some notes from my investigation so far:

The disk_encryption_key_sha256 property is a fully computed property upstream - the value should not be settable in a program.

The problem is that we don't respect that and generate the wrong schema for the property:

  "gcp:compute/InstanceAttachedDisk:InstanceAttachedDisk": {
      "properties": {
          "deviceName": {
              "type": "string",
              "description": "Name with which the attached disk will be accessible\nunder `/dev/disk/by-id/google-*`\n"
          },
          "diskEncryptionKeyRaw": {
              "type": "string",
              "description": "A 256-bit [customer-supplied encryption key]\n(https://cloud.google.com/compute/docs/disks/customer-supplied-encryption),\nencoded in [RFC 4648 base64](https://tools.ietf.org/html/rfc4648#section-4)\nto encrypt this disk. Only one of `kms_key_self_link` and `disk_encryption_key_raw` may be set.\n",
              "secret": true
          },
          "diskEncryptionKeySha256": {
              "type": "string",
              "description": "The [RFC 4648 base64](https://tools.ietf.org/html/rfc4648#section-4)\nencoded SHA-256 hash of the [customer-supplied encryption key]\n(https://cloud.google.com/compute/docs/disks/customer-supplied-encryption) that protects this resource.\n"
          },
          "kmsKeySelfLink": {
              "type": "string",
              "description": "The self_link of the encryption key that is\nstored in Google Cloud KMS to encrypt this disk. Only one of `kms_key_self_link`\nand `disk_encryption_key_raw` may be set.\n"
          },
          "mode": {
              "type": "string",
              "description": "Either \"READ_ONLY\" or \"READ_WRITE\", defaults to \"READ_WRITE\"\nIf you have a persistent disk with data that you want to share\nbetween multiple instances, detach it from any read-write instances and\nattach it to one or more instances in read-only mode.\n"
          },
          "source": {
              "type": "string",
              "description": "The name or self_link of the disk to attach to this instance.\n"
          }
      },
      "type": "object",
      "required": [
          "source"
      ],
      "language": {
          "nodejs": {
              "requiredOutputs": [
                  "deviceName",
                  "diskEncryptionKeySha256",
                  "kmsKeySelfLink",
                  "source"
              ]
          }
      }
  },

The type should have an inputProperties specified which should not have diskEncryptionKeySha256 in it to make it fully computed in the SDK.

VenelinMartinov commented 1 month ago

Opened https://github.com/pulumi/pulumi-terraform-bridge/issues/2178 in the pulumi-terraform-bridge for this problem.

In the meantime a workaround here would be to manually edit the state with pulumi stack export/import: https://www.pulumi.com/docs/cli/commands/pulumi_stack/

Note that things can go wrong here, so please try this on a dev stack first and make backups of your state before editting!

You'd need to:

  1. import the resource
  2. run pulumi stack export and save the stack to a file.
  3. Find the instance resource and remove the diskEncryptionKeySha256 from the inputs
  4. Run pulumi stack impot and import the edited stack state
  5. pulumi preview with the generated code to verify it matches the state.
  6. pulumi import the disks and attachments
  7. Add ignore changes attachedDisks to the instance and run pulumi preview with the disks and attachments to see if the state matches your code.
Josh-Ramirez commented 1 month ago

Hi @VenelinMartinov,

It looks like a few of the upstream issues have been closed. When do you expect this issue to be resolved?

Thanks again for all the help!

VenelinMartinov commented 4 weeks ago

Hey @Josh-Ramirez, this should be fixed in the newest provider version, LMK if you are still having issues with it!

VenelinMartinov commented 4 weeks ago

My bad, actually, the fix hasn't been released yet. I'll kick off a release now

VenelinMartinov commented 4 weeks ago

The CI pipeline is blocked, so the release did not go out. I'm addressing it today: https://github.com/pulumi/pulumi-gcp/issues/2273

Will update here once the release is out.

VenelinMartinov commented 4 weeks ago

Shipped in https://github.com/pulumi/pulumi-gcp/releases/tag/v7.33.0 🎉

LMK if you are still having trouble with this after upgrading.