mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-07-09 03:28:29 +00:00
Roll forward beta scaffolding PR (#1453)
* Revert "Merge pull request #1434 from terraform-providers/paddy_revert_beta" This reverts commit118cd71201
, reversing changes made tod59fcbbc59
. * add ConvertSelfLinkToV1 calls to places where beta links are stored
This commit is contained in:
parent
4c4b4be413
commit
8907321d60
|
@ -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)
|
|
||||||
}
|
|
|
@ -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
77
google/convert.go
Normal 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
79
google/convert_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ 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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -123,3 +124,7 @@ 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)
|
||||||
|
}
|
||||||
|
|
|
@ -12,9 +12,6 @@ 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,
|
||||||
|
@ -288,7 +285,6 @@ 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)
|
||||||
|
@ -296,26 +292,10 @@ func resourceComputeBackendServiceRead(d *schema.ResourceData, meta interface{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
service := &computeBeta.BackendService{}
|
service, err := config.clientComputeBeta.BackendServices.Get(project, d.Id()).Do()
|
||||||
switch computeApiVersion {
|
|
||||||
case v1:
|
|
||||||
v1Service, err := config.clientCompute.BackendServices.Get(
|
|
||||||
project, d.Id()).Do()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return handleNotFoundError(err, d, fmt.Sprintf("Backend Service %q", d.Get("name").(string)))
|
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)
|
||||||
d.Set("description", service.Description)
|
d.Set("description", service.Description)
|
||||||
|
@ -325,7 +305,7 @@ func resourceComputeBackendServiceRead(d *schema.ResourceData, meta interface{})
|
||||||
d.Set("session_affinity", service.SessionAffinity)
|
d.Set("session_affinity", service.SessionAffinity)
|
||||||
d.Set("timeout_sec", service.TimeoutSec)
|
d.Set("timeout_sec", service.TimeoutSec)
|
||||||
d.Set("fingerprint", service.Fingerprint)
|
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("backend", flattenBackends(service.Backends))
|
||||||
d.Set("connection_draining_timeout_sec", service.ConnectionDraining.DrainingTimeoutSec)
|
d.Set("connection_draining_timeout_sec", service.ConnectionDraining.DrainingTimeoutSec)
|
||||||
d.Set("iap", flattenIap(service.Iap))
|
d.Set("iap", flattenIap(service.Iap))
|
||||||
|
|
|
@ -10,12 +10,8 @@ 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,
|
||||||
|
@ -193,7 +189,6 @@ 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)
|
||||||
|
@ -206,31 +201,10 @@ func resourceComputeFirewallCreate(d *schema.ResourceData, meta interface{}) err
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.Firewalls.Insert(project, firewall).Do()
|
||||||
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("Error creating firewall: %s", err)
|
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
|
||||||
d.SetId(firewall.Name)
|
d.SetId(firewall.Name)
|
||||||
|
@ -268,7 +242,6 @@ 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)
|
||||||
|
@ -276,30 +249,11 @@ func resourceComputeFirewallRead(d *schema.ResourceData, meta interface{}) error
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
firewall := &computeBeta.Firewall{}
|
firewall, err := config.clientComputeBeta.Firewalls.Get(project, d.Id()).Do()
|
||||||
switch computeApiVersion {
|
|
||||||
case v1:
|
|
||||||
firewallV1, err := config.clientCompute.Firewalls.Get(project, d.Id()).Do()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return handleNotFoundError(err, d, fmt.Sprintf("Firewall %q", d.Get("name").(string)))
|
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))
|
||||||
d.Set("name", firewall.Name)
|
d.Set("name", firewall.Name)
|
||||||
d.Set("network", ConvertSelfLinkToV1(firewall.Network))
|
d.Set("network", ConvertSelfLinkToV1(firewall.Network))
|
||||||
|
@ -319,7 +273,6 @@ 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)
|
||||||
|
@ -334,31 +287,10 @@ func resourceComputeFirewallUpdate(d *schema.ResourceData, meta interface{}) err
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.Firewalls.Update(project, d.Id(), firewall).Do()
|
||||||
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("Error updating firewall: %s", err)
|
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")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -371,7 +303,6 @@ 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)
|
||||||
|
@ -380,19 +311,10 @@ func resourceComputeFirewallDelete(d *schema.ResourceData, meta interface{}) err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete the firewall
|
// Delete the firewall
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.Firewalls.Delete(project, d.Id()).Do()
|
||||||
switch computeApiVersion {
|
|
||||||
case v1:
|
|
||||||
op, err = config.clientCompute.Firewalls.Delete(project, d.Id()).Do()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error deleting firewall: %s", err)
|
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")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -8,14 +8,9 @@ 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"
|
compute "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,
|
||||||
|
@ -109,7 +104,6 @@ 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)
|
||||||
|
@ -127,31 +121,10 @@ func resourceComputeGlobalForwardingRuleCreate(d *schema.ResourceData, meta inte
|
||||||
Target: d.Get("target").(string),
|
Target: d.Get("target").(string),
|
||||||
}
|
}
|
||||||
|
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.GlobalForwardingRules.Insert(project, frule).Do()
|
||||||
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("Error creating Global Forwarding Rule: %s", err)
|
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
|
||||||
d.SetId(frule.Name)
|
d.SetId(frule.Name)
|
||||||
|
@ -165,12 +138,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, computeApiVersion, project, frule.Name)
|
fingerprint, err := resourceComputeGlobalForwardingRuleReadLabelFingerprint(config, project, frule.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = resourceComputeGlobalForwardingRuleSetLabels(config, computeApiVersion, project, frule.Name, labels, fingerprint)
|
err = resourceComputeGlobalForwardingRuleSetLabels(config, project, frule.Name, labels, fingerprint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -180,7 +153,6 @@ 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)
|
||||||
|
@ -192,35 +164,13 @@ 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 := &computeBeta.TargetReference{Target: target}
|
targetRef := &compute.TargetReference{Target: target}
|
||||||
|
|
||||||
var op interface{}
|
op, err := config.clientCompute.GlobalForwardingRules.SetTarget(
|
||||||
switch computeApiVersion {
|
project, d.Id(), targetRef).Do()
|
||||||
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("Error updating target: %s", err)
|
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")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -233,7 +183,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, computeApiVersion, project, d.Get("name").(string), labels, fingerprint)
|
err = resourceComputeGlobalForwardingRuleSetLabels(config, project, d.Get("name").(string), labels, fingerprint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -247,7 +197,6 @@ 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)
|
||||||
|
@ -255,30 +204,11 @@ func resourceComputeGlobalForwardingRuleRead(d *schema.ResourceData, meta interf
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
frule := &computeBeta.ForwardingRule{}
|
frule, err := config.clientComputeBeta.GlobalForwardingRules.Get(project, d.Id()).Do()
|
||||||
switch computeApiVersion {
|
|
||||||
case v1:
|
|
||||||
v1Frule, err := config.clientCompute.GlobalForwardingRules.Get(project, d.Id()).Do()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return handleNotFoundError(err, d, fmt.Sprintf("Global Forwarding Rule %q", d.Get("name").(string)))
|
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)
|
||||||
d.Set("description", frule.Description)
|
d.Set("description", frule.Description)
|
||||||
d.Set("target", frule.Target)
|
d.Set("target", frule.Target)
|
||||||
|
@ -295,7 +225,6 @@ 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)
|
||||||
|
@ -305,20 +234,10 @@ 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")
|
||||||
var op interface{}
|
op, err := config.clientCompute.GlobalForwardingRules.Delete(project, d.Id()).Do()
|
||||||
switch computeApiVersion {
|
|
||||||
case v1:
|
|
||||||
op, err = config.clientCompute.GlobalForwardingRules.Delete(project, d.Id()).Do()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error deleting GlobalForwardingRule: %s", err)
|
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
|
||||||
|
@ -330,44 +249,25 @@ 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, computeApiVersion ApiVersion,
|
func resourceComputeGlobalForwardingRuleReadLabelFingerprint(config *Config, project, name string) (string, error) {
|
||||||
project, name string) (string, error) {
|
|
||||||
switch computeApiVersion {
|
|
||||||
case v0beta:
|
|
||||||
frule, err := config.clientComputeBeta.GlobalForwardingRules.Get(project, name).Do()
|
frule, err := config.clientComputeBeta.GlobalForwardingRules.Get(project, name).Do()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("Unable to read global forwarding rule to update labels: %s", err)
|
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, computeApiVersion ApiVersion, project,
|
func resourceComputeGlobalForwardingRuleSetLabels(config *Config, project, name string, labels map[string]string, fingerprint string) error {
|
||||||
name string, labels map[string]string, fingerprint string) error {
|
|
||||||
var op interface{}
|
|
||||||
var err error
|
|
||||||
|
|
||||||
switch computeApiVersion {
|
|
||||||
case v0beta:
|
|
||||||
setLabels := computeBeta.GlobalSetLabelsRequest{
|
setLabels := computeBeta.GlobalSetLabelsRequest{
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
LabelFingerprint: fingerprint,
|
LabelFingerprint: fingerprint,
|
||||||
}
|
}
|
||||||
op, err = config.clientComputeBeta.GlobalForwardingRules.SetLabels(project, name, &setLabels).Do()
|
op, err := config.clientComputeBeta.GlobalForwardingRules.SetLabels(project, name, &setLabels).Do()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -19,9 +19,6 @@ 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,
|
||||||
|
@ -595,22 +592,10 @@ func getInstance(config *Config, d *schema.ResourceData) (*computeBeta.Instance,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
instance := &computeBeta.Instance{}
|
instance, err := config.clientComputeBeta.Instances.Get(project, zone, d.Id()).Do()
|
||||||
switch getComputeApiVersion(d, InstanceBaseApiVersion, InstanceVersionedFeatures) {
|
|
||||||
case v1:
|
|
||||||
instanceV1, err := config.clientCompute.Instances.Get(project, zone, d.Id()).Do()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, handleNotFoundError(err, d, fmt.Sprintf("Instance %s", d.Get("name").(string)))
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -745,17 +730,7 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[INFO] Requesting instance creation")
|
log.Printf("[INFO] Requesting instance creation")
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.Instances.Insert(project, zone.Name, instance).Do()
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
@ -887,7 +862,7 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
|
||||||
}
|
}
|
||||||
adIndex, inConfig := attachedDiskSources[source.RelativeLink()]
|
adIndex, inConfig := attachedDiskSources[source.RelativeLink()]
|
||||||
di := map[string]interface{}{
|
di := map[string]interface{}{
|
||||||
"source": disk.Source,
|
"source": ConvertSelfLinkToV1(disk.Source),
|
||||||
"device_name": disk.DeviceName,
|
"device_name": disk.DeviceName,
|
||||||
"mode": disk.Mode,
|
"mode": disk.Mode,
|
||||||
}
|
}
|
||||||
|
@ -1608,7 +1583,7 @@ func flattenBootDisk(d *schema.ResourceData, disk *computeBeta.AttachedDisk, con
|
||||||
result := map[string]interface{}{
|
result := map[string]interface{}{
|
||||||
"auto_delete": disk.AutoDelete,
|
"auto_delete": disk.AutoDelete,
|
||||||
"device_name": disk.DeviceName,
|
"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
|
// disk_encryption_key_raw is not returned from the API, so copy it from what the user
|
||||||
// originally specified to avoid diffs.
|
// originally specified to avoid diffs.
|
||||||
"disk_encryption_key_raw": d.Get("boot_disk.0.disk_encryption_key_raw"),
|
"disk_encryption_key_raw": d.Get("boot_disk.0.disk_encryption_key_raw"),
|
||||||
|
|
|
@ -14,12 +14,6 @@ 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,
|
||||||
|
@ -234,7 +228,6 @@ 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)
|
||||||
|
@ -266,29 +259,8 @@ func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta inte
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] InstanceGroupManager insert request: %#v", manager)
|
log.Printf("[DEBUG] InstanceGroupManager insert request: %#v", manager)
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.InstanceGroupManagers.Insert(
|
||||||
switch computeApiVersion {
|
project, zone, manager).Do()
|
||||||
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)
|
||||||
|
@ -319,7 +291,6 @@ 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)
|
||||||
|
@ -332,56 +303,14 @@ func getManager(d *schema.ResourceData, meta interface{}) (*computeBeta.Instance
|
||||||
return nil, err
|
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) {
|
getInstanceGroupManager := func(zone string) (interface{}, error) {
|
||||||
return config.clientComputeBeta.InstanceGroupManagers.Get(project, zone, d.Id()).Do()
|
return config.clientComputeBeta.InstanceGroupManagers.Get(project, zone, d.Id()).Do()
|
||||||
}
|
}
|
||||||
|
|
||||||
var v0betaManager *computeBeta.InstanceGroupManager
|
var manager *computeBeta.InstanceGroupManager
|
||||||
var e error
|
var e error
|
||||||
if zone, _ := getZone(d, config); zone != "" {
|
if zone, _ := getZone(d, config); zone != "" {
|
||||||
v0betaManager, e = config.clientComputeBeta.InstanceGroupManagers.Get(project, zone, d.Id()).Do()
|
manager, e = config.clientComputeBeta.InstanceGroupManagers.Get(project, zone, d.Id()).Do()
|
||||||
|
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, handleNotFoundError(e, d, fmt.Sprintf("Instance Group Manager %q", d.Get("name").(string)))
|
return nil, handleNotFoundError(e, d, fmt.Sprintf("Instance Group Manager %q", d.Get("name").(string)))
|
||||||
|
@ -395,10 +324,10 @@ func getManager(d *schema.ResourceData, meta interface{}) (*computeBeta.Instance
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
|
|
||||||
v0betaManager = resource.(*computeBeta.InstanceGroupManager)
|
manager = resource.(*computeBeta.InstanceGroupManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v0betaManager == nil {
|
if manager == nil {
|
||||||
log.Printf("[WARN] Removing Instance Group Manager %q because it's gone", d.Get("name").(string))
|
log.Printf("[WARN] Removing Instance Group Manager %q because it's gone", d.Get("name").(string))
|
||||||
|
|
||||||
// The resource doesn't exist anymore
|
// The resource doesn't exist anymore
|
||||||
|
@ -406,8 +335,6 @@ func getManager(d *schema.ResourceData, meta interface{}) (*computeBeta.Instance
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
manager = v0betaManager
|
|
||||||
}
|
|
||||||
return manager, nil
|
return manager, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,7 +351,7 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf
|
||||||
}
|
}
|
||||||
|
|
||||||
d.Set("base_instance_name", manager.BaseInstanceName)
|
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("name", manager.Name)
|
||||||
d.Set("zone", GetResourceNameFromSelfLink(manager.Zone))
|
d.Set("zone", GetResourceNameFromSelfLink(manager.Zone))
|
||||||
d.Set("description", manager.Description)
|
d.Set("description", manager.Description)
|
||||||
|
@ -433,7 +360,7 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf
|
||||||
d.Set("target_pools", manager.TargetPools)
|
d.Set("target_pools", manager.TargetPools)
|
||||||
d.Set("named_port", flattenNamedPortsBeta(manager.NamedPorts))
|
d.Set("named_port", flattenNamedPortsBeta(manager.NamedPorts))
|
||||||
d.Set("fingerprint", manager.Fingerprint)
|
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))
|
d.Set("self_link", ConvertSelfLinkToV1(manager.SelfLink))
|
||||||
update_strategy, ok := d.GetOk("update_strategy")
|
update_strategy, ok := d.GetOk("update_strategy")
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -459,7 +386,6 @@ 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)
|
||||||
|
@ -488,27 +414,8 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
|
||||||
TargetPools: targetPools,
|
TargetPools: targetPools,
|
||||||
}
|
}
|
||||||
|
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.InstanceGroupManagers.SetTargetPools(
|
||||||
switch computeApiVersion {
|
project, zone, d.Id(), setTargetPools).Do()
|
||||||
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)
|
||||||
|
@ -530,27 +437,8 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
|
||||||
InstanceTemplate: d.Get("instance_template").(string),
|
InstanceTemplate: d.Get("instance_template").(string),
|
||||||
}
|
}
|
||||||
|
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.InstanceGroupManagers.SetInstanceTemplate(
|
||||||
switch computeApiVersion {
|
project, zone, d.Id(), setInstanceTemplate).Do()
|
||||||
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)
|
||||||
|
@ -563,32 +451,12 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.Get("update_strategy").(string) == "RESTART" {
|
if d.Get("update_strategy").(string) == "RESTART" {
|
||||||
managedInstances := &computeBeta.InstanceGroupManagersListManagedInstancesResponse{}
|
managedInstances, err := config.clientComputeBeta.InstanceGroupManagers.ListManagedInstances(
|
||||||
switch computeApiVersion {
|
|
||||||
case v1:
|
|
||||||
managedInstancesV1, err := config.clientCompute.InstanceGroupManagers.ListManagedInstances(
|
|
||||||
project, zone, d.Id()).Do()
|
project, zone, d.Id()).Do()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error getting instance group managers instances: %s", err)
|
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)
|
||||||
instances := make([]string, managedInstanceCount)
|
instances := make([]string, managedInstanceCount)
|
||||||
for i, v := range managedInstances.ManagedInstances {
|
for i, v := range managedInstances.ManagedInstances {
|
||||||
|
@ -599,33 +467,11 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
|
||||||
Instances: instances,
|
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(
|
op, err = config.clientComputeBeta.InstanceGroupManagers.RecreateInstances(
|
||||||
project, zone, d.Id(), recreateInstancesV0beta).Do()
|
project, zone, d.Id(), recreateInstances).Do()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error restarting instance group managers instances: %s", err)
|
return fmt.Errorf("Error restarting instance group managers instances: %s", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the operation to complete
|
// Wait for the operation to complete
|
||||||
err = computeSharedOperationWaitTime(config.clientCompute, op, project, managedInstanceCount*4, "Restarting InstanceGroupManagers instances")
|
err = computeSharedOperationWaitTime(config.clientCompute, op, project, managedInstanceCount*4, "Restarting InstanceGroupManagers instances")
|
||||||
|
@ -669,27 +515,8 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the request:
|
// Make the request:
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.InstanceGroups.SetNamedPorts(
|
||||||
switch computeApiVersion {
|
project, zone, d.Id(), setNamedPorts).Do()
|
||||||
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)
|
||||||
|
@ -706,15 +533,8 @@ 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))
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.InstanceGroupManagers.Resize(
|
||||||
switch computeApiVersion {
|
|
||||||
case v1:
|
|
||||||
op, err = config.clientCompute.InstanceGroupManagers.Resize(
|
|
||||||
project, zone, d.Id(), targetSize).Do()
|
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)
|
||||||
|
@ -758,7 +578,6 @@ 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)
|
||||||
|
@ -771,25 +590,13 @@ func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta inte
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.InstanceGroupManagers.Delete(project, zone, d.Id()).Do()
|
||||||
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
|
attempt := 0
|
||||||
for err != nil && attempt < 20 {
|
for err != nil && attempt < 20 {
|
||||||
attempt++
|
attempt++
|
||||||
time.Sleep(2000 * time.Millisecond)
|
time.Sleep(2000 * time.Millisecond)
|
||||||
op, err = config.clientComputeBeta.InstanceGroupManagers.Delete(project, zone, d.Id()).Do()
|
op, err = config.clientComputeBeta.InstanceGroupManagers.Delete(project, zone, d.Id()).Do()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error deleting instance group manager: %s", err)
|
return fmt.Errorf("Error deleting instance group manager: %s", err)
|
||||||
|
@ -805,25 +612,13 @@ func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta inte
|
||||||
return err
|
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(
|
instanceGroup, err := config.clientComputeBeta.InstanceGroups.Get(
|
||||||
project, zone, d.Id()).Do()
|
project, zone, d.Id()).Do()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error getting instance group size: %s", err)
|
return fmt.Errorf("Error getting instance group size: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceGroupSize = instanceGroup.Size
|
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")
|
||||||
|
|
|
@ -292,9 +292,11 @@ 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),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
// TODO: Add import test for auto healing policies
|
resource.TestStep{
|
||||||
// Import doesn't work for auto healing policies because import is not supported
|
ResourceName: "google_compute_instance_group_manager.igm-basic",
|
||||||
// for beta features. See https://github.com/terraform-providers/terraform-provider-google/issues/694
|
ImportState: true,
|
||||||
|
ImportStateVerify: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,9 @@ 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,
|
||||||
|
@ -610,17 +606,7 @@ func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interfac
|
||||||
Name: itName,
|
Name: itName,
|
||||||
}
|
}
|
||||||
|
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.InstanceTemplates.Insert(project, instanceTemplate).Do()
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
@ -670,23 +656,10 @@ func resourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interface{
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceTemplate := &computeBeta.InstanceTemplate{}
|
instanceTemplate, err := config.clientComputeBeta.InstanceTemplates.Get(project, d.Id()).Do()
|
||||||
switch getComputeApiVersion(d, InstanceBaseApiVersion, InstanceVersionedFeatures) {
|
|
||||||
case v1:
|
|
||||||
instanceTemplateV1, err := config.clientCompute.InstanceTemplates.Get(project, d.Id()).Do()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return handleNotFoundError(err, d, fmt.Sprintf("Instance Template %q", d.Get("name").(string)))
|
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.
|
||||||
if instanceTemplate.Properties.Metadata != nil {
|
if instanceTemplate.Properties.Metadata != nil {
|
||||||
|
|
|
@ -8,9 +8,6 @@ import (
|
||||||
"google.golang.org/api/compute/v1"
|
"google.golang.org/api/compute/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ProjectMetadataBaseApiVersion = v1
|
|
||||||
var ProjectMetadataVersionedFeatures = []Feature{}
|
|
||||||
|
|
||||||
func resourceComputeProjectMetadata() *schema.Resource {
|
func resourceComputeProjectMetadata() *schema.Resource {
|
||||||
return &schema.Resource{
|
return &schema.Resource{
|
||||||
Create: resourceComputeProjectMetadataCreate,
|
Create: resourceComputeProjectMetadataCreate,
|
||||||
|
|
|
@ -12,16 +12,8 @@ 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,
|
||||||
|
@ -230,7 +222,6 @@ 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)
|
||||||
|
@ -256,19 +247,7 @@ func resourceComputeRegionInstanceGroupManagerCreate(d *schema.ResourceData, met
|
||||||
ForceSendFields: []string{"TargetSize"},
|
ForceSendFields: []string{"TargetSize"},
|
||||||
}
|
}
|
||||||
|
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.Insert(project, d.Get("region").(string), 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.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)
|
||||||
|
@ -287,7 +266,6 @@ 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)
|
||||||
|
@ -299,32 +277,12 @@ func getRegionalManager(d *schema.ResourceData, meta interface{}) (*computeBeta.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,7 +347,6 @@ 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)
|
||||||
|
@ -414,27 +371,8 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
|
||||||
TargetPools: targetPools,
|
TargetPools: targetPools,
|
||||||
}
|
}
|
||||||
|
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.SetTargetPools(
|
||||||
switch computeApiVersion {
|
project, region, d.Id(), setTargetPools).Do()
|
||||||
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)
|
||||||
|
@ -455,27 +393,8 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
|
||||||
InstanceTemplate: d.Get("instance_template").(string),
|
InstanceTemplate: d.Get("instance_template").(string),
|
||||||
}
|
}
|
||||||
|
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.SetInstanceTemplate(
|
||||||
switch computeApiVersion {
|
project, region, d.Id(), setInstanceTemplate).Do()
|
||||||
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)
|
||||||
|
@ -520,27 +439,8 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the request:
|
// Make the request:
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.RegionInstanceGroups.SetNamedPorts(
|
||||||
switch computeApiVersion {
|
project, region, d.Id(), setNamedPorts).Do()
|
||||||
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)
|
||||||
|
@ -557,15 +457,8 @@ 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))
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.Resize(
|
||||||
switch computeApiVersion {
|
|
||||||
case v1:
|
|
||||||
op, err = config.clientCompute.RegionInstanceGroupManagers.Resize(
|
|
||||||
project, region, d.Id(), targetSize).Do()
|
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)
|
||||||
|
@ -608,7 +501,6 @@ 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)
|
||||||
|
@ -618,13 +510,7 @@ func resourceComputeRegionInstanceGroupManagerDelete(d *schema.ResourceData, met
|
||||||
|
|
||||||
region := d.Get("region").(string)
|
region := d.Get("region").(string)
|
||||||
|
|
||||||
var op interface{}
|
op, err := config.clientComputeBeta.RegionInstanceGroupManagers.Delete(project, region, d.Id()).Do()
|
||||||
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)
|
||||||
|
|
|
@ -14,14 +14,6 @@ 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,
|
||||||
|
@ -130,7 +122,6 @@ 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 {
|
||||||
|
@ -160,21 +151,7 @@ func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) e
|
||||||
|
|
||||||
log.Printf("[DEBUG] Subnetwork insert request: %#v", subnetwork)
|
log.Printf("[DEBUG] Subnetwork insert request: %#v", subnetwork)
|
||||||
|
|
||||||
subnetworkV1 := &compute.Subnetwork{}
|
op, err := config.clientComputeBeta.Subnetworks.Insert(project, region, subnetwork).Do()
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
@ -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.
|
// "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(createSubnetID(subnetworkV1))
|
d.SetId(createSubnetIDBeta(subnetwork))
|
||||||
|
|
||||||
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 {
|
||||||
|
@ -197,45 +173,6 @@ 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)
|
||||||
|
@ -272,7 +209,6 @@ func resourceComputeSubnetworkReadV0Beta(d *schema.ResourceData, meta interface{
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@ -328,7 +264,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")) && computeApiVersion == v0beta {
|
if d.HasChange("secondary_ip_range") || d.HasChange("enable_flow_logs") {
|
||||||
v0BetaSubnetwork := &computeBeta.Subnetwork{
|
v0BetaSubnetwork := &computeBeta.Subnetwork{
|
||||||
Fingerprint: d.Get("fingerprint").(string),
|
Fingerprint: d.Get("fingerprint").(string),
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,7 +193,11 @@ 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(
|
||||||
|
@ -203,6 +207,11 @@ 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,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,23 +12,12 @@ 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"
|
||||||
"github.com/hashicorp/terraform/helper/validation"
|
"github.com/hashicorp/terraform/helper/validation"
|
||||||
"google.golang.org/api/container/v1"
|
|
||||||
containerBeta "google.golang.org/api/container/v1beta1"
|
containerBeta "google.golang.org/api/container/v1beta1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
instanceGroupManagerURL = regexp.MustCompile(fmt.Sprintf("^https://www.googleapis.com/compute/v1/projects/(%s)/zones/([a-z0-9-]*)/instanceGroupManagers/([^/]*)", ProjectRegex))
|
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{
|
networkConfig = &schema.Resource{
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"cidr_blocks": {
|
"cidr_blocks": {
|
||||||
|
@ -475,7 +464,6 @@ func resourceContainerCluster() *schema.Resource {
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) error {
|
func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
containerAPIVersion := getContainerApiVersion(d, ContainerClusterBaseApiVersion, ContainerClusterVersionedFeatures)
|
|
||||||
config := meta.(*Config)
|
config := meta.(*Config)
|
||||||
|
|
||||||
project, err := getProject(d, config)
|
project, err := getProject(d, config)
|
||||||
|
@ -651,25 +639,8 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
|
||||||
mutexKV.Lock(containerClusterMutexKey(project, location, clusterName))
|
mutexKV.Lock(containerClusterMutexKey(project, location, clusterName))
|
||||||
defer mutexKV.Unlock(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)
|
parent := fmt.Sprintf("projects/%s/locations/%s", project, location)
|
||||||
op, err = config.clientContainerBeta.Projects.Locations.Clusters.Create(parent, reqV1Beta).Do()
|
op, err := config.clientContainerBeta.Projects.Locations.Clusters.Create(parent, req).Do()
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -687,15 +658,8 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
|
||||||
log.Printf("[INFO] GKE cluster %s has been created", clusterName)
|
log.Printf("[INFO] GKE cluster %s has been created", clusterName)
|
||||||
|
|
||||||
if d.Get("remove_default_node_pool").(bool) {
|
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")
|
parent := fmt.Sprintf("%s/nodePools/%s", containerClusterFullName(project, location, clusterName), "default-pool")
|
||||||
op, err = config.clientContainerBeta.Projects.Locations.Clusters.NodePools.Delete(parent).Do()
|
op, err = config.clientContainerBeta.Projects.Locations.Clusters.NodePools.Delete(parent).Do()
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrapf("Error deleting default node pool: {{err}}", err)
|
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 {
|
func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
containerAPIVersion := getContainerApiVersion(d, ContainerClusterBaseApiVersion, ContainerClusterVersionedFeatures)
|
|
||||||
config := meta.(*Config)
|
config := meta.(*Config)
|
||||||
|
|
||||||
project, err := getProject(d, config)
|
project, err := getProject(d, config)
|
||||||
|
@ -723,20 +686,9 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
|
||||||
}
|
}
|
||||||
|
|
||||||
cluster := &containerBeta.Cluster{}
|
cluster := &containerBeta.Cluster{}
|
||||||
var clust interface{}
|
|
||||||
err = resource.Retry(2*time.Minute, func() *resource.RetryError {
|
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))
|
name := containerClusterFullName(project, location, d.Get("name").(string))
|
||||||
clust, err = config.clientContainerBeta.Projects.Locations.Clusters.Get(name).Do()
|
cluster, err = config.clientContainerBeta.Projects.Locations.Clusters.Get(name).Do()
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return resource.NonRetryableError(err)
|
|
||||||
}
|
|
||||||
err = Convert(clust, cluster)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return resource.NonRetryableError(err)
|
return resource.NonRetryableError(err)
|
||||||
}
|
}
|
||||||
|
@ -834,7 +786,6 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) error {
|
func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
containerAPIVersion := getContainerApiVersion(d, ContainerClusterBaseApiVersion, ContainerClusterVersionedFeatures)
|
|
||||||
config := meta.(*Config)
|
config := meta.(*Config)
|
||||||
|
|
||||||
project, err := getProject(d, config)
|
project, err := getProject(d, config)
|
||||||
|
@ -854,22 +805,10 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
|
|
||||||
lockKey := containerClusterMutexKey(project, location, clusterName)
|
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 {
|
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)
|
name := containerClusterFullName(project, location, clusterName)
|
||||||
op, err = config.clientContainerBeta.Projects.Locations.Clusters.Update(name, reqV1Beta).Do()
|
op, err := config.clientContainerBeta.Projects.Locations.Clusters.Update(name, req).Do()
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 the order of updating fields does matter, it is called out explicitly.
|
||||||
if d.HasChange("master_authorized_networks_config") {
|
if d.HasChange("master_authorized_networks_config") {
|
||||||
c := d.Get("master_authorized_networks_config")
|
c := d.Get("master_authorized_networks_config")
|
||||||
conf := &container.MasterAuthorizedNetworksConfig{}
|
req := &containerBeta.UpdateClusterRequest{
|
||||||
err := Convert(expandMasterAuthorizedNetworksConfig(c), conf)
|
Update: &containerBeta.ClusterUpdate{
|
||||||
if err != nil {
|
DesiredMasterAuthorizedNetworksConfig: expandMasterAuthorizedNetworksConfig(c),
|
||||||
return err
|
|
||||||
}
|
|
||||||
req := &container.UpdateClusterRequest{
|
|
||||||
Update: &container.ClusterUpdate{
|
|
||||||
DesiredMasterAuthorizedNetworksConfig: conf,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
// Only upgrade the master if the current version is lower than the desired version
|
||||||
if cur.LessThan(des) {
|
if cur.LessThan(des) {
|
||||||
req := &container.UpdateClusterRequest{
|
req := &containerBeta.UpdateClusterRequest{
|
||||||
Update: &container.ClusterUpdate{
|
Update: &containerBeta.ClusterUpdate{
|
||||||
DesiredMasterVersion: desiredMasterVersion,
|
DesiredMasterVersion: desiredMasterVersion,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -936,8 +870,8 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
|
|
||||||
if d.HasChange("node_version") {
|
if d.HasChange("node_version") {
|
||||||
desiredNodeVersion := d.Get("node_version").(string)
|
desiredNodeVersion := d.Get("node_version").(string)
|
||||||
req := &container.UpdateClusterRequest{
|
req := &containerBeta.UpdateClusterRequest{
|
||||||
Update: &container.ClusterUpdate{
|
Update: &containerBeta.ClusterUpdate{
|
||||||
DesiredNodeVersion: desiredNodeVersion,
|
DesiredNodeVersion: desiredNodeVersion,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -955,14 +889,9 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
|
|
||||||
if d.HasChange("addons_config") {
|
if d.HasChange("addons_config") {
|
||||||
if ac, ok := d.GetOk("addons_config"); ok {
|
if ac, ok := d.GetOk("addons_config"); ok {
|
||||||
conf := &container.AddonsConfig{}
|
req := &containerBeta.UpdateClusterRequest{
|
||||||
err := Convert(expandClusterAddonsConfig(ac), conf)
|
Update: &containerBeta.ClusterUpdate{
|
||||||
if err != nil {
|
DesiredAddonsConfig: expandClusterAddonsConfig(ac),
|
||||||
return err
|
|
||||||
}
|
|
||||||
req := &container.UpdateClusterRequest{
|
|
||||||
Update: &container.ClusterUpdate{
|
|
||||||
DesiredAddonsConfig: conf,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -979,37 +908,20 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.HasChange("maintenance_policy") {
|
if d.HasChange("maintenance_policy") {
|
||||||
var req *container.SetMaintenancePolicyRequest
|
var req *containerBeta.SetMaintenancePolicyRequest
|
||||||
if mp, ok := d.GetOk("maintenance_policy"); ok {
|
if mp, ok := d.GetOk("maintenance_policy"); ok {
|
||||||
pol := &container.MaintenancePolicy{}
|
req = &containerBeta.SetMaintenancePolicyRequest{
|
||||||
err := Convert(expandMaintenancePolicy(mp), pol)
|
MaintenancePolicy: expandMaintenancePolicy(mp),
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
req = &container.SetMaintenancePolicyRequest{
|
|
||||||
MaintenancePolicy: pol,
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
req = &container.SetMaintenancePolicyRequest{
|
req = &containerBeta.SetMaintenancePolicyRequest{
|
||||||
NullFields: []string{"MaintenancePolicy"},
|
NullFields: []string{"MaintenancePolicy"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateF := func() error {
|
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)
|
name := containerClusterFullName(project, location, clusterName)
|
||||||
op, err = config.clientContainerBeta.Projects.Locations.Clusters.SetMaintenancePolicy(name, reqV1Beta).Do()
|
op, err := config.clientContainerBeta.Projects.Locations.Clusters.SetMaintenancePolicy(name, req).Do()
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1044,8 +956,8 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
azSet.Add(location)
|
azSet.Add(location)
|
||||||
}
|
}
|
||||||
|
|
||||||
req := &container.UpdateClusterRequest{
|
req := &containerBeta.UpdateClusterRequest{
|
||||||
Update: &container.ClusterUpdate{
|
Update: &containerBeta.ClusterUpdate{
|
||||||
DesiredLocations: convertStringSet(azSet),
|
DesiredLocations: convertStringSet(azSet),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1060,8 +972,8 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
azSetNew.Add(location)
|
azSetNew.Add(location)
|
||||||
}
|
}
|
||||||
if !azSet.Equal(azSetNew) {
|
if !azSet.Equal(azSetNew) {
|
||||||
req = &container.UpdateClusterRequest{
|
req = &containerBeta.UpdateClusterRequest{
|
||||||
Update: &container.ClusterUpdate{
|
Update: &containerBeta.ClusterUpdate{
|
||||||
DesiredLocations: convertStringSet(azSetNew),
|
DesiredLocations: convertStringSet(azSetNew),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1080,26 +992,15 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
|
|
||||||
if d.HasChange("enable_legacy_abac") {
|
if d.HasChange("enable_legacy_abac") {
|
||||||
enabled := d.Get("enable_legacy_abac").(bool)
|
enabled := d.Get("enable_legacy_abac").(bool)
|
||||||
req := &container.SetLegacyAbacRequest{
|
req := &containerBeta.SetLegacyAbacRequest{
|
||||||
Enabled: enabled,
|
Enabled: enabled,
|
||||||
ForceSendFields: []string{"Enabled"},
|
ForceSendFields: []string{"Enabled"},
|
||||||
}
|
}
|
||||||
|
|
||||||
updateF := func() error {
|
updateF := func() error {
|
||||||
log.Println("[DEBUG] updating enable_legacy_abac")
|
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)
|
name := containerClusterFullName(project, location, clusterName)
|
||||||
op, err = config.clientContainerBeta.Projects.Locations.Clusters.SetLegacyAbac(name, reqV1Beta).Do()
|
op, err := config.clientContainerBeta.Projects.Locations.Clusters.SetLegacyAbac(name, req).Do()
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1123,8 +1024,8 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
if d.HasChange("monitoring_service") {
|
if d.HasChange("monitoring_service") {
|
||||||
desiredMonitoringService := d.Get("monitoring_service").(string)
|
desiredMonitoringService := d.Get("monitoring_service").(string)
|
||||||
|
|
||||||
req := &container.UpdateClusterRequest{
|
req := &containerBeta.UpdateClusterRequest{
|
||||||
Update: &container.ClusterUpdate{
|
Update: &containerBeta.ClusterUpdate{
|
||||||
DesiredMonitoringService: desiredMonitoringService,
|
DesiredMonitoringService: desiredMonitoringService,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1142,32 +1043,14 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
|
|
||||||
if d.HasChange("network_policy") {
|
if d.HasChange("network_policy") {
|
||||||
np := d.Get("network_policy")
|
np := d.Get("network_policy")
|
||||||
|
req := &containerBeta.SetNetworkPolicyRequest{
|
||||||
pol := &container.NetworkPolicy{}
|
NetworkPolicy: expandNetworkPolicy(np),
|
||||||
err := Convert(expandNetworkPolicy(np), pol)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
req := &container.SetNetworkPolicyRequest{
|
|
||||||
NetworkPolicy: pol,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateF := func() error {
|
updateF := func() error {
|
||||||
log.Println("[DEBUG] updating network_policy")
|
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)
|
name := containerClusterFullName(project, location, clusterName)
|
||||||
op, err = config.clientContainerBeta.Projects.Locations.Clusters.SetNetworkPolicy(name, reqV1Beta).Do()
|
op, err := config.clientContainerBeta.Projects.Locations.Clusters.SetNetworkPolicy(name, req).Do()
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1206,24 +1089,12 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
if d.HasChange("logging_service") {
|
if d.HasChange("logging_service") {
|
||||||
logging := d.Get("logging_service").(string)
|
logging := d.Get("logging_service").(string)
|
||||||
|
|
||||||
req := &container.SetLoggingServiceRequest{
|
req := &containerBeta.SetLoggingServiceRequest{
|
||||||
LoggingService: logging,
|
LoggingService: logging,
|
||||||
}
|
}
|
||||||
updateF := func() error {
|
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)
|
name := containerClusterFullName(project, location, clusterName)
|
||||||
op, err = config.clientContainerBeta.Projects.Locations.Clusters.SetLogging(name, reqV1Beta).Do()
|
op, err := config.clientContainerBeta.Projects.Locations.Clusters.SetLogging(name, req).Do()
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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) {
|
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")
|
name := fmt.Sprintf("%s/nodePools/%s", containerClusterFullName(project, location, clusterName), "default-pool")
|
||||||
op, err = config.clientContainerBeta.Projects.Locations.Clusters.NodePools.Delete(name).Do()
|
op, err := config.clientContainerBeta.Projects.Locations.Clusters.NodePools.Delete(name).Do()
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrapf("Error deleting default node pool: {{err}}", err)
|
return errwrap.Wrapf("Error deleting default node pool: {{err}}", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -431,9 +431,6 @@ func TestAccContainerCluster_withPrivateCluster(t *testing.T) {
|
||||||
ImportStateIdPrefix: "us-central1-a/",
|
ImportStateIdPrefix: "us-central1-a/",
|
||||||
ImportState: true,
|
ImportState: true,
|
||||||
ImportStateVerify: true,
|
ImportStateVerify: true,
|
||||||
ImportStateVerifyIgnore: []string{
|
|
||||||
"private_cluster",
|
|
||||||
"master_ipv4_cidr_block"},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -646,13 +643,7 @@ func TestAccContainerCluster_withWorkloadMetadataConfig(t *testing.T) {
|
||||||
ImportStateIdPrefix: "us-central1-a/",
|
ImportStateIdPrefix: "us-central1-a/",
|
||||||
ImportState: true,
|
ImportState: true,
|
||||||
ImportStateVerify: true,
|
ImportStateVerify: true,
|
||||||
// Import always uses the v1 API, so beta features don't get imported.
|
ImportStateVerifyIgnore: []string{"min_master_version"},
|
||||||
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"},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -1125,8 +1116,6 @@ func TestAccContainerCluster_withPodSecurityPolicy(t *testing.T) {
|
||||||
ImportStateIdPrefix: "us-central1-a/",
|
ImportStateIdPrefix: "us-central1-a/",
|
||||||
ImportState: true,
|
ImportState: true,
|
||||||
ImportStateVerify: 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),
|
Config: testAccContainerCluster_withPodSecurityPolicy(clusterName, false),
|
||||||
|
@ -1140,8 +1129,6 @@ func TestAccContainerCluster_withPodSecurityPolicy(t *testing.T) {
|
||||||
ImportStateIdPrefix: "us-central1-a/",
|
ImportStateIdPrefix: "us-central1-a/",
|
||||||
ImportState: true,
|
ImportState: true,
|
||||||
ImportStateVerify: 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
41
google/test_utils.go
Normal 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
|
||||||
|
}
|
|
@ -17,6 +17,14 @@ import (
|
||||||
"google.golang.org/api/googleapi"
|
"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.
|
// getRegionFromZone returns the region from a zone for Google cloud.
|
||||||
func getRegionFromZone(zone string) string {
|
func getRegionFromZone(zone string) string {
|
||||||
if zone != "" && len(zone) > 2 {
|
if zone != "" && len(zone) > 2 {
|
||||||
|
|
|
@ -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
|
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.
|
||||||
|
|
||||||
Resources will automatically be provisioned using Beta APIs when you specify a feature
|
Terraform resources that support beta features will always use the Beta APIs to provision
|
||||||
marked Beta in your Terraform config file.
|
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.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user