From 46bb9135278902f1169884c93fdef771209e812d Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Tue, 23 Nov 2021 20:46:59 +0000 Subject: [PATCH] Terraform support for Workbench Managed Notebooks (#5414) Signed-off-by: Modular Magician --- .changelog/5414.txt | 4 + google-beta/config.go | 2 +- google-beta/iam_notebooks_runtime.go | 222 ++ .../iam_notebooks_runtime_generated_test.go | 285 +++ google-beta/notebooks_operation.go | 2 +- google-beta/provider.go | 10 +- ...urce_notebooks_environment_sweeper_test.go | 4 +- google-beta/resource_notebooks_instance.go | 2 +- ...esource_notebooks_instance_sweeper_test.go | 4 +- ...esource_notebooks_location_sweeper_test.go | 4 +- google-beta/resource_notebooks_runtime.go | 2035 +++++++++++++++++ ...source_notebooks_runtime_generated_test.go | 219 ++ ...resource_notebooks_runtime_sweeper_test.go | 124 + .../docs/r/notebooks_instance.html.markdown | 2 +- .../docs/r/notebooks_runtime.html.markdown | 563 +++++ .../r/notebooks_runtime_iam.html.markdown | 152 ++ website/google.erb | 8 + 17 files changed, 3629 insertions(+), 13 deletions(-) create mode 100644 .changelog/5414.txt create mode 100644 google-beta/iam_notebooks_runtime.go create mode 100644 google-beta/iam_notebooks_runtime_generated_test.go create mode 100644 google-beta/resource_notebooks_runtime.go create mode 100644 google-beta/resource_notebooks_runtime_generated_test.go create mode 100644 google-beta/resource_notebooks_runtime_sweeper_test.go create mode 100644 website/docs/r/notebooks_runtime.html.markdown create mode 100644 website/docs/r/notebooks_runtime_iam.html.markdown diff --git a/.changelog/5414.txt b/.changelog/5414.txt new file mode 100644 index 0000000000..0e0aa53a2a --- /dev/null +++ b/.changelog/5414.txt @@ -0,0 +1,4 @@ +```release-note:new-resource +`google_notebooks_runtime` +notebooks: Added support for Workbench Managed Notebooks +``` diff --git a/google-beta/config.go b/google-beta/config.go index 7844d26459..00c0c2fa37 100644 --- a/google-beta/config.go +++ b/google-beta/config.go @@ -321,7 +321,7 @@ var DefaultBasePaths = map[string]string{ MonitoringBasePathKey: "https://monitoring.googleapis.com/", NetworkManagementBasePathKey: "https://networkmanagement.googleapis.com/v1/", NetworkServicesBasePathKey: "https://networkservices.googleapis.com/v1/", - NotebooksBasePathKey: "https://notebooks.googleapis.com/v1beta1/", + NotebooksBasePathKey: "https://notebooks.googleapis.com/v1/", OSConfigBasePathKey: "https://osconfig.googleapis.com/v1beta/", OSLoginBasePathKey: "https://oslogin.googleapis.com/v1/", PrivatecaBasePathKey: "https://privateca.googleapis.com/v1/", diff --git a/google-beta/iam_notebooks_runtime.go b/google-beta/iam_notebooks_runtime.go new file mode 100644 index 0000000000..b5e1564939 --- /dev/null +++ b/google-beta/iam_notebooks_runtime.go @@ -0,0 +1,222 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// 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" + + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "google.golang.org/api/cloudresourcemanager/v1" +) + +var NotebooksRuntimeIamSchema = map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + }, + "location": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + }, + "runtime_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + }, +} + +type NotebooksRuntimeIamUpdater struct { + project string + location string + runtimeName string + d TerraformResourceData + Config *Config +} + +func NotebooksRuntimeIamUpdaterProducer(d TerraformResourceData, config *Config) (ResourceIamUpdater, error) { + values := make(map[string]string) + + project, _ := getProject(d, config) + if project != "" { + if err := d.Set("project", project); err != nil { + return nil, fmt.Errorf("Error setting project: %s", err) + } + } + values["project"] = project + location, _ := getLocation(d, config) + if location != "" { + if err := d.Set("location", location); err != nil { + return nil, fmt.Errorf("Error setting location: %s", err) + } + } + values["location"] = location + if v, ok := d.GetOk("runtime_name"); ok { + values["runtime_name"] = v.(string) + } + + // We may have gotten either a long or short name, so attempt to parse long name if possible + m, err := getImportIdQualifiers([]string{"projects/(?P[^/]+)/locations/(?P[^/]+)/runtimes/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)"}, d, config, d.Get("runtime_name").(string)) + if err != nil { + return nil, err + } + + for k, v := range m { + values[k] = v + } + + u := &NotebooksRuntimeIamUpdater{ + project: values["project"], + location: values["location"], + runtimeName: values["runtime_name"], + d: d, + Config: config, + } + + if err := d.Set("project", u.project); err != nil { + return nil, fmt.Errorf("Error setting project: %s", err) + } + if err := d.Set("location", u.location); err != nil { + return nil, fmt.Errorf("Error setting location: %s", err) + } + if err := d.Set("runtime_name", u.GetResourceId()); err != nil { + return nil, fmt.Errorf("Error setting runtime_name: %s", err) + } + + return u, nil +} + +func NotebooksRuntimeIdParseFunc(d *schema.ResourceData, config *Config) error { + values := make(map[string]string) + + project, _ := getProject(d, config) + if project != "" { + values["project"] = project + } + + location, _ := getLocation(d, config) + if location != "" { + values["location"] = location + } + + m, err := getImportIdQualifiers([]string{"projects/(?P[^/]+)/locations/(?P[^/]+)/runtimes/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)"}, d, config, d.Id()) + if err != nil { + return err + } + + for k, v := range m { + values[k] = v + } + + u := &NotebooksRuntimeIamUpdater{ + project: values["project"], + location: values["location"], + runtimeName: values["runtime_name"], + d: d, + Config: config, + } + if err := d.Set("runtime_name", u.GetResourceId()); err != nil { + return fmt.Errorf("Error setting runtime_name: %s", err) + } + d.SetId(u.GetResourceId()) + return nil +} + +func (u *NotebooksRuntimeIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) { + url, err := u.qualifyRuntimeUrl("getIamPolicy") + if err != nil { + return nil, err + } + + project, err := getProject(u.d, u.Config) + if err != nil { + return nil, err + } + var obj map[string]interface{} + + userAgent, err := generateUserAgentString(u.d, u.Config.userAgent) + if err != nil { + return nil, err + } + + policy, err := sendRequest(u.Config, "GET", project, url, userAgent, obj) + if err != nil { + return nil, errwrap.Wrapf(fmt.Sprintf("Error retrieving IAM policy for %s: {{err}}", u.DescribeResource()), err) + } + + out := &cloudresourcemanager.Policy{} + err = Convert(policy, out) + if err != nil { + return nil, errwrap.Wrapf("Cannot convert a policy to a resource manager policy: {{err}}", err) + } + + return out, nil +} + +func (u *NotebooksRuntimeIamUpdater) SetResourceIamPolicy(policy *cloudresourcemanager.Policy) error { + json, err := ConvertToMap(policy) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + obj["policy"] = json + + url, err := u.qualifyRuntimeUrl("setIamPolicy") + if err != nil { + return err + } + project, err := getProject(u.d, u.Config) + if err != nil { + return err + } + + userAgent, err := generateUserAgentString(u.d, u.Config.userAgent) + if err != nil { + return err + } + + _, err = sendRequestWithTimeout(u.Config, "POST", project, url, userAgent, obj, u.d.Timeout(schema.TimeoutCreate)) + if err != nil { + return errwrap.Wrapf(fmt.Sprintf("Error setting IAM policy for %s: {{err}}", u.DescribeResource()), err) + } + + return nil +} + +func (u *NotebooksRuntimeIamUpdater) qualifyRuntimeUrl(methodIdentifier string) (string, error) { + urlTemplate := fmt.Sprintf("{{NotebooksBasePath}}%s:%s", fmt.Sprintf("projects/%s/locations/%s/runtimes/%s", u.project, u.location, u.runtimeName), methodIdentifier) + url, err := replaceVars(u.d, u.Config, urlTemplate) + if err != nil { + return "", err + } + return url, nil +} + +func (u *NotebooksRuntimeIamUpdater) GetResourceId() string { + return fmt.Sprintf("projects/%s/locations/%s/runtimes/%s", u.project, u.location, u.runtimeName) +} + +func (u *NotebooksRuntimeIamUpdater) GetMutexKey() string { + return fmt.Sprintf("iam-notebooks-runtime-%s", u.GetResourceId()) +} + +func (u *NotebooksRuntimeIamUpdater) DescribeResource() string { + return fmt.Sprintf("notebooks runtime %q", u.GetResourceId()) +} diff --git a/google-beta/iam_notebooks_runtime_generated_test.go b/google-beta/iam_notebooks_runtime_generated_test.go new file mode 100644 index 0000000000..0609f0c124 --- /dev/null +++ b/google-beta/iam_notebooks_runtime_generated_test.go @@ -0,0 +1,285 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// 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" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccNotebooksRuntimeIamBindingGenerated(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + "role": "roles/viewer", + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccNotebooksRuntimeIamBinding_basicGenerated(context), + }, + { + ResourceName: "google_notebooks_runtime_iam_binding.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/runtimes/%s roles/viewer", getTestProjectFromEnv(), "us-central1", fmt.Sprintf("tf-test-notebooks-runtime%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + { + // Test Iam Binding update + Config: testAccNotebooksRuntimeIamBinding_updateGenerated(context), + }, + { + ResourceName: "google_notebooks_runtime_iam_binding.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/runtimes/%s roles/viewer", getTestProjectFromEnv(), "us-central1", fmt.Sprintf("tf-test-notebooks-runtime%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccNotebooksRuntimeIamMemberGenerated(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + "role": "roles/viewer", + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + // Test Iam Member creation (no update for member, no need to test) + Config: testAccNotebooksRuntimeIamMember_basicGenerated(context), + }, + { + ResourceName: "google_notebooks_runtime_iam_member.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/runtimes/%s roles/viewer user:admin@hashicorptest.com", getTestProjectFromEnv(), "us-central1", fmt.Sprintf("tf-test-notebooks-runtime%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccNotebooksRuntimeIamPolicyGenerated(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + "role": "roles/viewer", + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccNotebooksRuntimeIamPolicy_basicGenerated(context), + }, + { + ResourceName: "google_notebooks_runtime_iam_policy.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/runtimes/%s", getTestProjectFromEnv(), "us-central1", fmt.Sprintf("tf-test-notebooks-runtime%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccNotebooksRuntimeIamPolicy_emptyBinding(context), + }, + { + ResourceName: "google_notebooks_runtime_iam_policy.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/runtimes/%s", getTestProjectFromEnv(), "us-central1", fmt.Sprintf("tf-test-notebooks-runtime%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccNotebooksRuntimeIamMember_basicGenerated(context map[string]interface{}) string { + return Nprintf(` +resource "google_notebooks_runtime" "runtime" { + name = "tf-test-notebooks-runtime%{random_suffix}" + location = "us-central1" + access_config { + access_type = "SINGLE_USER" + runtime_owner = "admin@hashicorptest.com" + } + virtual_machine { + virtual_machine_config { + machine_type = "n1-standard-4" + data_disk { + initialize_params { + disk_size_gb = "100" + disk_type = "PD_STANDARD" + } + } + } + } +} + +resource "google_notebooks_runtime_iam_member" "foo" { + project = google_notebooks_runtime.runtime.project + location = google_notebooks_runtime.runtime.location + runtime_name = google_notebooks_runtime.runtime.name + role = "%{role}" + member = "user:admin@hashicorptest.com" +} +`, context) +} + +func testAccNotebooksRuntimeIamPolicy_basicGenerated(context map[string]interface{}) string { + return Nprintf(` +resource "google_notebooks_runtime" "runtime" { + name = "tf-test-notebooks-runtime%{random_suffix}" + location = "us-central1" + access_config { + access_type = "SINGLE_USER" + runtime_owner = "admin@hashicorptest.com" + } + virtual_machine { + virtual_machine_config { + machine_type = "n1-standard-4" + data_disk { + initialize_params { + disk_size_gb = "100" + disk_type = "PD_STANDARD" + } + } + } + } +} + +data "google_iam_policy" "foo" { + binding { + role = "%{role}" + members = ["user:admin@hashicorptest.com"] + } +} + +resource "google_notebooks_runtime_iam_policy" "foo" { + project = google_notebooks_runtime.runtime.project + location = google_notebooks_runtime.runtime.location + runtime_name = google_notebooks_runtime.runtime.name + policy_data = data.google_iam_policy.foo.policy_data +} +`, context) +} + +func testAccNotebooksRuntimeIamPolicy_emptyBinding(context map[string]interface{}) string { + return Nprintf(` +resource "google_notebooks_runtime" "runtime" { + name = "tf-test-notebooks-runtime%{random_suffix}" + location = "us-central1" + access_config { + access_type = "SINGLE_USER" + runtime_owner = "admin@hashicorptest.com" + } + virtual_machine { + virtual_machine_config { + machine_type = "n1-standard-4" + data_disk { + initialize_params { + disk_size_gb = "100" + disk_type = "PD_STANDARD" + } + } + } + } +} + +data "google_iam_policy" "foo" { +} + +resource "google_notebooks_runtime_iam_policy" "foo" { + project = google_notebooks_runtime.runtime.project + location = google_notebooks_runtime.runtime.location + runtime_name = google_notebooks_runtime.runtime.name + policy_data = data.google_iam_policy.foo.policy_data +} +`, context) +} + +func testAccNotebooksRuntimeIamBinding_basicGenerated(context map[string]interface{}) string { + return Nprintf(` +resource "google_notebooks_runtime" "runtime" { + name = "tf-test-notebooks-runtime%{random_suffix}" + location = "us-central1" + access_config { + access_type = "SINGLE_USER" + runtime_owner = "admin@hashicorptest.com" + } + virtual_machine { + virtual_machine_config { + machine_type = "n1-standard-4" + data_disk { + initialize_params { + disk_size_gb = "100" + disk_type = "PD_STANDARD" + } + } + } + } +} + +resource "google_notebooks_runtime_iam_binding" "foo" { + project = google_notebooks_runtime.runtime.project + location = google_notebooks_runtime.runtime.location + runtime_name = google_notebooks_runtime.runtime.name + role = "%{role}" + members = ["user:admin@hashicorptest.com"] +} +`, context) +} + +func testAccNotebooksRuntimeIamBinding_updateGenerated(context map[string]interface{}) string { + return Nprintf(` +resource "google_notebooks_runtime" "runtime" { + name = "tf-test-notebooks-runtime%{random_suffix}" + location = "us-central1" + access_config { + access_type = "SINGLE_USER" + runtime_owner = "admin@hashicorptest.com" + } + virtual_machine { + virtual_machine_config { + machine_type = "n1-standard-4" + data_disk { + initialize_params { + disk_size_gb = "100" + disk_type = "PD_STANDARD" + } + } + } + } +} + +resource "google_notebooks_runtime_iam_binding" "foo" { + project = google_notebooks_runtime.runtime.project + location = google_notebooks_runtime.runtime.location + runtime_name = google_notebooks_runtime.runtime.name + role = "%{role}" + members = ["user:admin@hashicorptest.com", "user:paddy@hashicorp.com"] +} +`, context) +} diff --git a/google-beta/notebooks_operation.go b/google-beta/notebooks_operation.go index bba9949045..8b26ea6900 100644 --- a/google-beta/notebooks_operation.go +++ b/google-beta/notebooks_operation.go @@ -31,7 +31,7 @@ func (w *NotebooksOperationWaiter) QueryOp() (interface{}, error) { return nil, fmt.Errorf("Cannot query operation, it's unset or nil.") } // Returns the proper get. - url := fmt.Sprintf("https://notebooks.googleapis.com/v1beta1/%s", w.CommonOperationWaiter.Op.Name) + url := fmt.Sprintf("https://notebooks.googleapis.com/v1/%s", w.CommonOperationWaiter.Op.Name) return sendRequest(w.Config, "GET", w.Project, url, w.UserAgent, nil) } diff --git a/google-beta/provider.go b/google-beta/provider.go index 095b3de62f..d57fb5345b 100644 --- a/google-beta/provider.go +++ b/google-beta/provider.go @@ -894,9 +894,9 @@ func Provider() *schema.Provider { return provider } -// Generated resources: 240 -// Generated IAM resources: 120 -// Total generated resources: 360 +// Generated resources: 241 +// Generated IAM resources: 123 +// Total generated resources: 364 func ResourceMap() map[string]*schema.Resource { resourceMap, _ := ResourceMapWithErrors() return resourceMap @@ -1190,6 +1190,10 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) { "google_notebooks_instance_iam_binding": ResourceIamBinding(NotebooksInstanceIamSchema, NotebooksInstanceIamUpdaterProducer, NotebooksInstanceIdParseFunc), "google_notebooks_instance_iam_member": ResourceIamMember(NotebooksInstanceIamSchema, NotebooksInstanceIamUpdaterProducer, NotebooksInstanceIdParseFunc), "google_notebooks_instance_iam_policy": ResourceIamPolicy(NotebooksInstanceIamSchema, NotebooksInstanceIamUpdaterProducer, NotebooksInstanceIdParseFunc), + "google_notebooks_runtime": resourceNotebooksRuntime(), + "google_notebooks_runtime_iam_binding": ResourceIamBinding(NotebooksRuntimeIamSchema, NotebooksRuntimeIamUpdaterProducer, NotebooksRuntimeIdParseFunc), + "google_notebooks_runtime_iam_member": ResourceIamMember(NotebooksRuntimeIamSchema, NotebooksRuntimeIamUpdaterProducer, NotebooksRuntimeIdParseFunc), + "google_notebooks_runtime_iam_policy": ResourceIamPolicy(NotebooksRuntimeIamSchema, NotebooksRuntimeIamUpdaterProducer, NotebooksRuntimeIdParseFunc), "google_notebooks_location": resourceNotebooksLocation(), "google_os_config_patch_deployment": resourceOSConfigPatchDeployment(), "google_os_config_guest_policies": resourceOSConfigGuestPolicies(), diff --git a/google-beta/resource_notebooks_environment_sweeper_test.go b/google-beta/resource_notebooks_environment_sweeper_test.go index bbd1d18982..3904ee665b 100644 --- a/google-beta/resource_notebooks_environment_sweeper_test.go +++ b/google-beta/resource_notebooks_environment_sweeper_test.go @@ -61,7 +61,7 @@ func testSweepNotebooksEnvironment(region string) error { }, } - listTemplate := strings.Split("https://notebooks.googleapis.com/v1beta1/projects/{{project}}/locations/{{location}}/environments", "?")[0] + listTemplate := strings.Split("https://notebooks.googleapis.com/v1/projects/{{project}}/locations/{{location}}/environments", "?")[0] listUrl, err := replaceVars(d, config, listTemplate) if err != nil { log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) @@ -99,7 +99,7 @@ func testSweepNotebooksEnvironment(region string) error { continue } - deleteTemplate := "https://notebooks.googleapis.com/v1beta1/projects/{{project}}/locations/{{location}}/environments/{{name}}" + deleteTemplate := "https://notebooks.googleapis.com/v1/projects/{{project}}/locations/{{location}}/environments/{{name}}" deleteUrl, err := replaceVars(d, config, deleteTemplate) if err != nil { log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) diff --git a/google-beta/resource_notebooks_instance.go b/google-beta/resource_notebooks_instance.go index 6e91e2fe5e..2f9de61c13 100644 --- a/google-beta/resource_notebooks_instance.go +++ b/google-beta/resource_notebooks_instance.go @@ -375,7 +375,7 @@ Format: projects/{project_id}/regions/{region}/subnetworks/{subnetwork_id}`, Type: schema.TypeList, Optional: true, ForceNew: true, - Description: `The Compute Engine tags to add to runtime.`, + Description: `The Compute Engine tags to add to instance.`, Elem: &schema.Schema{ Type: schema.TypeString, }, diff --git a/google-beta/resource_notebooks_instance_sweeper_test.go b/google-beta/resource_notebooks_instance_sweeper_test.go index b1bfc74131..037c7db1c5 100644 --- a/google-beta/resource_notebooks_instance_sweeper_test.go +++ b/google-beta/resource_notebooks_instance_sweeper_test.go @@ -61,7 +61,7 @@ func testSweepNotebooksInstance(region string) error { }, } - listTemplate := strings.Split("https://notebooks.googleapis.com/v1beta1/projects/{{project}}/locations/{{location}}/instances", "?")[0] + listTemplate := strings.Split("https://notebooks.googleapis.com/v1/projects/{{project}}/locations/{{location}}/instances", "?")[0] listUrl, err := replaceVars(d, config, listTemplate) if err != nil { log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) @@ -99,7 +99,7 @@ func testSweepNotebooksInstance(region string) error { continue } - deleteTemplate := "https://notebooks.googleapis.com/v1beta1/projects/{{project}}/locations/{{location}}/instances/{{name}}" + deleteTemplate := "https://notebooks.googleapis.com/v1/projects/{{project}}/locations/{{location}}/instances/{{name}}" deleteUrl, err := replaceVars(d, config, deleteTemplate) if err != nil { log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) diff --git a/google-beta/resource_notebooks_location_sweeper_test.go b/google-beta/resource_notebooks_location_sweeper_test.go index f76d85fe89..87ebebfe6d 100644 --- a/google-beta/resource_notebooks_location_sweeper_test.go +++ b/google-beta/resource_notebooks_location_sweeper_test.go @@ -61,7 +61,7 @@ func testSweepNotebooksLocation(region string) error { }, } - listTemplate := strings.Split("https://notebooks.googleapis.com/v1beta1/projects/{{project}}/locations", "?")[0] + listTemplate := strings.Split("https://notebooks.googleapis.com/v1/projects/{{project}}/locations", "?")[0] listUrl, err := replaceVars(d, config, listTemplate) if err != nil { log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) @@ -99,7 +99,7 @@ func testSweepNotebooksLocation(region string) error { continue } - deleteTemplate := "https://notebooks.googleapis.com/v1beta1/projects/{{project}}/locations/{{name}}" + deleteTemplate := "https://notebooks.googleapis.com/v1/projects/{{project}}/locations/{{name}}" deleteUrl, err := replaceVars(d, config, deleteTemplate) if err != nil { log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) diff --git a/google-beta/resource_notebooks_runtime.go b/google-beta/resource_notebooks_runtime.go new file mode 100644 index 0000000000..9b672ea2e1 --- /dev/null +++ b/google-beta/resource_notebooks_runtime.go @@ -0,0 +1,2035 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// 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" + "strconv" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +const notebooksRuntimeGoogleProvidedLabel = "goog-caip-managed-notebook" + +func NotebooksRuntimeLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + // Suppress diffs for the label provided by Google + if strings.Contains(k, notebooksRuntimeGoogleProvidedLabel) && new == "" { + return true + } + + // Let diff be determined by labels (above) + if strings.Contains(k, "labels.%") { + return true + } + + // For other keys, don't suppress diff. + return false +} + +// NotReturnedByAPIDiffSuppress +func NotReturnedByAPIDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + return true +} + +func resourceNotebooksRuntime() *schema.Resource { + return &schema.Resource{ + Create: resourceNotebooksRuntimeCreate, + Read: resourceNotebooksRuntimeRead, + Update: resourceNotebooksRuntimeUpdate, + Delete: resourceNotebooksRuntimeDelete, + + Importer: &schema.ResourceImporter{ + State: resourceNotebooksRuntimeImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(15 * time.Minute), + Update: schema.DefaultTimeout(15 * time.Minute), + Delete: schema.DefaultTimeout(15 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: `A reference to the zone where the machine resides.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name specified for the Notebook instance.`, + }, + "access_config": { + Type: schema.TypeList, + Optional: true, + Description: `The config settings for accessing runtime.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "access_type": { + Type: schema.TypeString, + Optional: true, + Description: `The type of access mode this instance. For valid values, see +'https://cloud.google.com/vertex-ai/docs/workbench/reference/ +rest/v1/projects.locations.runtimes#RuntimeAccessType'.`, + }, + "runtime_owner": { + Type: schema.TypeString, + Optional: true, + Description: `The owner of this runtime after creation. Format: 'alias@example.com'. +Currently supports one owner only.`, + }, + "proxy_uri": { + Type: schema.TypeString, + Computed: true, + Description: `The proxy endpoint that is used to access the runtime.`, + }, + }, + }, + }, + "software_config": { + Type: schema.TypeList, + Optional: true, + Description: `The config settings for software inside the runtime.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "custom_gpu_driver_path": { + Type: schema.TypeString, + Optional: true, + Description: `Specify a custom Cloud Storage path where the GPU driver is stored. +If not specified, we'll automatically choose from official GPU drivers.`, + }, + "enable_health_monitoring": { + Type: schema.TypeBool, + Optional: true, + Description: `Verifies core internal services are running. Default: True.`, + Default: true, + }, + "idle_shutdown": { + Type: schema.TypeBool, + Optional: true, + Description: `Runtime will automatically shutdown after idle_shutdown_time. +Default: True`, + Default: true, + }, + "idle_shutdown_timeout": { + Type: schema.TypeInt, + Optional: true, + Description: `Time in minutes to wait before shuting down runtime. +Default: 180 minutes`, + }, + "install_gpu_driver": { + Type: schema.TypeBool, + Optional: true, + Description: `Install Nvidia Driver automatically.`, + }, + "notebook_upgrade_schedule": { + Type: schema.TypeString, + Optional: true, + Description: `Cron expression in UTC timezone for schedule instance auto upgrade. +Please follow the [cron format](https://en.wikipedia.org/wiki/Cron).`, + }, + "post_startup_script": { + Type: schema.TypeString, + Optional: true, + Description: `Path to a Bash script that automatically runs after a notebook instance +fully boots up. The path must be a URL or +Cloud Storage path (gs://path-to-file/file-name).`, + }, + }, + }, + }, + "virtual_machine": { + Type: schema.TypeList, + Optional: true, + Description: `Use a Compute Engine VM image to start the managed notebook instance.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "virtual_machine_config": { + Type: schema.TypeList, + Optional: true, + Description: `Virtual Machine configuration settings.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "data_disk": { + Type: schema.TypeList, + Required: true, + Description: `Data disk option configuration settings.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "initialize_params": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Input only. Specifies the parameters for a new disk that will +be created alongside the new instance. Use initialization +parameters to create boot disks or local SSDs attached to the +new instance. This property is mutually exclusive with the +source property; you can only define one or the other, but not +both.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "description": { + Type: schema.TypeString, + Optional: true, + Description: `Provide this property when creating the disk.`, + }, + "disk_name": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies the disk name. If not specified, the default is +to use the name of the instance. If the disk with the +instance name exists already in the given zone/region, a +new name will be automatically generated.`, + }, + "disk_size_gb": { + Type: schema.TypeInt, + Optional: true, + Description: `Specifies the size of the disk in base-2 GB. If not +specified, the disk will be the same size as the image +(usually 10GB). If specified, the size must be equal to +or larger than 10GB. Default 100 GB.`, + }, + "disk_type": { + Type: schema.TypeString, + Optional: true, + Description: `The type of the boot disk attached to this runtime, +defaults to standard persistent disk. For valid values, +see 'https://cloud.google.com/vertex-ai/docs/workbench/ +reference/rest/v1/projects.locations.runtimes#disktype'`, + }, + "labels": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + Description: `Labels to apply to this disk. These can be later modified +by the disks.setLabels method. This field is only +applicable for persistent disks.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "interface": { + Type: schema.TypeString, + Optional: true, + Description: `"Specifies the disk interface to use for attaching this disk, +which is either SCSI or NVME. The default is SCSI. Persistent +disks must always use SCSI and the request will fail if you attempt +to attach a persistent disk in any other format than SCSI. Local SSDs +can use either NVME or SCSI. For performance characteristics of SCSI +over NVMe, see Local SSD performance. Valid values: * NVME * SCSI".`, + }, + "mode": { + Type: schema.TypeString, + Optional: true, + Description: `The mode in which to attach this disk, either READ_WRITE +or READ_ONLY. If not specified, the default is to attach +the disk in READ_WRITE mode.`, + }, + "source": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies a valid partial or full URL to an existing +Persistent Disk resource.`, + }, + "type": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies the type of the disk, either SCRATCH or PERSISTENT. +If not specified, the default is PERSISTENT.`, + }, + "auto_delete": { + Type: schema.TypeBool, + Computed: true, + Description: `Optional. Specifies whether the disk will be auto-deleted +when the instance is deleted (but not when the disk is +detached from the instance).`, + }, + "boot": { + Type: schema.TypeBool, + Computed: true, + Description: `Optional. Indicates that this is a boot disk. The virtual +machine will use the first partition of the disk for its +root filesystem.`, + }, + "device_name": { + Type: schema.TypeString, + Computed: true, + Description: `Optional. Specifies a unique device name of your choice +that is reflected into the /dev/disk/by-id/google-* tree +of a Linux operating system running within the instance. +This name can be used to reference the device for mounting, +resizing, and so on, from within the instance. +If not specified, the server chooses a default device name +to apply to this disk, in the form persistent-disk-x, where +x is a number assigned by Google Compute Engine. This field +is only applicable for persistent disks.`, + }, + "guest_os_features": { + Type: schema.TypeList, + Computed: true, + Description: `Indicates a list of features to enable on the guest operating +system. Applicable only for bootable images. To see a list of +available features, read 'https://cloud.google.com/compute/docs/ +images/create-delete-deprecate-private-images#guest-os-features' +options. ''`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "index": { + Type: schema.TypeInt, + Computed: true, + Description: `Output only. A zero-based index to this disk, where 0 is +reserved for the boot disk. If you have many disks attached +to an instance, each disk would have a unique index number.`, + }, + "kind": { + Type: schema.TypeString, + Computed: true, + Description: `Type of the resource. Always compute#attachedDisk for attached +disks.`, + }, + "licenses": { + Type: schema.TypeList, + Computed: true, + Description: `Output only. Any valid publicly visible licenses.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "machine_type": { + Type: schema.TypeString, + Required: true, + Description: `The Compute Engine machine type used for runtimes.`, + }, + "accelerator_config": { + Type: schema.TypeList, + Optional: true, + Description: `The Compute Engine accelerator configuration for this runtime.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "core_count": { + Type: schema.TypeInt, + Optional: true, + Description: `Count of cores of this accelerator.`, + }, + "type": { + Type: schema.TypeString, + Optional: true, + Description: `Accelerator model. For valid values, see +'https://cloud.google.com/vertex-ai/docs/workbench/reference/ +rest/v1/projects.locations.runtimes#AcceleratorType'`, + }, + }, + }, + }, + "container_images": { + Type: schema.TypeList, + Optional: true, + DiffSuppressFunc: NotReturnedByAPIDiffSuppress, + Description: `Use a list of container images to start the notebook instance.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "repository": { + Type: schema.TypeString, + Required: true, + Description: `The path to the container image repository. +For example: gcr.io/{project_id}/{imageName}`, + }, + "tag": { + Type: schema.TypeString, + Optional: true, + Description: `The tag of the container image. If not specified, this defaults to the latest tag.`, + }, + }, + }, + }, + "encryption_config": { + Type: schema.TypeList, + Optional: true, + Description: `Encryption settings for virtual machine data disk.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "kms_key": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud KMS resource identifier of the customer-managed +encryption key used to protect a resource, such as a disks. +It has the following format: +'projects/{PROJECT_ID}/locations/{REGION}/keyRings/ +{KEY_RING_NAME}/cryptoKeys/{KEY_NAME}'`, + }, + }, + }, + }, + "internal_ip_only": { + Type: schema.TypeBool, + Optional: true, + Description: `If true, runtime will only have internal IP addresses. By default, +runtimes are not restricted to internal IP addresses, and will +have ephemeral external IP addresses assigned to each vm. This +'internal_ip_only' restriction can only be enabled for subnetwork +enabled networks, and all dependencies must be configured to be +accessible without external IP addresses.`, + }, + "labels": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + DiffSuppressFunc: NotebooksRuntimeLabelDiffSuppress, + Description: `The labels to associate with this runtime. Label **keys** must +contain 1 to 63 characters, and must conform to [RFC 1035] +(https://www.ietf.org/rfc/rfc1035.txt). Label **values** may be +empty, but, if present, must contain 1 to 63 characters, and must +conform to [RFC 1035](https://www.ietf.org/rfc/rfc1035.txt). No +more than 32 labels can be associated with a cluster.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "metadata": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + Description: `The Compute Engine metadata entries to add to virtual machine. +(see [Project and instance metadata](https://cloud.google.com +/compute/docs/storing-retrieving-metadata#project_and_instance +_metadata)).`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "network": { + Type: schema.TypeString, + Optional: true, + Description: `The Compute Engine network to be used for machine communications. +Cannot be specified with subnetwork. If neither 'network' nor +'subnet' is specified, the "default" network of the project is +used, if it exists. A full URL or partial URI. Examples: + * 'https://www.googleapis.com/compute/v1/projects/[project_id]/ + regions/global/default' + * 'projects/[project_id]/regions/global/default' +Runtimes are managed resources inside Google Infrastructure. +Runtimes support the following network configurations: + * Google Managed Network (Network & subnet are empty) + * Consumer Project VPC (network & subnet are required). Requires + configuring Private Service Access. + * Shared VPC (network & subnet are required). Requires + configuring Private Service Access.`, + }, + "nic_type": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"UNSPECIFIED_NIC_TYPE", "VIRTIO_NET", "GVNIC", ""}, false), + Description: `The type of vNIC to be used on this interface. This may be gVNIC +or VirtioNet. Possible values: ["UNSPECIFIED_NIC_TYPE", "VIRTIO_NET", "GVNIC"]`, + }, + "shielded_instance_config": { + Type: schema.TypeList, + Optional: true, + Description: `Shielded VM Instance configuration settings.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_integrity_monitoring": { + Type: schema.TypeBool, + Optional: true, + Description: `Defines whether the instance has integrity monitoring enabled. +Enables monitoring and attestation of the boot integrity of +the instance. The attestation is performed against the +integrity policy baseline. This baseline is initially derived +from the implicitly trusted boot image when the instance is +created. Enabled by default.`, + }, + "enable_secure_boot": { + Type: schema.TypeBool, + Optional: true, + Description: `Defines whether the instance has Secure Boot enabled.Secure +Boot helps ensure that the system only runs authentic software +by verifying the digital signature of all boot components, and +halting the boot process if signature verification fails. +Disabled by default.`, + }, + "enable_vtpm": { + Type: schema.TypeBool, + Optional: true, + Description: `Defines whether the instance has the vTPM enabled. Enabled by +default.`, + }, + }, + }, + }, + "subnet": { + Type: schema.TypeString, + Optional: true, + Description: `The Compute Engine subnetwork to be used for machine +communications. Cannot be specified with network. A full URL or +partial URI are valid. Examples: + * 'https://www.googleapis.com/compute/v1/projects/[project_id]/ + regions/us-east1/subnetworks/sub0' + * 'projects/[project_id]/regions/us-east1/subnetworks/sub0'`, + }, + "tags": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `The Compute Engine tags to add to runtime (see [Tagging instances] +(https://cloud.google.com/compute/docs/ +label-or-tag-resources#tags)).`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "guest_attributes": { + Type: schema.TypeMap, + Computed: true, + Description: `The Compute Engine guest attributes. (see [Project and instance +guest attributes](https://cloud.google.com/compute/docs/ +storing-retrieving-metadata#guest_attributes)).`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "zone": { + Type: schema.TypeString, + Computed: true, + Description: `The zone where the virtual machine is located.`, + }, + }, + }, + }, + "instance_id": { + Type: schema.TypeString, + Computed: true, + Description: `The unique identifier of the Managed Compute Engine instance.`, + }, + "instance_name": { + Type: schema.TypeString, + Computed: true, + Description: `The user-friendly name of the Managed Compute Engine instance.`, + }, + }, + }, + ExactlyOneOf: []string{"virtual_machine"}, + }, + "health_state": { + Type: schema.TypeString, + Computed: true, + Description: `The health state of this runtime. For a list of possible output +values, see 'https://cloud.google.com/vertex-ai/docs/workbench/ +reference/rest/v1/projects.locations.runtimes#healthstate'.`, + }, + "metrics": { + Type: schema.TypeList, + Computed: true, + Description: `Contains Runtime daemon metrics such as Service status and JupyterLab +status`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "system_metrics": { + Type: schema.TypeMap, + Computed: true, + Description: `Contains runtime daemon metrics, such as OS and kernels and +sessions stats.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "state": { + Type: schema.TypeString, + Computed: true, + Description: `The state of this runtime.`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func resourceNotebooksRuntimeCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + virtualMachineProp, err := expandNotebooksRuntimeVirtualMachine(d.Get("virtual_machine"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("virtual_machine"); !isEmptyValue(reflect.ValueOf(virtualMachineProp)) && (ok || !reflect.DeepEqual(v, virtualMachineProp)) { + obj["virtualMachine"] = virtualMachineProp + } + accessConfigProp, err := expandNotebooksRuntimeAccessConfig(d.Get("access_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("access_config"); !isEmptyValue(reflect.ValueOf(accessConfigProp)) && (ok || !reflect.DeepEqual(v, accessConfigProp)) { + obj["accessConfig"] = accessConfigProp + } + softwareConfigProp, err := expandNotebooksRuntimeSoftwareConfig(d.Get("software_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("software_config"); !isEmptyValue(reflect.ValueOf(softwareConfigProp)) && (ok || !reflect.DeepEqual(v, softwareConfigProp)) { + obj["softwareConfig"] = softwareConfigProp + } + + url, err := replaceVars(d, config, "{{NotebooksBasePath}}projects/{{project}}/locations/{{location}}/runtimes?runtimeId={{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new Runtime: %#v", obj) + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for Runtime: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := sendRequestWithTimeout(config, "POST", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return fmt.Errorf("Error creating Runtime: %s", err) + } + + // Store the ID now + id, err := replaceVars(d, config, "projects/{{project}}/locations/{{location}}/runtimes/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + // Use the resource in the operation response to populate + // identity fields and d.Id() before read + var opRes map[string]interface{} + err = notebooksOperationWaitTimeWithResponse( + config, res, &opRes, project, "Creating Runtime", userAgent, + d.Timeout(schema.TimeoutCreate)) + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create Runtime: %s", err) + } + + // This may have caused the ID to update - update it if so. + id, err = replaceVars(d, config, "projects/{{project}}/locations/{{location}}/runtimes/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + log.Printf("[DEBUG] Finished creating Runtime %q: %#v", d.Id(), res) + + return resourceNotebooksRuntimeRead(d, meta) +} + +func resourceNotebooksRuntimeRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + url, err := replaceVars(d, config, "{{NotebooksBasePath}}projects/{{project}}/locations/{{location}}/runtimes/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for Runtime: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := sendRequest(config, "GET", billingProject, url, userAgent, nil) + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("NotebooksRuntime %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading Runtime: %s", err) + } + + if err := d.Set("virtual_machine", flattenNotebooksRuntimeVirtualMachine(res["virtualMachine"], d, config)); err != nil { + return fmt.Errorf("Error reading Runtime: %s", err) + } + if err := d.Set("state", flattenNotebooksRuntimeState(res["state"], d, config)); err != nil { + return fmt.Errorf("Error reading Runtime: %s", err) + } + if err := d.Set("health_state", flattenNotebooksRuntimeHealthState(res["healthState"], d, config)); err != nil { + return fmt.Errorf("Error reading Runtime: %s", err) + } + if err := d.Set("access_config", flattenNotebooksRuntimeAccessConfig(res["accessConfig"], d, config)); err != nil { + return fmt.Errorf("Error reading Runtime: %s", err) + } + if err := d.Set("software_config", flattenNotebooksRuntimeSoftwareConfig(res["softwareConfig"], d, config)); err != nil { + return fmt.Errorf("Error reading Runtime: %s", err) + } + if err := d.Set("metrics", flattenNotebooksRuntimeMetrics(res["metrics"], d, config)); err != nil { + return fmt.Errorf("Error reading Runtime: %s", err) + } + + return nil +} + +func resourceNotebooksRuntimeUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for Runtime: %s", err) + } + billingProject = project + + obj := make(map[string]interface{}) + virtualMachineProp, err := expandNotebooksRuntimeVirtualMachine(d.Get("virtual_machine"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("virtual_machine"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, virtualMachineProp)) { + obj["virtualMachine"] = virtualMachineProp + } + accessConfigProp, err := expandNotebooksRuntimeAccessConfig(d.Get("access_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("access_config"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, accessConfigProp)) { + obj["accessConfig"] = accessConfigProp + } + softwareConfigProp, err := expandNotebooksRuntimeSoftwareConfig(d.Get("software_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("software_config"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, softwareConfigProp)) { + obj["softwareConfig"] = softwareConfigProp + } + + url, err := replaceVars(d, config, "{{NotebooksBasePath}}projects/{{project}}/locations/{{location}}/runtimes/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating Runtime %q: %#v", d.Id(), obj) + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := sendRequestWithTimeout(config, "PUT", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return fmt.Errorf("Error updating Runtime %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating Runtime %q: %#v", d.Id(), res) + } + + err = notebooksOperationWaitTime( + config, res, project, "Updating Runtime", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + + return resourceNotebooksRuntimeRead(d, meta) +} + +func resourceNotebooksRuntimeDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for Runtime: %s", err) + } + billingProject = project + + url, err := replaceVars(d, config, "{{NotebooksBasePath}}projects/{{project}}/locations/{{location}}/runtimes/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + log.Printf("[DEBUG] Deleting Runtime %q", d.Id()) + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := sendRequestWithTimeout(config, "DELETE", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutDelete)) + if err != nil { + return handleNotFoundError(err, d, "Runtime") + } + + err = notebooksOperationWaitTime( + config, res, project, "Deleting Runtime", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting Runtime %q: %#v", d.Id(), res) + return nil +} + +func resourceNotebooksRuntimeImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + if err := parseImportId([]string{ + "projects/(?P[^/]+)/locations/(?P[^/]+)/runtimes/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := replaceVars(d, config, "projects/{{project}}/locations/{{location}}/runtimes/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenNotebooksRuntimeVirtualMachine(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["instance_name"] = + flattenNotebooksRuntimeVirtualMachineInstanceName(original["instanceName"], d, config) + transformed["instance_id"] = + flattenNotebooksRuntimeVirtualMachineInstanceId(original["instanceId"], d, config) + transformed["virtual_machine_config"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfig(original["virtualMachineConfig"], d, config) + return []interface{}{transformed} +} +func flattenNotebooksRuntimeVirtualMachineInstanceName(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineInstanceId(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["zone"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigZone(original["zone"], d, config) + transformed["machine_type"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigMachineType(original["machineType"], d, config) + transformed["data_disk"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDisk(original["dataDisk"], d, config) + transformed["container_images"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigContainerImages(original["containerImages"], d, config) + transformed["encryption_config"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigEncryptionConfig(original["encryptionConfig"], d, config) + transformed["shielded_instance_config"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfig(original["shieldedInstanceConfig"], d, config) + transformed["accelerator_config"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigAcceleratorConfig(original["acceleratorConfig"], d, config) + transformed["network"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigNetwork(original["network"], d, config) + transformed["subnet"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigSubnet(original["subnet"], d, config) + transformed["internal_ip_only"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigInternalIpOnly(original["internalIpOnly"], d, config) + transformed["tags"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigTags(original["tags"], d, config) + transformed["guest_attributes"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigGuestAttributes(original["guestAttributes"], d, config) + transformed["metadata"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigMetadata(original["metadata"], d, config) + transformed["labels"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigLabels(original["labels"], d, config) + transformed["nic_type"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigNicType(original["nicType"], d, config) + return []interface{}{transformed} +} +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigZone(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigMachineType(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDisk(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["auto_delete"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskAutoDelete(original["autoDelete"], d, config) + transformed["boot"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskBoot(original["boot"], d, config) + transformed["device_name"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskDeviceName(original["deviceName"], d, config) + transformed["guest_os_features"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskGuestOsFeatures(original["guestOsFeatures"], d, config) + transformed["index"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskIndex(original["index"], d, config) + transformed["initialize_params"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParams(original["initializeParams"], d, config) + transformed["interface"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInterface(original["interface"], d, config) + transformed["kind"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskKind(original["kind"], d, config) + transformed["licenses"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskLicenses(original["licenses"], d, config) + transformed["mode"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskMode(original["mode"], d, config) + transformed["source"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskSource(original["source"], d, config) + transformed["type"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskType(original["type"], d, config) + return []interface{}{transformed} +} +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskAutoDelete(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskBoot(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskDeviceName(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskGuestOsFeatures(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskIndex(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParams(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["description"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDescription(original["description"], d, config) + transformed["disk_name"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDiskName(original["diskName"], d, config) + transformed["disk_size_gb"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDiskSizeGb(original["diskSizeGb"], d, config) + transformed["disk_type"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDiskType(original["diskType"], d, config) + transformed["labels"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsLabels(original["labels"], d, config) + return []interface{}{transformed} +} +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDescription(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDiskName(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDiskSizeGb(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDiskType(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsLabels(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInterface(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskKind(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskLicenses(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskMode(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskSource(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskType(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigContainerImages(v interface{}, d *schema.ResourceData, config *Config) 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{}{ + "repository": flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigContainerImagesRepository(original["repository"], d, config), + "tag": flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigContainerImagesTag(original["tag"], d, config), + }) + } + return transformed +} +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigContainerImagesRepository(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigContainerImagesTag(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigEncryptionConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["kms_key"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigEncryptionConfigKmsKey(original["kmsKey"], d, config) + return []interface{}{transformed} +} +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigEncryptionConfigKmsKey(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["enable_secure_boot"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfigEnableSecureBoot(original["enableSecureBoot"], d, config) + transformed["enable_vtpm"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfigEnableVtpm(original["enableVtpm"], d, config) + transformed["enable_integrity_monitoring"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfigEnableIntegrityMonitoring(original["enableIntegrityMonitoring"], d, config) + return []interface{}{transformed} +} +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfigEnableSecureBoot(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfigEnableVtpm(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfigEnableIntegrityMonitoring(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigAcceleratorConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["type"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigAcceleratorConfigType(original["type"], d, config) + transformed["core_count"] = + flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigAcceleratorConfigCoreCount(original["coreCount"], d, config) + return []interface{}{transformed} +} +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigAcceleratorConfigType(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigAcceleratorConfigCoreCount(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigNetwork(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigSubnet(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigInternalIpOnly(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigTags(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigGuestAttributes(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigMetadata(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigLabels(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeVirtualMachineVirtualMachineConfigNicType(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeState(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeHealthState(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeAccessConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["access_type"] = + flattenNotebooksRuntimeAccessConfigAccessType(original["accessType"], d, config) + transformed["runtime_owner"] = + flattenNotebooksRuntimeAccessConfigRuntimeOwner(original["runtimeOwner"], d, config) + transformed["proxy_uri"] = + flattenNotebooksRuntimeAccessConfigProxyUri(original["proxyUri"], d, config) + return []interface{}{transformed} +} +func flattenNotebooksRuntimeAccessConfigAccessType(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeAccessConfigRuntimeOwner(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeAccessConfigProxyUri(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeSoftwareConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["notebook_upgrade_schedule"] = + flattenNotebooksRuntimeSoftwareConfigNotebookUpgradeSchedule(original["notebookUpgradeSchedule"], d, config) + transformed["enable_health_monitoring"] = + flattenNotebooksRuntimeSoftwareConfigEnableHealthMonitoring(original["enableHealthMonitoring"], d, config) + transformed["idle_shutdown"] = + flattenNotebooksRuntimeSoftwareConfigIdleShutdown(original["idleShutdown"], d, config) + transformed["idle_shutdown_timeout"] = + flattenNotebooksRuntimeSoftwareConfigIdleShutdownTimeout(original["idleShutdownTimeout"], d, config) + transformed["install_gpu_driver"] = + flattenNotebooksRuntimeSoftwareConfigInstallGpuDriver(original["installGpuDriver"], d, config) + transformed["custom_gpu_driver_path"] = + flattenNotebooksRuntimeSoftwareConfigCustomGpuDriverPath(original["customGpuDriverPath"], d, config) + transformed["post_startup_script"] = + flattenNotebooksRuntimeSoftwareConfigPostStartupScript(original["postStartupScript"], d, config) + return []interface{}{transformed} +} +func flattenNotebooksRuntimeSoftwareConfigNotebookUpgradeSchedule(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeSoftwareConfigEnableHealthMonitoring(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeSoftwareConfigIdleShutdown(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeSoftwareConfigIdleShutdownTimeout(v interface{}, d *schema.ResourceData, config *Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenNotebooksRuntimeSoftwareConfigInstallGpuDriver(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeSoftwareConfigCustomGpuDriverPath(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeSoftwareConfigPostStartupScript(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenNotebooksRuntimeMetrics(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["system_metrics"] = + flattenNotebooksRuntimeMetricsSystemMetrics(original["systemMetrics"], d, config) + return []interface{}{transformed} +} +func flattenNotebooksRuntimeMetricsSystemMetrics(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func expandNotebooksRuntimeVirtualMachine(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{}) + + transformedInstanceName, err := expandNotebooksRuntimeVirtualMachineInstanceName(original["instance_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedInstanceName); val.IsValid() && !isEmptyValue(val) { + transformed["instanceName"] = transformedInstanceName + } + + transformedInstanceId, err := expandNotebooksRuntimeVirtualMachineInstanceId(original["instance_id"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedInstanceId); val.IsValid() && !isEmptyValue(val) { + transformed["instanceId"] = transformedInstanceId + } + + transformedVirtualMachineConfig, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfig(original["virtual_machine_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedVirtualMachineConfig); val.IsValid() && !isEmptyValue(val) { + transformed["virtualMachineConfig"] = transformedVirtualMachineConfig + } + + return transformed, nil +} + +func expandNotebooksRuntimeVirtualMachineInstanceName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineInstanceId(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfig(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{}) + + transformedZone, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigZone(original["zone"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedZone); val.IsValid() && !isEmptyValue(val) { + transformed["zone"] = transformedZone + } + + transformedMachineType, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigMachineType(original["machine_type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMachineType); val.IsValid() && !isEmptyValue(val) { + transformed["machineType"] = transformedMachineType + } + + transformedDataDisk, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDisk(original["data_disk"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDataDisk); val.IsValid() && !isEmptyValue(val) { + transformed["dataDisk"] = transformedDataDisk + } + + transformedContainerImages, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigContainerImages(original["container_images"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedContainerImages); val.IsValid() && !isEmptyValue(val) { + transformed["containerImages"] = transformedContainerImages + } + + transformedEncryptionConfig, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigEncryptionConfig(original["encryption_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEncryptionConfig); val.IsValid() && !isEmptyValue(val) { + transformed["encryptionConfig"] = transformedEncryptionConfig + } + + transformedShieldedInstanceConfig, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfig(original["shielded_instance_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedShieldedInstanceConfig); val.IsValid() && !isEmptyValue(val) { + transformed["shieldedInstanceConfig"] = transformedShieldedInstanceConfig + } + + transformedAcceleratorConfig, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigAcceleratorConfig(original["accelerator_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAcceleratorConfig); val.IsValid() && !isEmptyValue(val) { + transformed["acceleratorConfig"] = transformedAcceleratorConfig + } + + transformedNetwork, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigNetwork(original["network"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetwork); val.IsValid() && !isEmptyValue(val) { + transformed["network"] = transformedNetwork + } + + transformedSubnet, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigSubnet(original["subnet"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSubnet); val.IsValid() && !isEmptyValue(val) { + transformed["subnet"] = transformedSubnet + } + + transformedInternalIpOnly, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigInternalIpOnly(original["internal_ip_only"], d, config) + if err != nil { + return nil, err + } else { + transformed["internalIpOnly"] = transformedInternalIpOnly + } + + transformedTags, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigTags(original["tags"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTags); val.IsValid() && !isEmptyValue(val) { + transformed["tags"] = transformedTags + } + + transformedGuestAttributes, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigGuestAttributes(original["guest_attributes"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedGuestAttributes); val.IsValid() && !isEmptyValue(val) { + transformed["guestAttributes"] = transformedGuestAttributes + } + + transformedMetadata, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigMetadata(original["metadata"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMetadata); val.IsValid() && !isEmptyValue(val) { + transformed["metadata"] = transformedMetadata + } + + transformedLabels, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigLabels(original["labels"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLabels); val.IsValid() && !isEmptyValue(val) { + transformed["labels"] = transformedLabels + } + + transformedNicType, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigNicType(original["nic_type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNicType); val.IsValid() && !isEmptyValue(val) { + transformed["nicType"] = transformedNicType + } + + return transformed, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigZone(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigMachineType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDisk(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{}) + + transformedAutoDelete, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskAutoDelete(original["auto_delete"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAutoDelete); val.IsValid() && !isEmptyValue(val) { + transformed["autoDelete"] = transformedAutoDelete + } + + transformedBoot, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskBoot(original["boot"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedBoot); val.IsValid() && !isEmptyValue(val) { + transformed["boot"] = transformedBoot + } + + transformedDeviceName, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskDeviceName(original["device_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDeviceName); val.IsValid() && !isEmptyValue(val) { + transformed["deviceName"] = transformedDeviceName + } + + transformedGuestOsFeatures, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskGuestOsFeatures(original["guest_os_features"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedGuestOsFeatures); val.IsValid() && !isEmptyValue(val) { + transformed["guestOsFeatures"] = transformedGuestOsFeatures + } + + transformedIndex, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskIndex(original["index"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIndex); val.IsValid() && !isEmptyValue(val) { + transformed["index"] = transformedIndex + } + + transformedInitializeParams, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParams(original["initialize_params"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedInitializeParams); val.IsValid() && !isEmptyValue(val) { + transformed["initializeParams"] = transformedInitializeParams + } + + transformedInterface, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInterface(original["interface"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedInterface); val.IsValid() && !isEmptyValue(val) { + transformed["interface"] = transformedInterface + } + + transformedKind, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskKind(original["kind"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedKind); val.IsValid() && !isEmptyValue(val) { + transformed["kind"] = transformedKind + } + + transformedLicenses, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskLicenses(original["licenses"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLicenses); val.IsValid() && !isEmptyValue(val) { + transformed["licenses"] = transformedLicenses + } + + transformedMode, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskMode(original["mode"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMode); val.IsValid() && !isEmptyValue(val) { + transformed["mode"] = transformedMode + } + + transformedSource, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskSource(original["source"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSource); val.IsValid() && !isEmptyValue(val) { + transformed["source"] = transformedSource + } + + transformedType, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskType(original["type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedType); val.IsValid() && !isEmptyValue(val) { + transformed["type"] = transformedType + } + + return transformed, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskAutoDelete(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskBoot(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskDeviceName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskGuestOsFeatures(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskIndex(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParams(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{}) + + transformedDescription, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDescription(original["description"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDescription); val.IsValid() && !isEmptyValue(val) { + transformed["description"] = transformedDescription + } + + transformedDiskName, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDiskName(original["disk_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDiskName); val.IsValid() && !isEmptyValue(val) { + transformed["diskName"] = transformedDiskName + } + + transformedDiskSizeGb, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDiskSizeGb(original["disk_size_gb"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDiskSizeGb); val.IsValid() && !isEmptyValue(val) { + transformed["diskSizeGb"] = transformedDiskSizeGb + } + + transformedDiskType, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDiskType(original["disk_type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDiskType); val.IsValid() && !isEmptyValue(val) { + transformed["diskType"] = transformedDiskType + } + + transformedLabels, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsLabels(original["labels"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLabels); val.IsValid() && !isEmptyValue(val) { + transformed["labels"] = transformedLabels + } + + return transformed, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDiskName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDiskSizeGb(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsDiskType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInitializeParamsLabels(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 +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskInterface(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskKind(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskLicenses(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskMode(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskSource(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigDataDiskType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigContainerImages(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedRepository, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigContainerImagesRepository(original["repository"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRepository); val.IsValid() && !isEmptyValue(val) { + transformed["repository"] = transformedRepository + } + + transformedTag, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigContainerImagesTag(original["tag"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTag); val.IsValid() && !isEmptyValue(val) { + transformed["tag"] = transformedTag + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigContainerImagesRepository(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigContainerImagesTag(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigEncryptionConfig(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{}) + + transformedKmsKey, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigEncryptionConfigKmsKey(original["kms_key"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedKmsKey); val.IsValid() && !isEmptyValue(val) { + transformed["kmsKey"] = transformedKmsKey + } + + return transformed, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigEncryptionConfigKmsKey(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfig(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{}) + + transformedEnableSecureBoot, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfigEnableSecureBoot(original["enable_secure_boot"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnableSecureBoot); val.IsValid() && !isEmptyValue(val) { + transformed["enableSecureBoot"] = transformedEnableSecureBoot + } + + transformedEnableVtpm, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfigEnableVtpm(original["enable_vtpm"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnableVtpm); val.IsValid() && !isEmptyValue(val) { + transformed["enableVtpm"] = transformedEnableVtpm + } + + transformedEnableIntegrityMonitoring, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfigEnableIntegrityMonitoring(original["enable_integrity_monitoring"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnableIntegrityMonitoring); val.IsValid() && !isEmptyValue(val) { + transformed["enableIntegrityMonitoring"] = transformedEnableIntegrityMonitoring + } + + return transformed, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfigEnableSecureBoot(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfigEnableVtpm(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigShieldedInstanceConfigEnableIntegrityMonitoring(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigAcceleratorConfig(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{}) + + transformedType, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigAcceleratorConfigType(original["type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedType); val.IsValid() && !isEmptyValue(val) { + transformed["type"] = transformedType + } + + transformedCoreCount, err := expandNotebooksRuntimeVirtualMachineVirtualMachineConfigAcceleratorConfigCoreCount(original["core_count"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCoreCount); val.IsValid() && !isEmptyValue(val) { + transformed["coreCount"] = transformedCoreCount + } + + return transformed, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigAcceleratorConfigType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigAcceleratorConfigCoreCount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigNetwork(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigSubnet(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigInternalIpOnly(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigTags(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigGuestAttributes(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 +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigMetadata(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 +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigLabels(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 +} + +func expandNotebooksRuntimeVirtualMachineVirtualMachineConfigNicType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeAccessConfig(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{}) + + transformedAccessType, err := expandNotebooksRuntimeAccessConfigAccessType(original["access_type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAccessType); val.IsValid() && !isEmptyValue(val) { + transformed["accessType"] = transformedAccessType + } + + transformedRuntimeOwner, err := expandNotebooksRuntimeAccessConfigRuntimeOwner(original["runtime_owner"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRuntimeOwner); val.IsValid() && !isEmptyValue(val) { + transformed["runtimeOwner"] = transformedRuntimeOwner + } + + transformedProxyUri, err := expandNotebooksRuntimeAccessConfigProxyUri(original["proxy_uri"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedProxyUri); val.IsValid() && !isEmptyValue(val) { + transformed["proxyUri"] = transformedProxyUri + } + + return transformed, nil +} + +func expandNotebooksRuntimeAccessConfigAccessType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeAccessConfigRuntimeOwner(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeAccessConfigProxyUri(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeSoftwareConfig(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{}) + + transformedNotebookUpgradeSchedule, err := expandNotebooksRuntimeSoftwareConfigNotebookUpgradeSchedule(original["notebook_upgrade_schedule"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNotebookUpgradeSchedule); val.IsValid() && !isEmptyValue(val) { + transformed["notebookUpgradeSchedule"] = transformedNotebookUpgradeSchedule + } + + transformedEnableHealthMonitoring, err := expandNotebooksRuntimeSoftwareConfigEnableHealthMonitoring(original["enable_health_monitoring"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnableHealthMonitoring); val.IsValid() && !isEmptyValue(val) { + transformed["enableHealthMonitoring"] = transformedEnableHealthMonitoring + } + + transformedIdleShutdown, err := expandNotebooksRuntimeSoftwareConfigIdleShutdown(original["idle_shutdown"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIdleShutdown); val.IsValid() && !isEmptyValue(val) { + transformed["idleShutdown"] = transformedIdleShutdown + } + + transformedIdleShutdownTimeout, err := expandNotebooksRuntimeSoftwareConfigIdleShutdownTimeout(original["idle_shutdown_timeout"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIdleShutdownTimeout); val.IsValid() && !isEmptyValue(val) { + transformed["idleShutdownTimeout"] = transformedIdleShutdownTimeout + } + + transformedInstallGpuDriver, err := expandNotebooksRuntimeSoftwareConfigInstallGpuDriver(original["install_gpu_driver"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedInstallGpuDriver); val.IsValid() && !isEmptyValue(val) { + transformed["installGpuDriver"] = transformedInstallGpuDriver + } + + transformedCustomGpuDriverPath, err := expandNotebooksRuntimeSoftwareConfigCustomGpuDriverPath(original["custom_gpu_driver_path"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCustomGpuDriverPath); val.IsValid() && !isEmptyValue(val) { + transformed["customGpuDriverPath"] = transformedCustomGpuDriverPath + } + + transformedPostStartupScript, err := expandNotebooksRuntimeSoftwareConfigPostStartupScript(original["post_startup_script"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPostStartupScript); val.IsValid() && !isEmptyValue(val) { + transformed["postStartupScript"] = transformedPostStartupScript + } + + return transformed, nil +} + +func expandNotebooksRuntimeSoftwareConfigNotebookUpgradeSchedule(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeSoftwareConfigEnableHealthMonitoring(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeSoftwareConfigIdleShutdown(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeSoftwareConfigIdleShutdownTimeout(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeSoftwareConfigInstallGpuDriver(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeSoftwareConfigCustomGpuDriverPath(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandNotebooksRuntimeSoftwareConfigPostStartupScript(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} diff --git a/google-beta/resource_notebooks_runtime_generated_test.go b/google-beta/resource_notebooks_runtime_generated_test.go new file mode 100644 index 0000000000..7878ff30da --- /dev/null +++ b/google-beta/resource_notebooks_runtime_generated_test.go @@ -0,0 +1,219 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// 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" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccNotebooksRuntime_notebookRuntimeBasicExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckNotebooksRuntimeDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNotebooksRuntime_notebookRuntimeBasicExample(context), + }, + { + ResourceName: "google_notebooks_runtime.runtime", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location"}, + }, + }, + }) +} + +func testAccNotebooksRuntime_notebookRuntimeBasicExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_notebooks_runtime" "runtime" { + name = "tf-test-notebooks-runtime%{random_suffix}" + location = "us-central1" + access_config { + access_type = "SINGLE_USER" + runtime_owner = "admin@hashicorptest.com" + } + virtual_machine { + virtual_machine_config { + machine_type = "n1-standard-4" + data_disk { + initialize_params { + disk_size_gb = "100" + disk_type = "PD_STANDARD" + } + } + } + } +} +`, context) +} + +func TestAccNotebooksRuntime_notebookRuntimeBasicGpuExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckNotebooksRuntimeDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNotebooksRuntime_notebookRuntimeBasicGpuExample(context), + }, + { + ResourceName: "google_notebooks_runtime.runtime_gpu", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location"}, + }, + }, + }) +} + +func testAccNotebooksRuntime_notebookRuntimeBasicGpuExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_notebooks_runtime" "runtime_gpu" { + name = "tf-test-notebooks-runtime-gpu%{random_suffix}" + location = "us-central1" + access_config { + access_type = "SINGLE_USER" + runtime_owner = "admin@hashicorptest.com" + } + software_config { + install_gpu_driver = true + } + virtual_machine { + virtual_machine_config { + machine_type = "n1-standard-4" + data_disk { + initialize_params { + disk_size_gb = "100" + disk_type = "PD_STANDARD" + } + } + accelerator_config { + core_count = "1" + type = "NVIDIA_TESLA_V100" + } + } + } +} +`, context) +} + +func TestAccNotebooksRuntime_notebookRuntimeBasicContainerExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckNotebooksRuntimeDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNotebooksRuntime_notebookRuntimeBasicContainerExample(context), + }, + { + ResourceName: "google_notebooks_runtime.runtime_container", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location"}, + }, + }, + }) +} + +func testAccNotebooksRuntime_notebookRuntimeBasicContainerExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_notebooks_runtime" "runtime_container" { + name = "tf-test-notebooks-runtime-container%{random_suffix}" + location = "us-central1" + access_config { + access_type = "SINGLE_USER" + runtime_owner = "admin@hashicorptest.com" + } + virtual_machine { + virtual_machine_config { + machine_type = "n1-standard-4" + data_disk { + initialize_params { + disk_size_gb = "100" + disk_type = "PD_STANDARD" + } + } + container_images { + repository = "gcr.io/deeplearning-platform-release/base-cpu" + tag = "latest" + } + container_images { + repository = "gcr.io/deeplearning-platform-release/beam-notebooks" + tag = "latest" + } + } + } +} +`, context) +} + +func testAccCheckNotebooksRuntimeDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_notebooks_runtime" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := googleProviderConfig(t) + + url, err := replaceVarsForTest(config, rs, "{{NotebooksBasePath}}projects/{{project}}/locations/{{location}}/runtimes/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = sendRequest(config, "GET", billingProject, url, config.userAgent, nil) + if err == nil { + return fmt.Errorf("NotebooksRuntime still exists at %s", url) + } + } + + return nil + } +} diff --git a/google-beta/resource_notebooks_runtime_sweeper_test.go b/google-beta/resource_notebooks_runtime_sweeper_test.go new file mode 100644 index 0000000000..9a494c6470 --- /dev/null +++ b/google-beta/resource_notebooks_runtime_sweeper_test.go @@ -0,0 +1,124 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// 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 ( + "context" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func init() { + resource.AddTestSweepers("NotebooksRuntime", &resource.Sweeper{ + Name: "NotebooksRuntime", + F: testSweepNotebooksRuntime, + }) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepNotebooksRuntime(region string) error { + resourceName := "NotebooksRuntime" + log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) + + config, err := sharedConfigForRegion(region) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err) + return err + } + + err = config.LoadAndValidate(context.Background()) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err) + return err + } + + t := &testing.T{} + billingId := getTestBillingAccountFromEnv(t) + + // Setup variables to replace in list template + d := &ResourceDataMock{ + FieldsInSchema: map[string]interface{}{ + "project": config.Project, + "region": region, + "location": region, + "zone": "-", + "billing_account": billingId, + }, + } + + listTemplate := strings.Split("https://notebooks.googleapis.com/v1/projects/{{project}}/locations/{{location}}/runtimes", "?")[0] + listUrl, err := replaceVars(d, config, listTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) + return nil + } + + res, err := sendRequest(config, "GET", config.Project, listUrl, config.userAgent, nil) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) + return nil + } + + resourceList, ok := res["runtimes"] + if !ok { + log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") + return nil + } + + rl := resourceList.([]interface{}) + + log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) + // Keep count of items that aren't sweepable for logging. + nonPrefixCount := 0 + for _, ri := range rl { + obj := ri.(map[string]interface{}) + if obj["name"] == nil { + log.Printf("[INFO][SWEEPER_LOG] %s resource name was nil", resourceName) + return nil + } + + name := GetResourceNameFromSelfLink(obj["name"].(string)) + // Skip resources that shouldn't be sweeped + if !isSweepableTestResource(name) { + nonPrefixCount++ + continue + } + + deleteTemplate := "https://notebooks.googleapis.com/v1/projects/{{project}}/locations/{{location}}/runtimes/{{name}}" + deleteUrl, err := replaceVars(d, config, deleteTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) + return nil + } + deleteUrl = deleteUrl + name + + // Don't wait on operations as we may have a lot to delete + _, err = sendRequest(config, "DELETE", config.Project, deleteUrl, config.userAgent, nil) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err) + } else { + log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) + } + } + + if nonPrefixCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) + } + + return nil +} diff --git a/website/docs/r/notebooks_instance.html.markdown b/website/docs/r/notebooks_instance.html.markdown index 8104bbf255..b104154bcd 100644 --- a/website/docs/r/notebooks_instance.html.markdown +++ b/website/docs/r/notebooks_instance.html.markdown @@ -295,7 +295,7 @@ The following arguments are supported: * `tags` - (Optional) - The Compute Engine tags to add to runtime. + The Compute Engine tags to add to instance. * `metadata` - (Optional) diff --git a/website/docs/r/notebooks_runtime.html.markdown b/website/docs/r/notebooks_runtime.html.markdown new file mode 100644 index 0000000000..f39344233d --- /dev/null +++ b/website/docs/r/notebooks_runtime.html.markdown @@ -0,0 +1,563 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: MMv1 *** +# +# ---------------------------------------------------------------------------- +# +# 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. +# +# ---------------------------------------------------------------------------- +subcategory: "Cloud AI Notebooks" +layout: "google" +page_title: "Google: google_notebooks_runtime" +sidebar_current: "docs-google-notebooks-runtime" +description: |- + A Cloud AI Platform Notebook runtime. +--- + +# google\_notebooks\_runtime + +A Cloud AI Platform Notebook runtime. + + +~> **Note:** Due to limitations of the Notebooks Runtime API, many fields +in this resource do not properly detect drift. These fields will also not +appear in state once imported. + + +To get more information about Runtime, see: + +* [API documentation](https://cloud.google.com/ai-platform/notebooks/docs/reference/rest) +* How-to Guides + * [Official Documentation](https://cloud.google.com/ai-platform-notebooks) + + +## Example Usage - Notebook Runtime Basic + + +```hcl +resource "google_notebooks_runtime" "runtime" { + name = "notebooks-runtime" + location = "us-central1" + access_config { + access_type = "SINGLE_USER" + runtime_owner = "admin@hashicorptest.com" + } + virtual_machine { + virtual_machine_config { + machine_type = "n1-standard-4" + data_disk { + initialize_params { + disk_size_gb = "100" + disk_type = "PD_STANDARD" + } + } + } + } +} +``` + +## Example Usage - Notebook Runtime Basic Gpu + + +```hcl +resource "google_notebooks_runtime" "runtime_gpu" { + name = "notebooks-runtime-gpu" + location = "us-central1" + access_config { + access_type = "SINGLE_USER" + runtime_owner = "admin@hashicorptest.com" + } + software_config { + install_gpu_driver = true + } + virtual_machine { + virtual_machine_config { + machine_type = "n1-standard-4" + data_disk { + initialize_params { + disk_size_gb = "100" + disk_type = "PD_STANDARD" + } + } + accelerator_config { + core_count = "1" + type = "NVIDIA_TESLA_V100" + } + } + } +} +``` + +## Example Usage - Notebook Runtime Basic Container + + +```hcl +resource "google_notebooks_runtime" "runtime_container" { + name = "notebooks-runtime-container" + location = "us-central1" + access_config { + access_type = "SINGLE_USER" + runtime_owner = "admin@hashicorptest.com" + } + virtual_machine { + virtual_machine_config { + machine_type = "n1-standard-4" + data_disk { + initialize_params { + disk_size_gb = "100" + disk_type = "PD_STANDARD" + } + } + container_images { + repository = "gcr.io/deeplearning-platform-release/base-cpu" + tag = "latest" + } + container_images { + repository = "gcr.io/deeplearning-platform-release/beam-notebooks" + tag = "latest" + } + } + } +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `name` - + (Required) + The name specified for the Notebook instance. + +* `location` - + (Required) + A reference to the zone where the machine resides. + + +- - - + + +* `virtual_machine` - + (Optional) + Use a Compute Engine VM image to start the managed notebook instance. + Structure is [documented below](#nested_virtual_machine). + +* `access_config` - + (Optional) + The config settings for accessing runtime. + Structure is [documented below](#nested_access_config). + +* `software_config` - + (Optional) + The config settings for software inside the runtime. + Structure is [documented below](#nested_software_config). + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + +The `virtual_machine` block supports: + +* `instance_name` - + The user-friendly name of the Managed Compute Engine instance. + +* `instance_id` - + The unique identifier of the Managed Compute Engine instance. + +* `virtual_machine_config` - + (Optional) + Virtual Machine configuration settings. + Structure is [documented below](#nested_virtual_machine_config). + + +The `virtual_machine_config` block supports: + +* `zone` - + The zone where the virtual machine is located. + +* `machine_type` - + (Required) + The Compute Engine machine type used for runtimes. + +* `data_disk` - + (Required) + Data disk option configuration settings. + Structure is [documented below](#nested_data_disk). + +* `container_images` - + (Optional) + Use a list of container images to start the notebook instance. + Structure is [documented below](#nested_container_images). + +* `encryption_config` - + (Optional) + Encryption settings for virtual machine data disk. + Structure is [documented below](#nested_encryption_config). + +* `shielded_instance_config` - + (Optional) + Shielded VM Instance configuration settings. + Structure is [documented below](#nested_shielded_instance_config). + +* `accelerator_config` - + (Optional) + The Compute Engine accelerator configuration for this runtime. + Structure is [documented below](#nested_accelerator_config). + +* `network` - + (Optional) + The Compute Engine network to be used for machine communications. + Cannot be specified with subnetwork. If neither `network` nor + `subnet` is specified, the "default" network of the project is + used, if it exists. A full URL or partial URI. Examples: + * `https://www.googleapis.com/compute/v1/projects/[project_id]/ + regions/global/default` + * `projects/[project_id]/regions/global/default` + Runtimes are managed resources inside Google Infrastructure. + Runtimes support the following network configurations: + * Google Managed Network (Network & subnet are empty) + * Consumer Project VPC (network & subnet are required). Requires + configuring Private Service Access. + * Shared VPC (network & subnet are required). Requires + configuring Private Service Access. + +* `subnet` - + (Optional) + The Compute Engine subnetwork to be used for machine + communications. Cannot be specified with network. A full URL or + partial URI are valid. Examples: + * `https://www.googleapis.com/compute/v1/projects/[project_id]/ + regions/us-east1/subnetworks/sub0` + * `projects/[project_id]/regions/us-east1/subnetworks/sub0` + +* `internal_ip_only` - + (Optional) + If true, runtime will only have internal IP addresses. By default, + runtimes are not restricted to internal IP addresses, and will + have ephemeral external IP addresses assigned to each vm. This + `internal_ip_only` restriction can only be enabled for subnetwork + enabled networks, and all dependencies must be configured to be + accessible without external IP addresses. + +* `tags` - + (Optional) + The Compute Engine tags to add to runtime (see [Tagging instances] + (https://cloud.google.com/compute/docs/ + label-or-tag-resources#tags)). + +* `guest_attributes` - + The Compute Engine guest attributes. (see [Project and instance + guest attributes](https://cloud.google.com/compute/docs/ + storing-retrieving-metadata#guest_attributes)). + +* `metadata` - + (Optional) + The Compute Engine metadata entries to add to virtual machine. + (see [Project and instance metadata](https://cloud.google.com + /compute/docs/storing-retrieving-metadata#project_and_instance + _metadata)). + +* `labels` - + (Optional) + The labels to associate with this runtime. Label **keys** must + contain 1 to 63 characters, and must conform to [RFC 1035] + (https://www.ietf.org/rfc/rfc1035.txt). Label **values** may be + empty, but, if present, must contain 1 to 63 characters, and must + conform to [RFC 1035](https://www.ietf.org/rfc/rfc1035.txt). No + more than 32 labels can be associated with a cluster. + +* `nic_type` - + (Optional) + The type of vNIC to be used on this interface. This may be gVNIC + or VirtioNet. + Possible values are `UNSPECIFIED_NIC_TYPE`, `VIRTIO_NET`, and `GVNIC`. + + +The `data_disk` block supports: + +* `auto_delete` - + Optional. Specifies whether the disk will be auto-deleted + when the instance is deleted (but not when the disk is + detached from the instance). + +* `boot` - + Optional. Indicates that this is a boot disk. The virtual + machine will use the first partition of the disk for its + root filesystem. + +* `device_name` - + Optional. Specifies a unique device name of your choice + that is reflected into the /dev/disk/by-id/google-* tree + of a Linux operating system running within the instance. + This name can be used to reference the device for mounting, + resizing, and so on, from within the instance. + If not specified, the server chooses a default device name + to apply to this disk, in the form persistent-disk-x, where + x is a number assigned by Google Compute Engine. This field + is only applicable for persistent disks. + +* `guest_os_features` - + Indicates a list of features to enable on the guest operating + system. Applicable only for bootable images. To see a list of + available features, read `https://cloud.google.com/compute/docs/ + images/create-delete-deprecate-private-images#guest-os-features` + options. `` + +* `index` - + Output only. A zero-based index to this disk, where 0 is + reserved for the boot disk. If you have many disks attached + to an instance, each disk would have a unique index number. + +* `initialize_params` - + (Optional) + Input only. Specifies the parameters for a new disk that will + be created alongside the new instance. Use initialization + parameters to create boot disks or local SSDs attached to the + new instance. This property is mutually exclusive with the + source property; you can only define one or the other, but not + both. + Structure is [documented below](#nested_initialize_params). + +* `interface` - + (Optional) + "Specifies the disk interface to use for attaching this disk, + which is either SCSI or NVME. The default is SCSI. Persistent + disks must always use SCSI and the request will fail if you attempt + to attach a persistent disk in any other format than SCSI. Local SSDs + can use either NVME or SCSI. For performance characteristics of SCSI + over NVMe, see Local SSD performance. Valid values: * NVME * SCSI". + +* `kind` - + Type of the resource. Always compute#attachedDisk for attached + disks. + +* `licenses` - + Output only. Any valid publicly visible licenses. + +* `mode` - + (Optional) + The mode in which to attach this disk, either READ_WRITE + or READ_ONLY. If not specified, the default is to attach + the disk in READ_WRITE mode. + +* `source` - + (Optional) + Specifies a valid partial or full URL to an existing + Persistent Disk resource. + +* `type` - + (Optional) + Specifies the type of the disk, either SCRATCH or PERSISTENT. + If not specified, the default is PERSISTENT. + + +The `initialize_params` block supports: + +* `description` - + (Optional) + Provide this property when creating the disk. + +* `disk_name` - + (Optional) + Specifies the disk name. If not specified, the default is + to use the name of the instance. If the disk with the + instance name exists already in the given zone/region, a + new name will be automatically generated. + +* `disk_size_gb` - + (Optional) + Specifies the size of the disk in base-2 GB. If not + specified, the disk will be the same size as the image + (usually 10GB). If specified, the size must be equal to + or larger than 10GB. Default 100 GB. + +* `disk_type` - + (Optional) + The type of the boot disk attached to this runtime, + defaults to standard persistent disk. For valid values, + see `https://cloud.google.com/vertex-ai/docs/workbench/ + reference/rest/v1/projects.locations.runtimes#disktype` + +* `labels` - + (Optional) + Labels to apply to this disk. These can be later modified + by the disks.setLabels method. This field is only + applicable for persistent disks. + +The `container_images` block supports: + +* `repository` - + (Required) + The path to the container image repository. + For example: gcr.io/{project_id}/{imageName} + +* `tag` - + (Optional) + The tag of the container image. If not specified, this defaults to the latest tag. + +The `encryption_config` block supports: + +* `kms_key` - + (Optional) + The Cloud KMS resource identifier of the customer-managed + encryption key used to protect a resource, such as a disks. + It has the following format: + `projects/{PROJECT_ID}/locations/{REGION}/keyRings/ + {KEY_RING_NAME}/cryptoKeys/{KEY_NAME}` + +The `shielded_instance_config` block supports: + +* `enable_secure_boot` - + (Optional) + Defines whether the instance has Secure Boot enabled.Secure + Boot helps ensure that the system only runs authentic software + by verifying the digital signature of all boot components, and + halting the boot process if signature verification fails. + Disabled by default. + +* `enable_vtpm` - + (Optional) + Defines whether the instance has the vTPM enabled. Enabled by + default. + +* `enable_integrity_monitoring` - + (Optional) + Defines whether the instance has integrity monitoring enabled. + Enables monitoring and attestation of the boot integrity of + the instance. The attestation is performed against the + integrity policy baseline. This baseline is initially derived + from the implicitly trusted boot image when the instance is + created. Enabled by default. + +The `accelerator_config` block supports: + +* `type` - + (Optional) + Accelerator model. For valid values, see + `https://cloud.google.com/vertex-ai/docs/workbench/reference/ + rest/v1/projects.locations.runtimes#AcceleratorType` + +* `core_count` - + (Optional) + Count of cores of this accelerator. + +The `access_config` block supports: + +* `access_type` - + (Optional) + The type of access mode this instance. For valid values, see + `https://cloud.google.com/vertex-ai/docs/workbench/reference/ + rest/v1/projects.locations.runtimes#RuntimeAccessType`. + +* `runtime_owner` - + (Optional) + The owner of this runtime after creation. Format: `alias@example.com`. + Currently supports one owner only. + +* `proxy_uri` - + The proxy endpoint that is used to access the runtime. + +The `software_config` block supports: + +* `notebook_upgrade_schedule` - + (Optional) + Cron expression in UTC timezone for schedule instance auto upgrade. + Please follow the [cron format](https://en.wikipedia.org/wiki/Cron). + +* `enable_health_monitoring` - + (Optional) + Verifies core internal services are running. Default: True. + +* `idle_shutdown` - + (Optional) + Runtime will automatically shutdown after idle_shutdown_time. + Default: True + +* `idle_shutdown_timeout` - + (Optional) + Time in minutes to wait before shuting down runtime. + Default: 180 minutes + +* `install_gpu_driver` - + (Optional) + Install Nvidia Driver automatically. + +* `custom_gpu_driver_path` - + (Optional) + Specify a custom Cloud Storage path where the GPU driver is stored. + If not specified, we'll automatically choose from official GPU drivers. + +* `post_startup_script` - + (Optional) + Path to a Bash script that automatically runs after a notebook instance + fully boots up. The path must be a URL or + Cloud Storage path (gs://path-to-file/file-name). + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/locations/{{location}}/runtimes/{{name}}` + +* `state` - + The state of this runtime. + +* `health_state` - + The health state of this runtime. For a list of possible output + values, see `https://cloud.google.com/vertex-ai/docs/workbench/ + reference/rest/v1/projects.locations.runtimes#healthstate`. + +* `metrics` - + Contains Runtime daemon metrics such as Service status and JupyterLab + status + Structure is [documented below](#nested_metrics). + + +The `metrics` block contains: + +* `system_metrics` - + Contains runtime daemon metrics, such as OS and kernels and + sessions stats. + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 15 minutes. +- `update` - Default is 15 minutes. +- `delete` - Default is 15 minutes. + +## Import + + +Runtime can be imported using any of these accepted formats: + +``` +$ terraform import google_notebooks_runtime.default projects/{{project}}/locations/{{location}}/runtimes/{{name}} +$ terraform import google_notebooks_runtime.default {{project}}/{{location}}/{{name}} +$ terraform import google_notebooks_runtime.default {{location}}/{{name}} +``` + +## User Project Overrides + +This resource supports [User Project Overrides](https://www.terraform.io/docs/providers/google/guides/provider_reference.html#user_project_override). diff --git a/website/docs/r/notebooks_runtime_iam.html.markdown b/website/docs/r/notebooks_runtime_iam.html.markdown new file mode 100644 index 0000000000..937ba7531d --- /dev/null +++ b/website/docs/r/notebooks_runtime_iam.html.markdown @@ -0,0 +1,152 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: MMv1 *** +# +# ---------------------------------------------------------------------------- +# +# 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. +# +# ---------------------------------------------------------------------------- +subcategory: "Cloud AI Notebooks" +layout: "google" +page_title: "Google: google_notebooks_runtime_iam" +sidebar_current: "docs-google-notebooks-runtime-iam" +description: |- + Collection of resources to manage IAM policy for Cloud AI Notebooks Runtime +--- + +# IAM policy for Cloud AI Notebooks Runtime +Three different resources help you manage your IAM policy for Cloud AI Notebooks Runtime. Each of these resources serves a different use case: + +* `google_notebooks_runtime_iam_policy`: Authoritative. Sets the IAM policy for the runtime and replaces any existing policy already attached. +* `google_notebooks_runtime_iam_binding`: Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other roles within the IAM policy for the runtime are preserved. +* `google_notebooks_runtime_iam_member`: Non-authoritative. Updates the IAM policy to grant a role to a new member. Other members for the role for the runtime are preserved. + +~> **Note:** `google_notebooks_runtime_iam_policy` **cannot** be used in conjunction with `google_notebooks_runtime_iam_binding` and `google_notebooks_runtime_iam_member` or they will fight over what your policy should be. + +~> **Note:** `google_notebooks_runtime_iam_binding` resources **can be** used in conjunction with `google_notebooks_runtime_iam_member` resources **only if** they do not grant privilege to the same role. + + + + +## google\_notebooks\_runtime\_iam\_policy + +```hcl +data "google_iam_policy" "admin" { + binding { + role = "roles/viewer" + members = [ + "user:jane@example.com", + ] + } +} + +resource "google_notebooks_runtime_iam_policy" "policy" { + project = google_notebooks_runtime.runtime.project + location = google_notebooks_runtime.runtime.location + runtime_name = google_notebooks_runtime.runtime.name + policy_data = data.google_iam_policy.admin.policy_data +} +``` + +## google\_notebooks\_runtime\_iam\_binding + +```hcl +resource "google_notebooks_runtime_iam_binding" "binding" { + project = google_notebooks_runtime.runtime.project + location = google_notebooks_runtime.runtime.location + runtime_name = google_notebooks_runtime.runtime.name + role = "roles/viewer" + members = [ + "user:jane@example.com", + ] +} +``` + +## google\_notebooks\_runtime\_iam\_member + +```hcl +resource "google_notebooks_runtime_iam_member" "member" { + project = google_notebooks_runtime.runtime.project + location = google_notebooks_runtime.runtime.location + runtime_name = google_notebooks_runtime.runtime.name + role = "roles/viewer" + member = "user:jane@example.com" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `runtime_name` - (Required) Used to find the parent resource to bind the IAM policy to +* `location` - (Required) A reference to the zone where the machine resides. Used to find the parent resource to bind the IAM policy to + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the project will be parsed from the identifier of the parent resource. If no project is provided in the parent identifier and no project is specified, the provider project is used. + +* `member/members` - (Required) Identities that will be granted the privilege in `role`. + Each entry can have one of the following values: + * **allUsers**: A special identifier that represents anyone who is on the internet; with or without a Google account. + * **allAuthenticatedUsers**: A special identifier that represents anyone who is authenticated with a Google account or a service account. + * **user:{emailid}**: An email address that represents a specific Google account. For example, alice@gmail.com or joe@example.com. + * **serviceAccount:{emailid}**: An email address that represents a service account. For example, my-other-app@appspot.gserviceaccount.com. + * **group:{emailid}**: An email address that represents a Google group. For example, admins@example.com. + * **domain:{domain}**: A G Suite domain (primary, instead of alias) name that represents all the users of that domain. For example, google.com or example.com. + * **projectOwner:projectid**: Owners of the given project. For example, "projectOwner:my-example-project" + * **projectEditor:projectid**: Editors of the given project. For example, "projectEditor:my-example-project" + * **projectViewer:projectid**: Viewers of the given project. For example, "projectViewer:my-example-project" + +* `role` - (Required) The role that should be applied. Only one + `google_notebooks_runtime_iam_binding` can be used per role. Note that custom roles must be of the format + `[projects|organizations]/{parent-name}/roles/{role-name}`. + +* `policy_data` - (Required only by `google_notebooks_runtime_iam_policy`) The policy data generated by + a `google_iam_policy` data source. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are +exported: + +* `etag` - (Computed) The etag of the IAM policy. + +## Import + +For all import syntaxes, the "resource in question" can take any of the following forms: + +* projects/{{project}}/locations/{{location}}/runtimes/{{runtime_name}} +* {{project}}/{{location}}/{{runtime_name}} +* {{location}}/{{runtime_name}} +* {{runtime_name}} + +Any variables not passed in the import command will be taken from the provider configuration. + +Cloud AI Notebooks runtime IAM resources can be imported using the resource identifiers, role, and member. + +IAM member imports use space-delimited identifiers: the resource in question, the role, and the member identity, e.g. +``` +$ terraform import google_notebooks_runtime_iam_member.editor "projects/{{project}}/locations/{{location}}/runtimes/{{runtime_name}} roles/viewer user:jane@example.com" +``` + +IAM binding imports use space-delimited identifiers: the resource in question and the role, e.g. +``` +$ terraform import google_notebooks_runtime_iam_binding.editor "projects/{{project}}/locations/{{location}}/runtimes/{{runtime_name}} roles/viewer" +``` + +IAM policy imports use the identifier of the resource in question, e.g. +``` +$ terraform import google_notebooks_runtime_iam_policy.editor projects/{{project}}/locations/{{location}}/runtimes/{{runtime_name}} +``` + +-> **Custom Roles**: If you're importing a IAM resource with a custom role, make sure to use the + full name of the custom role, e.g. `[projects/my-project|organizations/my-org]/roles/my-custom-role`. + +## User Project Overrides + +This resource supports [User Project Overrides](https://www.terraform.io/docs/providers/google/guides/provider_reference.html#user_project_override). diff --git a/website/google.erb b/website/google.erb index c6182fe741..aba260f3f0 100644 --- a/website/google.erb +++ b/website/google.erb @@ -595,6 +595,14 @@ google_notebooks_location +
  • + google_notebooks_runtime +
  • + +
  • + google_notebooks_runtime_iam +
  • +