Roll forward beta scaffolding PR (#1453)

* Revert "Merge pull request #1434 from terraform-providers/paddy_revert_beta"

This reverts commit 118cd71201, reversing
changes made to d59fcbbc59.

* add ConvertSelfLinkToV1 calls to places where beta links are stored
This commit is contained in:
Dana Hoffman 2018-05-09 11:24:40 -07:00 committed by GitHub
parent 4c4b4be413
commit 8907321d60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 411 additions and 1554 deletions

View File

@ -1,254 +0,0 @@
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

@ -1,326 +0,0 @@
package google
import (
"reflect"
"testing"
)
type ExpectedApiVersions struct {
Create ApiVersion
ReadDelete ApiVersion
Update ApiVersion
}
func TestApiVersion(t *testing.T) {
baseVersion := v1
betaVersion := v0beta
maxTestApiVersion := func(versionsInUse map[ApiVersion]struct{}) ApiVersion {
if _, ok := versionsInUse[betaVersion]; ok {
return betaVersion
}
return baseVersion
}
cases := map[string]struct {
Features []Feature
FieldsInSchema map[string]interface{}
UpdatedFields []string
UpdateOnlyFields []Feature
ExpectedApiVersions
}{
"no beta field": {
FieldsInSchema: map[string]interface{}{
"normal_field": "foo",
},
ExpectedApiVersions: ExpectedApiVersions{
Create: baseVersion,
ReadDelete: baseVersion,
Update: baseVersion,
},
},
"beta field not set": {
Features: []Feature{{Version: betaVersion, Item: "beta_field"}},
FieldsInSchema: map[string]interface{}{
"normal_field": "foo",
},
ExpectedApiVersions: ExpectedApiVersions{
Create: baseVersion,
ReadDelete: baseVersion,
Update: baseVersion,
},
},
"beta field set": {
Features: []Feature{{Version: betaVersion, Item: "beta_field"}},
FieldsInSchema: map[string]interface{}{
"normal_field": "foo",
"beta_field": "bar",
},
ExpectedApiVersions: ExpectedApiVersions{
Create: betaVersion,
ReadDelete: betaVersion,
Update: betaVersion,
},
},
"update only beta field": {
FieldsInSchema: map[string]interface{}{
"normal_field": "foo",
},
UpdatedFields: []string{"beta_update_field"},
UpdateOnlyFields: []Feature{{Version: betaVersion, Item: "beta_update_field"}},
ExpectedApiVersions: ExpectedApiVersions{
Create: baseVersion,
ReadDelete: baseVersion,
Update: betaVersion,
},
},
"nested beta field not set": {
Features: []Feature{{Version: betaVersion, Item: "list_field.*.beta_nested_field"}},
FieldsInSchema: map[string]interface{}{
"list_field.#": 2,
"list_field.0.normal_field": "foo",
"list_field.1.normal_field": "bar",
},
ExpectedApiVersions: ExpectedApiVersions{
Create: baseVersion,
ReadDelete: baseVersion,
Update: baseVersion,
},
},
"nested beta field set": {
Features: []Feature{{Version: betaVersion, Item: "list_field.*.beta_nested_field"}},
FieldsInSchema: map[string]interface{}{
"list_field.#": 2,
"list_field.0.normal_field": "foo",
"list_field.1.normal_field": "bar",
"list_field.1.beta_nested_field": "baz",
},
ExpectedApiVersions: ExpectedApiVersions{
Create: betaVersion,
ReadDelete: betaVersion,
Update: betaVersion,
},
},
"double nested fields set": {
Features: []Feature{{Version: betaVersion, Item: "list_field.*.nested_list_field.*.beta_nested_field"}},
FieldsInSchema: map[string]interface{}{
"list_field.#": 1,
"list_field.0.nested_list_field.#": 1,
"list_field.0.nested_list_field.0.beta_nested_field": "foo",
},
ExpectedApiVersions: ExpectedApiVersions{
Create: betaVersion,
ReadDelete: betaVersion,
Update: betaVersion,
},
},
"beta field has default value": {
Features: []Feature{{Version: betaVersion, Item: "beta_field", DefaultValue: "bar"}},
FieldsInSchema: map[string]interface{}{
"normal_field": "foo",
"beta_field": "bar",
},
ExpectedApiVersions: ExpectedApiVersions{
Create: baseVersion,
ReadDelete: baseVersion,
Update: baseVersion,
},
},
"beta field is updated to default value": {
Features: []Feature{{Version: betaVersion, Item: "beta_field", DefaultValue: "bar"}},
FieldsInSchema: map[string]interface{}{
"normal_field": "foo",
"beta_field": "bar",
},
UpdatedFields: []string{"beta_field"},
ExpectedApiVersions: ExpectedApiVersions{
Create: baseVersion,
ReadDelete: baseVersion,
Update: betaVersion,
},
},
"nested beta field has default value": {
Features: []Feature{{Version: betaVersion, Item: "list_field.*.beta_nested_field", DefaultValue: "baz"}},
FieldsInSchema: map[string]interface{}{
"list_field.#": 2,
"list_field.0.normal_field": "foo",
"list_field.1.normal_field": "bar",
"list_field.1.beta_nested_field": "baz",
},
ExpectedApiVersions: ExpectedApiVersions{
Create: baseVersion,
ReadDelete: baseVersion,
Update: baseVersion,
},
},
"nested beta field is updated default value": {
Features: []Feature{{Version: betaVersion, Item: "list_field.*.beta_nested_field", DefaultValue: "baz"}},
FieldsInSchema: map[string]interface{}{
"list_field.#": 2,
"list_field.0.normal_field": "foo",
"list_field.1.normal_field": "bar",
"list_field.1.beta_nested_field": "baz",
},
UpdatedFields: []string{"list_field.1.beta_nested_field"},
ExpectedApiVersions: ExpectedApiVersions{
Create: baseVersion,
ReadDelete: baseVersion,
Update: betaVersion,
},
},
}
for tn, tc := range cases {
// Create
// All fields with value have HasChange set to true.
keys := make([]string, 0, len(tc.FieldsInSchema))
for key := range tc.FieldsInSchema {
keys = append(keys, key)
}
d := &ResourceDataMock{
FieldsInSchema: tc.FieldsInSchema,
FieldsWithHasChange: keys,
}
apiVersion := getApiVersion(d, v1, tc.Features, maxTestApiVersion)
if apiVersion != tc.ExpectedApiVersions.Create {
t.Errorf("bad: %s, Expected to see version %v for create, got version %v", tn, tc.ExpectedApiVersions.Create, apiVersion)
}
// Read/Delete
// All fields have HasChange set to false.
d = &ResourceDataMock{
FieldsInSchema: tc.FieldsInSchema,
}
apiVersion = getApiVersion(d, v1, tc.Features, maxTestApiVersion)
if apiVersion != tc.ExpectedApiVersions.ReadDelete {
t.Errorf("bad: %s, Expected to see version %v for read/delete, got version %v", tn, tc.ExpectedApiVersions.ReadDelete, apiVersion)
}
// Update
// Only fields defined as updated in the test case have HasChange set to true.
d = &ResourceDataMock{
FieldsInSchema: tc.FieldsInSchema,
FieldsWithHasChange: tc.UpdatedFields,
}
apiVersion = getApiVersionUpdate(d, v1, tc.Features, tc.UpdateOnlyFields, maxTestApiVersion)
if apiVersion != tc.ExpectedApiVersions.Update {
t.Errorf("bad: %s, Expected to see version %v for update, got version %v", tn, tc.ExpectedApiVersions.Update, apiVersion)
}
}
}
func TestSetOmittedFields(t *testing.T) {
type Inner struct {
InnerNotOmitted string `json:"notOmitted"`
InnerOmitted []string `json:"-"`
}
type InputOuter struct {
NotOmitted string `json:"notOmitted"`
Omitted []string `json:"-"`
Struct Inner
Pointer *Inner
StructSlice []Inner
PointerSlice []*Inner
Unset *Inner
OnlyInInputType *Inner
}
type OutputOuter struct {
NotOmitted string `json:"notOmitted"`
Omitted []string `json:"-"`
Struct Inner
Pointer *Inner
StructSlice []Inner
PointerSlice []*Inner
Unset *Inner
OnlyInOutputType *Inner
}
input := &InputOuter{
NotOmitted: "foo",
Omitted: []string{"foo"},
Struct: Inner{
InnerNotOmitted: "foo",
InnerOmitted: []string{"foo"},
},
Pointer: &Inner{
InnerNotOmitted: "foo",
InnerOmitted: []string{"foo"},
},
StructSlice: []Inner{
{
InnerNotOmitted: "foo",
InnerOmitted: []string{"foo"},
}, {
InnerNotOmitted: "bar",
InnerOmitted: []string{"bar"},
},
},
PointerSlice: []*Inner{
{
InnerNotOmitted: "foo",
InnerOmitted: []string{"foo"},
}, {
InnerNotOmitted: "bar",
InnerOmitted: []string{"bar"},
},
},
OnlyInInputType: &Inner{
InnerNotOmitted: "foo",
InnerOmitted: []string{"foo"},
},
}
output := &OutputOuter{}
Convert(input, output)
if input.NotOmitted != output.NotOmitted ||
!reflect.DeepEqual(input.Omitted, output.Omitted) ||
!reflect.DeepEqual(input.Struct, output.Struct) ||
!reflect.DeepEqual(input.Pointer, output.Pointer) ||
!reflect.DeepEqual(input.StructSlice, output.StructSlice) ||
!reflect.DeepEqual(input.PointerSlice, output.PointerSlice) ||
!(input.Unset == nil && output.Unset == nil) {
t.Errorf("Structs were not equivalent after conversion:\nInput:%#v\nOutput: %#v", input, output)
}
}
type ResourceDataMock struct {
FieldsInSchema map[string]interface{}
FieldsWithHasChange []string
id string
}
func (d *ResourceDataMock) HasChange(key string) bool {
exists := false
for _, val := range d.FieldsWithHasChange {
if key == val {
exists = true
}
}
return exists
}
func (d *ResourceDataMock) GetOk(key string) (interface{}, bool) {
for k, v := range d.FieldsInSchema {
if key == k {
return v, true
}
}
return nil, false
}
func (d *ResourceDataMock) Set(key string, value interface{}) error {
d.FieldsInSchema[key] = value
return nil
}
func (d *ResourceDataMock) SetId(v string) {
d.id = v
}
func (d *ResourceDataMock) Id() string {
return d.id
}

77
google/convert.go Normal file
View File

@ -0,0 +1,77 @@
package google
import (
"encoding/json"
"reflect"
)
// 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())
}
}
}
}

79
google/convert_test.go Normal file
View File

@ -0,0 +1,79 @@
package google
import (
"reflect"
"testing"
)
func TestSetOmittedFields(t *testing.T) {
type Inner struct {
InnerNotOmitted string `json:"notOmitted"`
InnerOmitted []string `json:"-"`
}
type InputOuter struct {
NotOmitted string `json:"notOmitted"`
Omitted []string `json:"-"`
Struct Inner
Pointer *Inner
StructSlice []Inner
PointerSlice []*Inner
Unset *Inner
OnlyInInputType *Inner
}
type OutputOuter struct {
NotOmitted string `json:"notOmitted"`
Omitted []string `json:"-"`
Struct Inner
Pointer *Inner
StructSlice []Inner
PointerSlice []*Inner
Unset *Inner
OnlyInOutputType *Inner
}
input := &InputOuter{
NotOmitted: "foo",
Omitted: []string{"foo"},
Struct: Inner{
InnerNotOmitted: "foo",
InnerOmitted: []string{"foo"},
},
Pointer: &Inner{
InnerNotOmitted: "foo",
InnerOmitted: []string{"foo"},
},
StructSlice: []Inner{
{
InnerNotOmitted: "foo",
InnerOmitted: []string{"foo"},
}, {
InnerNotOmitted: "bar",
InnerOmitted: []string{"bar"},
},
},
PointerSlice: []*Inner{
{
InnerNotOmitted: "foo",
InnerOmitted: []string{"foo"},
}, {
InnerNotOmitted: "bar",
InnerOmitted: []string{"bar"},
},
},
OnlyInInputType: &Inner{
InnerNotOmitted: "foo",
InnerOmitted: []string{"foo"},
},
}
output := &OutputOuter{}
Convert(input, output)
if input.NotOmitted != output.NotOmitted ||
!reflect.DeepEqual(input.Omitted, output.Omitted) ||
!reflect.DeepEqual(input.Struct, output.Struct) ||
!reflect.DeepEqual(input.Pointer, output.Pointer) ||
!reflect.DeepEqual(input.StructSlice, output.StructSlice) ||
!reflect.DeepEqual(input.PointerSlice, output.PointerSlice) ||
!(input.Unset == nil && output.Unset == nil) {
t.Errorf("Structs were not equivalent after conversion:\nInput:%#v\nOutput: %#v", input, output)
}
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"github.com/hashicorp/terraform/helper/schema"
computeBeta "google.golang.org/api/compute/v0.beta"
"google.golang.org/api/compute/v1"
)
@ -123,3 +124,7 @@ func flattenSecondaryRanges(secondaryRanges []*compute.SubnetworkSecondaryRange)
func createSubnetID(s *compute.Subnetwork) string {
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,9 +12,6 @@ import (
compute "google.golang.org/api/compute/v1"
)
var BackendServiceBaseApiVersion = v1
var BackendServiceVersionedFeatures = []Feature{Feature{Version: v0beta, Item: "security_policy"}}
func resourceComputeBackendService() *schema.Resource {
return &schema.Resource{
Create: resourceComputeBackendServiceCreate,
@ -288,7 +285,6 @@ func resourceComputeBackendServiceCreate(d *schema.ResourceData, meta interface{
}
func resourceComputeBackendServiceRead(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, BackendServiceBaseApiVersion, BackendServiceVersionedFeatures)
config := meta.(*Config)
project, err := getProject(d, config)
@ -296,25 +292,9 @@ func resourceComputeBackendServiceRead(d *schema.ResourceData, meta interface{})
return err
}
service := &computeBeta.BackendService{}
switch computeApiVersion {
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)))
}
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)
@ -325,7 +305,7 @@ func resourceComputeBackendServiceRead(d *schema.ResourceData, meta interface{})
d.Set("session_affinity", service.SessionAffinity)
d.Set("timeout_sec", service.TimeoutSec)
d.Set("fingerprint", service.Fingerprint)
d.Set("self_link", service.SelfLink)
d.Set("self_link", ConvertSelfLinkToV1(service.SelfLink))
d.Set("backend", flattenBackends(service.Backends))
d.Set("connection_draining_timeout_sec", service.ConnectionDraining.DrainingTimeoutSec)
d.Set("iap", flattenIap(service.Iap))

View File

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

View File

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

View File

@ -19,9 +19,6 @@ import (
"google.golang.org/api/googleapi"
)
var InstanceBaseApiVersion = v1
var InstanceVersionedFeatures = []Feature{}
func resourceComputeInstance() *schema.Resource {
return &schema.Resource{
Create: resourceComputeInstanceCreate,
@ -595,21 +592,9 @@ func getInstance(config *Config, d *schema.ResourceData) (*computeBeta.Instance,
if err != nil {
return nil, err
}
instance := &computeBeta.Instance{}
switch getComputeApiVersion(d, InstanceBaseApiVersion, InstanceVersionedFeatures) {
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)))
}
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
}
@ -745,17 +730,7 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err
}
log.Printf("[INFO] Requesting instance creation")
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()
}
op, err := config.clientComputeBeta.Instances.Insert(project, zone.Name, instance).Do()
if err != nil {
return fmt.Errorf("Error creating instance: %s", err)
}
@ -887,7 +862,7 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
}
adIndex, inConfig := attachedDiskSources[source.RelativeLink()]
di := map[string]interface{}{
"source": disk.Source,
"source": ConvertSelfLinkToV1(disk.Source),
"device_name": disk.DeviceName,
"mode": disk.Mode,
}
@ -1608,7 +1583,7 @@ func flattenBootDisk(d *schema.ResourceData, disk *computeBeta.AttachedDisk, con
result := map[string]interface{}{
"auto_delete": disk.AutoDelete,
"device_name": disk.DeviceName,
"source": disk.Source,
"source": ConvertSelfLinkToV1(disk.Source),
// disk_encryption_key_raw is not returned from the API, so copy it from what the user
// originally specified to avoid diffs.
"disk_encryption_key_raw": d.Get("boot_disk.0.disk_encryption_key_raw"),

View File

@ -14,12 +14,6 @@ import (
"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 {
return &schema.Resource{
Create: resourceComputeInstanceGroupManagerCreate,
@ -234,7 +228,6 @@ func getNamedPortsBeta(nps []interface{}) []*computeBeta.NamedPort {
}
func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, InstanceGroupManagerBaseApiVersion, InstanceGroupManagerVersionedFeatures)
config := meta.(*Config)
project, err := getProject(d, config)
@ -266,29 +259,8 @@ func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta inte
}
log.Printf("[DEBUG] InstanceGroupManager insert request: %#v", manager)
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.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()
}
op, err := config.clientComputeBeta.InstanceGroupManagers.Insert(
project, zone, manager).Do()
if err != nil {
return fmt.Errorf("Error creating InstanceGroupManager: %s", err)
@ -319,7 +291,6 @@ func flattenNamedPortsBeta(namedPorts []*computeBeta.NamedPort) []map[string]int
}
func getManager(d *schema.ResourceData, meta interface{}) (*computeBeta.InstanceGroupManager, error) {
computeApiVersion := getComputeApiVersion(d, InstanceGroupManagerBaseApiVersion, InstanceGroupManagerVersionedFeatures)
config := meta.(*Config)
project, err := getProject(d, config)
@ -332,82 +303,38 @@ func getManager(d *schema.ResourceData, meta interface{}) (*computeBeta.Instance
return nil, err
}
manager := &computeBeta.InstanceGroupManager{}
switch computeApiVersion {
case v1:
getInstanceGroupManager := func(zone string) (interface{}, error) {
return config.clientCompute.InstanceGroupManagers.Get(project, zone, d.Id()).Do()
}
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
getInstanceGroupManager := func(zone string) (interface{}, error) {
return config.clientComputeBeta.InstanceGroupManagers.Get(project, zone, d.Id()).Do()
}
var manager *computeBeta.InstanceGroupManager
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)
}
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
}
@ -424,7 +351,7 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf
}
d.Set("base_instance_name", manager.BaseInstanceName)
d.Set("instance_template", manager.InstanceTemplate)
d.Set("instance_template", ConvertSelfLinkToV1(manager.InstanceTemplate))
d.Set("name", manager.Name)
d.Set("zone", GetResourceNameFromSelfLink(manager.Zone))
d.Set("description", manager.Description)
@ -433,7 +360,7 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf
d.Set("target_pools", manager.TargetPools)
d.Set("named_port", flattenNamedPortsBeta(manager.NamedPorts))
d.Set("fingerprint", manager.Fingerprint)
d.Set("instance_group", manager.InstanceGroup)
d.Set("instance_group", ConvertSelfLinkToV1(manager.InstanceGroup))
d.Set("self_link", ConvertSelfLinkToV1(manager.SelfLink))
update_strategy, ok := d.GetOk("update_strategy")
if !ok {
@ -459,7 +386,6 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf
}
func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersionUpdate(d, InstanceGroupManagerBaseApiVersion, InstanceGroupManagerVersionedFeatures, []Feature{})
config := meta.(*Config)
project, err := getProject(d, config)
@ -488,27 +414,8 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
TargetPools: targetPools,
}
var op interface{}
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()
}
op, err := config.clientComputeBeta.InstanceGroupManagers.SetTargetPools(
project, zone, d.Id(), setTargetPools).Do()
if err != nil {
return fmt.Errorf("Error updating InstanceGroupManager: %s", err)
@ -530,27 +437,8 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
InstanceTemplate: d.Get("instance_template").(string),
}
var op interface{}
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()
}
op, err := config.clientComputeBeta.InstanceGroupManagers.SetInstanceTemplate(
project, zone, d.Id(), setInstanceTemplate).Do()
if err != nil {
return fmt.Errorf("Error updating InstanceGroupManager: %s", err)
@ -563,30 +451,10 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
}
if d.Get("update_strategy").(string) == "RESTART" {
managedInstances := &computeBeta.InstanceGroupManagersListManagedInstancesResponse{}
switch computeApiVersion {
case v1:
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
}
managedInstances, err := config.clientComputeBeta.InstanceGroupManagers.ListManagedInstances(
project, zone, d.Id()).Do()
if err != nil {
return fmt.Errorf("Error getting instance group managers instances: %s", err)
}
managedInstanceCount := len(managedInstances.ManagedInstances)
@ -599,32 +467,10 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
Instances: instances,
}
var op interface{}
switch computeApiVersion {
case v1:
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)
}
op, err = config.clientComputeBeta.InstanceGroupManagers.RecreateInstances(
project, zone, d.Id(), recreateInstances).Do()
if err != nil {
return fmt.Errorf("Error restarting instance group managers instances: %s", err)
}
// Wait for the operation to complete
@ -669,27 +515,8 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
}
// Make the request:
var op interface{}
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()
}
op, err := config.clientComputeBeta.InstanceGroups.SetNamedPorts(
project, zone, d.Id(), setNamedPorts).Do()
if err != nil {
return fmt.Errorf("Error updating InstanceGroupManager: %s", err)
@ -706,15 +533,8 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
if d.HasChange("target_size") {
targetSize := int64(d.Get("target_size").(int))
var op interface{}
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()
}
op, err := config.clientComputeBeta.InstanceGroupManagers.Resize(
project, zone, d.Id(), targetSize).Do()
if err != nil {
return fmt.Errorf("Error updating InstanceGroupManager: %s", err)
@ -758,7 +578,6 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
}
func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, InstanceGroupManagerBaseApiVersion, InstanceGroupManagerVersionedFeatures)
config := meta.(*Config)
project, err := getProject(d, config)
@ -771,24 +590,12 @@ func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta inte
return err
}
var op interface{}
switch computeApiVersion {
case v1:
op, err = config.clientCompute.InstanceGroupManagers.Delete(project, zone, d.Id()).Do()
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()
attempt := 0
for err != nil && attempt < 20 {
attempt++
time.Sleep(2000 * time.Millisecond)
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 {
@ -805,26 +612,14 @@ func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta inte
return err
}
var instanceGroupSize int64
switch computeApiVersion {
case v1:
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
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
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 {
return fmt.Errorf("Error, instance group isn't shrinking during delete")
}

View File

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

View File

@ -6,13 +6,9 @@ import (
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
computeBeta "google.golang.org/api/compute/v0.beta"
"google.golang.org/api/compute/v1"
"google.golang.org/api/googleapi"
)
var InstanceTemplateBaseApiVersion = v1
var InstanceTemplateVersionedFeatures = []Feature{}
func resourceComputeInstanceTemplate() *schema.Resource {
return &schema.Resource{
Create: resourceComputeInstanceTemplateCreate,
@ -610,17 +606,7 @@ func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interfac
Name: itName,
}
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()
}
op, err := config.clientComputeBeta.InstanceTemplates.Insert(project, instanceTemplate).Do()
if err != nil {
return fmt.Errorf("Error creating instance template: %s", err)
}
@ -670,22 +656,9 @@ func resourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interface{
return err
}
instanceTemplate := &computeBeta.InstanceTemplate{}
switch getComputeApiVersion(d, InstanceBaseApiVersion, InstanceVersionedFeatures) {
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)))
}
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.

View File

@ -8,9 +8,6 @@ import (
"google.golang.org/api/compute/v1"
)
var ProjectMetadataBaseApiVersion = v1
var ProjectMetadataVersionedFeatures = []Feature{}
func resourceComputeProjectMetadata() *schema.Resource {
return &schema.Resource{
Create: resourceComputeProjectMetadataCreate,

View File

@ -12,16 +12,8 @@ import (
"github.com/hashicorp/terraform/helper/validation"
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 {
return &schema.Resource{
Create: resourceComputeRegionInstanceGroupManagerCreate,
@ -230,7 +222,6 @@ func resourceComputeRegionInstanceGroupManager() *schema.Resource {
}
func resourceComputeRegionInstanceGroupManagerCreate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, RegionInstanceGroupManagerBaseApiVersion, RegionInstanceGroupManagerVersionedFeatures)
config := meta.(*Config)
project, err := getProject(d, config)
@ -256,19 +247,7 @@ func resourceComputeRegionInstanceGroupManagerCreate(d *schema.ResourceData, met
ForceSendFields: []string{"TargetSize"},
}
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()
}
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.Insert(project, d.Get("region").(string), manager).Do()
if err != nil {
return fmt.Errorf("Error creating RegionInstanceGroupManager: %s", err)
@ -287,7 +266,6 @@ func resourceComputeRegionInstanceGroupManagerCreate(d *schema.ResourceData, met
type getInstanceManagerFunc func(*schema.ResourceData, interface{}) (*computeBeta.InstanceGroupManager, error)
func getRegionalManager(d *schema.ResourceData, meta interface{}) (*computeBeta.InstanceGroupManager, error) {
computeApiVersion := getComputeApiVersion(d, RegionInstanceGroupManagerBaseApiVersion, RegionInstanceGroupManagerVersionedFeatures)
config := meta.(*Config)
project, err := getProject(d, config)
@ -299,32 +277,12 @@ func getRegionalManager(d *schema.ResourceData, meta interface{}) (*computeBeta.
if err != nil {
return nil, err
}
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 {
return nil, handleNotFoundError(err, d, fmt.Sprintf("Region Instance Manager %q", d.Get("name").(string)))
}
return manager, nil
}
@ -389,7 +347,6 @@ func resourceComputeRegionInstanceGroupManagerRead(d *schema.ResourceData, meta
}
func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersionUpdate(d, RegionInstanceGroupManagerBaseApiVersion, RegionInstanceGroupManagerVersionedFeatures, []Feature{})
config := meta.(*Config)
project, err := getProject(d, config)
@ -414,27 +371,8 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
TargetPools: targetPools,
}
var op interface{}
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()
}
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.SetTargetPools(
project, region, d.Id(), setTargetPools).Do()
if err != nil {
return fmt.Errorf("Error updating RegionInstanceGroupManager: %s", err)
@ -455,27 +393,8 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
InstanceTemplate: d.Get("instance_template").(string),
}
var op interface{}
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()
}
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.SetInstanceTemplate(
project, region, d.Id(), setInstanceTemplate).Do()
if err != nil {
return fmt.Errorf("Error updating RegionInstanceGroupManager: %s", err)
@ -520,27 +439,8 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
}
// Make the request:
var op interface{}
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()
}
op, err := config.clientComputeBeta.RegionInstanceGroups.SetNamedPorts(
project, region, d.Id(), setNamedPorts).Do()
if err != nil {
return fmt.Errorf("Error updating RegionInstanceGroupManager: %s", err)
@ -557,15 +457,8 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
if d.HasChange("target_size") {
targetSize := int64(d.Get("target_size").(int))
var op interface{}
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()
}
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.Resize(
project, region, d.Id(), targetSize).Do()
if err != nil {
return fmt.Errorf("Error resizing RegionInstanceGroupManager: %s", err)
@ -608,7 +501,6 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
}
func resourceComputeRegionInstanceGroupManagerDelete(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, RegionInstanceGroupManagerBaseApiVersion, RegionInstanceGroupManagerVersionedFeatures)
config := meta.(*Config)
project, err := getProject(d, config)
@ -618,13 +510,7 @@ func resourceComputeRegionInstanceGroupManagerDelete(d *schema.ResourceData, met
region := d.Get("region").(string)
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()
}
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.Delete(project, region, d.Id()).Do()
if err != nil {
return fmt.Errorf("Error deleting region instance group manager: %s", err)

View File

@ -14,14 +14,6 @@ import (
"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 {
return &schema.Resource{
Create: resourceComputeSubnetworkCreate,
@ -130,7 +122,6 @@ func resourceComputeSubnetwork() *schema.Resource {
}
func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, SubnetworkBaseApiVersion, SubnetworkVersionedFeatures)
config := meta.(*Config)
network, err := ParseNetworkFieldValue(d.Get("network").(string), d, config)
if err != nil {
@ -160,21 +151,7 @@ func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) e
log.Printf("[DEBUG] Subnetwork insert request: %#v", subnetwork)
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()
}
op, err := config.clientComputeBeta.Subnetworks.Insert(project, region, subnetwork).Do()
if err != nil {
return fmt.Errorf("Error creating subnetwork: %s", err)
}
@ -184,9 +161,8 @@ 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.
// 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
subnetworkV1.Region = region
subnetwork.Region = region
d.SetId(createSubnetID(subnetworkV1))
d.SetId(createSubnetIDBeta(subnetwork))
err = computeSharedOperationWaitTime(config.clientCompute, op, project, int(d.Timeout(schema.TimeoutCreate).Minutes()), "Creating Subnetwork")
if err != nil {
@ -197,45 +173,6 @@ func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) e
}
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)
region, err := getRegion(d, config)
@ -272,7 +209,6 @@ func resourceComputeSubnetworkReadV0Beta(d *schema.ResourceData, meta interface{
}
func resourceComputeSubnetworkUpdate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, SubnetworkBaseApiVersion, SubnetworkVersionedFeatures)
config := meta.(*Config)
region, err := getRegion(d, config)
@ -328,7 +264,7 @@ func resourceComputeSubnetworkUpdate(d *schema.ResourceData, meta interface{}) e
d.SetPartial("ip_cidr_range")
}
if (d.HasChange("secondary_ip_range") || d.HasChange("enable_flow_logs")) && computeApiVersion == v0beta {
if d.HasChange("secondary_ip_range") || d.HasChange("enable_flow_logs") {
v0BetaSubnetwork := &computeBeta.Subnetwork{
Fingerprint: d.Get("fingerprint").(string),
}

View File

@ -193,7 +193,11 @@ func TestAccComputeSubnetwork_flowLogs(t *testing.T) {
"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),
Check: resource.ComposeTestCheckFunc(
@ -203,6 +207,11 @@ func TestAccComputeSubnetwork_flowLogs(t *testing.T) {
"enable_flow_logs", "false"),
),
},
{
ResourceName: "google_compute_subnetwork.network-with-flow-logs",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

View File

@ -12,23 +12,12 @@ import (
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"google.golang.org/api/container/v1"
containerBeta "google.golang.org/api/container/v1beta1"
)
var (
instanceGroupManagerURL = regexp.MustCompile(fmt.Sprintf("^https://www.googleapis.com/compute/v1/projects/(%s)/zones/([a-z0-9-]*)/instanceGroupManagers/([^/]*)", ProjectRegex))
ContainerClusterBaseApiVersion = v1
ContainerClusterVersionedFeatures = []Feature{
{Version: v1beta1, Item: "pod_security_policy_config"},
{Version: v1beta1, Item: "node_config.*.taint"},
{Version: v1beta1, Item: "node_config.*.workload_metadata_config"},
{Version: v1beta1, Item: "private_cluster"},
{Version: v1beta1, Item: "master_ipv4_cidr_block"},
{Version: v1beta1, Item: "region"},
}
networkConfig = &schema.Resource{
Schema: map[string]*schema.Schema{
"cidr_blocks": {
@ -475,7 +464,6 @@ func resourceContainerCluster() *schema.Resource {
}
func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) error {
containerAPIVersion := getContainerApiVersion(d, ContainerClusterBaseApiVersion, ContainerClusterVersionedFeatures)
config := meta.(*Config)
project, err := getProject(d, config)
@ -651,25 +639,8 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
mutexKV.Lock(containerClusterMutexKey(project, location, clusterName))
defer mutexKV.Unlock(containerClusterMutexKey(project, location, clusterName))
var op interface{}
switch containerAPIVersion {
case v1:
reqV1 := &container.CreateClusterRequest{}
err = Convert(req, reqV1)
if err != nil {
return err
}
op, err = config.clientContainer.Projects.Zones.Clusters.Create(project, location, reqV1).Do()
case v1beta1:
reqV1Beta := &containerBeta.CreateClusterRequest{}
err = Convert(req, reqV1Beta)
if err != nil {
return err
}
parent := fmt.Sprintf("projects/%s/locations/%s", project, location)
op, err = config.clientContainerBeta.Projects.Locations.Clusters.Create(parent, reqV1Beta).Do()
}
parent := fmt.Sprintf("projects/%s/locations/%s", project, location)
op, err := config.clientContainerBeta.Projects.Locations.Clusters.Create(parent, req).Do()
if err != nil {
return err
}
@ -687,15 +658,8 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
log.Printf("[INFO] GKE cluster %s has been created", clusterName)
if d.Get("remove_default_node_pool").(bool) {
var op interface{}
switch containerAPIVersion {
case v1:
op, err = config.clientContainer.Projects.Zones.Clusters.NodePools.Delete(
project, location, clusterName, "default-pool").Do()
case v1beta1:
parent := fmt.Sprintf("%s/nodePools/%s", containerClusterFullName(project, location, clusterName), "default-pool")
op, err = config.clientContainerBeta.Projects.Locations.Clusters.NodePools.Delete(parent).Do()
}
parent := fmt.Sprintf("%s/nodePools/%s", containerClusterFullName(project, location, clusterName), "default-pool")
op, err = config.clientContainerBeta.Projects.Locations.Clusters.NodePools.Delete(parent).Do()
if err != nil {
return errwrap.Wrapf("Error deleting default node pool: {{err}}", err)
}
@ -709,7 +673,6 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
}
func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) error {
containerAPIVersion := getContainerApiVersion(d, ContainerClusterBaseApiVersion, ContainerClusterVersionedFeatures)
config := meta.(*Config)
project, err := getProject(d, config)
@ -723,20 +686,9 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
}
cluster := &containerBeta.Cluster{}
var clust interface{}
err = resource.Retry(2*time.Minute, func() *resource.RetryError {
switch containerAPIVersion {
case v1:
clust, err = config.clientContainer.Projects.Zones.Clusters.Get(
project, location, d.Get("name").(string)).Do()
case v1beta1:
name := containerClusterFullName(project, location, d.Get("name").(string))
clust, err = config.clientContainerBeta.Projects.Locations.Clusters.Get(name).Do()
}
if err != nil {
return resource.NonRetryableError(err)
}
err = Convert(clust, cluster)
name := containerClusterFullName(project, location, d.Get("name").(string))
cluster, err = config.clientContainerBeta.Projects.Locations.Clusters.Get(name).Do()
if err != nil {
return resource.NonRetryableError(err)
}
@ -834,7 +786,6 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
}
func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) error {
containerAPIVersion := getContainerApiVersion(d, ContainerClusterBaseApiVersion, ContainerClusterVersionedFeatures)
config := meta.(*Config)
project, err := getProject(d, config)
@ -854,22 +805,10 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
lockKey := containerClusterMutexKey(project, location, clusterName)
updateFunc := func(req *container.UpdateClusterRequest, updateDescription string) func() error {
updateFunc := func(req *containerBeta.UpdateClusterRequest, updateDescription string) func() error {
return func() error {
var err error
var op interface{}
switch containerAPIVersion {
case v1:
op, err = config.clientContainer.Projects.Zones.Clusters.Update(project, location, clusterName, req).Do()
case v1beta1:
reqV1Beta := &containerBeta.UpdateClusterRequest{}
err = Convert(req, reqV1Beta)
if err != nil {
return err
}
name := containerClusterFullName(project, location, clusterName)
op, err = config.clientContainerBeta.Projects.Locations.Clusters.Update(name, reqV1Beta).Do()
}
name := containerClusterFullName(project, location, clusterName)
op, err := config.clientContainerBeta.Projects.Locations.Clusters.Update(name, req).Do()
if err != nil {
return err
}
@ -883,14 +822,9 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
// if the order of updating fields does matter, it is called out explicitly.
if d.HasChange("master_authorized_networks_config") {
c := d.Get("master_authorized_networks_config")
conf := &container.MasterAuthorizedNetworksConfig{}
err := Convert(expandMasterAuthorizedNetworksConfig(c), conf)
if err != nil {
return err
}
req := &container.UpdateClusterRequest{
Update: &container.ClusterUpdate{
DesiredMasterAuthorizedNetworksConfig: conf,
req := &containerBeta.UpdateClusterRequest{
Update: &containerBeta.ClusterUpdate{
DesiredMasterAuthorizedNetworksConfig: expandMasterAuthorizedNetworksConfig(c),
},
}
@ -918,8 +852,8 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
// Only upgrade the master if the current version is lower than the desired version
if cur.LessThan(des) {
req := &container.UpdateClusterRequest{
Update: &container.ClusterUpdate{
req := &containerBeta.UpdateClusterRequest{
Update: &containerBeta.ClusterUpdate{
DesiredMasterVersion: desiredMasterVersion,
},
}
@ -936,8 +870,8 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
if d.HasChange("node_version") {
desiredNodeVersion := d.Get("node_version").(string)
req := &container.UpdateClusterRequest{
Update: &container.ClusterUpdate{
req := &containerBeta.UpdateClusterRequest{
Update: &containerBeta.ClusterUpdate{
DesiredNodeVersion: desiredNodeVersion,
},
}
@ -955,14 +889,9 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
if d.HasChange("addons_config") {
if ac, ok := d.GetOk("addons_config"); ok {
conf := &container.AddonsConfig{}
err := Convert(expandClusterAddonsConfig(ac), conf)
if err != nil {
return err
}
req := &container.UpdateClusterRequest{
Update: &container.ClusterUpdate{
DesiredAddonsConfig: conf,
req := &containerBeta.UpdateClusterRequest{
Update: &containerBeta.ClusterUpdate{
DesiredAddonsConfig: expandClusterAddonsConfig(ac),
},
}
@ -979,37 +908,20 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
}
if d.HasChange("maintenance_policy") {
var req *container.SetMaintenancePolicyRequest
var req *containerBeta.SetMaintenancePolicyRequest
if mp, ok := d.GetOk("maintenance_policy"); ok {
pol := &container.MaintenancePolicy{}
err := Convert(expandMaintenancePolicy(mp), pol)
if err != nil {
return err
}
req = &container.SetMaintenancePolicyRequest{
MaintenancePolicy: pol,
req = &containerBeta.SetMaintenancePolicyRequest{
MaintenancePolicy: expandMaintenancePolicy(mp),
}
} else {
req = &container.SetMaintenancePolicyRequest{
req = &containerBeta.SetMaintenancePolicyRequest{
NullFields: []string{"MaintenancePolicy"},
}
}
updateF := func() error {
var op interface{}
switch containerAPIVersion {
case v1:
op, err = config.clientContainer.Projects.Zones.Clusters.SetMaintenancePolicy(
project, location, clusterName, req).Do()
case v1beta1:
reqV1Beta := &containerBeta.SetMaintenancePolicyRequest{}
err = Convert(req, reqV1Beta)
if err != nil {
return err
}
name := containerClusterFullName(project, location, clusterName)
op, err = config.clientContainerBeta.Projects.Locations.Clusters.SetMaintenancePolicy(name, reqV1Beta).Do()
}
name := containerClusterFullName(project, location, clusterName)
op, err := config.clientContainerBeta.Projects.Locations.Clusters.SetMaintenancePolicy(name, req).Do()
if err != nil {
return err
@ -1044,8 +956,8 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
azSet.Add(location)
}
req := &container.UpdateClusterRequest{
Update: &container.ClusterUpdate{
req := &containerBeta.UpdateClusterRequest{
Update: &containerBeta.ClusterUpdate{
DesiredLocations: convertStringSet(azSet),
},
}
@ -1060,8 +972,8 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
azSetNew.Add(location)
}
if !azSet.Equal(azSetNew) {
req = &container.UpdateClusterRequest{
Update: &container.ClusterUpdate{
req = &containerBeta.UpdateClusterRequest{
Update: &containerBeta.ClusterUpdate{
DesiredLocations: convertStringSet(azSetNew),
},
}
@ -1080,26 +992,15 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
if d.HasChange("enable_legacy_abac") {
enabled := d.Get("enable_legacy_abac").(bool)
req := &container.SetLegacyAbacRequest{
req := &containerBeta.SetLegacyAbacRequest{
Enabled: enabled,
ForceSendFields: []string{"Enabled"},
}
updateF := func() error {
log.Println("[DEBUG] updating enable_legacy_abac")
var op interface{}
switch containerAPIVersion {
case v1:
op, err = config.clientContainer.Projects.Zones.Clusters.LegacyAbac(project, location, clusterName, req).Do()
case v1beta1:
reqV1Beta := &containerBeta.SetLegacyAbacRequest{}
err = Convert(req, reqV1Beta)
if err != nil {
return err
}
name := containerClusterFullName(project, location, clusterName)
op, err = config.clientContainerBeta.Projects.Locations.Clusters.SetLegacyAbac(name, reqV1Beta).Do()
}
name := containerClusterFullName(project, location, clusterName)
op, err := config.clientContainerBeta.Projects.Locations.Clusters.SetLegacyAbac(name, req).Do()
if err != nil {
return err
}
@ -1123,8 +1024,8 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
if d.HasChange("monitoring_service") {
desiredMonitoringService := d.Get("monitoring_service").(string)
req := &container.UpdateClusterRequest{
Update: &container.ClusterUpdate{
req := &containerBeta.UpdateClusterRequest{
Update: &containerBeta.ClusterUpdate{
DesiredMonitoringService: desiredMonitoringService,
},
}
@ -1142,32 +1043,14 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
if d.HasChange("network_policy") {
np := d.Get("network_policy")
pol := &container.NetworkPolicy{}
err := Convert(expandNetworkPolicy(np), pol)
if err != nil {
return err
}
req := &container.SetNetworkPolicyRequest{
NetworkPolicy: pol,
req := &containerBeta.SetNetworkPolicyRequest{
NetworkPolicy: expandNetworkPolicy(np),
}
updateF := func() error {
log.Println("[DEBUG] updating network_policy")
var op interface{}
switch containerAPIVersion {
case v1:
op, err = config.clientContainer.Projects.Zones.Clusters.SetNetworkPolicy(
project, location, clusterName, req).Do()
case v1beta1:
reqV1Beta := &containerBeta.SetNetworkPolicyRequest{}
err = Convert(req, reqV1Beta)
if err != nil {
return err
}
name := containerClusterFullName(project, location, clusterName)
op, err = config.clientContainerBeta.Projects.Locations.Clusters.SetNetworkPolicy(name, reqV1Beta).Do()
}
name := containerClusterFullName(project, location, clusterName)
op, err := config.clientContainerBeta.Projects.Locations.Clusters.SetNetworkPolicy(name, req).Do()
if err != nil {
return err
}
@ -1206,24 +1089,12 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
if d.HasChange("logging_service") {
logging := d.Get("logging_service").(string)
req := &container.SetLoggingServiceRequest{
req := &containerBeta.SetLoggingServiceRequest{
LoggingService: logging,
}
updateF := func() error {
var op interface{}
switch containerAPIVersion {
case v1:
op, err = config.clientContainer.Projects.Zones.Clusters.Logging(
project, location, clusterName, req).Do()
case v1beta1:
reqV1Beta := &containerBeta.SetLoggingServiceRequest{}
err = Convert(req, reqV1Beta)
if err != nil {
return err
}
name := containerClusterFullName(project, location, clusterName)
op, err = config.clientContainerBeta.Projects.Locations.Clusters.SetLogging(name, reqV1Beta).Do()
}
name := containerClusterFullName(project, location, clusterName)
op, err := config.clientContainerBeta.Projects.Locations.Clusters.SetLogging(name, req).Do()
if err != nil {
return err
}
@ -1267,15 +1138,8 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
}
if d.HasChange("remove_default_node_pool") && d.Get("remove_default_node_pool").(bool) {
var op interface{}
switch containerAPIVersion {
case v1:
op, err = config.clientContainer.Projects.Zones.Clusters.NodePools.Delete(
project, location, clusterName, "default-pool").Do()
case v1beta1:
name := fmt.Sprintf("%s/nodePools/%s", containerClusterFullName(project, location, clusterName), "default-pool")
op, err = config.clientContainerBeta.Projects.Locations.Clusters.NodePools.Delete(name).Do()
}
name := fmt.Sprintf("%s/nodePools/%s", containerClusterFullName(project, location, clusterName), "default-pool")
op, err := config.clientContainerBeta.Projects.Locations.Clusters.NodePools.Delete(name).Do()
if err != nil {
return errwrap.Wrapf("Error deleting default node pool: {{err}}", err)
}

View File

@ -431,9 +431,6 @@ func TestAccContainerCluster_withPrivateCluster(t *testing.T) {
ImportStateIdPrefix: "us-central1-a/",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"private_cluster",
"master_ipv4_cidr_block"},
},
},
})
@ -642,17 +639,11 @@ func TestAccContainerCluster_withWorkloadMetadataConfig(t *testing.T) {
),
},
{
ResourceName: "google_container_cluster.with_workload_metadata_config",
ImportStateIdPrefix: "us-central1-a/",
ImportState: true,
ImportStateVerify: true,
// Import always uses the v1 API, so beta features don't get imported.
ImportStateVerifyIgnore: []string{
"node_config.0.workload_metadata_config.#",
"node_config.0.workload_metadata_config.0.node_metadata",
"node_pool.0.node_config.0.workload_metadata_config.#",
"node_pool.0.node_config.0.workload_metadata_config.0.node_metadata",
"min_master_version"},
ResourceName: "google_container_cluster.with_workload_metadata_config",
ImportStateIdPrefix: "us-central1-a/",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"min_master_version"},
},
},
})
@ -1125,8 +1116,6 @@ func TestAccContainerCluster_withPodSecurityPolicy(t *testing.T) {
ImportStateIdPrefix: "us-central1-a/",
ImportState: true,
ImportStateVerify: true,
// Import always uses the v1 API, so beta features don't get imported.
ImportStateVerifyIgnore: []string{"pod_security_policy_config.#", "pod_security_policy_config.0.enabled"},
},
{
Config: testAccContainerCluster_withPodSecurityPolicy(clusterName, false),
@ -1140,8 +1129,6 @@ func TestAccContainerCluster_withPodSecurityPolicy(t *testing.T) {
ImportStateIdPrefix: "us-central1-a/",
ImportState: true,
ImportStateVerify: true,
// Import always uses the v1 API, so beta features don't get imported.
ImportStateVerifyIgnore: []string{"pod_security_policy_config.#", "pod_security_policy_config.0.enabled"},
},
},
})

41
google/test_utils.go Normal file
View File

@ -0,0 +1,41 @@
package google
type ResourceDataMock struct {
FieldsInSchema map[string]interface{}
FieldsWithHasChange []string
id string
}
func (d *ResourceDataMock) HasChange(key string) bool {
exists := false
for _, val := range d.FieldsWithHasChange {
if key == val {
exists = true
}
}
return exists
}
func (d *ResourceDataMock) GetOk(key string) (interface{}, bool) {
for k, v := range d.FieldsInSchema {
if key == k {
return v, true
}
}
return nil, false
}
func (d *ResourceDataMock) Set(key string, value interface{}) error {
d.FieldsInSchema[key] = value
return nil
}
func (d *ResourceDataMock) SetId(v string) {
d.id = v
}
func (d *ResourceDataMock) Id() string {
return d.id
}

View File

@ -17,6 +17,14 @@ import (
"google.golang.org/api/googleapi"
)
type TerraformResourceData interface {
HasChange(string) bool
GetOk(string) (interface{}, bool)
Set(string, interface{}) error
SetId(string)
Id() string
}
// getRegionFromZone returns the region from a zone for Google cloud.
func getRegionFromZone(zone string) string {
if zone != "" && len(zone) > 2 {

View File

@ -112,5 +112,6 @@ 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
is publicly announced, and is when they generally become publicly available.
Resources will automatically be provisioned using Beta APIs when you specify a feature
marked Beta in your Terraform config file.
Terraform resources that support beta features will always use the Beta APIs to provision
the resource. Importing a resource that supports beta features will always import those
features, even if the resource was created in a matter that was not explicitly beta.