Revert "remove switch statements between api versions for compute"

This reverts commit bf1b3a24e8c1cac832e74d9d0e145c7010a4c2f1.
This commit is contained in:
Paddy Carver 2018-05-04 07:51:45 -07:00
parent d59fcbbc59
commit aa2626b490
13 changed files with 1021 additions and 151 deletions

254
google/api_versions.go Normal file
View File

@ -0,0 +1,254 @@
package google
import (
"encoding/json"
"fmt"
"reflect"
"strings"
)
type ApiVersion uint8
const (
v1 ApiVersion = iota
v0beta
v1beta1
)
var OrderedComputeApiVersions = []ApiVersion{
v0beta,
v1,
}
var OrderedContainerApiVersions = []ApiVersion{
v1beta1,
v1,
}
// Convert between two types by converting to/from JSON. Intended to switch
// between multiple API versions, as they are strict supersets of one another.
// item and out are pointers to structs
func Convert(item, out interface{}) error {
bytes, err := json.Marshal(item)
if err != nil {
return err
}
err = json.Unmarshal(bytes, out)
if err != nil {
return err
}
// Converting between maps and structs only occurs when autogenerated resources convert the result
// of an HTTP request. Those results do not contain omitted fields, so no need to set them.
if _, ok := item.(map[string]interface{}); !ok {
setOmittedFields(item, out)
}
return nil
}
func setOmittedFields(item, out interface{}) {
// Both inputs must be pointers, see https://blog.golang.org/laws-of-reflection:
// "To modify a reflection object, the value must be settable."
iVal := reflect.ValueOf(item).Elem()
oVal := reflect.ValueOf(out).Elem()
// Loop through all the fields of the struct to look for omitted fields and nested fields
for i := 0; i < iVal.NumField(); i++ {
iField := iVal.Field(i)
if isEmptyValue(iField) {
continue
}
fieldInfo := iVal.Type().Field(i)
oField := oVal.FieldByName(fieldInfo.Name)
// Only look at fields that exist in the output struct
if !oField.IsValid() {
continue
}
// If the field contains a 'json:"="' tag, then it was omitted from the Marshal/Unmarshal
// call and needs to be added back in.
if fieldInfo.Tag.Get("json") == "-" {
oField.Set(iField)
}
// If this field is a struct, *struct, []struct, or []*struct, recurse.
if iField.Kind() == reflect.Struct {
setOmittedFields(iField.Addr().Interface(), oField.Addr().Interface())
}
if iField.Kind() == reflect.Ptr && iField.Type().Elem().Kind() == reflect.Struct {
setOmittedFields(iField.Interface(), oField.Interface())
}
if iField.Kind() == reflect.Slice && iField.Type().Elem().Kind() == reflect.Struct {
for j := 0; j < iField.Len(); j++ {
setOmittedFields(iField.Index(j).Addr().Interface(), oField.Index(j).Addr().Interface())
}
}
if iField.Kind() == reflect.Slice && iField.Type().Elem().Kind() == reflect.Ptr &&
iField.Type().Elem().Elem().Kind() == reflect.Struct {
for j := 0; j < iField.Len(); j++ {
setOmittedFields(iField.Index(j).Interface(), oField.Index(j).Interface())
}
}
}
}
type TerraformResourceData interface {
HasChange(string) bool
GetOk(string) (interface{}, bool)
Set(string, interface{}) error
SetId(string)
Id() string
}
// Compare the fields set in schema against a list of features and their versions to determine
// what version of the API is required in order to manage the resource.
func getApiVersion(d TerraformResourceData, resourceVersion ApiVersion, features []Feature, maxVersionFunc func(map[ApiVersion]struct{}) ApiVersion) ApiVersion {
versions := map[ApiVersion]struct{}{resourceVersion: struct{}{}}
for _, feature := range features {
if feature.InUseByDefault(d) {
versions[feature.Version] = struct{}{}
}
}
return maxVersionFunc(versions)
}
func getComputeApiVersion(d TerraformResourceData, resourceVersion ApiVersion, features []Feature) ApiVersion {
return getApiVersion(d, resourceVersion, features, maxComputeVersion)
}
func getContainerApiVersion(d TerraformResourceData, resourceVersion ApiVersion, features []Feature) ApiVersion {
return getApiVersion(d, resourceVersion, features, maxContainerVersion)
}
// Compare the fields set in schema against a list of features and their version, and a
// list of features that exist at the base resource version that can only be update at some other
// version, to determine what version of the API is required in order to update the resource.
func getApiVersionUpdate(d TerraformResourceData, resourceVersion ApiVersion, features, updateOnlyFields []Feature, maxVersionFunc func(map[ApiVersion]struct{}) ApiVersion) ApiVersion {
versions := map[ApiVersion]struct{}{resourceVersion: struct{}{}}
for _, feature := range features {
if feature.InUseByUpdate(d) {
versions[feature.Version] = struct{}{}
}
}
for _, feature := range updateOnlyFields {
if feature.HasChangeBy(d) {
versions[feature.Version] = struct{}{}
}
}
return maxVersionFunc(versions)
}
func getComputeApiVersionUpdate(d TerraformResourceData, resourceVersion ApiVersion, features, updateOnlyFields []Feature) ApiVersion {
return getApiVersionUpdate(d, resourceVersion, features, updateOnlyFields, maxComputeVersion)
}
func getContainerApiVersionUpdate(d TerraformResourceData, resourceVersion ApiVersion, features, updateOnlyFields []Feature) ApiVersion {
return getApiVersionUpdate(d, resourceVersion, features, updateOnlyFields, maxContainerVersion)
}
// A field of a resource and the version of the Compute API required to use it.
type Feature struct {
Version ApiVersion
// Path to the beta field.
//
// The feature is considered to be in-use if the field referenced by "Item" is set in the state.
// The path can reference:
// - a beta field at the top-level (e.g. "min_cpu_platform").
// - a beta field nested inside a list (e.g. "network_interface.*.alias_ip_range" is considered to be
// in-use if the "alias_ip_range" field is set in the state for any of the network interfaces).
//
// Note: beta field nested inside a SET are NOT supported at the moment.
Item string
// Optional, only set if your field has a default value.
// If the value for the field is equal to the DefaultValue, we assume the beta feature is not activated.
DefaultValue interface{}
}
// Returns true when a feature has been modified.
// This is most important when updating a resource to remove versioned feature usage; if the
// resource is reverting to its base version, it needs to perform a final update at the higher
// version in order to remove high version features.
func (s Feature) HasChangeBy(d TerraformResourceData) bool {
return d.HasChange(s.Item)
}
type InUseFunc func(d TerraformResourceData, path string, defaultValue interface{}) bool
func defaultInUseFunc(d TerraformResourceData, path string, defaultValue interface{}) bool {
// At read and delete time, there is no change.
// At create time, all fields are marked has changed. We should only consider the feature active if the field has
// a value set and that this value is not the default value.
value, ok := d.GetOk(path)
return ok && value != defaultValue
}
func updateInUseFunc(d TerraformResourceData, path string, defaultValue interface{}) bool {
// During a resource update, if the beta field has changes, the feature is considered active even if the new value
// is the default value. This is because the beta API must be called to change the value of the field back to the
// default value.
value, ok := d.GetOk(path)
return (ok && value != defaultValue) || d.HasChange(path)
}
// Return true when a feature appears in schema and doesn't hold the default value.
func (s Feature) InUseByDefault(d TerraformResourceData) bool {
return inUseBy(d, s.Item, s.DefaultValue, defaultInUseFunc)
}
func (s Feature) InUseByUpdate(d TerraformResourceData) bool {
return inUseBy(d, s.Item, s.DefaultValue, updateInUseFunc)
}
func inUseBy(d TerraformResourceData, path string, defaultValue interface{}, inUseFunc InUseFunc) bool {
pos := strings.Index(path, "*")
if pos == -1 {
return inUseFunc(d, path, defaultValue)
}
prefix := path[0:pos]
suffix := path[pos+1:]
v, ok := d.GetOk(prefix + "#")
if !ok {
return false
}
count := v.(int)
for i := 0; i < count; i++ {
nestedPath := fmt.Sprintf("%s%d%s", prefix, i, suffix)
if inUseBy(d, nestedPath, defaultValue, inUseFunc) {
return true
}
}
return false
}
func maxVersion(versionsInUse map[ApiVersion]struct{}, orderedVersions []ApiVersion) ApiVersion {
for _, version := range orderedVersions {
if _, ok := versionsInUse[version]; ok {
return version
}
}
// Fallback to the final, most stable version
return orderedVersions[len(orderedVersions)-1]
}
func maxComputeVersion(versionsInUse map[ApiVersion]struct{}) ApiVersion {
return maxVersion(versionsInUse, OrderedComputeApiVersions)
}
func maxContainerVersion(versionsInUse map[ApiVersion]struct{}) ApiVersion {
return maxVersion(versionsInUse, OrderedContainerApiVersions)
}

View File

@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
computeBeta "google.golang.org/api/compute/v0.beta"
"google.golang.org/api/compute/v1" "google.golang.org/api/compute/v1"
) )
@ -124,7 +123,3 @@ func flattenSecondaryRanges(secondaryRanges []*compute.SubnetworkSecondaryRange)
func createSubnetID(s *compute.Subnetwork) string { func createSubnetID(s *compute.Subnetwork) string {
return fmt.Sprintf("%s/%s", s.Region, s.Name) return fmt.Sprintf("%s/%s", s.Region, s.Name)
} }
func createSubnetIDBeta(s *computeBeta.Subnetwork) string {
return fmt.Sprintf("%s/%s", s.Region, s.Name)
}

View File

@ -12,6 +12,9 @@ import (
compute "google.golang.org/api/compute/v1" compute "google.golang.org/api/compute/v1"
) )
var BackendServiceBaseApiVersion = v1
var BackendServiceVersionedFeatures = []Feature{Feature{Version: v0beta, Item: "security_policy"}}
func resourceComputeBackendService() *schema.Resource { func resourceComputeBackendService() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
Create: resourceComputeBackendServiceCreate, Create: resourceComputeBackendServiceCreate,
@ -285,6 +288,7 @@ func resourceComputeBackendServiceCreate(d *schema.ResourceData, meta interface{
} }
func resourceComputeBackendServiceRead(d *schema.ResourceData, meta interface{}) error { func resourceComputeBackendServiceRead(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, BackendServiceBaseApiVersion, BackendServiceVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -292,9 +296,25 @@ func resourceComputeBackendServiceRead(d *schema.ResourceData, meta interface{})
return err return err
} }
service, err := config.clientComputeBeta.BackendServices.Get(project, d.Id()).Do() service := &computeBeta.BackendService{}
if err != nil { switch computeApiVersion {
return handleNotFoundError(err, d, fmt.Sprintf("Backend Service %q", d.Get("name").(string))) case v1:
v1Service, err := config.clientCompute.BackendServices.Get(
project, d.Id()).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Backend Service %q", d.Get("name").(string)))
}
err = Convert(v1Service, service)
if err != nil {
return err
}
case v0beta:
var err error
service, err = config.clientComputeBeta.BackendServices.Get(
project, d.Id()).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Backend Service %q", d.Get("name").(string)))
}
} }
d.Set("name", service.Name) d.Set("name", service.Name)

View File

@ -10,8 +10,12 @@ import (
"github.com/hashicorp/terraform/helper/validation" "github.com/hashicorp/terraform/helper/validation"
computeBeta "google.golang.org/api/compute/v0.beta" computeBeta "google.golang.org/api/compute/v0.beta"
"google.golang.org/api/compute/v1"
) )
var FirewallBaseApiVersion = v1
var FirewallVersionedFeatures = []Feature{}
func resourceComputeFirewall() *schema.Resource { func resourceComputeFirewall() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
Create: resourceComputeFirewallCreate, Create: resourceComputeFirewallCreate,
@ -189,6 +193,7 @@ func resourceComputeFirewallRuleHash(v interface{}) int {
} }
func resourceComputeFirewallCreate(d *schema.ResourceData, meta interface{}) error { func resourceComputeFirewallCreate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, FirewallBaseApiVersion, FirewallVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -201,9 +206,30 @@ func resourceComputeFirewallCreate(d *schema.ResourceData, meta interface{}) err
return err return err
} }
op, err := config.clientComputeBeta.Firewalls.Insert(project, firewall).Do() var op interface{}
if err != nil { switch computeApiVersion {
return fmt.Errorf("Error creating firewall: %s", err) case v1:
firewallV1 := &compute.Firewall{}
err = Convert(firewall, firewallV1)
if err != nil {
return err
}
op, err = config.clientCompute.Firewalls.Insert(project, firewallV1).Do()
if err != nil {
return fmt.Errorf("Error creating firewall: %s", err)
}
case v0beta:
firewallV0Beta := &computeBeta.Firewall{}
err = Convert(firewall, firewallV0Beta)
if err != nil {
return err
}
op, err = config.clientComputeBeta.Firewalls.Insert(project, firewallV0Beta).Do()
if err != nil {
return fmt.Errorf("Error creating firewall: %s", err)
}
} }
// It probably maybe worked, so store the ID now // It probably maybe worked, so store the ID now
@ -242,6 +268,7 @@ func flattenFirewallDenied(denied []*computeBeta.FirewallDenied) []map[string]in
} }
func resourceComputeFirewallRead(d *schema.ResourceData, meta interface{}) error { func resourceComputeFirewallRead(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, FirewallBaseApiVersion, FirewallVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -249,9 +276,28 @@ func resourceComputeFirewallRead(d *schema.ResourceData, meta interface{}) error
return err return err
} }
firewall, err := config.clientComputeBeta.Firewalls.Get(project, d.Id()).Do() firewall := &computeBeta.Firewall{}
if err != nil { switch computeApiVersion {
return handleNotFoundError(err, d, fmt.Sprintf("Firewall %q", d.Get("name").(string))) case v1:
firewallV1, err := config.clientCompute.Firewalls.Get(project, d.Id()).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Firewall %q", d.Get("name").(string)))
}
err = Convert(firewallV1, firewall)
if err != nil {
return err
}
case v0beta:
firewallV0Beta, err := config.clientComputeBeta.Firewalls.Get(project, d.Id()).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Firewall %q", d.Get("name").(string)))
}
err = Convert(firewallV0Beta, firewall)
if err != nil {
return err
}
} }
d.Set("self_link", ConvertSelfLinkToV1(firewall.SelfLink)) d.Set("self_link", ConvertSelfLinkToV1(firewall.SelfLink))
@ -273,6 +319,7 @@ func resourceComputeFirewallRead(d *schema.ResourceData, meta interface{}) error
} }
func resourceComputeFirewallUpdate(d *schema.ResourceData, meta interface{}) error { func resourceComputeFirewallUpdate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersionUpdate(d, FirewallBaseApiVersion, FirewallVersionedFeatures, []Feature{})
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -287,9 +334,30 @@ func resourceComputeFirewallUpdate(d *schema.ResourceData, meta interface{}) err
return err return err
} }
op, err := config.clientComputeBeta.Firewalls.Update(project, d.Id(), firewall).Do() var op interface{}
if err != nil { switch computeApiVersion {
return fmt.Errorf("Error updating firewall: %s", err) case v1:
firewallV1 := &compute.Firewall{}
err = Convert(firewall, firewallV1)
if err != nil {
return err
}
op, err = config.clientCompute.Firewalls.Update(project, d.Id(), firewallV1).Do()
if err != nil {
return fmt.Errorf("Error updating firewall: %s", err)
}
case v0beta:
firewallV0Beta := &computeBeta.Firewall{}
err = Convert(firewall, firewallV0Beta)
if err != nil {
return err
}
op, err = config.clientComputeBeta.Firewalls.Update(project, d.Id(), firewallV0Beta).Do()
if err != nil {
return fmt.Errorf("Error updating firewall: %s", err)
}
} }
err = computeSharedOperationWait(config.clientCompute, op, project, "Updating Firewall") err = computeSharedOperationWait(config.clientCompute, op, project, "Updating Firewall")
@ -303,6 +371,7 @@ func resourceComputeFirewallUpdate(d *schema.ResourceData, meta interface{}) err
} }
func resourceComputeFirewallDelete(d *schema.ResourceData, meta interface{}) error { func resourceComputeFirewallDelete(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, FirewallBaseApiVersion, FirewallVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -311,9 +380,18 @@ func resourceComputeFirewallDelete(d *schema.ResourceData, meta interface{}) err
} }
// Delete the firewall // Delete the firewall
op, err := config.clientComputeBeta.Firewalls.Delete(project, d.Id()).Do() var op interface{}
if err != nil { switch computeApiVersion {
return fmt.Errorf("Error deleting firewall: %s", err) case v1:
op, err = config.clientCompute.Firewalls.Delete(project, d.Id()).Do()
if err != nil {
return fmt.Errorf("Error deleting firewall: %s", err)
}
case v0beta:
op, err = config.clientComputeBeta.Firewalls.Delete(project, d.Id()).Do()
if err != nil {
return fmt.Errorf("Error deleting firewall: %s", err)
}
} }
err = computeSharedOperationWait(config.clientCompute, op, project, "Deleting Firewall") err = computeSharedOperationWait(config.clientCompute, op, project, "Deleting Firewall")

View File

@ -8,9 +8,14 @@ import (
"github.com/hashicorp/terraform/helper/validation" "github.com/hashicorp/terraform/helper/validation"
computeBeta "google.golang.org/api/compute/v0.beta" computeBeta "google.golang.org/api/compute/v0.beta"
compute "google.golang.org/api/compute/v1" "google.golang.org/api/compute/v1"
) )
var GlobalForwardingRuleBaseApiVersion = v1
var GlobalForwardingRuleVersionedFeatures = []Feature{
{Version: v0beta, Item: "labels"},
}
func resourceComputeGlobalForwardingRule() *schema.Resource { func resourceComputeGlobalForwardingRule() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
Create: resourceComputeGlobalForwardingRuleCreate, Create: resourceComputeGlobalForwardingRuleCreate,
@ -104,6 +109,7 @@ func resourceComputeGlobalForwardingRule() *schema.Resource {
} }
func resourceComputeGlobalForwardingRuleCreate(d *schema.ResourceData, meta interface{}) error { func resourceComputeGlobalForwardingRuleCreate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, GlobalForwardingRuleBaseApiVersion, GlobalForwardingRuleVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -121,9 +127,30 @@ func resourceComputeGlobalForwardingRuleCreate(d *schema.ResourceData, meta inte
Target: d.Get("target").(string), Target: d.Get("target").(string),
} }
op, err := config.clientComputeBeta.GlobalForwardingRules.Insert(project, frule).Do() var op interface{}
if err != nil { switch computeApiVersion {
return fmt.Errorf("Error creating Global Forwarding Rule: %s", err) case v1:
v1Frule := &compute.ForwardingRule{}
err = Convert(frule, v1Frule)
if err != nil {
return err
}
op, err = config.clientCompute.GlobalForwardingRules.Insert(project, v1Frule).Do()
if err != nil {
return fmt.Errorf("Error creating Global Forwarding Rule: %s", err)
}
case v0beta:
v0BetaFrule := &computeBeta.ForwardingRule{}
err = Convert(frule, v0BetaFrule)
if err != nil {
return err
}
op, err = config.clientComputeBeta.GlobalForwardingRules.Insert(project, v0BetaFrule).Do()
if err != nil {
return fmt.Errorf("Error creating Global Forwarding Rule: %s", err)
}
} }
// It probably maybe worked, so store the ID now // It probably maybe worked, so store the ID now
@ -138,12 +165,12 @@ func resourceComputeGlobalForwardingRuleCreate(d *schema.ResourceData, meta inte
if _, ok := d.GetOk("labels"); ok { if _, ok := d.GetOk("labels"); ok {
labels := expandLabels(d) labels := expandLabels(d)
// Do a read to get the fingerprint value so we can update // Do a read to get the fingerprint value so we can update
fingerprint, err := resourceComputeGlobalForwardingRuleReadLabelFingerprint(config, project, frule.Name) fingerprint, err := resourceComputeGlobalForwardingRuleReadLabelFingerprint(config, computeApiVersion, project, frule.Name)
if err != nil { if err != nil {
return err return err
} }
err = resourceComputeGlobalForwardingRuleSetLabels(config, project, frule.Name, labels, fingerprint) err = resourceComputeGlobalForwardingRuleSetLabels(config, computeApiVersion, project, frule.Name, labels, fingerprint)
if err != nil { if err != nil {
return err return err
} }
@ -153,6 +180,7 @@ func resourceComputeGlobalForwardingRuleCreate(d *schema.ResourceData, meta inte
} }
func resourceComputeGlobalForwardingRuleUpdate(d *schema.ResourceData, meta interface{}) error { func resourceComputeGlobalForwardingRuleUpdate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersionUpdate(d, GlobalForwardingRuleBaseApiVersion, GlobalForwardingRuleVersionedFeatures, []Feature{})
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -164,12 +192,34 @@ func resourceComputeGlobalForwardingRuleUpdate(d *schema.ResourceData, meta inte
if d.HasChange("target") { if d.HasChange("target") {
target := d.Get("target").(string) target := d.Get("target").(string)
targetRef := &compute.TargetReference{Target: target} targetRef := &computeBeta.TargetReference{Target: target}
op, err := config.clientCompute.GlobalForwardingRules.SetTarget( var op interface{}
project, d.Id(), targetRef).Do() switch computeApiVersion {
if err != nil { case v1:
return fmt.Errorf("Error updating target: %s", err) v1TargetRef := &compute.TargetReference{}
err = Convert(targetRef, v1TargetRef)
if err != nil {
return err
}
op, err = config.clientCompute.GlobalForwardingRules.SetTarget(
project, d.Id(), v1TargetRef).Do()
if err != nil {
return fmt.Errorf("Error updating target: %s", err)
}
case v0beta:
v0BetaTargetRef := &compute.TargetReference{}
err = Convert(targetRef, v0BetaTargetRef)
if err != nil {
return err
}
op, err = config.clientCompute.GlobalForwardingRules.SetTarget(
project, d.Id(), v0BetaTargetRef).Do()
if err != nil {
return fmt.Errorf("Error updating target: %s", err)
}
} }
err = computeSharedOperationWait(config.clientCompute, op, project, "Updating Global Forwarding Rule") err = computeSharedOperationWait(config.clientCompute, op, project, "Updating Global Forwarding Rule")
@ -183,7 +233,7 @@ func resourceComputeGlobalForwardingRuleUpdate(d *schema.ResourceData, meta inte
labels := expandLabels(d) labels := expandLabels(d)
fingerprint := d.Get("label_fingerprint").(string) fingerprint := d.Get("label_fingerprint").(string)
err = resourceComputeGlobalForwardingRuleSetLabels(config, project, d.Get("name").(string), labels, fingerprint) err = resourceComputeGlobalForwardingRuleSetLabels(config, computeApiVersion, project, d.Get("name").(string), labels, fingerprint)
if err != nil { if err != nil {
return err return err
} }
@ -197,6 +247,7 @@ func resourceComputeGlobalForwardingRuleUpdate(d *schema.ResourceData, meta inte
} }
func resourceComputeGlobalForwardingRuleRead(d *schema.ResourceData, meta interface{}) error { func resourceComputeGlobalForwardingRuleRead(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, GlobalForwardingRuleBaseApiVersion, GlobalForwardingRuleVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -204,9 +255,28 @@ func resourceComputeGlobalForwardingRuleRead(d *schema.ResourceData, meta interf
return err return err
} }
frule, err := config.clientComputeBeta.GlobalForwardingRules.Get(project, d.Id()).Do() frule := &computeBeta.ForwardingRule{}
if err != nil { switch computeApiVersion {
return handleNotFoundError(err, d, fmt.Sprintf("Global Forwarding Rule %q", d.Get("name").(string))) case v1:
v1Frule, err := config.clientCompute.GlobalForwardingRules.Get(project, d.Id()).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Global Forwarding Rule %q", d.Get("name").(string)))
}
err = Convert(v1Frule, frule)
if err != nil {
return err
}
case v0beta:
v0BetaFrule, err := config.clientComputeBeta.GlobalForwardingRules.Get(project, d.Id()).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Global Forwarding Rule %q", d.Get("name").(string)))
}
err = Convert(v0BetaFrule, frule)
if err != nil {
return err
}
} }
d.Set("name", frule.Name) d.Set("name", frule.Name)
@ -225,6 +295,7 @@ func resourceComputeGlobalForwardingRuleRead(d *schema.ResourceData, meta interf
} }
func resourceComputeGlobalForwardingRuleDelete(d *schema.ResourceData, meta interface{}) error { func resourceComputeGlobalForwardingRuleDelete(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, GlobalForwardingRuleBaseApiVersion, GlobalForwardingRuleVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -234,10 +305,20 @@ func resourceComputeGlobalForwardingRuleDelete(d *schema.ResourceData, meta inte
// Delete the GlobalForwardingRule // Delete the GlobalForwardingRule
log.Printf("[DEBUG] GlobalForwardingRule delete request") log.Printf("[DEBUG] GlobalForwardingRule delete request")
op, err := config.clientCompute.GlobalForwardingRules.Delete(project, d.Id()).Do() var op interface{}
if err != nil { switch computeApiVersion {
return fmt.Errorf("Error deleting GlobalForwardingRule: %s", err) case v1:
op, err = config.clientCompute.GlobalForwardingRules.Delete(project, d.Id()).Do()
if err != nil {
return fmt.Errorf("Error deleting GlobalForwardingRule: %s", err)
}
case v0beta:
op, err = config.clientComputeBeta.GlobalForwardingRules.Delete(project, d.Id()).Do()
if err != nil {
return fmt.Errorf("Error deleting GlobalForwardingRule: %s", err)
}
} }
err = computeSharedOperationWait(config.clientCompute, op, project, "Deleting GlobalForwarding Rule") err = computeSharedOperationWait(config.clientCompute, op, project, "Deleting GlobalForwarding Rule")
if err != nil { if err != nil {
return err return err
@ -249,24 +330,43 @@ func resourceComputeGlobalForwardingRuleDelete(d *schema.ResourceData, meta inte
// resourceComputeGlobalForwardingRuleReadLabelFingerprint performs a read on the remote resource and returns only the // resourceComputeGlobalForwardingRuleReadLabelFingerprint performs a read on the remote resource and returns only the
// fingerprint. Used on create when setting labels as we don't know the label fingerprint initially. // fingerprint. Used on create when setting labels as we don't know the label fingerprint initially.
func resourceComputeGlobalForwardingRuleReadLabelFingerprint(config *Config, project, name string) (string, error) { func resourceComputeGlobalForwardingRuleReadLabelFingerprint(config *Config, computeApiVersion ApiVersion,
frule, err := config.clientComputeBeta.GlobalForwardingRules.Get(project, name).Do() project, name string) (string, error) {
if err != nil { switch computeApiVersion {
return "", fmt.Errorf("Unable to read global forwarding rule to update labels: %s", err) case v0beta:
} frule, err := config.clientComputeBeta.GlobalForwardingRules.Get(project, name).Do()
if err != nil {
return "", fmt.Errorf("Unable to read global forwarding rule to update labels: %s", err)
}
return frule.LabelFingerprint, nil return frule.LabelFingerprint, nil
default:
return "", fmt.Errorf(
"Unable to read label fingerprint due to an internal error: can only handle v0beta but compute api logic indicates %d",
computeApiVersion)
}
} }
// resourceComputeGlobalForwardingRuleSetLabels sets the Labels attribute on a forwarding rule. // resourceComputeGlobalForwardingRuleSetLabels sets the Labels attribute on a forwarding rule.
func resourceComputeGlobalForwardingRuleSetLabels(config *Config, project, name string, labels map[string]string, fingerprint string) error { func resourceComputeGlobalForwardingRuleSetLabels(config *Config, computeApiVersion ApiVersion, project,
setLabels := computeBeta.GlobalSetLabelsRequest{ name string, labels map[string]string, fingerprint string) error {
Labels: labels, var op interface{}
LabelFingerprint: fingerprint, var err error
}
op, err := config.clientComputeBeta.GlobalForwardingRules.SetLabels(project, name, &setLabels).Do() switch computeApiVersion {
if err != nil { case v0beta:
return err setLabels := computeBeta.GlobalSetLabelsRequest{
Labels: labels,
LabelFingerprint: fingerprint,
}
op, err = config.clientComputeBeta.GlobalForwardingRules.SetLabels(project, name, &setLabels).Do()
if err != nil {
return err
}
default:
return fmt.Errorf(
"Unable to set labels due to an internal error: can only handle v0beta but compute api logic indicates %d",
computeApiVersion)
} }
err = computeSharedOperationWait(config.clientCompute, op, project, "Setting labels on Global Forwarding Rule") err = computeSharedOperationWait(config.clientCompute, op, project, "Setting labels on Global Forwarding Rule")

View File

@ -19,6 +19,9 @@ import (
"google.golang.org/api/googleapi" "google.golang.org/api/googleapi"
) )
var InstanceBaseApiVersion = v1
var InstanceVersionedFeatures = []Feature{}
func resourceComputeInstance() *schema.Resource { func resourceComputeInstance() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
Create: resourceComputeInstanceCreate, Create: resourceComputeInstanceCreate,
@ -592,9 +595,21 @@ func getInstance(config *Config, d *schema.ResourceData) (*computeBeta.Instance,
if err != nil { if err != nil {
return nil, err return nil, err
} }
instance, err := config.clientComputeBeta.Instances.Get(project, zone, d.Id()).Do() instance := &computeBeta.Instance{}
if err != nil { switch getComputeApiVersion(d, InstanceBaseApiVersion, InstanceVersionedFeatures) {
return nil, handleNotFoundError(err, d, fmt.Sprintf("Instance %s", d.Get("name").(string))) case v1:
instanceV1, err := config.clientCompute.Instances.Get(project, zone, d.Id()).Do()
if err != nil {
return nil, handleNotFoundError(err, d, fmt.Sprintf("Instance %s", d.Get("name").(string)))
}
if err := Convert(instanceV1, instance); err != nil {
return nil, err
}
case v0beta:
instance, err = config.clientComputeBeta.Instances.Get(project, zone, d.Id()).Do()
if err != nil {
return nil, handleNotFoundError(err, d, fmt.Sprintf("Instance %s", d.Get("name").(string)))
}
} }
return instance, nil return instance, nil
} }
@ -730,7 +745,17 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err
} }
log.Printf("[INFO] Requesting instance creation") log.Printf("[INFO] Requesting instance creation")
op, err := config.clientComputeBeta.Instances.Insert(project, zone.Name, instance).Do() var op interface{}
switch getComputeApiVersion(d, InstanceBaseApiVersion, InstanceVersionedFeatures) {
case v1:
instanceV1 := &compute.Instance{}
if err := Convert(instance, instanceV1); err != nil {
return err
}
op, err = config.clientCompute.Instances.Insert(project, zone.Name, instanceV1).Do()
case v0beta:
op, err = config.clientComputeBeta.Instances.Insert(project, zone.Name, instance).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error creating instance: %s", err) return fmt.Errorf("Error creating instance: %s", err)
} }

View File

@ -14,6 +14,12 @@ import (
"google.golang.org/api/compute/v1" "google.golang.org/api/compute/v1"
) )
var InstanceGroupManagerBaseApiVersion = v1
var InstanceGroupManagerVersionedFeatures = []Feature{
Feature{Version: v0beta, Item: "auto_healing_policies"},
Feature{Version: v0beta, Item: "rolling_update_policy"},
}
func resourceComputeInstanceGroupManager() *schema.Resource { func resourceComputeInstanceGroupManager() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
Create: resourceComputeInstanceGroupManagerCreate, Create: resourceComputeInstanceGroupManagerCreate,
@ -228,6 +234,7 @@ func getNamedPortsBeta(nps []interface{}) []*computeBeta.NamedPort {
} }
func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta interface{}) error { func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, InstanceGroupManagerBaseApiVersion, InstanceGroupManagerVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -259,8 +266,29 @@ func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta inte
} }
log.Printf("[DEBUG] InstanceGroupManager insert request: %#v", manager) log.Printf("[DEBUG] InstanceGroupManager insert request: %#v", manager)
op, err := config.clientComputeBeta.InstanceGroupManagers.Insert( var op interface{}
project, zone, manager).Do() switch computeApiVersion {
case v1:
managerV1 := &compute.InstanceGroupManager{}
err = Convert(manager, managerV1)
if err != nil {
return err
}
managerV1.ForceSendFields = manager.ForceSendFields
op, err = config.clientCompute.InstanceGroupManagers.Insert(
project, zone, managerV1).Do()
case v0beta:
managerV0beta := &computeBeta.InstanceGroupManager{}
err = Convert(manager, managerV0beta)
if err != nil {
return err
}
managerV0beta.ForceSendFields = manager.ForceSendFields
op, err = config.clientComputeBeta.InstanceGroupManagers.Insert(
project, zone, managerV0beta).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error creating InstanceGroupManager: %s", err) return fmt.Errorf("Error creating InstanceGroupManager: %s", err)
@ -291,6 +319,7 @@ func flattenNamedPortsBeta(namedPorts []*computeBeta.NamedPort) []map[string]int
} }
func getManager(d *schema.ResourceData, meta interface{}) (*computeBeta.InstanceGroupManager, error) { func getManager(d *schema.ResourceData, meta interface{}) (*computeBeta.InstanceGroupManager, error) {
computeApiVersion := getComputeApiVersion(d, InstanceGroupManagerBaseApiVersion, InstanceGroupManagerVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -303,38 +332,82 @@ func getManager(d *schema.ResourceData, meta interface{}) (*computeBeta.Instance
return nil, err return nil, err
} }
getInstanceGroupManager := func(zone string) (interface{}, error) { manager := &computeBeta.InstanceGroupManager{}
return config.clientComputeBeta.InstanceGroupManagers.Get(project, zone, d.Id()).Do() switch computeApiVersion {
} case v1:
getInstanceGroupManager := func(zone string) (interface{}, error) {
var manager *computeBeta.InstanceGroupManager return config.clientCompute.InstanceGroupManagers.Get(project, zone, d.Id()).Do()
var e error
if zone, _ := getZone(d, config); zone != "" {
manager, e = config.clientComputeBeta.InstanceGroupManagers.Get(project, zone, d.Id()).Do()
if e != nil {
return nil, handleNotFoundError(e, d, fmt.Sprintf("Instance Group Manager %q", d.Get("name").(string)))
}
} else {
// If the resource was imported, the only info we have is the ID. Try to find the resource
// by searching in the region of the project.
var resource interface{}
resource, e = getZonalBetaResourceFromRegion(getInstanceGroupManager, region, config.clientComputeBeta, project)
if e != nil {
return nil, e
} }
manager = resource.(*computeBeta.InstanceGroupManager) var v1Manager *compute.InstanceGroupManager
var e error
if zone, _ := getZone(d, config); zone != "" {
v1Manager, e = config.clientCompute.InstanceGroupManagers.Get(project, zone, d.Id()).Do()
if e != nil {
return nil, handleNotFoundError(e, d, fmt.Sprintf("Instance Group Manager %q", d.Get("name").(string)))
}
} else {
// If the resource was imported, the only info we have is the ID. Try to find the resource
// by searching in the region of the project.
var resource interface{}
resource, e = getZonalResourceFromRegion(getInstanceGroupManager, region, config.clientCompute, project)
if e != nil {
return nil, e
}
v1Manager = resource.(*compute.InstanceGroupManager)
}
if v1Manager == nil {
log.Printf("[WARN] Removing Instance Group Manager %q because it's gone", d.Get("name").(string))
// The resource doesn't exist anymore
d.SetId("")
return nil, nil
}
err = Convert(v1Manager, manager)
if err != nil {
return nil, err
}
case v0beta:
getInstanceGroupManager := func(zone string) (interface{}, error) {
return config.clientComputeBeta.InstanceGroupManagers.Get(project, zone, d.Id()).Do()
}
var v0betaManager *computeBeta.InstanceGroupManager
var e error
if zone, _ := getZone(d, config); zone != "" {
v0betaManager, e = config.clientComputeBeta.InstanceGroupManagers.Get(project, zone, d.Id()).Do()
if e != nil {
return nil, handleNotFoundError(e, d, fmt.Sprintf("Instance Group Manager %q", d.Get("name").(string)))
}
} else {
// If the resource was imported, the only info we have is the ID. Try to find the resource
// by searching in the region of the project.
var resource interface{}
resource, e = getZonalBetaResourceFromRegion(getInstanceGroupManager, region, config.clientComputeBeta, project)
if e != nil {
return nil, e
}
v0betaManager = resource.(*computeBeta.InstanceGroupManager)
}
if v0betaManager == nil {
log.Printf("[WARN] Removing Instance Group Manager %q because it's gone", d.Get("name").(string))
// The resource doesn't exist anymore
d.SetId("")
return nil, nil
}
manager = v0betaManager
} }
if manager == nil {
log.Printf("[WARN] Removing Instance Group Manager %q because it's gone", d.Get("name").(string))
// The resource doesn't exist anymore
d.SetId("")
return nil, nil
}
return manager, nil return manager, nil
} }
@ -386,6 +459,7 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf
} }
func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta interface{}) error { func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersionUpdate(d, InstanceGroupManagerBaseApiVersion, InstanceGroupManagerVersionedFeatures, []Feature{})
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -414,8 +488,27 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
TargetPools: targetPools, TargetPools: targetPools,
} }
op, err := config.clientComputeBeta.InstanceGroupManagers.SetTargetPools( var op interface{}
project, zone, d.Id(), setTargetPools).Do() switch computeApiVersion {
case v1:
setTargetPoolsV1 := &compute.InstanceGroupManagersSetTargetPoolsRequest{}
err = Convert(setTargetPools, setTargetPoolsV1)
if err != nil {
return err
}
op, err = config.clientCompute.InstanceGroupManagers.SetTargetPools(
project, zone, d.Id(), setTargetPoolsV1).Do()
case v0beta:
setTargetPoolsV0beta := &computeBeta.InstanceGroupManagersSetTargetPoolsRequest{}
err = Convert(setTargetPools, setTargetPoolsV0beta)
if err != nil {
return err
}
op, err = config.clientComputeBeta.InstanceGroupManagers.SetTargetPools(
project, zone, d.Id(), setTargetPoolsV0beta).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error updating InstanceGroupManager: %s", err) return fmt.Errorf("Error updating InstanceGroupManager: %s", err)
@ -437,8 +530,27 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
InstanceTemplate: d.Get("instance_template").(string), InstanceTemplate: d.Get("instance_template").(string),
} }
op, err := config.clientComputeBeta.InstanceGroupManagers.SetInstanceTemplate( var op interface{}
project, zone, d.Id(), setInstanceTemplate).Do() switch computeApiVersion {
case v1:
setInstanceTemplateV1 := &compute.InstanceGroupManagersSetInstanceTemplateRequest{}
err = Convert(setInstanceTemplate, setInstanceTemplateV1)
if err != nil {
return err
}
op, err = config.clientCompute.InstanceGroupManagers.SetInstanceTemplate(
project, zone, d.Id(), setInstanceTemplateV1).Do()
case v0beta:
setInstanceTemplateV0beta := &computeBeta.InstanceGroupManagersSetInstanceTemplateRequest{}
err = Convert(setInstanceTemplate, setInstanceTemplateV0beta)
if err != nil {
return err
}
op, err = config.clientComputeBeta.InstanceGroupManagers.SetInstanceTemplate(
project, zone, d.Id(), setInstanceTemplateV0beta).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error updating InstanceGroupManager: %s", err) return fmt.Errorf("Error updating InstanceGroupManager: %s", err)
@ -451,10 +563,30 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
} }
if d.Get("update_strategy").(string) == "RESTART" { if d.Get("update_strategy").(string) == "RESTART" {
managedInstances, err := config.clientComputeBeta.InstanceGroupManagers.ListManagedInstances( managedInstances := &computeBeta.InstanceGroupManagersListManagedInstancesResponse{}
project, zone, d.Id()).Do() switch computeApiVersion {
if err != nil { case v1:
return fmt.Errorf("Error getting instance group managers instances: %s", err) managedInstancesV1, err := config.clientCompute.InstanceGroupManagers.ListManagedInstances(
project, zone, d.Id()).Do()
if err != nil {
return fmt.Errorf("Error getting instance group managers instances: %s", err)
}
err = Convert(managedInstancesV1, managedInstances)
if err != nil {
return err
}
case v0beta:
managedInstancesV0beta, err := config.clientComputeBeta.InstanceGroupManagers.ListManagedInstances(
project, zone, d.Id()).Do()
if err != nil {
return fmt.Errorf("Error getting instance group managers instances: %s", err)
}
err = Convert(managedInstancesV0beta, managedInstances)
if err != nil {
return err
}
} }
managedInstanceCount := len(managedInstances.ManagedInstances) managedInstanceCount := len(managedInstances.ManagedInstances)
@ -467,10 +599,32 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
Instances: instances, Instances: instances,
} }
op, err = config.clientComputeBeta.InstanceGroupManagers.RecreateInstances( var op interface{}
project, zone, d.Id(), recreateInstances).Do() switch computeApiVersion {
if err != nil { case v1:
return fmt.Errorf("Error restarting instance group managers instances: %s", err) recreateInstancesV1 := &compute.InstanceGroupManagersRecreateInstancesRequest{}
err = Convert(recreateInstances, recreateInstancesV1)
if err != nil {
return err
}
op, err = config.clientCompute.InstanceGroupManagers.RecreateInstances(
project, zone, d.Id(), recreateInstancesV1).Do()
if err != nil {
return fmt.Errorf("Error restarting instance group managers instances: %s", err)
}
case v0beta:
recreateInstancesV0beta := &computeBeta.InstanceGroupManagersRecreateInstancesRequest{}
err = Convert(recreateInstances, recreateInstancesV0beta)
if err != nil {
return err
}
op, err = config.clientComputeBeta.InstanceGroupManagers.RecreateInstances(
project, zone, d.Id(), recreateInstancesV0beta).Do()
if err != nil {
return fmt.Errorf("Error restarting instance group managers instances: %s", err)
}
} }
// Wait for the operation to complete // Wait for the operation to complete
@ -515,8 +669,27 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
} }
// Make the request: // Make the request:
op, err := config.clientComputeBeta.InstanceGroups.SetNamedPorts( var op interface{}
project, zone, d.Id(), setNamedPorts).Do() switch computeApiVersion {
case v1:
setNamedPortsV1 := &compute.InstanceGroupsSetNamedPortsRequest{}
err = Convert(setNamedPorts, setNamedPortsV1)
if err != nil {
return err
}
op, err = config.clientCompute.InstanceGroups.SetNamedPorts(
project, zone, d.Id(), setNamedPortsV1).Do()
case v0beta:
setNamedPortsV0beta := &computeBeta.InstanceGroupsSetNamedPortsRequest{}
err = Convert(setNamedPorts, setNamedPortsV0beta)
if err != nil {
return err
}
op, err = config.clientComputeBeta.InstanceGroups.SetNamedPorts(
project, zone, d.Id(), setNamedPortsV0beta).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error updating InstanceGroupManager: %s", err) return fmt.Errorf("Error updating InstanceGroupManager: %s", err)
@ -533,8 +706,15 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
if d.HasChange("target_size") { if d.HasChange("target_size") {
targetSize := int64(d.Get("target_size").(int)) targetSize := int64(d.Get("target_size").(int))
op, err := config.clientComputeBeta.InstanceGroupManagers.Resize( var op interface{}
project, zone, d.Id(), targetSize).Do() switch computeApiVersion {
case v1:
op, err = config.clientCompute.InstanceGroupManagers.Resize(
project, zone, d.Id(), targetSize).Do()
case v0beta:
op, err = config.clientComputeBeta.InstanceGroupManagers.Resize(
project, zone, d.Id(), targetSize).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error updating InstanceGroupManager: %s", err) return fmt.Errorf("Error updating InstanceGroupManager: %s", err)
@ -578,6 +758,7 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
} }
func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta interface{}) error { func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, InstanceGroupManagerBaseApiVersion, InstanceGroupManagerVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -590,12 +771,24 @@ func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta inte
return err return err
} }
op, err := config.clientComputeBeta.InstanceGroupManagers.Delete(project, zone, d.Id()).Do() var op interface{}
attempt := 0 switch computeApiVersion {
for err != nil && attempt < 20 { case v1:
attempt++ op, err = config.clientCompute.InstanceGroupManagers.Delete(project, zone, d.Id()).Do()
time.Sleep(2000 * time.Millisecond) attempt := 0
for err != nil && attempt < 20 {
attempt++
time.Sleep(2000 * time.Millisecond)
op, err = config.clientCompute.InstanceGroupManagers.Delete(project, zone, d.Id()).Do()
}
case v0beta:
op, err = config.clientComputeBeta.InstanceGroupManagers.Delete(project, zone, d.Id()).Do() op, err = config.clientComputeBeta.InstanceGroupManagers.Delete(project, zone, d.Id()).Do()
attempt := 0
for err != nil && attempt < 20 {
attempt++
time.Sleep(2000 * time.Millisecond)
op, err = config.clientComputeBeta.InstanceGroupManagers.Delete(project, zone, d.Id()).Do()
}
} }
if err != nil { if err != nil {
@ -612,13 +805,25 @@ func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta inte
return err return err
} }
instanceGroup, err := config.clientComputeBeta.InstanceGroups.Get( var instanceGroupSize int64
project, zone, d.Id()).Do() switch computeApiVersion {
if err != nil { case v1:
return fmt.Errorf("Error getting instance group size: %s", err) instanceGroup, err := config.clientCompute.InstanceGroups.Get(
} project, zone, d.Id()).Do()
if err != nil {
return fmt.Errorf("Error getting instance group size: %s", err)
}
instanceGroupSize := instanceGroup.Size instanceGroupSize = instanceGroup.Size
case v0beta:
instanceGroup, err := config.clientComputeBeta.InstanceGroups.Get(
project, zone, d.Id()).Do()
if err != nil {
return fmt.Errorf("Error getting instance group size: %s", err)
}
instanceGroupSize = instanceGroup.Size
}
if instanceGroupSize >= currentSize { if instanceGroupSize >= currentSize {
return fmt.Errorf("Error, instance group isn't shrinking during delete") return fmt.Errorf("Error, instance group isn't shrinking during delete")

View File

@ -292,11 +292,9 @@ func TestAccInstanceGroupManager_autoHealingPolicies(t *testing.T) {
testAccCheckInstanceGroupManagerAutoHealingPolicies("google_compute_instance_group_manager.igm-basic", hck, 10), testAccCheckInstanceGroupManagerAutoHealingPolicies("google_compute_instance_group_manager.igm-basic", hck, 10),
), ),
}, },
resource.TestStep{ // TODO: Add import test for auto healing policies
ResourceName: "google_compute_instance_group_manager.igm-basic", // Import doesn't work for auto healing policies because import is not supported
ImportState: true, // for beta features. See https://github.com/terraform-providers/terraform-provider-google/issues/694
ImportStateVerify: true,
},
}, },
}) })
} }

View File

@ -6,9 +6,13 @@ import (
"github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
computeBeta "google.golang.org/api/compute/v0.beta" computeBeta "google.golang.org/api/compute/v0.beta"
"google.golang.org/api/compute/v1"
"google.golang.org/api/googleapi" "google.golang.org/api/googleapi"
) )
var InstanceTemplateBaseApiVersion = v1
var InstanceTemplateVersionedFeatures = []Feature{}
func resourceComputeInstanceTemplate() *schema.Resource { func resourceComputeInstanceTemplate() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
Create: resourceComputeInstanceTemplateCreate, Create: resourceComputeInstanceTemplateCreate,
@ -606,7 +610,17 @@ func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interfac
Name: itName, Name: itName,
} }
op, err := config.clientComputeBeta.InstanceTemplates.Insert(project, instanceTemplate).Do() var op interface{}
switch getComputeApiVersion(d, InstanceTemplateBaseApiVersion, InstanceGroupManagerVersionedFeatures) {
case v1:
instanceTemplateV1 := &compute.InstanceTemplate{}
if err := Convert(instanceTemplate, instanceTemplateV1); err != nil {
return err
}
op, err = config.clientCompute.InstanceTemplates.Insert(project, instanceTemplateV1).Do()
case v0beta:
op, err = config.clientComputeBeta.InstanceTemplates.Insert(project, instanceTemplate).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error creating instance template: %s", err) return fmt.Errorf("Error creating instance template: %s", err)
} }
@ -656,9 +670,22 @@ func resourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interface{
return err return err
} }
instanceTemplate, err := config.clientComputeBeta.InstanceTemplates.Get(project, d.Id()).Do() instanceTemplate := &computeBeta.InstanceTemplate{}
if err != nil { switch getComputeApiVersion(d, InstanceBaseApiVersion, InstanceVersionedFeatures) {
return handleNotFoundError(err, d, fmt.Sprintf("Instance Template %q", d.Get("name").(string))) case v1:
instanceTemplateV1, err := config.clientCompute.InstanceTemplates.Get(project, d.Id()).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Instance Template %q", d.Get("name").(string)))
}
if err := Convert(instanceTemplateV1, instanceTemplate); err != nil {
return err
}
case v0beta:
var err error
instanceTemplate, err = config.clientComputeBeta.InstanceTemplates.Get(project, d.Id()).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Instance Template %q", d.Get("name").(string)))
}
} }
// Set the metadata fingerprint if there is one. // Set the metadata fingerprint if there is one.

View File

@ -12,8 +12,16 @@ import (
"github.com/hashicorp/terraform/helper/validation" "github.com/hashicorp/terraform/helper/validation"
computeBeta "google.golang.org/api/compute/v0.beta" computeBeta "google.golang.org/api/compute/v0.beta"
"google.golang.org/api/compute/v1"
) )
var RegionInstanceGroupManagerBaseApiVersion = v1
var RegionInstanceGroupManagerVersionedFeatures = []Feature{
Feature{Version: v0beta, Item: "auto_healing_policies"},
Feature{Version: v0beta, Item: "distribution_policy_zones"},
Feature{Version: v0beta, Item: "rolling_update_policy"},
}
func resourceComputeRegionInstanceGroupManager() *schema.Resource { func resourceComputeRegionInstanceGroupManager() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
Create: resourceComputeRegionInstanceGroupManagerCreate, Create: resourceComputeRegionInstanceGroupManagerCreate,
@ -222,6 +230,7 @@ func resourceComputeRegionInstanceGroupManager() *schema.Resource {
} }
func resourceComputeRegionInstanceGroupManagerCreate(d *schema.ResourceData, meta interface{}) error { func resourceComputeRegionInstanceGroupManagerCreate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, RegionInstanceGroupManagerBaseApiVersion, RegionInstanceGroupManagerVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -247,7 +256,19 @@ func resourceComputeRegionInstanceGroupManagerCreate(d *schema.ResourceData, met
ForceSendFields: []string{"TargetSize"}, ForceSendFields: []string{"TargetSize"},
} }
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.Insert(project, d.Get("region").(string), manager).Do() var op interface{}
switch computeApiVersion {
case v1:
managerV1 := &compute.InstanceGroupManager{}
err = Convert(manager, managerV1)
if err != nil {
return err
}
managerV1.ForceSendFields = manager.ForceSendFields
op, err = config.clientCompute.RegionInstanceGroupManagers.Insert(project, d.Get("region").(string), managerV1).Do()
case v0beta:
op, err = config.clientComputeBeta.RegionInstanceGroupManagers.Insert(project, d.Get("region").(string), manager).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error creating RegionInstanceGroupManager: %s", err) return fmt.Errorf("Error creating RegionInstanceGroupManager: %s", err)
@ -266,6 +287,7 @@ func resourceComputeRegionInstanceGroupManagerCreate(d *schema.ResourceData, met
type getInstanceManagerFunc func(*schema.ResourceData, interface{}) (*computeBeta.InstanceGroupManager, error) type getInstanceManagerFunc func(*schema.ResourceData, interface{}) (*computeBeta.InstanceGroupManager, error)
func getRegionalManager(d *schema.ResourceData, meta interface{}) (*computeBeta.InstanceGroupManager, error) { func getRegionalManager(d *schema.ResourceData, meta interface{}) (*computeBeta.InstanceGroupManager, error) {
computeApiVersion := getComputeApiVersion(d, RegionInstanceGroupManagerBaseApiVersion, RegionInstanceGroupManagerVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -274,12 +296,32 @@ func getRegionalManager(d *schema.ResourceData, meta interface{}) (*computeBeta.
} }
region := d.Get("region").(string) region := d.Get("region").(string)
manager := &computeBeta.InstanceGroupManager{}
switch computeApiVersion {
case v1:
v1Manager := &compute.InstanceGroupManager{}
v1Manager, err = config.clientCompute.RegionInstanceGroupManagers.Get(project, region, d.Id()).Do()
if v1Manager == nil {
log.Printf("[WARN] Removing Region Instance Group Manager %q because it's gone", d.Get("name").(string))
// The resource doesn't exist anymore
d.SetId("")
return nil, nil
}
err = Convert(v1Manager, manager)
if err != nil {
return nil, err
}
case v0beta:
manager, err = config.clientComputeBeta.RegionInstanceGroupManagers.Get(project, region, d.Id()).Do()
}
manager, err := config.clientComputeBeta.RegionInstanceGroupManagers.Get(project, region, d.Id()).Do()
if err != nil { if err != nil {
return nil, handleNotFoundError(err, d, fmt.Sprintf("Region Instance Manager %q", d.Get("name").(string))) return nil, handleNotFoundError(err, d, fmt.Sprintf("Region Instance Manager %q", d.Get("name").(string)))
} }
return manager, nil return manager, nil
} }
@ -344,6 +386,7 @@ func resourceComputeRegionInstanceGroupManagerRead(d *schema.ResourceData, meta
} }
func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, meta interface{}) error { func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersionUpdate(d, RegionInstanceGroupManagerBaseApiVersion, RegionInstanceGroupManagerVersionedFeatures, []Feature{})
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -368,8 +411,27 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
TargetPools: targetPools, TargetPools: targetPools,
} }
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.SetTargetPools( var op interface{}
project, region, d.Id(), setTargetPools).Do() switch computeApiVersion {
case v1:
setTargetPoolsV1 := &compute.RegionInstanceGroupManagersSetTargetPoolsRequest{}
err = Convert(setTargetPools, setTargetPoolsV1)
if err != nil {
return err
}
op, err = config.clientCompute.RegionInstanceGroupManagers.SetTargetPools(
project, region, d.Id(), setTargetPoolsV1).Do()
case v0beta:
setTargetPoolsV0beta := &computeBeta.RegionInstanceGroupManagersSetTargetPoolsRequest{}
err = Convert(setTargetPools, setTargetPoolsV0beta)
if err != nil {
return err
}
op, err = config.clientComputeBeta.RegionInstanceGroupManagers.SetTargetPools(
project, region, d.Id(), setTargetPoolsV0beta).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error updating RegionInstanceGroupManager: %s", err) return fmt.Errorf("Error updating RegionInstanceGroupManager: %s", err)
@ -390,8 +452,27 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
InstanceTemplate: d.Get("instance_template").(string), InstanceTemplate: d.Get("instance_template").(string),
} }
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.SetInstanceTemplate( var op interface{}
project, region, d.Id(), setInstanceTemplate).Do() switch computeApiVersion {
case v1:
setInstanceTemplateV1 := &compute.RegionInstanceGroupManagersSetTemplateRequest{}
err = Convert(setInstanceTemplate, setInstanceTemplateV1)
if err != nil {
return err
}
op, err = config.clientCompute.RegionInstanceGroupManagers.SetInstanceTemplate(
project, region, d.Id(), setInstanceTemplateV1).Do()
case v0beta:
setInstanceTemplateV0beta := &computeBeta.RegionInstanceGroupManagersSetTemplateRequest{}
err = Convert(setInstanceTemplate, setInstanceTemplateV0beta)
if err != nil {
return err
}
op, err = config.clientComputeBeta.RegionInstanceGroupManagers.SetInstanceTemplate(
project, region, d.Id(), setInstanceTemplateV0beta).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error updating RegionInstanceGroupManager: %s", err) return fmt.Errorf("Error updating RegionInstanceGroupManager: %s", err)
@ -436,8 +517,27 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
} }
// Make the request: // Make the request:
op, err := config.clientComputeBeta.RegionInstanceGroups.SetNamedPorts( var op interface{}
project, region, d.Id(), setNamedPorts).Do() switch computeApiVersion {
case v1:
setNamedPortsV1 := &compute.RegionInstanceGroupsSetNamedPortsRequest{}
err = Convert(setNamedPorts, setNamedPortsV1)
if err != nil {
return err
}
op, err = config.clientCompute.RegionInstanceGroups.SetNamedPorts(
project, region, d.Id(), setNamedPortsV1).Do()
case v0beta:
setNamedPortsV0beta := &computeBeta.RegionInstanceGroupsSetNamedPortsRequest{}
err = Convert(setNamedPorts, setNamedPortsV0beta)
if err != nil {
return err
}
op, err = config.clientComputeBeta.RegionInstanceGroups.SetNamedPorts(
project, region, d.Id(), setNamedPortsV0beta).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error updating RegionInstanceGroupManager: %s", err) return fmt.Errorf("Error updating RegionInstanceGroupManager: %s", err)
@ -454,8 +554,15 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
if d.HasChange("target_size") { if d.HasChange("target_size") {
targetSize := int64(d.Get("target_size").(int)) targetSize := int64(d.Get("target_size").(int))
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.Resize( var op interface{}
project, region, d.Id(), targetSize).Do() switch computeApiVersion {
case v1:
op, err = config.clientCompute.RegionInstanceGroupManagers.Resize(
project, region, d.Id(), targetSize).Do()
case v0beta:
op, err = config.clientComputeBeta.RegionInstanceGroupManagers.Resize(
project, region, d.Id(), targetSize).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error resizing RegionInstanceGroupManager: %s", err) return fmt.Errorf("Error resizing RegionInstanceGroupManager: %s", err)
@ -498,6 +605,7 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
} }
func resourceComputeRegionInstanceGroupManagerDelete(d *schema.ResourceData, meta interface{}) error { func resourceComputeRegionInstanceGroupManagerDelete(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, RegionInstanceGroupManagerBaseApiVersion, RegionInstanceGroupManagerVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
project, err := getProject(d, config) project, err := getProject(d, config)
@ -507,7 +615,13 @@ func resourceComputeRegionInstanceGroupManagerDelete(d *schema.ResourceData, met
region := d.Get("region").(string) region := d.Get("region").(string)
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.Delete(project, region, d.Id()).Do() var op interface{}
switch computeApiVersion {
case v1:
op, err = config.clientCompute.RegionInstanceGroupManagers.Delete(project, region, d.Id()).Do()
case v0beta:
op, err = config.clientComputeBeta.RegionInstanceGroupManagers.Delete(project, region, d.Id()).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error deleting region instance group manager: %s", err) return fmt.Errorf("Error deleting region instance group manager: %s", err)

View File

@ -14,6 +14,14 @@ import (
"google.golang.org/api/compute/v1" "google.golang.org/api/compute/v1"
) )
var (
SubnetworkBaseApiVersion = v1
SubnetworkVersionedFeatures = []Feature{
{Version: v0beta, Item: "secondary_ip_range"},
{Version: v0beta, Item: "enable_flow_logs"},
}
)
func resourceComputeSubnetwork() *schema.Resource { func resourceComputeSubnetwork() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
Create: resourceComputeSubnetworkCreate, Create: resourceComputeSubnetworkCreate,
@ -122,6 +130,7 @@ func resourceComputeSubnetwork() *schema.Resource {
} }
func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) error { func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, SubnetworkBaseApiVersion, SubnetworkVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
network, err := ParseNetworkFieldValue(d.Get("network").(string), d, config) network, err := ParseNetworkFieldValue(d.Get("network").(string), d, config)
if err != nil { if err != nil {
@ -151,7 +160,21 @@ func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) e
log.Printf("[DEBUG] Subnetwork insert request: %#v", subnetwork) log.Printf("[DEBUG] Subnetwork insert request: %#v", subnetwork)
op, err := config.clientComputeBeta.Subnetworks.Insert(project, region, subnetwork).Do() subnetworkV1 := &compute.Subnetwork{}
err = Convert(subnetwork, subnetworkV1)
if err != nil {
return err
}
subnetworkV1.ForceSendFields = subnetwork.ForceSendFields
var op interface{}
switch computeApiVersion {
case v1:
op, err = config.clientCompute.Subnetworks.Insert(project, region, subnetworkV1).Do()
case v0beta:
op, err = config.clientComputeBeta.Subnetworks.Insert(project, region, subnetwork).Do()
}
if err != nil { if err != nil {
return fmt.Errorf("Error creating subnetwork: %s", err) return fmt.Errorf("Error creating subnetwork: %s", err)
} }
@ -161,8 +184,9 @@ func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) e
// "When creating a new subnetwork, its name has to be unique in that project for that region, even across networks. // "When creating a new subnetwork, its name has to be unique in that project for that region, even across networks.
// The same name can appear twice in a project, as long as each one is in a different region." // The same name can appear twice in a project, as long as each one is in a different region."
// https://cloud.google.com/compute/docs/subnetworks // https://cloud.google.com/compute/docs/subnetworks
subnetworkV1.Region = region
subnetwork.Region = region subnetwork.Region = region
d.SetId(createSubnetIDBeta(subnetwork)) d.SetId(createSubnetID(subnetworkV1))
err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutCreate).Minutes()), "Creating Subnetwork") err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutCreate).Minutes()), "Creating Subnetwork")
if err != nil { if err != nil {
@ -173,6 +197,45 @@ func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) e
} }
func resourceComputeSubnetworkRead(d *schema.ResourceData, meta interface{}) error { func resourceComputeSubnetworkRead(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, SubnetworkBaseApiVersion, SubnetworkVersionedFeatures)
if computeApiVersion == v0beta {
return resourceComputeSubnetworkReadV0Beta(d, meta)
}
config := meta.(*Config)
region, err := getRegion(d, config)
if err != nil {
return err
}
project, err := getProject(d, config)
if err != nil {
return err
}
name := d.Get("name").(string)
subnetwork, err := config.clientCompute.Subnetworks.Get(project, region, name).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Subnetwork %q", name))
}
d.Set("name", subnetwork.Name)
d.Set("ip_cidr_range", subnetwork.IpCidrRange)
d.Set("network", subnetwork.Network)
d.Set("description", subnetwork.Description)
d.Set("private_ip_google_access", subnetwork.PrivateIpGoogleAccess)
d.Set("gateway_address", subnetwork.GatewayAddress)
d.Set("secondary_ip_range", flattenSecondaryRanges(subnetwork.SecondaryIpRanges))
d.Set("project", project)
d.Set("region", region)
d.Set("self_link", ConvertSelfLinkToV1(subnetwork.SelfLink))
return nil
}
func resourceComputeSubnetworkReadV0Beta(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config) config := meta.(*Config)
region, err := getRegion(d, config) region, err := getRegion(d, config)
@ -209,6 +272,7 @@ func resourceComputeSubnetworkRead(d *schema.ResourceData, meta interface{}) err
} }
func resourceComputeSubnetworkUpdate(d *schema.ResourceData, meta interface{}) error { func resourceComputeSubnetworkUpdate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, SubnetworkBaseApiVersion, SubnetworkVersionedFeatures)
config := meta.(*Config) config := meta.(*Config)
region, err := getRegion(d, config) region, err := getRegion(d, config)
@ -264,7 +328,7 @@ func resourceComputeSubnetworkUpdate(d *schema.ResourceData, meta interface{}) e
d.SetPartial("ip_cidr_range") d.SetPartial("ip_cidr_range")
} }
if d.HasChange("secondary_ip_range") || d.HasChange("enable_flow_logs") { if (d.HasChange("secondary_ip_range") || d.HasChange("enable_flow_logs")) && computeApiVersion == v0beta {
v0BetaSubnetwork := &computeBeta.Subnetwork{ v0BetaSubnetwork := &computeBeta.Subnetwork{
Fingerprint: d.Get("fingerprint").(string), Fingerprint: d.Get("fingerprint").(string),
} }

View File

@ -193,11 +193,7 @@ func TestAccComputeSubnetwork_flowLogs(t *testing.T) {
"enable_flow_logs", "true"), "enable_flow_logs", "true"),
), ),
}, },
{ // no import, as import currently doesn't work for beta
ResourceName: "google_compute_subnetwork.network-with-flow-logs",
ImportState: true,
ImportStateVerify: true,
},
{ {
Config: testAccComputeSubnetwork_flowLogs(cnName, subnetworkName, false), Config: testAccComputeSubnetwork_flowLogs(cnName, subnetworkName, false),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
@ -207,11 +203,6 @@ func TestAccComputeSubnetwork_flowLogs(t *testing.T) {
"enable_flow_logs", "false"), "enable_flow_logs", "false"),
), ),
}, },
{
ResourceName: "google_compute_subnetwork.network-with-flow-logs",
ImportState: true,
ImportStateVerify: true,
},
}, },
}) })
} }

View File

@ -112,6 +112,5 @@ deprecation policy, and no SLA, but are otherwise considered to be feature-compl
with only minor outstanding issues after their Alpha period. Beta is when a GCP feature with only minor outstanding issues after their Alpha period. Beta is when a GCP feature
is publicly announced, and is when they generally become publicly available. is publicly announced, and is when they generally become publicly available.
Terraform resources that support beta features will always use the Beta APIs to provision Resources will automatically be provisioned using Beta APIs when you specify a feature
the resource. Importing a resource that supports beta features will always import those marked Beta in your Terraform config file.
features, even if the resource was created in a matter that was not explicitly beta.