blob: 512240ad75408e046c87d22fe4cb585bccff566d [file] [log] [blame] [edit]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** Type: MMv1 ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package compute
import (
"context"
"errors"
"fmt"
"log"
"net/http"
"reflect"
"strings"
"time"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"google.golang.org/api/googleapi"
"github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource"
transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport"
)
// diffsupress for hyperdisk provisioned_iops
func hyperDiskIopsUpdateDiffSupress(_ context.Context, d *schema.ResourceDiff, meta interface{}) error {
if !strings.Contains(d.Get("type").(string), "hyperdisk") {
resourceSchema := ResourceComputeDisk().Schema
for field := range resourceSchema {
if field == "provisioned_iops" && d.HasChange(field) {
if err := d.ForceNew(field); err != nil {
return err
}
}
}
}
return nil
}
// Suppress all diffs, used for Disk.Interface which is a nonfunctional field
func AlwaysDiffSuppress(_, _, _ string, _ *schema.ResourceData) bool {
return true
}
// diffsupress for beta and to check change in source_disk attribute
func sourceDiskDiffSupress(_, old, new string, _ *schema.ResourceData) bool {
s1 := strings.TrimPrefix(old, "https://www.googleapis.com/compute/beta")
s2 := strings.TrimPrefix(new, "https://www.googleapis.com/compute/v1")
if strings.HasSuffix(s1, s2) {
return true
}
return false
}
// Is the new disk size smaller than the old one?
func IsDiskShrinkage(_ context.Context, old, new, _ interface{}) bool {
// It's okay to remove size entirely.
if old == nil || new == nil {
return false
}
return new.(int) < old.(int)
}
// We cannot suppress the diff for the case when family name is not part of the image name since we can't
// make a network call in a DiffSuppressFunc.
func DiskImageDiffSuppress(_, old, new string, _ *schema.ResourceData) bool {
// Understand that this function solves a messy problem ("how do we tell if the diff between two images
// is 'ForceNew-worthy', without making a network call?") in the best way we can: through a series of special
// cases and regexes. If you find yourself here because you are trying to add a new special case,
// you are probably looking for the diskImageFamilyEquals function and its subfunctions.
// In order to keep this maintainable, we need to ensure that the positive and negative examples
// in resource_compute_disk_test.go are as complete as possible.
// 'old' is read from the API.
// It always has the format 'https://www.googleapis.com/compute/v1/projects/(%s)/global/images/(%s)'
matches := resolveImageLink.FindStringSubmatch(old)
if matches == nil {
// Image read from the API doesn't have the expected format. In practice, it should never happen
return false
}
oldProject := matches[1]
oldName := matches[2]
// Partial or full self link family
if resolveImageProjectFamily.MatchString(new) {
// Value matches pattern "projects/{project}/global/images/family/{family-name}$"
matches := resolveImageProjectFamily.FindStringSubmatch(new)
newProject := matches[1]
newFamilyName := matches[2]
return diskImageProjectNameEquals(oldProject, newProject) && diskImageFamilyEquals(oldName, newFamilyName)
}
// Partial or full self link image
if resolveImageProjectImage.MatchString(new) {
// Value matches pattern "projects/{project}/global/images/{image-name}$"
matches := resolveImageProjectImage.FindStringSubmatch(new)
newProject := matches[1]
newImageName := matches[2]
return diskImageProjectNameEquals(oldProject, newProject) && diskImageEquals(oldName, newImageName)
}
// Partial link without project family
if resolveImageGlobalFamily.MatchString(new) {
// Value is "global/images/family/{family-name}"
matches := resolveImageGlobalFamily.FindStringSubmatch(new)
familyName := matches[1]
return diskImageFamilyEquals(oldName, familyName)
}
// Partial link without project image
if resolveImageGlobalImage.MatchString(new) {
// Value is "global/images/{image-name}"
matches := resolveImageGlobalImage.FindStringSubmatch(new)
imageName := matches[1]
return diskImageEquals(oldName, imageName)
}
// Family shorthand
if resolveImageFamilyFamily.MatchString(new) {
// Value is "family/{family-name}"
matches := resolveImageFamilyFamily.FindStringSubmatch(new)
familyName := matches[1]
return diskImageFamilyEquals(oldName, familyName)
}
// Shorthand for image or family
if resolveImageProjectImageShorthand.MatchString(new) {
// Value is "{project}/{image-name}" or "{project}/{family-name}"
matches := resolveImageProjectImageShorthand.FindStringSubmatch(new)
newProject := matches[1]
newName := matches[2]
return diskImageProjectNameEquals(oldProject, newProject) &&
(diskImageEquals(oldName, newName) || diskImageFamilyEquals(oldName, newName))
}
// Image or family only
if diskImageEquals(oldName, new) || diskImageFamilyEquals(oldName, new) {
// Value is "{image-name}" or "{family-name}"
return true
}
return false
}
func diskImageProjectNameEquals(project1, project2 string) bool {
// Convert short project name to full name
// For instance, centos => centos-cloud
fullProjectName, ok := ImageMap[project2]
if ok {
project2 = fullProjectName
}
return project1 == project2
}
func diskImageEquals(oldImageName, newImageName string) bool {
return oldImageName == newImageName
}
func diskImageFamilyEquals(imageName, familyName string) bool {
// Handles the case when the image name includes the family name
// e.g. image name: debian-11-bullseye-v20220719, family name: debian-11
// First condition is to check if image contains arm64 because of case like:
// image name: opensuse-leap-15-4-v20220713-arm64, family name: opensuse-leap (should not be evaluated during handling of amd64 cases)
// In second condition, we have to check for amd64 because of cases like:
// image name: ubuntu-2210-kinetic-amd64-v20221022, family name: ubuntu-2210 (should not suppress)
if !strings.Contains(imageName, "-arm64") && strings.Contains(imageName, strings.TrimSuffix(familyName, "-amd64")) {
if strings.Contains(imageName, "-amd64") {
return strings.HasSuffix(familyName, "-amd64")
} else {
return !strings.HasSuffix(familyName, "-amd64")
}
}
// We have to check for arm64 because of cases like:
// image name: opensuse-leap-15-4-v20220713-arm64, family name: opensuse-leap (should not suppress)
if strings.Contains(imageName, strings.TrimSuffix(familyName, "-arm64")) {
if strings.Contains(imageName, "-arm64") {
return strings.HasSuffix(familyName, "-arm64")
} else {
return !strings.HasSuffix(familyName, "-arm64")
}
}
if suppressCanonicalFamilyDiff(imageName, familyName) {
return true
}
if suppressCosFamilyDiff(imageName, familyName) {
return true
}
if suppressWindowsSqlFamilyDiff(imageName, familyName) {
return true
}
if suppressWindowsFamilyDiff(imageName, familyName) {
return true
}
return false
}
// e.g. image: ubuntu-1404-trusty-v20180122, family: ubuntu-1404-lts
func suppressCanonicalFamilyDiff(imageName, familyName string) bool {
parts := canonicalUbuntuLtsImage.FindStringSubmatch(imageName)
if len(parts) == 4 {
var f string
if parts[3] == "" {
f = fmt.Sprintf("ubuntu-%s%s-lts", parts[1], parts[2])
} else {
f = fmt.Sprintf("ubuntu-%s%s-lts-%s", parts[1], parts[2], parts[3])
}
if f == familyName {
return true
}
}
return false
}
// e.g. image: cos-NN-*, family: cos-NN-lts
func suppressCosFamilyDiff(imageName, familyName string) bool {
parts := cosLtsImage.FindStringSubmatch(imageName)
if len(parts) == 2 {
f := fmt.Sprintf("cos-%s-lts", parts[1])
if f == familyName {
return true
}
}
return false
}
// e.g. image: sql-2017-standard-windows-2016-dc-v20180109, family: sql-std-2017-win-2016
// e.g. image: sql-2017-express-windows-2012-r2-dc-v20180109, family: sql-exp-2017-win-2012-r2
func suppressWindowsSqlFamilyDiff(imageName, familyName string) bool {
parts := windowsSqlImage.FindStringSubmatch(imageName)
if len(parts) == 5 {
edition := parts[2] // enterprise, standard or web.
sqlVersion := parts[1]
windowsVersion := parts[3]
// Translate edition
switch edition {
case "enterprise":
edition = "ent"
case "standard":
edition = "std"
case "express":
edition = "exp"
}
var f string
if revision := parts[4]; revision != "" {
// With revision
f = fmt.Sprintf("sql-%s-%s-win-%s-r%s", edition, sqlVersion, windowsVersion, revision)
} else {
// No revision
f = fmt.Sprintf("sql-%s-%s-win-%s", edition, sqlVersion, windowsVersion)
}
if f == familyName {
return true
}
}
return false
}
// e.g. image: windows-server-1709-dc-core-v20180109, family: windows-1709-core
// e.g. image: windows-server-1709-dc-core-for-containers-v20180109, family: "windows-1709-core-for-containers
func suppressWindowsFamilyDiff(imageName, familyName string) bool {
updatedFamilyString := strings.Replace(familyName, "windows-", "windows-server-", 1)
updatedImageName := strings.Replace(imageName, "-dc-", "-", 1)
return strings.Contains(updatedImageName, updatedFamilyString)
}
func ResourceComputeDisk() *schema.Resource {
return &schema.Resource{
Create: resourceComputeDiskCreate,
Read: resourceComputeDiskRead,
Update: resourceComputeDiskUpdate,
Delete: resourceComputeDiskDelete,
Importer: &schema.ResourceImporter{
State: resourceComputeDiskImport,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(20 * time.Minute),
Update: schema.DefaultTimeout(20 * time.Minute),
Delete: schema.DefaultTimeout(20 * time.Minute),
},
CustomizeDiff: customdiff.All(
customdiff.ForceNewIfChange("size", IsDiskShrinkage),
hyperDiskIopsUpdateDiffSupress,
tpgresource.SetLabelsDiff,
tpgresource.DefaultProviderProject,
),
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `Name of the resource. Provided by the client when the resource is
created. The name must be 1-63 characters long, and comply with
RFC1035. Specifically, the name must be 1-63 characters long and match
the regular expression '[a-z]([-a-z0-9]*[a-z0-9])?' which means the
first character must be a lowercase letter, and all following
characters must be a dash, lowercase letter, or digit, except the last
character, which cannot be a dash.`,
},
"access_mode": {
Type: schema.TypeString,
Computed: true,
Optional: true,
Description: `The accessMode of the disk.
For example:
* READ_WRITE_SINGLE
* READ_WRITE_MANY
* READ_ONLY_SINGLE`,
},
"async_primary_disk": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
DiffSuppressFunc: tpgresource.CompareSelfLinkRelativePaths,
Description: `A nested object resource`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"disk": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `Primary disk for asynchronous disk replication.`,
},
},
},
},
"description": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: `An optional description of this resource. Provide this property when
you create the resource.`,
},
"disk_encryption_key": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Description: `Encrypts the disk using a customer-supplied encryption key.
After you encrypt a disk with a customer-supplied key, you must
provide the same key if you use the disk later (e.g. to create a disk
snapshot or an image, or to attach the disk to a virtual machine).
Customer-supplied encryption keys do not protect access to metadata of
the disk.
If you do not provide an encryption key when creating the disk, then
the disk will be encrypted using an automatically generated key and
you do not need to provide a key to use the disk later.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"kms_key_self_link": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
DiffSuppressFunc: tpgresource.CompareSelfLinkRelativePaths,
Description: `The self link of the encryption key used to encrypt the disk. Also called KmsKeyName
in the cloud console. Your project's Compute Engine System service account
('service-{{PROJECT_NUMBER}}@compute-system.iam.gserviceaccount.com') must have
'roles/cloudkms.cryptoKeyEncrypterDecrypter' to use this feature.
See https://cloud.google.com/compute/docs/disks/customer-managed-encryption#encrypt_a_new_persistent_disk_with_your_own_keys`,
},
"kms_key_service_account": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: `The service account used for the encryption request for the given KMS key.
If absent, the Compute Engine Service Agent service account is used.`,
},
"raw_key": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: `Specifies a 256-bit customer-supplied encryption key, encoded in
RFC 4648 base64 to either encrypt or decrypt this resource.`,
Sensitive: true,
},
"rsa_encrypted_key": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: `Specifies an RFC 4648 base64 encoded, RSA-wrapped 2048-bit
customer-supplied encryption key to either encrypt or decrypt
this resource. You can provide either the rawKey or the rsaEncryptedKey.`,
Sensitive: true,
},
"sha256": {
Type: schema.TypeString,
Computed: true,
Description: `The RFC 4648 base64 encoded SHA-256 hash of the customer-supplied
encryption key that protects this resource.`,
},
},
},
},
"enable_confidential_compute": {
Type: schema.TypeBool,
Computed: true,
Optional: true,
ForceNew: true,
Description: `Whether this disk is using confidential compute mode.
Note: Only supported on hyperdisk skus, disk_encryption_key is required when setting to true`,
},
"guest_os_features": {
Type: schema.TypeSet,
Computed: true,
Optional: true,
ForceNew: true,
Description: `A list of features to enable on the guest operating system.
Applicable only for bootable disks.`,
Elem: computeDiskGuestOsFeaturesSchema(),
// Default schema.HashSchema is used.
},
"image": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
DiffSuppressFunc: DiskImageDiffSuppress,
Description: `The image from which to initialize this disk. This can be
one of: the image's 'self_link', 'projects/{project}/global/images/{image}',
'projects/{project}/global/images/family/{family}', 'global/images/{image}',
'global/images/family/{family}', 'family/{family}', '{project}/{family}',
'{project}/{image}', '{family}', or '{image}'. If referred by family, the
images names must include the family name. If they don't, use the
[google_compute_image data source](/docs/providers/google/d/compute_image.html).
For instance, the image 'centos-6-v20180104' includes its family name 'centos-6'.
These images can be referred by family name here.`,
},
"interface": {
Type: schema.TypeString,
Optional: true,
Deprecated: "`interface` is deprecated and will be removed in a future major release. This field is no longer used and can be safely removed from your configurations; disk interfaces are automatically determined on attachment.",
ForceNew: true,
DiffSuppressFunc: AlwaysDiffSuppress,
Description: `Specifies the disk interface to use for attaching this disk, which is either SCSI or NVME. The default is SCSI.`,
Default: "SCSI",
},
"labels": {
Type: schema.TypeMap,
Optional: true,
Description: `Labels to apply to this disk. A list of key->value pairs.
**Note**: This field is non-authoritative, and will only manage the labels present in your configuration.
Please refer to the field 'effective_labels' for all of the labels present on the resource.`,
Elem: &schema.Schema{Type: schema.TypeString},
},
"licenses": {
Type: schema.TypeList,
Computed: true,
Optional: true,
ForceNew: true,
Description: `Any applicable license URI.`,
Elem: &schema.Schema{
Type: schema.TypeString,
DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName,
},
},
"multi_writer": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Description: `Indicates whether or not the disk can be read/write attached to more than one instance.`,
},
"physical_block_size_bytes": {
Type: schema.TypeInt,
Computed: true,
Optional: true,
ForceNew: true,
Description: `Physical block size of the persistent disk, in bytes. If not present
in a request, a default value is used. Currently supported sizes
are 4096 and 16384, other sizes may be added in the future.
If an unsupported value is requested, the error message will list
the supported values for the caller's project.`,
},
"provisioned_iops": {
Type: schema.TypeInt,
Computed: true,
Optional: true,
Description: `Indicates how many IOPS must be provisioned for the disk.
Note: Updating currently is only supported by hyperdisk skus without the need to delete and recreate the disk, hyperdisk
allows for an update of IOPS every 4 hours. To update your hyperdisk more frequently, you'll need to manually delete and recreate it`,
},
"provisioned_throughput": {
Type: schema.TypeInt,
Computed: true,
Optional: true,
Description: `Indicates how much Throughput must be provisioned for the disk.
Note: Updating currently is only supported by hyperdisk skus without the need to delete and recreate the disk, hyperdisk
allows for an update of Throughput every 4 hours. To update your hyperdisk more frequently, you'll need to manually delete and recreate it`,
},
"resource_policies": {
Type: schema.TypeList,
Computed: true,
Optional: true,
ForceNew: true,
Description: `Resource policies applied to this disk for automatic snapshot creations.
~>**NOTE** This value does not support updating the
resource policy, as resource policies can not be updated more than
one at a time. Use
['google_compute_disk_resource_policy_attachment'](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_disk_resource_policy_attachment)
to allow for updating the resource policy attached to the disk.`,
Elem: &schema.Schema{
Type: schema.TypeString,
DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName,
},
},
"size": {
Type: schema.TypeInt,
Computed: true,
Optional: true,
Description: `Size of the persistent disk, specified in GB. You can specify this
field when creating a persistent disk using the 'image' or
'snapshot' parameter, or specify it alone to create an empty
persistent disk.
If you specify this field along with 'image' or 'snapshot',
the value must not be less than the size of the image
or the size of the snapshot.
~>**NOTE** If you change the size, Terraform updates the disk size
if upsizing is detected but recreates the disk if downsizing is requested.
You can add 'lifecycle.prevent_destroy' in the config to prevent destroying
and recreating.`,
},
"snapshot": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName,
Description: `The source snapshot used to create this disk. You can provide this as
a partial or full URL to the resource. If the snapshot is in another
project than this disk, you must supply a full URL. For example, the
following are valid values:
* 'https://www.googleapis.com/compute/v1/projects/project/global/snapshots/snapshot'
* 'projects/project/global/snapshots/snapshot'
* 'global/snapshots/snapshot'
* 'snapshot'`,
},
"source_disk": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
DiffSuppressFunc: sourceDiskDiffSupress,
Description: `The source disk used to create this disk. You can provide this as a partial or full URL to the resource.
For example, the following are valid values:
* https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/disks/{disk}
* https://www.googleapis.com/compute/v1/projects/{project}/regions/{region}/disks/{disk}
* projects/{project}/zones/{zone}/disks/{disk}
* projects/{project}/regions/{region}/disks/{disk}
* zones/{zone}/disks/{disk}
* regions/{region}/disks/{disk}`,
},
"source_image_encryption_key": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Description: `The customer-supplied encryption key of the source image. Required if
the source image is protected by a customer-supplied encryption key.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"kms_key_self_link": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
DiffSuppressFunc: tpgresource.CompareSelfLinkRelativePaths,
Description: `The self link of the encryption key used to encrypt the disk. Also called KmsKeyName
in the cloud console. Your project's Compute Engine System service account
('service-{{PROJECT_NUMBER}}@compute-system.iam.gserviceaccount.com') must have
'roles/cloudkms.cryptoKeyEncrypterDecrypter' to use this feature.
See https://cloud.google.com/compute/docs/disks/customer-managed-encryption#encrypt_a_new_persistent_disk_with_your_own_keys`,
},
"kms_key_service_account": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: `The service account used for the encryption request for the given KMS key.
If absent, the Compute Engine Service Agent service account is used.`,
},
"raw_key": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: `Specifies a 256-bit customer-supplied encryption key, encoded in
RFC 4648 base64 to either encrypt or decrypt this resource.`,
},
"sha256": {
Type: schema.TypeString,
Computed: true,
Description: `The RFC 4648 base64 encoded SHA-256 hash of the customer-supplied
encryption key that protects this resource.`,
},
},
},
},
"source_snapshot_encryption_key": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Description: `The customer-supplied encryption key of the source snapshot. Required
if the source snapshot is protected by a customer-supplied encryption
key.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"kms_key_self_link": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
DiffSuppressFunc: tpgresource.CompareSelfLinkRelativePaths,
Description: `The self link of the encryption key used to encrypt the disk. Also called KmsKeyName
in the cloud console. Your project's Compute Engine System service account
('service-{{PROJECT_NUMBER}}@compute-system.iam.gserviceaccount.com') must have
'roles/cloudkms.cryptoKeyEncrypterDecrypter' to use this feature.
See https://cloud.google.com/compute/docs/disks/customer-managed-encryption#encrypt_a_new_persistent_disk_with_your_own_keys`,
},
"kms_key_service_account": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: `The service account used for the encryption request for the given KMS key.
If absent, the Compute Engine Service Agent service account is used.`,
},
"raw_key": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: `Specifies a 256-bit customer-supplied encryption key, encoded in
RFC 4648 base64 to either encrypt or decrypt this resource.`,
},
"sha256": {
Type: schema.TypeString,
Computed: true,
Description: `The RFC 4648 base64 encoded SHA-256 hash of the customer-supplied
encryption key that protects this resource.`,
},
},
},
},
"storage_pool": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
DiffSuppressFunc: tpgresource.CompareResourceNames,
Description: `The URL of the storage pool in which the new disk is created.
For example:
* https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/storagePools/{storagePool}
* /projects/{project}/zones/{zone}/storagePools/{storagePool}`,
},
"type": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
DiffSuppressFunc: tpgresource.CompareResourceNames,
Description: `URL of the disk type resource describing which disk type to use to
create the disk. Provide this when creating the disk.`,
Default: "pd-standard",
},
"zone": {
Type: schema.TypeString,
Computed: true,
Optional: true,
ForceNew: true,
DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName,
Description: `A reference to the zone where the disk resides.`,
},
"disk_id": {
Type: schema.TypeString,
Computed: true,
Description: `The unique identifier for the resource. This identifier is defined by the server.`,
},
"creation_timestamp": {
Type: schema.TypeString,
Computed: true,
Description: `Creation timestamp in RFC3339 text format.`,
},
"effective_labels": {
Type: schema.TypeMap,
Computed: true,
Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`,
Elem: &schema.Schema{Type: schema.TypeString},
},
"label_fingerprint": {
Type: schema.TypeString,
Computed: true,
Description: `The fingerprint used for optimistic locking of this resource. Used
internally during updates.`,
},
"last_attach_timestamp": {
Type: schema.TypeString,
Computed: true,
Description: `Last attach timestamp in RFC3339 text format.`,
},
"last_detach_timestamp": {
Type: schema.TypeString,
Computed: true,
Description: `Last detach timestamp in RFC3339 text format.`,
},
"source_disk_id": {
Type: schema.TypeString,
Computed: true,
Description: `The ID value of the disk used to create this image. This value may
be used to determine whether the image was taken from the current
or a previous instance of a given disk name.`,
},
"source_image_id": {
Type: schema.TypeString,
Computed: true,
Description: `The ID value of the image used to create this disk. This value
identifies the exact image that was used to create this persistent
disk. For example, if you created the persistent disk from an image
that was later deleted and recreated under the same name, the source
image ID would identify the exact version of the image that was used.`,
},
"source_snapshot_id": {
Type: schema.TypeString,
Computed: true,
Description: `The unique ID of the snapshot used to create this disk. This value
identifies the exact snapshot that was used to create this persistent
disk. For example, if you created the persistent disk from a snapshot
that was later deleted and recreated under the same name, the source
snapshot ID would identify the exact version of the snapshot that was
used.`,
},
"terraform_labels": {
Type: schema.TypeMap,
Computed: true,
Description: `The combination of labels configured directly on the resource
and default labels configured on the provider.`,
Elem: &schema.Schema{Type: schema.TypeString},
},
"users": {
Type: schema.TypeList,
Computed: true,
Description: `Links to the users of the disk (attached instances) in form:
project/zones/zone/instances/instance`,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"project": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"self_link": {
Type: schema.TypeString,
Computed: true,
},
},
UseJSONNumber: true,
}
}
func computeDiskGuestOsFeaturesSchema() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"type": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `The type of supported feature. Read [Enabling guest operating system features](https://cloud.google.com/compute/docs/images/create-delete-deprecate-private-images#guest-os-features) to see a list of available options.`,
},
},
}
}
func resourceComputeDiskCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return err
}
obj := make(map[string]interface{})
labelFingerprintProp, err := expandComputeDiskLabelFingerprint(d.Get("label_fingerprint"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("label_fingerprint"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelFingerprintProp)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) {
obj["labelFingerprint"] = labelFingerprintProp
}
descriptionProp, err := expandComputeDiskDescription(d.Get("description"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("description"); !tpgresource.IsEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
obj["description"] = descriptionProp
}
nameProp, err := expandComputeDiskName(d.Get("name"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("name"); !tpgresource.IsEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
obj["name"] = nameProp
}
sizeGbProp, err := expandComputeDiskSize(d.Get("size"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("size"); !tpgresource.IsEmptyValue(reflect.ValueOf(sizeGbProp)) && (ok || !reflect.DeepEqual(v, sizeGbProp)) {
obj["sizeGb"] = sizeGbProp
}
physicalBlockSizeBytesProp, err := expandComputeDiskPhysicalBlockSizeBytes(d.Get("physical_block_size_bytes"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("physical_block_size_bytes"); !tpgresource.IsEmptyValue(reflect.ValueOf(physicalBlockSizeBytesProp)) && (ok || !reflect.DeepEqual(v, physicalBlockSizeBytesProp)) {
obj["physicalBlockSizeBytes"] = physicalBlockSizeBytesProp
}
sourceDiskProp, err := expandComputeDiskSourceDisk(d.Get("source_disk"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("source_disk"); !tpgresource.IsEmptyValue(reflect.ValueOf(sourceDiskProp)) && (ok || !reflect.DeepEqual(v, sourceDiskProp)) {
obj["sourceDisk"] = sourceDiskProp
}
typeProp, err := expandComputeDiskType(d.Get("type"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("type"); !tpgresource.IsEmptyValue(reflect.ValueOf(typeProp)) && (ok || !reflect.DeepEqual(v, typeProp)) {
obj["type"] = typeProp
}
sourceImageProp, err := expandComputeDiskImage(d.Get("image"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("image"); !tpgresource.IsEmptyValue(reflect.ValueOf(sourceImageProp)) && (ok || !reflect.DeepEqual(v, sourceImageProp)) {
obj["sourceImage"] = sourceImageProp
}
resourcePoliciesProp, err := expandComputeDiskResourcePolicies(d.Get("resource_policies"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("resource_policies"); !tpgresource.IsEmptyValue(reflect.ValueOf(resourcePoliciesProp)) && (ok || !reflect.DeepEqual(v, resourcePoliciesProp)) {
obj["resourcePolicies"] = resourcePoliciesProp
}
enableConfidentialComputeProp, err := expandComputeDiskEnableConfidentialCompute(d.Get("enable_confidential_compute"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("enable_confidential_compute"); !tpgresource.IsEmptyValue(reflect.ValueOf(enableConfidentialComputeProp)) && (ok || !reflect.DeepEqual(v, enableConfidentialComputeProp)) {
obj["enableConfidentialCompute"] = enableConfidentialComputeProp
}
multiWriterProp, err := expandComputeDiskMultiWriter(d.Get("multi_writer"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("multi_writer"); !tpgresource.IsEmptyValue(reflect.ValueOf(multiWriterProp)) && (ok || !reflect.DeepEqual(v, multiWriterProp)) {
obj["multiWriter"] = multiWriterProp
}
provisionedIopsProp, err := expandComputeDiskProvisionedIops(d.Get("provisioned_iops"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("provisioned_iops"); !tpgresource.IsEmptyValue(reflect.ValueOf(provisionedIopsProp)) && (ok || !reflect.DeepEqual(v, provisionedIopsProp)) {
obj["provisionedIops"] = provisionedIopsProp
}
provisionedThroughputProp, err := expandComputeDiskProvisionedThroughput(d.Get("provisioned_throughput"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("provisioned_throughput"); !tpgresource.IsEmptyValue(reflect.ValueOf(provisionedThroughputProp)) && (ok || !reflect.DeepEqual(v, provisionedThroughputProp)) {
obj["provisionedThroughput"] = provisionedThroughputProp
}
asyncPrimaryDiskProp, err := expandComputeDiskAsyncPrimaryDisk(d.Get("async_primary_disk"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("async_primary_disk"); !tpgresource.IsEmptyValue(reflect.ValueOf(asyncPrimaryDiskProp)) && (ok || !reflect.DeepEqual(v, asyncPrimaryDiskProp)) {
obj["asyncPrimaryDisk"] = asyncPrimaryDiskProp
}
guestOsFeaturesProp, err := expandComputeDiskGuestOsFeatures(d.Get("guest_os_features"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("guest_os_features"); !tpgresource.IsEmptyValue(reflect.ValueOf(guestOsFeaturesProp)) && (ok || !reflect.DeepEqual(v, guestOsFeaturesProp)) {
obj["guestOsFeatures"] = guestOsFeaturesProp
}
licensesProp, err := expandComputeDiskLicenses(d.Get("licenses"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("licenses"); !tpgresource.IsEmptyValue(reflect.ValueOf(licensesProp)) && (ok || !reflect.DeepEqual(v, licensesProp)) {
obj["licenses"] = licensesProp
}
storagePoolProp, err := expandComputeDiskStoragePool(d.Get("storage_pool"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("storage_pool"); !tpgresource.IsEmptyValue(reflect.ValueOf(storagePoolProp)) && (ok || !reflect.DeepEqual(v, storagePoolProp)) {
obj["storagePool"] = storagePoolProp
}
accessModeProp, err := expandComputeDiskAccessMode(d.Get("access_mode"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("access_mode"); !tpgresource.IsEmptyValue(reflect.ValueOf(accessModeProp)) && (ok || !reflect.DeepEqual(v, accessModeProp)) {
obj["accessMode"] = accessModeProp
}
labelsProp, err := expandComputeDiskEffectiveLabels(d.Get("effective_labels"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
obj["labels"] = labelsProp
}
zoneProp, err := expandComputeDiskZone(d.Get("zone"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("zone"); !tpgresource.IsEmptyValue(reflect.ValueOf(zoneProp)) && (ok || !reflect.DeepEqual(v, zoneProp)) {
obj["zone"] = zoneProp
}
sourceImageEncryptionKeyProp, err := expandComputeDiskSourceImageEncryptionKey(d.Get("source_image_encryption_key"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("source_image_encryption_key"); !tpgresource.IsEmptyValue(reflect.ValueOf(sourceImageEncryptionKeyProp)) && (ok || !reflect.DeepEqual(v, sourceImageEncryptionKeyProp)) {
obj["sourceImageEncryptionKey"] = sourceImageEncryptionKeyProp
}
diskEncryptionKeyProp, err := expandComputeDiskDiskEncryptionKey(d.Get("disk_encryption_key"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("disk_encryption_key"); !tpgresource.IsEmptyValue(reflect.ValueOf(diskEncryptionKeyProp)) && (ok || !reflect.DeepEqual(v, diskEncryptionKeyProp)) {
obj["diskEncryptionKey"] = diskEncryptionKeyProp
}
sourceSnapshotProp, err := expandComputeDiskSnapshot(d.Get("snapshot"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("snapshot"); !tpgresource.IsEmptyValue(reflect.ValueOf(sourceSnapshotProp)) && (ok || !reflect.DeepEqual(v, sourceSnapshotProp)) {
obj["sourceSnapshot"] = sourceSnapshotProp
}
sourceSnapshotEncryptionKeyProp, err := expandComputeDiskSourceSnapshotEncryptionKey(d.Get("source_snapshot_encryption_key"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("source_snapshot_encryption_key"); !tpgresource.IsEmptyValue(reflect.ValueOf(sourceSnapshotEncryptionKeyProp)) && (ok || !reflect.DeepEqual(v, sourceSnapshotEncryptionKeyProp)) {
obj["sourceSnapshotEncryptionKey"] = sourceSnapshotEncryptionKeyProp
}
obj, err = resourceComputeDiskEncoder(d, meta, obj)
if err != nil {
return err
}
url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/disks")
if err != nil {
return err
}
log.Printf("[DEBUG] Creating new Disk: %#v", obj)
billingProject := ""
project, err := tpgresource.GetProject(d, config)
if err != nil {
return fmt.Errorf("Error fetching project for Disk: %s", err)
}
billingProject = project
// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}
headers := make(http.Header)
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "POST",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
Body: obj,
Timeout: d.Timeout(schema.TimeoutCreate),
Headers: headers,
})
if err != nil {
return fmt.Errorf("Error creating Disk: %s", err)
}
// Store the ID now
id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/zones/{{zone}}/disks/{{name}}")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
err = ComputeOperationWaitTime(
config, res, project, "Creating Disk", userAgent,
d.Timeout(schema.TimeoutCreate))
if err != nil {
// The resource didn't actually create
d.SetId("")
return fmt.Errorf("Error waiting to create Disk: %s", err)
}
log.Printf("[DEBUG] Finished creating Disk %q: %#v", d.Id(), res)
return resourceComputeDiskRead(d, meta)
}
func resourceComputeDiskRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return err
}
url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/disks/{{name}}")
if err != nil {
return err
}
billingProject := ""
project, err := tpgresource.GetProject(d, config)
if err != nil {
return fmt.Errorf("Error fetching project for Disk: %s", err)
}
billingProject = project
// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}
headers := make(http.Header)
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "GET",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
Headers: headers,
})
if err != nil {
return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("ComputeDisk %q", d.Id()))
}
res, err = resourceComputeDiskDecoder(d, meta, res)
if err != nil {
return err
}
if res == nil {
// Decoding the object has resulted in it being gone. It may be marked deleted
log.Printf("[DEBUG] Removing ComputeDisk because it no longer exists.")
d.SetId("")
return nil
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("label_fingerprint", flattenComputeDiskLabelFingerprint(res["labelFingerprint"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("creation_timestamp", flattenComputeDiskCreationTimestamp(res["creationTimestamp"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("description", flattenComputeDiskDescription(res["description"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("last_attach_timestamp", flattenComputeDiskLastAttachTimestamp(res["lastAttachTimestamp"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("last_detach_timestamp", flattenComputeDiskLastDetachTimestamp(res["lastDetachTimestamp"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("labels", flattenComputeDiskLabels(res["labels"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("name", flattenComputeDiskName(res["name"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("size", flattenComputeDiskSize(res["sizeGb"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("users", flattenComputeDiskUsers(res["users"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("physical_block_size_bytes", flattenComputeDiskPhysicalBlockSizeBytes(res["physicalBlockSizeBytes"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("source_disk", flattenComputeDiskSourceDisk(res["sourceDisk"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("source_disk_id", flattenComputeDiskSourceDiskId(res["sourceDiskId"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("disk_id", flattenComputeDiskDiskId(res["id"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("type", flattenComputeDiskType(res["type"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("image", flattenComputeDiskImage(res["sourceImage"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("resource_policies", flattenComputeDiskResourcePolicies(res["resourcePolicies"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("enable_confidential_compute", flattenComputeDiskEnableConfidentialCompute(res["enableConfidentialCompute"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("multi_writer", flattenComputeDiskMultiWriter(res["multiWriter"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("provisioned_iops", flattenComputeDiskProvisionedIops(res["provisionedIops"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("provisioned_throughput", flattenComputeDiskProvisionedThroughput(res["provisionedThroughput"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("async_primary_disk", flattenComputeDiskAsyncPrimaryDisk(res["asyncPrimaryDisk"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("guest_os_features", flattenComputeDiskGuestOsFeatures(res["guestOsFeatures"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("licenses", flattenComputeDiskLicenses(res["licenses"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("storage_pool", flattenComputeDiskStoragePool(res["storagePool"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("access_mode", flattenComputeDiskAccessMode(res["accessMode"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("terraform_labels", flattenComputeDiskTerraformLabels(res["labels"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("effective_labels", flattenComputeDiskEffectiveLabels(res["labels"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("zone", flattenComputeDiskZone(res["zone"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("source_image_encryption_key", flattenComputeDiskSourceImageEncryptionKey(res["sourceImageEncryptionKey"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("source_image_id", flattenComputeDiskSourceImageId(res["sourceImageId"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("disk_encryption_key", flattenComputeDiskDiskEncryptionKey(res["diskEncryptionKey"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("snapshot", flattenComputeDiskSnapshot(res["sourceSnapshot"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("source_snapshot_encryption_key", flattenComputeDiskSourceSnapshotEncryptionKey(res["sourceSnapshotEncryptionKey"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("source_snapshot_id", flattenComputeDiskSourceSnapshotId(res["sourceSnapshotId"], d, config)); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
if err := d.Set("self_link", tpgresource.ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil {
return fmt.Errorf("Error reading Disk: %s", err)
}
return nil
}
func resourceComputeDiskUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return err
}
billingProject := ""
project, err := tpgresource.GetProject(d, config)
if err != nil {
return fmt.Errorf("Error fetching project for Disk: %s", err)
}
billingProject = project
d.Partial(true)
if d.HasChange("label_fingerprint") || d.HasChange("effective_labels") {
obj := make(map[string]interface{})
labelFingerprintProp, err := expandComputeDiskLabelFingerprint(d.Get("label_fingerprint"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("label_fingerprint"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) {
obj["labelFingerprint"] = labelFingerprintProp
}
labelsProp, err := expandComputeDiskEffectiveLabels(d.Get("effective_labels"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
obj["labels"] = labelsProp
}
obj, err = resourceComputeDiskUpdateEncoder(d, meta, obj)
if err != nil {
return err
}
url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/disks/{{name}}/setLabels")
if err != nil {
return err
}
headers := make(http.Header)
// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "POST",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
Body: obj,
Timeout: d.Timeout(schema.TimeoutUpdate),
Headers: headers,
})
if err != nil {
return fmt.Errorf("Error updating Disk %q: %s", d.Id(), err)
} else {
log.Printf("[DEBUG] Finished updating Disk %q: %#v", d.Id(), res)
}
err = ComputeOperationWaitTime(
config, res, project, "Updating Disk", userAgent,
d.Timeout(schema.TimeoutUpdate))
if err != nil {
return err
}
}
if d.HasChange("size") {
obj := make(map[string]interface{})
sizeGbProp, err := expandComputeDiskSize(d.Get("size"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("size"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, sizeGbProp)) {
obj["sizeGb"] = sizeGbProp
}
obj, err = resourceComputeDiskUpdateEncoder(d, meta, obj)
if err != nil {
return err
}
url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/disks/{{name}}/resize")
if err != nil {
return err
}
headers := make(http.Header)
// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "POST",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
Body: obj,
Timeout: d.Timeout(schema.TimeoutUpdate),
Headers: headers,
})
if err != nil {
return fmt.Errorf("Error updating Disk %q: %s", d.Id(), err)
} else {
log.Printf("[DEBUG] Finished updating Disk %q: %#v", d.Id(), res)
}
err = ComputeOperationWaitTime(
config, res, project, "Updating Disk", userAgent,
d.Timeout(schema.TimeoutUpdate))
if err != nil {
return err
}
}
if d.HasChange("provisioned_iops") {
obj := make(map[string]interface{})
provisionedIopsProp, err := expandComputeDiskProvisionedIops(d.Get("provisioned_iops"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("provisioned_iops"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, provisionedIopsProp)) {
obj["provisionedIops"] = provisionedIopsProp
}
obj, err = resourceComputeDiskUpdateEncoder(d, meta, obj)
if err != nil {
return err
}
url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/disks/{{name}}?paths=provisionedIops")
if err != nil {
return err
}
headers := make(http.Header)
// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "PATCH",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
Body: obj,
Timeout: d.Timeout(schema.TimeoutUpdate),
Headers: headers,
})
if err != nil {
return fmt.Errorf("Error updating Disk %q: %s", d.Id(), err)
} else {
log.Printf("[DEBUG] Finished updating Disk %q: %#v", d.Id(), res)
}
err = ComputeOperationWaitTime(
config, res, project, "Updating Disk", userAgent,
d.Timeout(schema.TimeoutUpdate))
if err != nil {
return err
}
}
if d.HasChange("provisioned_throughput") {
obj := make(map[string]interface{})
provisionedThroughputProp, err := expandComputeDiskProvisionedThroughput(d.Get("provisioned_throughput"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("provisioned_throughput"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, provisionedThroughputProp)) {
obj["provisionedThroughput"] = provisionedThroughputProp
}
obj, err = resourceComputeDiskUpdateEncoder(d, meta, obj)
if err != nil {
return err
}
url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/disks/{{name}}?paths=provisionedThroughput")
if err != nil {
return err
}
headers := make(http.Header)
// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "PATCH",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
Body: obj,
Timeout: d.Timeout(schema.TimeoutUpdate),
Headers: headers,
})
if err != nil {
return fmt.Errorf("Error updating Disk %q: %s", d.Id(), err)
} else {
log.Printf("[DEBUG] Finished updating Disk %q: %#v", d.Id(), res)
}
err = ComputeOperationWaitTime(
config, res, project, "Updating Disk", userAgent,
d.Timeout(schema.TimeoutUpdate))
if err != nil {
return err
}
}
if d.HasChange("access_mode") {
obj := make(map[string]interface{})
accessModeProp, err := expandComputeDiskAccessMode(d.Get("access_mode"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("access_mode"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, accessModeProp)) {
obj["accessMode"] = accessModeProp
}
obj, err = resourceComputeDiskUpdateEncoder(d, meta, obj)
if err != nil {
return err
}
url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/disks/{{name}}?paths=accessMode")
if err != nil {
return err
}
headers := make(http.Header)
// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "PATCH",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
Body: obj,
Timeout: d.Timeout(schema.TimeoutUpdate),
Headers: headers,
})
if err != nil {
return fmt.Errorf("Error updating Disk %q: %s", d.Id(), err)
} else {
log.Printf("[DEBUG] Finished updating Disk %q: %#v", d.Id(), res)
}
err = ComputeOperationWaitTime(
config, res, project, "Updating Disk", userAgent,
d.Timeout(schema.TimeoutUpdate))
if err != nil {
return err
}
}
d.Partial(false)
return resourceComputeDiskRead(d, meta)
}
func resourceComputeDiskDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return err
}
billingProject := ""
project, err := tpgresource.GetProject(d, config)
if err != nil {
return fmt.Errorf("Error fetching project for Disk: %s", err)
}
billingProject = project
url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/disks/{{name}}")
if err != nil {
return err
}
var obj map[string]interface{}
// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}
headers := make(http.Header)
readRes, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "GET",
Project: project,
RawURL: url,
UserAgent: userAgent,
})
if err != nil {
return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("ComputeDisk %q", d.Id()))
}
// if disks are attached to instances, they must be detached before the disk can be deleted
if v, ok := readRes["users"].([]interface{}); ok {
type detachArgs struct{ project, zone, instance, deviceName string }
var detachCalls []detachArgs
for _, instance := range tpgresource.ConvertStringArr(v) {
self := d.Get("self_link").(string)
instanceProject, instanceZone, instanceName, err := tpgresource.GetLocationalResourcePropertiesFromSelfLinkString(instance)
if err != nil {
return err
}
i, err := config.NewComputeClient(userAgent).Instances.Get(instanceProject, instanceZone, instanceName).Do()
if err != nil {
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
log.Printf("[WARN] instance %q not found, not bothering to detach disks", instance)
continue
}
return fmt.Errorf("Error retrieving instance %s: %s", instance, err.Error())
}
for _, disk := range i.Disks {
if tpgresource.CompareSelfLinkOrResourceName("", disk.Source, self, nil) {
detachCalls = append(detachCalls, detachArgs{
project: instanceProject,
zone: tpgresource.GetResourceNameFromSelfLink(i.Zone),
instance: i.Name,
deviceName: disk.DeviceName,
})
}
}
}
for _, call := range detachCalls {
op, err := config.NewComputeClient(userAgent).Instances.DetachDisk(call.project, call.zone, call.instance, call.deviceName).Do()
if err != nil {
return fmt.Errorf("Error detaching disk %s from instance %s/%s/%s: %s", call.deviceName, call.project,
call.zone, call.instance, err.Error())
}
err = ComputeOperationWaitTime(config, op, call.project,
fmt.Sprintf("Detaching disk from %s/%s/%s", call.project, call.zone, call.instance), userAgent, d.Timeout(schema.TimeoutDelete))
if err != nil {
var opErr ComputeOperationError
if errors.As(err, &opErr) && len(opErr.Errors) == 1 && opErr.Errors[0].Code == "RESOURCE_NOT_FOUND" {
log.Printf("[WARN] instance %q was deleted while awaiting detach", call.instance)
continue
}
return err
}
}
}
log.Printf("[DEBUG] Deleting Disk %q", d.Id())
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "DELETE",
Project: billingProject,
RawURL: url,
UserAgent: userAgent,
Body: obj,
Timeout: d.Timeout(schema.TimeoutDelete),
Headers: headers,
})
if err != nil {
return transport_tpg.HandleNotFoundError(err, d, "Disk")
}
err = ComputeOperationWaitTime(
config, res, project, "Deleting Disk", userAgent,
d.Timeout(schema.TimeoutDelete))
if err != nil {
return err
}
log.Printf("[DEBUG] Finished deleting Disk %q: %#v", d.Id(), res)
return nil
}
func resourceComputeDiskImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*transport_tpg.Config)
if err := tpgresource.ParseImportId([]string{
"^projects/(?P<project>[^/]+)/zones/(?P<zone>[^/]+)/disks/(?P<name>[^/]+)$",
"^(?P<project>[^/]+)/(?P<zone>[^/]+)/(?P<name>[^/]+)$",
"^(?P<zone>[^/]+)/(?P<name>[^/]+)$",
"^(?P<name>[^/]+)$",
}, d, config); err != nil {
return nil, err
}
// Replace import id for the resource id
id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/zones/{{zone}}/disks/{{name}}")
if err != nil {
return nil, fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
return []*schema.ResourceData{d}, nil
}
func flattenComputeDiskLabelFingerprint(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskCreationTimestamp(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskLastAttachTimestamp(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskLastDetachTimestamp(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
transformed := make(map[string]interface{})
if l, ok := d.GetOkExists("labels"); ok {
for k := range l.(map[string]interface{}) {
transformed[k] = v.(map[string]interface{})[k]
}
}
return transformed
}
func flattenComputeDiskName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskSize(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
// Handles the string fixed64 format
if strVal, ok := v.(string); ok {
if intVal, err := tpgresource.StringToFixed64(strVal); err == nil {
return intVal
}
}
// number values are represented as float64
if floatVal, ok := v.(float64); ok {
intVal := int(floatVal)
return intVal
}
return v // let terraform core handle it otherwise
}
func flattenComputeDiskUsers(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
return tpgresource.ConvertAndMapStringArr(v.([]interface{}), tpgresource.ConvertSelfLinkToV1)
}
func flattenComputeDiskPhysicalBlockSizeBytes(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
// Handles the string fixed64 format
if strVal, ok := v.(string); ok {
if intVal, err := tpgresource.StringToFixed64(strVal); err == nil {
return intVal
}
}
// number values are represented as float64
if floatVal, ok := v.(float64); ok {
intVal := int(floatVal)
return intVal
}
return v // let terraform core handle it otherwise
}
func flattenComputeDiskSourceDisk(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskSourceDiskId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskDiskId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
return tpgresource.NameFromSelfLinkStateFunc(v)
}
func flattenComputeDiskImage(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskResourcePolicies(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
return tpgresource.ConvertAndMapStringArr(v.([]interface{}), tpgresource.ConvertSelfLinkToV1)
}
func flattenComputeDiskEnableConfidentialCompute(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskMultiWriter(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskProvisionedIops(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
// Handles the string fixed64 format
if strVal, ok := v.(string); ok {
if intVal, err := tpgresource.StringToFixed64(strVal); err == nil {
return intVal
}
}
// number values are represented as float64
if floatVal, ok := v.(float64); ok {
intVal := int(floatVal)
return intVal
}
return v // let terraform core handle it otherwise
}
func flattenComputeDiskProvisionedThroughput(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
// Handles the string fixed64 format
if strVal, ok := v.(string); ok {
if intVal, err := tpgresource.StringToFixed64(strVal); err == nil {
return intVal
}
}
// number values are represented as float64
if floatVal, ok := v.(float64); ok {
intVal := int(floatVal)
return intVal
}
return v // let terraform core handle it otherwise
}
func flattenComputeDiskAsyncPrimaryDisk(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["disk"] =
flattenComputeDiskAsyncPrimaryDiskDisk(original["disk"], d, config)
return []interface{}{transformed}
}
func flattenComputeDiskAsyncPrimaryDiskDisk(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskGuestOsFeatures(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
l := v.([]interface{})
transformed := schema.NewSet(schema.HashResource(computeDiskGuestOsFeaturesSchema()), []interface{}{})
for _, raw := range l {
original := raw.(map[string]interface{})
if len(original) < 1 {
// Do not include empty json objects coming back from the api
continue
}
transformed.Add(map[string]interface{}{
"type": flattenComputeDiskGuestOsFeaturesType(original["type"], d, config),
})
}
return transformed
}
func flattenComputeDiskGuestOsFeaturesType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskLicenses(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
return tpgresource.ConvertAndMapStringArr(v.([]interface{}), tpgresource.ConvertSelfLinkToV1)
}
func flattenComputeDiskStoragePool(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
return tpgresource.NameFromSelfLinkStateFunc(v)
}
func flattenComputeDiskAccessMode(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
transformed := make(map[string]interface{})
if l, ok := d.GetOkExists("terraform_labels"); ok {
for k := range l.(map[string]interface{}) {
transformed[k] = v.(map[string]interface{})[k]
}
}
return transformed
}
func flattenComputeDiskEffectiveLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskZone(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
return tpgresource.NameFromSelfLinkStateFunc(v)
}
func flattenComputeDiskSourceImageEncryptionKey(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["raw_key"] =
flattenComputeDiskSourceImageEncryptionKeyRawKey(original["rawKey"], d, config)
transformed["sha256"] =
flattenComputeDiskSourceImageEncryptionKeySha256(original["sha256"], d, config)
transformed["kms_key_self_link"] =
flattenComputeDiskSourceImageEncryptionKeyKmsKeySelfLink(original["kmsKeyName"], d, config)
transformed["kms_key_service_account"] =
flattenComputeDiskSourceImageEncryptionKeyKmsKeyServiceAccount(original["kmsKeyServiceAccount"], d, config)
return []interface{}{transformed}
}
func flattenComputeDiskSourceImageEncryptionKeyRawKey(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskSourceImageEncryptionKeySha256(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskSourceImageEncryptionKeyKmsKeySelfLink(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskSourceImageEncryptionKeyKmsKeyServiceAccount(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskSourceImageId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskDiskEncryptionKey(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["raw_key"] =
flattenComputeDiskDiskEncryptionKeyRawKey(original["rawKey"], d, config)
transformed["rsa_encrypted_key"] =
flattenComputeDiskDiskEncryptionKeyRsaEncryptedKey(original["rsaEncryptedKey"], d, config)
transformed["sha256"] =
flattenComputeDiskDiskEncryptionKeySha256(original["sha256"], d, config)
transformed["kms_key_self_link"] =
flattenComputeDiskDiskEncryptionKeyKmsKeySelfLink(original["kmsKeyName"], d, config)
transformed["kms_key_service_account"] =
flattenComputeDiskDiskEncryptionKeyKmsKeyServiceAccount(original["kmsKeyServiceAccount"], d, config)
return []interface{}{transformed}
}
func flattenComputeDiskDiskEncryptionKeyRawKey(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskDiskEncryptionKeyRsaEncryptedKey(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskDiskEncryptionKeySha256(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskDiskEncryptionKeyKmsKeySelfLink(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskDiskEncryptionKeyKmsKeyServiceAccount(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskSnapshot(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
return tpgresource.ConvertSelfLinkToV1(v.(string))
}
func flattenComputeDiskSourceSnapshotEncryptionKey(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["raw_key"] =
flattenComputeDiskSourceSnapshotEncryptionKeyRawKey(original["rawKey"], d, config)
transformed["kms_key_self_link"] =
flattenComputeDiskSourceSnapshotEncryptionKeyKmsKeySelfLink(original["kmsKeyName"], d, config)
transformed["sha256"] =
flattenComputeDiskSourceSnapshotEncryptionKeySha256(original["sha256"], d, config)
transformed["kms_key_service_account"] =
flattenComputeDiskSourceSnapshotEncryptionKeyKmsKeyServiceAccount(original["kmsKeyServiceAccount"], d, config)
return []interface{}{transformed}
}
func flattenComputeDiskSourceSnapshotEncryptionKeyRawKey(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskSourceSnapshotEncryptionKeyKmsKeySelfLink(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskSourceSnapshotEncryptionKeySha256(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskSourceSnapshotEncryptionKeyKmsKeyServiceAccount(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func flattenComputeDiskSourceSnapshotId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
func expandComputeDiskLabelFingerprint(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskDescription(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskSize(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskPhysicalBlockSizeBytes(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskSourceDisk(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
f, err := tpgresource.ParseZonalFieldValue("diskTypes", v.(string), "project", "zone", d, config, true)
if err != nil {
return nil, fmt.Errorf("Invalid value for type: %s", err)
}
return f.RelativeLink(), nil
}
func expandComputeDiskImage(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskResourcePolicies(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
req := make([]interface{}, 0, len(l))
for _, raw := range l {
if raw == nil {
return nil, fmt.Errorf("Invalid value for resource_policies: nil")
}
f, err := tpgresource.ParseRegionalFieldValue("resourcePolicies", raw.(string), "project", "region", "zone", d, config, true)
if err != nil {
return nil, fmt.Errorf("Invalid value for resource_policies: %s", err)
}
req = append(req, f.RelativeLink())
}
return req, nil
}
func expandComputeDiskEnableConfidentialCompute(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskMultiWriter(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskProvisionedIops(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskProvisionedThroughput(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskAsyncPrimaryDisk(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})
transformedDisk, err := expandComputeDiskAsyncPrimaryDiskDisk(original["disk"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedDisk); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["disk"] = transformedDisk
}
return transformed, nil
}
func expandComputeDiskAsyncPrimaryDiskDisk(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskGuestOsFeatures(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
v = v.(*schema.Set).List()
l := v.([]interface{})
req := make([]interface{}, 0, len(l))
for _, raw := range l {
if raw == nil {
continue
}
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})
transformedType, err := expandComputeDiskGuestOsFeaturesType(original["type"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedType); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["type"] = transformedType
}
req = append(req, transformed)
}
return req, nil
}
func expandComputeDiskGuestOsFeaturesType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskLicenses(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
req := make([]interface{}, 0, len(l))
for _, raw := range l {
if raw == nil {
return nil, fmt.Errorf("Invalid value for licenses: nil")
}
f, err := tpgresource.ParseGlobalFieldValue("licenses", raw.(string), "project", d, config, true)
if err != nil {
return nil, fmt.Errorf("Invalid value for licenses: %s", err)
}
req = append(req, f.RelativeLink())
}
return req, nil
}
func expandComputeDiskStoragePool(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskAccessMode(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
if v == nil {
return map[string]string{}, nil
}
m := make(map[string]string)
for k, val := range v.(map[string]interface{}) {
m[k] = val.(string)
}
return m, nil
}
func expandComputeDiskZone(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
f, err := tpgresource.ParseGlobalFieldValue("zones", v.(string), "project", d, config, true)
if err != nil {
return nil, fmt.Errorf("Invalid value for zone: %s", err)
}
return f.RelativeLink(), nil
}
func expandComputeDiskSourceImageEncryptionKey(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})
transformedRawKey, err := expandComputeDiskSourceImageEncryptionKeyRawKey(original["raw_key"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedRawKey); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["rawKey"] = transformedRawKey
}
transformedSha256, err := expandComputeDiskSourceImageEncryptionKeySha256(original["sha256"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedSha256); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["sha256"] = transformedSha256
}
transformedKmsKeySelfLink, err := expandComputeDiskSourceImageEncryptionKeyKmsKeySelfLink(original["kms_key_self_link"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedKmsKeySelfLink); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["kmsKeyName"] = transformedKmsKeySelfLink
}
transformedKmsKeyServiceAccount, err := expandComputeDiskSourceImageEncryptionKeyKmsKeyServiceAccount(original["kms_key_service_account"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedKmsKeyServiceAccount); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["kmsKeyServiceAccount"] = transformedKmsKeyServiceAccount
}
return transformed, nil
}
func expandComputeDiskSourceImageEncryptionKeyRawKey(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskSourceImageEncryptionKeySha256(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskSourceImageEncryptionKeyKmsKeySelfLink(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskSourceImageEncryptionKeyKmsKeyServiceAccount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskDiskEncryptionKey(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})
transformedRawKey, err := expandComputeDiskDiskEncryptionKeyRawKey(original["raw_key"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedRawKey); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["rawKey"] = transformedRawKey
}
transformedRsaEncryptedKey, err := expandComputeDiskDiskEncryptionKeyRsaEncryptedKey(original["rsa_encrypted_key"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedRsaEncryptedKey); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["rsaEncryptedKey"] = transformedRsaEncryptedKey
}
transformedSha256, err := expandComputeDiskDiskEncryptionKeySha256(original["sha256"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedSha256); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["sha256"] = transformedSha256
}
transformedKmsKeySelfLink, err := expandComputeDiskDiskEncryptionKeyKmsKeySelfLink(original["kms_key_self_link"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedKmsKeySelfLink); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["kmsKeyName"] = transformedKmsKeySelfLink
}
transformedKmsKeyServiceAccount, err := expandComputeDiskDiskEncryptionKeyKmsKeyServiceAccount(original["kms_key_service_account"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedKmsKeyServiceAccount); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["kmsKeyServiceAccount"] = transformedKmsKeyServiceAccount
}
return transformed, nil
}
func expandComputeDiskDiskEncryptionKeyRawKey(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskDiskEncryptionKeyRsaEncryptedKey(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskDiskEncryptionKeySha256(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskDiskEncryptionKeyKmsKeySelfLink(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskDiskEncryptionKeyKmsKeyServiceAccount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskSnapshot(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
f, err := tpgresource.ParseGlobalFieldValue("snapshots", v.(string), "project", d, config, true)
if err != nil {
return nil, fmt.Errorf("Invalid value for snapshot: %s", err)
}
return f.RelativeLink(), nil
}
func expandComputeDiskSourceSnapshotEncryptionKey(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})
transformedRawKey, err := expandComputeDiskSourceSnapshotEncryptionKeyRawKey(original["raw_key"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedRawKey); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["rawKey"] = transformedRawKey
}
transformedKmsKeySelfLink, err := expandComputeDiskSourceSnapshotEncryptionKeyKmsKeySelfLink(original["kms_key_self_link"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedKmsKeySelfLink); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["kmsKeyName"] = transformedKmsKeySelfLink
}
transformedSha256, err := expandComputeDiskSourceSnapshotEncryptionKeySha256(original["sha256"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedSha256); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["sha256"] = transformedSha256
}
transformedKmsKeyServiceAccount, err := expandComputeDiskSourceSnapshotEncryptionKeyKmsKeyServiceAccount(original["kms_key_service_account"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedKmsKeyServiceAccount); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["kmsKeyServiceAccount"] = transformedKmsKeyServiceAccount
}
return transformed, nil
}
func expandComputeDiskSourceSnapshotEncryptionKeyRawKey(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskSourceSnapshotEncryptionKeyKmsKeySelfLink(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskSourceSnapshotEncryptionKeySha256(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func expandComputeDiskSourceSnapshotEncryptionKeyKmsKeyServiceAccount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
func resourceComputeDiskEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) {
config := meta.(*transport_tpg.Config)
project, err := tpgresource.GetProject(d, config)
if err != nil {
return nil, err
}
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return nil, err
}
if v, ok := d.GetOk("type"); ok {
log.Printf("[DEBUG] Loading disk type: %s", v.(string))
diskType, err := readDiskType(config, d, v.(string))
if err != nil {
return nil, fmt.Errorf(
"Error loading disk type '%s': %s",
v.(string), err)
}
obj["type"] = diskType.RelativeLink()
}
if v, ok := d.GetOk("image"); ok {
log.Printf("[DEBUG] Resolving image name: %s", v.(string))
imageUrl, err := ResolveImage(config, project, v.(string), userAgent)
if err != nil {
return nil, fmt.Errorf(
"Error resolving image name '%s': %s",
v.(string), err)
}
obj["sourceImage"] = imageUrl
log.Printf("[DEBUG] Image name resolved to: %s", imageUrl)
}
return obj, nil
}
func resourceComputeDiskUpdateEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) {
if (d.HasChange("provisioned_iops") && strings.Contains(d.Get("type").(string), "hyperdisk")) || (d.HasChange("provisioned_throughput") && strings.Contains(d.Get("type").(string), "hyperdisk")) || (d.HasChange("access_mode") && strings.Contains(d.Get("type").(string), "hyperdisk")) {
nameProp := d.Get("name")
if v, ok := d.GetOkExists("name"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, nameProp)) {
obj["name"] = nameProp
}
}
return obj, nil
}
func resourceComputeDiskDecoder(d *schema.ResourceData, meta interface{}, res map[string]interface{}) (map[string]interface{}, error) {
if v, ok := res["diskEncryptionKey"]; ok {
original := v.(map[string]interface{})
transformed := make(map[string]interface{})
// The raw key won't be returned, so we need to use the original.
transformed["rawKey"] = d.Get("disk_encryption_key.0.raw_key")
transformed["rsaEncryptedKey"] = d.Get("disk_encryption_key.0.rsa_encrypted_key")
transformed["sha256"] = original["sha256"]
if kmsKeyName, ok := original["kmsKeyName"]; ok {
// The response for crypto keys often includes the version of the key which needs to be removed
// format: projects/<project>/locations/<region>/keyRings/<keyring>/cryptoKeys/<key>/cryptoKeyVersions/1
transformed["kmsKeyName"] = strings.Split(kmsKeyName.(string), "/cryptoKeyVersions")[0]
}
if kmsKeyServiceAccount, ok := original["kmsKeyServiceAccount"]; ok {
transformed["kmsKeyServiceAccount"] = kmsKeyServiceAccount
}
res["diskEncryptionKey"] = transformed
}
if v, ok := res["sourceImageEncryptionKey"]; ok {
original := v.(map[string]interface{})
transformed := make(map[string]interface{})
// The raw key won't be returned, so we need to use the original.
transformed["rawKey"] = d.Get("source_image_encryption_key.0.raw_key")
transformed["sha256"] = original["sha256"]
if kmsKeyName, ok := original["kmsKeyName"]; ok {
// The response for crypto keys often includes the version of the key which needs to be removed
// format: projects/<project>/locations/<region>/keyRings/<keyring>/cryptoKeys/<key>/cryptoKeyVersions/1
transformed["kmsKeyName"] = strings.Split(kmsKeyName.(string), "/cryptoKeyVersions")[0]
}
if kmsKeyServiceAccount, ok := original["kmsKeyServiceAccount"]; ok {
transformed["kmsKeyServiceAccount"] = kmsKeyServiceAccount
}
res["sourceImageEncryptionKey"] = transformed
}
if v, ok := res["sourceSnapshotEncryptionKey"]; ok {
original := v.(map[string]interface{})
transformed := make(map[string]interface{})
// The raw key won't be returned, so we need to use the original.
transformed["rawKey"] = d.Get("source_snapshot_encryption_key.0.raw_key")
transformed["sha256"] = original["sha256"]
if kmsKeyName, ok := original["kmsKeyName"]; ok {
// The response for crypto keys often includes the version of the key which needs to be removed
// format: projects/<project>/locations/<region>/keyRings/<keyring>/cryptoKeys/<key>/cryptoKeyVersions/1
transformed["kmsKeyName"] = strings.Split(kmsKeyName.(string), "/cryptoKeyVersions")[0]
}
if kmsKeyServiceAccount, ok := original["kmsKeyServiceAccount"]; ok {
transformed["kmsKeyServiceAccount"] = kmsKeyServiceAccount
}
res["sourceSnapshotEncryptionKey"] = transformed
}
return res, nil
}