vsphere/internal/virtualdevice/virtual_machine_disk_subresource.go
func diskApplyOperationCreateUpdate(
	index int,
	newData map[string]interface{},
	oldDataSet []interface{},
	c *govmomi.Client,
	d *schema.ResourceData,
	l *object.VirtualDeviceList,
	spec *[]types.BaseVirtualDeviceConfigSpec,
	updates *[]interface{},
) error {
	var name string
	var err error
	if name, err = diskLabelOrName(newData); err != nil {
		return err
	}
	if name == diskDeletedName || name == diskDetachedName {
		// This is a "dummy" deleted resource and should be skipped over
		return nil
	}
	for _, oe := range oldDataSet {
		oldData := oe.(map[string]interface{})
		if newData["uuid"] == oldData["uuid"] {
			// This is an update
			r := NewDiskSubresource(c, d, newData, oldData, index)
			// If the only thing changing here is the datastore, or keep_on_remove,
			// this is a no-op as far as a device change is concerned. Datastore
			// changes are handled during storage vMotion later on during the
			// update phase. keep_on_remove is a Terraform-only attribute and only
			// needs to be committed to state.
			omc, err := copystructure.Copy(oldData)
			if err != nil {
				return fmt.Errorf("%s: error generating copy of old disk data: %s", r.Addr(), err)
			}
			oldCopy := omc.(map[string]interface{})
			oldCopy["datastore_id"] = newData["datastore_id"]
			oldCopy["keep_on_remove"] = newData["keep_on_remove"]
			// TODO: Remove these in 2.0, when all attributes should bear a label and
			// name is gone, and we won't need to exempt transitions.
			oldCopy["label"] = newData["label"]
			oldCopy["name"] = newData["name"]
			if reflect.DeepEqual(oldCopy, newData) {
				*updates = append(*updates, r.Data())
				return nil
			}
			uspec, err := r.Update(*l)
			if err != nil {
				return fmt.Errorf("%s: %s", r.Addr(), err)
			}
			*l = applyDeviceChange(*l, uspec)
			*spec = append(*spec, uspec...)
			*updates = append(*updates, r.Data())
			return nil
		}
	}
	// New data was not found - this is a create operation
	r := NewDiskSubresource(c, d, newData, nil, index)
	cspec, err := r.Create(*l)
	if err != nil {
		return fmt.Errorf("%s: %s", r.Addr(), err)
	}
	*l = applyDeviceChange(*l, cspec)
	*spec = append(*spec, cspec...)
	*updates = append(*updates, r.Data())
	return nil
}
func diskApplyOperationCreateUpdate(
	index int,
	newData map[string]interface{},
	oldDataSet []interface{},
	c *govmomi.Client,
	d *schema.ResourceData,
	l *object.VirtualDeviceList,
	spec *[]types.BaseVirtualDeviceConfigSpec,
	updates *[]interface{},
) error {
	var name string
	var err error
	if name, err = diskLabelOrName(newData); err != nil {
		return err
	}
	if name == diskDeletedName || name == diskDetachedName {
		// This is a "dummy" deleted resource and should be skipped over
		return nil
	}
	for _, oe := range oldDataSet {
		oldData := oe.(map[string]interface{})
		if newData["uuid"] == oldData["uuid"] {
			// This is an update
			r := NewDiskSubresource(c, d, newData, oldData, index)
			// If the only thing changing here is the datastore, or keep_on_remove,
			// this is a no-op as far as a device change is concerned. Datastore
			// changes are handled during storage vMotion later on during the
			// update phase. keep_on_remove is a Terraform-only attribute and only
			// needs to be committed to state.
			omc, err := copystructure.Copy(oldData)
			if err != nil {
				return fmt.Errorf("%s: error generating copy of old disk data: %s", r.Addr(), err)
			}
			oldCopy := omc.(map[string]interface{})
			oldCopy["datastore_id"] = newData["datastore_id"]
			oldCopy["keep_on_remove"] = newData["keep_on_remove"]
			// TODO: Remove these in 2.0, when all attributes should bear a label and
			// name is gone, and we won't need to exempt transitions.
			oldCopy["label"] = newData["label"]
			oldCopy["name"] = newData["name"]
			if reflect.DeepEqual(oldCopy, newData) {
				*updates = append(*updates, r.Data())
				return nil
			}
			uspec, err := r.Update(*l)
			if err != nil {
				return fmt.Errorf("%s: %s", r.Addr(), err)
			}
			*l = applyDeviceChange(*l, uspec)
			*spec = append(*spec, uspec...)
			*updates = append(*updates, r.Data())
			return nil
		}
	}
	// New data was not found - this is a create operation
	r := NewDiskSubresource(c, d, newData, nil, index)
	cspec, err := r.Create(*l)
	if err != nil {
		return fmt.Errorf("%s: %s", r.Addr(), err)
	}
	*l = applyDeviceChange(*l, cspec)
	*spec = append(*spec, cspec...)
	*updates = append(*updates, r.Data())
	return nil
}
// diskApplyOperationCreateUpdate is an inner-loop helper for disk creation and
// update operations.