2019-03-05 00:07:10 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
|
|
|
|
//
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// This file is automatically generated by Magic Modules and manual
|
|
|
|
// changes will be clobbered when the file is regenerated.
|
|
|
|
//
|
|
|
|
// Please read more about how to change this file in
|
|
|
|
// .github/CONTRIBUTING.md.
|
|
|
|
//
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
package google
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"reflect"
|
2019-03-05 21:44:21 +00:00
|
|
|
"regexp"
|
2019-03-05 00:07:10 +00:00
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
|
|
)
|
|
|
|
|
|
|
|
// compareTpuNodeSchedulingConfig diff suppresses for the default
|
|
|
|
// scheduling, i.e. if preemptible is false, the API may either return no
|
|
|
|
// schedulingConfig or an empty schedulingConfig.
|
|
|
|
func compareTpuNodeSchedulingConfig(k, old, new string, d *schema.ResourceData) bool {
|
|
|
|
if k == "scheduling_config.0.preemptible" {
|
|
|
|
return old == "" && new == "false"
|
|
|
|
}
|
|
|
|
if k == "scheduling_config.#" {
|
|
|
|
o, n := d.GetChange("scheduling_config.0.preemptible")
|
|
|
|
return o.(bool) == n.(bool)
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2019-03-05 21:44:21 +00:00
|
|
|
func validateHttpHeaders() schema.SchemaValidateFunc {
|
|
|
|
return func(i interface{}, k string) (s []string, es []error) {
|
|
|
|
headers := i.(map[string]interface{})
|
|
|
|
if _, ok := headers["Content-Length"]; ok {
|
|
|
|
es = append(es, fmt.Errorf("Cannot set the Content-Length header on %s", k))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for key := range headers {
|
|
|
|
match, _ := regexp.MatchString("(X-Google-|X-AppEngine-).*", key)
|
|
|
|
if match {
|
|
|
|
es = append(es, fmt.Errorf("Cannot set the %s header on %s", key, k))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-05 00:07:10 +00:00
|
|
|
func resourceTpuNode() *schema.Resource {
|
|
|
|
return &schema.Resource{
|
|
|
|
Create: resourceTpuNodeCreate,
|
|
|
|
Read: resourceTpuNodeRead,
|
|
|
|
Update: resourceTpuNodeUpdate,
|
|
|
|
Delete: resourceTpuNodeDelete,
|
|
|
|
|
|
|
|
Importer: &schema.ResourceImporter{
|
|
|
|
State: resourceTpuNodeImport,
|
|
|
|
},
|
|
|
|
|
|
|
|
Timeouts: &schema.ResourceTimeout{
|
|
|
|
Create: schema.DefaultTimeout(900 * time.Second),
|
|
|
|
Update: schema.DefaultTimeout(900 * time.Second),
|
|
|
|
Delete: schema.DefaultTimeout(900 * time.Second),
|
|
|
|
},
|
|
|
|
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"accelerator_type": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
"cidr_block": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
"name": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
"tensorflow_version": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
"zone": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
"description": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
"labels": {
|
|
|
|
Type: schema.TypeMap,
|
|
|
|
Optional: true,
|
|
|
|
ForceNew: true,
|
|
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
|
|
},
|
|
|
|
"network": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
Optional: true,
|
|
|
|
ForceNew: true,
|
|
|
|
DiffSuppressFunc: compareSelfLinkOrResourceName,
|
|
|
|
},
|
|
|
|
"scheduling_config": {
|
|
|
|
Type: schema.TypeList,
|
|
|
|
Optional: true,
|
|
|
|
ForceNew: true,
|
|
|
|
DiffSuppressFunc: compareTpuNodeSchedulingConfig,
|
|
|
|
MaxItems: 1,
|
|
|
|
Elem: &schema.Resource{
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"preemptible": {
|
|
|
|
Type: schema.TypeBool,
|
|
|
|
Optional: true,
|
|
|
|
ForceNew: true,
|
|
|
|
DiffSuppressFunc: compareTpuNodeSchedulingConfig,
|
|
|
|
Default: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"network_endpoints": {
|
|
|
|
Type: schema.TypeList,
|
|
|
|
Computed: true,
|
|
|
|
Elem: &schema.Resource{
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"ip_address": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"port": {
|
|
|
|
Type: schema.TypeInt,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"service_account": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"project": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceTpuNodeCreate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
config := meta.(*Config)
|
|
|
|
|
|
|
|
obj := make(map[string]interface{})
|
|
|
|
nameProp, err := expandTpuNodeName(d.Get("name"), d, config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
|
|
|
|
obj["name"] = nameProp
|
|
|
|
}
|
|
|
|
descriptionProp, err := expandTpuNodeDescription(d.Get("description"), d, config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
|
|
|
|
obj["description"] = descriptionProp
|
|
|
|
}
|
|
|
|
acceleratorTypeProp, err := expandTpuNodeAcceleratorType(d.Get("accelerator_type"), d, config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
} else if v, ok := d.GetOkExists("accelerator_type"); !isEmptyValue(reflect.ValueOf(acceleratorTypeProp)) && (ok || !reflect.DeepEqual(v, acceleratorTypeProp)) {
|
|
|
|
obj["acceleratorType"] = acceleratorTypeProp
|
|
|
|
}
|
|
|
|
tensorflowVersionProp, err := expandTpuNodeTensorflowVersion(d.Get("tensorflow_version"), d, config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
} else if v, ok := d.GetOkExists("tensorflow_version"); !isEmptyValue(reflect.ValueOf(tensorflowVersionProp)) && (ok || !reflect.DeepEqual(v, tensorflowVersionProp)) {
|
|
|
|
obj["tensorflowVersion"] = tensorflowVersionProp
|
|
|
|
}
|
|
|
|
networkProp, err := expandTpuNodeNetwork(d.Get("network"), d, config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
} else if v, ok := d.GetOkExists("network"); !isEmptyValue(reflect.ValueOf(networkProp)) && (ok || !reflect.DeepEqual(v, networkProp)) {
|
|
|
|
obj["network"] = networkProp
|
|
|
|
}
|
|
|
|
cidrBlockProp, err := expandTpuNodeCidrBlock(d.Get("cidr_block"), d, config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
} else if v, ok := d.GetOkExists("cidr_block"); !isEmptyValue(reflect.ValueOf(cidrBlockProp)) && (ok || !reflect.DeepEqual(v, cidrBlockProp)) {
|
|
|
|
obj["cidrBlock"] = cidrBlockProp
|
|
|
|
}
|
|
|
|
schedulingConfigProp, err := expandTpuNodeSchedulingConfig(d.Get("scheduling_config"), d, config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
} else if v, ok := d.GetOkExists("scheduling_config"); !isEmptyValue(reflect.ValueOf(schedulingConfigProp)) && (ok || !reflect.DeepEqual(v, schedulingConfigProp)) {
|
|
|
|
obj["schedulingConfig"] = schedulingConfigProp
|
|
|
|
}
|
|
|
|
labelsProp, err := expandTpuNodeLabels(d.Get("labels"), d, config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
} else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
|
|
|
|
obj["labels"] = labelsProp
|
|
|
|
}
|
|
|
|
|
|
|
|
url, err := replaceVars(d, config, "https://tpu.googleapis.com/v1/projects/{{project}}/locations/{{zone}}/nodes?nodeId={{name}}")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("[DEBUG] Creating new Node: %#v", obj)
|
|
|
|
res, err := sendRequestWithTimeout(config, "POST", url, obj, d.Timeout(schema.TimeoutCreate))
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error creating Node: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store the ID now
|
|
|
|
id, err := replaceVars(d, config, "{{project}}/{{zone}}/{{name}}")
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error constructing id: %s", err)
|
|
|
|
}
|
|
|
|
d.SetId(id)
|
|
|
|
|
|
|
|
project, err := getProject(d, config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
waitErr := tpuOperationWaitTime(
|
|
|
|
config, res, project, "Creating Node",
|
|
|
|
int(d.Timeout(schema.TimeoutCreate).Minutes()))
|
|
|
|
|
|
|
|
if waitErr != nil {
|
|
|
|
// The resource didn't actually create
|
|
|
|
d.SetId("")
|
|
|
|
return fmt.Errorf("Error waiting to create Node: %s", waitErr)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("[DEBUG] Finished creating Node %q: %#v", d.Id(), res)
|
|
|
|
|
|
|
|
return resourceTpuNodeRead(d, meta)
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceTpuNodeRead(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
config := meta.(*Config)
|
|
|
|
|
|
|
|
url, err := replaceVars(d, config, "https://tpu.googleapis.com/v1/projects/{{project}}/locations/{{zone}}/nodes/{{name}}")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
res, err := sendRequest(config, "GET", url, nil)
|
|
|
|
if err != nil {
|
|
|
|
return handleNotFoundError(err, d, fmt.Sprintf("TpuNode %q", d.Id()))
|
|
|
|
}
|
|
|
|
|
|
|
|
project, err := getProject(d, config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := d.Set("project", project); err != nil {
|
|
|
|
return fmt.Errorf("Error reading Node: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := d.Set("name", flattenTpuNodeName(res["name"], d)); err != nil {
|
|
|
|
return fmt.Errorf("Error reading Node: %s", err)
|
|
|
|
}
|
|
|
|
if err := d.Set("description", flattenTpuNodeDescription(res["description"], d)); err != nil {
|
|
|
|
return fmt.Errorf("Error reading Node: %s", err)
|
|
|
|
}
|
|
|
|
if err := d.Set("accelerator_type", flattenTpuNodeAcceleratorType(res["acceleratorType"], d)); err != nil {
|
|
|
|
return fmt.Errorf("Error reading Node: %s", err)
|
|
|
|
}
|
|
|
|
if err := d.Set("tensorflow_version", flattenTpuNodeTensorflowVersion(res["tensorflowVersion"], d)); err != nil {
|
|
|
|
return fmt.Errorf("Error reading Node: %s", err)
|
|
|
|
}
|
|
|
|
if err := d.Set("network", flattenTpuNodeNetwork(res["network"], d)); err != nil {
|
|
|
|
return fmt.Errorf("Error reading Node: %s", err)
|
|
|
|
}
|
|
|
|
if err := d.Set("cidr_block", flattenTpuNodeCidrBlock(res["cidrBlock"], d)); err != nil {
|
|
|
|
return fmt.Errorf("Error reading Node: %s", err)
|
|
|
|
}
|
|
|
|
if err := d.Set("service_account", flattenTpuNodeServiceAccount(res["serviceAccount"], d)); err != nil {
|
|
|
|
return fmt.Errorf("Error reading Node: %s", err)
|
|
|
|
}
|
|
|
|
if err := d.Set("scheduling_config", flattenTpuNodeSchedulingConfig(res["schedulingConfig"], d)); err != nil {
|
|
|
|
return fmt.Errorf("Error reading Node: %s", err)
|
|
|
|
}
|
|
|
|
if err := d.Set("network_endpoints", flattenTpuNodeNetworkEndpoints(res["networkEndpoints"], d)); err != nil {
|
|
|
|
return fmt.Errorf("Error reading Node: %s", err)
|
|
|
|
}
|
|
|
|
if err := d.Set("labels", flattenTpuNodeLabels(res["labels"], d)); err != nil {
|
|
|
|
return fmt.Errorf("Error reading Node: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceTpuNodeUpdate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
config := meta.(*Config)
|
|
|
|
|
|
|
|
d.Partial(true)
|
|
|
|
|
|
|
|
if d.HasChange("tensorflow_version") {
|
|
|
|
obj := make(map[string]interface{})
|
|
|
|
tensorflowVersionProp, err := expandTpuNodeTensorflowVersion(d.Get("tensorflow_version"), d, config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
} else if v, ok := d.GetOkExists("tensorflow_version"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, tensorflowVersionProp)) {
|
|
|
|
obj["tensorflowVersion"] = tensorflowVersionProp
|
|
|
|
}
|
|
|
|
|
|
|
|
url, err := replaceVars(d, config, "https://tpu.googleapis.com/v1/projects/{{project}}/locations/{{zone}}/nodes/{{name}}:reimage")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
res, err := sendRequestWithTimeout(config, "POST", url, obj, d.Timeout(schema.TimeoutUpdate))
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error updating Node %q: %s", d.Id(), err)
|
|
|
|
}
|
|
|
|
|
|
|
|
project, err := getProject(d, config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = tpuOperationWaitTime(
|
|
|
|
config, res, project, "Updating Node",
|
|
|
|
int(d.Timeout(schema.TimeoutUpdate).Minutes()))
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
d.SetPartial("tensorflow_version")
|
|
|
|
}
|
|
|
|
|
|
|
|
d.Partial(false)
|
|
|
|
|
|
|
|
return resourceTpuNodeRead(d, meta)
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceTpuNodeDelete(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
config := meta.(*Config)
|
|
|
|
|
|
|
|
url, err := replaceVars(d, config, "https://tpu.googleapis.com/v1/projects/{{project}}/locations/{{zone}}/nodes/{{name}}")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var obj map[string]interface{}
|
|
|
|
log.Printf("[DEBUG] Deleting Node %q", d.Id())
|
|
|
|
res, err := sendRequestWithTimeout(config, "DELETE", url, obj, d.Timeout(schema.TimeoutDelete))
|
|
|
|
if err != nil {
|
|
|
|
return handleNotFoundError(err, d, "Node")
|
|
|
|
}
|
|
|
|
|
|
|
|
project, err := getProject(d, config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = tpuOperationWaitTime(
|
|
|
|
config, res, project, "Deleting Node",
|
|
|
|
int(d.Timeout(schema.TimeoutDelete).Minutes()))
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("[DEBUG] Finished deleting Node %q: %#v", d.Id(), res)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceTpuNodeImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
|
|
|
|
config := meta.(*Config)
|
|
|
|
if err := parseImportId([]string{"projects/(?P<project>[^/]+)/locations/(?P<zone>[^/]+)/nodes/(?P<name>[^/]+)", "(?P<project>[^/]+)/(?P<zone>[^/]+)/(?P<name>[^/]+)", "(?P<name>[^/]+)"}, d, config); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Replace import id for the resource id
|
|
|
|
id, err := replaceVars(d, config, "{{project}}/{{zone}}/{{name}}")
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("Error constructing id: %s", err)
|
|
|
|
}
|
|
|
|
d.SetId(id)
|
|
|
|
|
|
|
|
return []*schema.ResourceData{d}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func flattenTpuNodeName(v interface{}, d *schema.ResourceData) interface{} {
|
|
|
|
if v == nil {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
return NameFromSelfLinkStateFunc(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
func flattenTpuNodeDescription(v interface{}, d *schema.ResourceData) interface{} {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func flattenTpuNodeAcceleratorType(v interface{}, d *schema.ResourceData) interface{} {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func flattenTpuNodeTensorflowVersion(v interface{}, d *schema.ResourceData) interface{} {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func flattenTpuNodeNetwork(v interface{}, d *schema.ResourceData) interface{} {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func flattenTpuNodeCidrBlock(v interface{}, d *schema.ResourceData) interface{} {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func flattenTpuNodeServiceAccount(v interface{}, d *schema.ResourceData) interface{} {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func flattenTpuNodeSchedulingConfig(v interface{}, d *schema.ResourceData) interface{} {
|
|
|
|
if v == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
original := v.(map[string]interface{})
|
|
|
|
if len(original) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
transformed := make(map[string]interface{})
|
|
|
|
transformed["preemptible"] =
|
|
|
|
flattenTpuNodeSchedulingConfigPreemptible(original["preemptible"], d)
|
|
|
|
return []interface{}{transformed}
|
|
|
|
}
|
|
|
|
func flattenTpuNodeSchedulingConfigPreemptible(v interface{}, d *schema.ResourceData) interface{} {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func flattenTpuNodeNetworkEndpoints(v interface{}, d *schema.ResourceData) interface{} {
|
|
|
|
if v == nil {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
l := v.([]interface{})
|
|
|
|
transformed := make([]interface{}, 0, len(l))
|
|
|
|
for _, raw := range l {
|
|
|
|
original := raw.(map[string]interface{})
|
|
|
|
if len(original) < 1 {
|
|
|
|
// Do not include empty json objects coming back from the api
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
transformed = append(transformed, map[string]interface{}{
|
|
|
|
"ip_address": flattenTpuNodeNetworkEndpointsIpAddress(original["ipAddress"], d),
|
|
|
|
"port": flattenTpuNodeNetworkEndpointsPort(original["port"], d),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return transformed
|
|
|
|
}
|
|
|
|
func flattenTpuNodeNetworkEndpointsIpAddress(v interface{}, d *schema.ResourceData) interface{} {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func flattenTpuNodeNetworkEndpointsPort(v interface{}, d *schema.ResourceData) interface{} {
|
|
|
|
// Handles the string fixed64 format
|
|
|
|
if strVal, ok := v.(string); ok {
|
|
|
|
if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil {
|
|
|
|
return intVal
|
|
|
|
} // let terraform core handle it if we can't convert the string to an int.
|
|
|
|
}
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func flattenTpuNodeLabels(v interface{}, d *schema.ResourceData) interface{} {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func expandTpuNodeName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
|
|
|
|
return v, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func expandTpuNodeDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
|
|
|
|
return v, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func expandTpuNodeAcceleratorType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
|
|
|
|
return v, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func expandTpuNodeTensorflowVersion(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
|
|
|
|
return v, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func expandTpuNodeNetwork(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
|
|
|
|
return v, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func expandTpuNodeCidrBlock(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
|
|
|
|
return v, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func expandTpuNodeSchedulingConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
|
|
|
|
l := v.([]interface{})
|
|
|
|
if len(l) == 0 || l[0] == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
raw := l[0]
|
|
|
|
original := raw.(map[string]interface{})
|
|
|
|
transformed := make(map[string]interface{})
|
|
|
|
|
|
|
|
transformedPreemptible, err := expandTpuNodeSchedulingConfigPreemptible(original["preemptible"], d, config)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
} else if val := reflect.ValueOf(transformedPreemptible); val.IsValid() && !isEmptyValue(val) {
|
|
|
|
transformed["preemptible"] = transformedPreemptible
|
|
|
|
}
|
|
|
|
|
|
|
|
return transformed, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func expandTpuNodeSchedulingConfigPreemptible(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
|
|
|
|
return v, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func expandTpuNodeLabels(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
|
|
|
|
if v == nil {
|
|
|
|
return map[string]string{}, nil
|
|
|
|
}
|
|
|
|
m := make(map[string]string)
|
|
|
|
for k, val := range v.(map[string]interface{}) {
|
|
|
|
m[k] = val.(string)
|
|
|
|
}
|
|
|
|
return m, nil
|
|
|
|
}
|