From 1990828602c2f8a18f80c034f9b271c947b723e6 Mon Sep 17 00:00:00 2001 From: Mukul Gupta Date: Thu, 4 Nov 2021 14:38:21 -0700 Subject: [PATCH 1/6] Fixing hyperlink in Troubleshooting.md --- docs/TROUBLESHOOTING.md | 4 +- modules/data_science/.terraform.lock.hcl | 96 ++++++++++++++++++++++++ modules/data_science/main.tf | 81 +++++++++++++------- modules/data_science/outputs.tf | 4 +- modules/data_science/variables.tf | 31 +++++++- 5 files changed, 185 insertions(+), 31 deletions(-) create mode 100644 modules/data_science/.terraform.lock.hcl diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 209e931d..a17c8a3e 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -3,7 +3,7 @@ ## Overview The troubleshooting section aims to identify the most common recurring problems users may face when deploying and using RAD Lab. - If you can't find a solution, please don't hesitate to create a [GitHub](https://github.com/GPS-Demos/radlab/issues) issue. + If you can't find a solution, please don't hesitate to create a [GitHub](https://github.com/GoogleCloudPlatform/rad-lab/issues) issue. >**NOTE:** This is not an officially supported Google product @@ -20,7 +20,7 @@ Error Occurred - Deployment failed for ID: ``` -**Solution**: If you see below error in your initial deployment run, rerun the deployment via ``` python3 radlab.py``` using the and select `Update` (#4 in [Steps to Install RAD Lab Modules](https://github.com/GPS-Demos/radlab#steps-to-install-rad-lab-modules)). This may have been caused as the Org Policy ```constraints/compute.vmExternalIpAccess``` is not completely rolled out. +**Solution**: If you see below error in your initial deployment run, rerun the deployment via ``` python3 radlab.py``` using the and select `Update` (in [Steps to Install RAD Lab Modules](../scripts/radlab-installer/README.md#steps-to-install-rad-lab-modules). This may have been caused as the Org Policy ```constraints/compute.vmExternalIpAccess``` is not completely rolled out. NOTE: Similarly if the error occurs for any other org policies then the workaround is same as above. diff --git a/modules/data_science/.terraform.lock.hcl b/modules/data_science/.terraform.lock.hcl new file mode 100644 index 00000000..81ab3aaf --- /dev/null +++ b/modules/data_science/.terraform.lock.hcl @@ -0,0 +1,96 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/google" { + version = "3.90.1" + constraints = ">= 2.12.0, >= 3.43.0, ~> 3.45, >= 3.50.0, >= 3.87.0, < 4.0.0" + hashes = [ + "h1:9TYwyR4R4dIop7wV2lvvYZHw9RUVd/YRWR+9jjXpyfw=", + "zh:07aabc8e46a5a2b29932e10677b23d4ce9d9a25f22ab61d3307a6b0e7998c84e", + "zh:0b63cd9534a98ed0fee794da495833046ad5319bd2da3102e21a941b7e2b857e", + "zh:17f815d57e1426edf8818323ab8e1022c8ec60dce0ced89a3b8e5dde5a95b3cc", + "zh:37855eae3542f2ebc6416984b124533d00299e0e01dcd7d2bc2205469cb9eceb", + "zh:579aa32a8e3fa317ddbd28c99a6449ae8864a5b7d10247bca6496f399cb36701", + "zh:703f71e0231cfe7a025c61db361d928189adba1d4fad2fe77f783dc73c8afe30", + "zh:afcd80c31cb1ed75ce6813269618e01ab29af68dae7aae1c51521c13acdaa678", + "zh:b21302f65a0d37045216912695d1ef718a1fe1732c30dc5654891fe2519b8e4e", + "zh:b69d0c8a74c2cd6233681db37e01aaaf1a6fb6bb24c83f7715bd2b456083e29d", + "zh:d4fb305816b143cb26c1827c79e56651347fd41809a57184e4807fb3f804f510", + "zh:fa24173ef9524bdfa1c5cada5188489554b08374f9519fe545f3fc1d3a9d9d4f", + ] +} + +provider "registry.terraform.io/hashicorp/google-beta" { + version = "3.90.1" + constraints = ">= 3.1.0, >= 3.43.0, ~> 3.45, >= 3.50.0, >= 3.87.0, < 4.0.0" + hashes = [ + "h1:GYvCJnoIaT9clM2aAbfe0qsnRy4OdRfJ0NwO0dWnCJI=", + "zh:2d647e42313f4e3f36480d2508a5056373099843a16558c21d5c798899a1e2d7", + "zh:51a637b35d8c923cb02eb9a13c72526a72364f0a99100470cb253c5116446475", + "zh:52940431348d23998fdd9216b7fa666e3bcfd6c3ad9751f8f076fbd5529006de", + "zh:53d36e0ada5a5b95d0b66a8cdfa65adf25d5a49a826f7f4a6f891955c0d19600", + "zh:6564b0c6692c8ef571254e3279b5803893b50825abb4e4b175b8eff19af4e447", + "zh:747757f0582561e18d930295ea14dfde4ca485be87b2bb7097e410f40076707b", + "zh:a828fb94d2a2d99c435215a780ce1fcd2cbf8bd2dfce86d9989a9a978c100eec", + "zh:b81949694ec1bf59cd0a838149b33792e3ceed35b18333dbfbcd28052bc94f23", + "zh:db255de73e0c5c030c6d54fc9217b20169e2c19fd7dde8e0415c495dd48907f0", + "zh:e5966c5ac5887b02cef0b3aa703c986d5a74e95279be4ec1db93843e9c92e64a", + "zh:eb172abc91f80b9f13c942cf6b1081095b6d9796f024a301f218eaf7f5241121", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.1.0" + constraints = ">= 2.1.0" + hashes = [ + "h1:xhbHC6in3nQryvTQBWKxebi3inG5OCgHgc4fRxL0ymc=", + "zh:02a1675fd8de126a00460942aaae242e65ca3380b5bb192e8773ef3da9073fd2", + "zh:53e30545ff8926a8e30ad30648991ca8b93b6fa496272cd23b26763c8ee84515", + "zh:5f9200bf708913621d0f6514179d89700e9aa3097c77dac730e8ba6e5901d521", + "zh:9ebf4d9704faba06b3ec7242c773c0fbfe12d62db7d00356d4f55385fc69bfb2", + "zh:a6576c81adc70326e4e1c999c04ad9ca37113a6e925aefab4765e5a5198efa7e", + "zh:a8a42d13346347aff6c63a37cda9b2c6aa5cc384a55b2fe6d6adfa390e609c53", + "zh:c797744d08a5307d50210e0454f91ca4d1c7621c68740441cf4579390452321d", + "zh:cecb6a304046df34c11229f20a80b24b1603960b794d68361a67c5efe58e62b8", + "zh:e1371aa1e502000d9974cfaff5be4cfa02f47b17400005a16f14d2ef30dc2a70", + "zh:fc39cc1fe71234a0b0369d5c5c7f876c71b956d23d7d6f518289737a001ba69b", + "zh:fea4227271ebf7d9e2b61b89ce2328c7262acd9fd190e1fd6d15a591abfa848e", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.1.0" + constraints = ">= 2.2.0" + hashes = [ + "h1:rKYu5ZUbXwrLG1w81k7H3nce/Ys6yAxXhWcbtk36HjY=", + "zh:2bbb3339f0643b5daa07480ef4397bd23a79963cc364cdfbb4e86354cb7725bc", + "zh:3cd456047805bf639fbf2c761b1848880ea703a054f76db51852008b11008626", + "zh:4f251b0eda5bb5e3dc26ea4400dba200018213654b69b4a5f96abee815b4f5ff", + "zh:7011332745ea061e517fe1319bd6c75054a314155cb2c1199a5b01fe1889a7e2", + "zh:738ed82858317ccc246691c8b85995bc125ac3b4143043219bd0437adc56c992", + "zh:7dbe52fac7bb21227acd7529b487511c91f4107db9cc4414f50d04ffc3cab427", + "zh:a3a9251fb15f93e4cfc1789800fc2d7414bbc18944ad4c5c98f466e6477c42bc", + "zh:a543ec1a3a8c20635cf374110bd2f87c07374cf2c50617eee2c669b3ceeeaa9f", + "zh:d9ab41d556a48bd7059f0810cf020500635bfc696c9fc3adab5ea8915c1d886b", + "zh:d9e13427a7d011dbd654e591b0337e6074eef8c3b9bb11b2e39eaaf257044fd7", + "zh:f7605bd1437752114baf601bdf6931debe6dc6bfe3006eb7e9bb9080931dca8a", + ] +} + +provider "registry.terraform.io/hashicorp/time" { + version = "0.7.2" + hashes = [ + "h1:NKy1QrNLlP5mKy5Tea6lQSRsVoyydJQKh6WvNTdBF4I=", + "zh:0bbe0158c2a9e3f5be911b7e94477586110c51746bb13d102054f22754565bda", + "zh:3250af7fd49b8aaf2ccc895588af05197d886e38b727e3ba33bcbb8cc96ad34d", + "zh:35e4de0437f4fa9c1ad69aaf8136413be2369ea607d78e04bb68dc66a6a520b8", + "zh:369756417a6272e79cad31eb2c82c202f6a4b6e4204a893f656644ba9e149fa2", + "zh:390370f1179d89b33c3a0731691e772d5450a7d59fc66671ec625e201db74aa2", + "zh:3d12ac905259d225c685bc42e5507ed0fbdaa5a09c30dce7c1932d908df857f7", + "zh:75f63e5e1c68e6c5bccba4568c3564e2774eb3a7a19189eb8e2b6e0d58c8f8cc", + "zh:7c22a2078a608e3e0278c4cbc9c483909062ebd1843bddaf8f176346c6d378b1", + "zh:7cfb3c02f78f0060d59c757c4726ab45a962ce4a9cf4833beca704a1020785bd", + "zh:a0325917f47c28a2ed088dedcea0d9520d91b264e63cc667fe4336ac993c0c11", + "zh:c181551d4c0a40b52e236f1755cc340aeca0fb5dcfd08b3b1c393a7667d2f327", + ] +} diff --git a/modules/data_science/main.tf b/modules/data_science/main.tf index b87f8014..05ec4b88 100644 --- a/modules/data_science/main.tf +++ b/modules/data_science/main.tf @@ -15,7 +15,11 @@ */ locals { - + random_id = var.random_id != null ? var.random_id : random_id.default.hex + project = (var.create_project + ? try(module.project_radlab_ds_analytics.0, null) + : try(data.google_project.existing_project.0, null) + ) region = join("-", [split("-", var.zone)[0], split("-", var.zone)[1]]) notebook_sa_project_roles = [ @@ -25,30 +29,50 @@ locals { "roles/storage.objectViewer" ] - radlab_ds_analytics_project_id = "radlab-ds-analytics-${var.random_id}" + project_services = [ + "compute.googleapis.com", + "bigquery.googleapis.com", + "notebooks.googleapis.com", + "bigquerystorage.googleapis.com" + ] +} - radlab_ds_data_project_id = "radlab-ds-data-${var.random_id}" +resource "random_id" "default" { + byte_length = 2 } ##################### # ANALYTICS PROJECT # ##################### +data "google_project" "existing_project" { + count = var.create_project ? 0 : 1 + project_id = var.project_name +} + module "project_radlab_ds_analytics" { + count = var.create_project ? 1 : 0 source = "terraform-google-modules/project-factory/google" version = "~> 11.0" - name = local.radlab_ds_analytics_project_id + name = format("%s-%s", var.project_name, local.random_id) random_project_id = false folder_id = var.folder_id billing_account = var.billing_account_id org_id = var.organization_id - activate_apis = [ - "compute.googleapis.com", - "bigquery.googleapis.com", - "notebooks.googleapis.com", - "bigquerystorage.googleapis.com", + activate_apis = [] +} + +resource "google_project_service" "enabled_services" { + for_each = toset(local.project_services) + project = local.project.project_id + service = each.value + disable_dependent_services = true + disable_on_destroy = true + + depends_on = [ + module.project_radlab_ds_analytics ] } @@ -56,7 +80,7 @@ module "vpc_ai_notebook" { source = "terraform-google-modules/network/google" version = "~> 3.0" - project_id = module.project_radlab_ds_analytics.project_id + project_id = local.project.project_id network_name = "ai-notebook" routing_mode = "GLOBAL" description = "VPC Network created via Terraform" @@ -88,12 +112,16 @@ module "vpc_ai_notebook" { }] } ] + + depends_on = [ + google_project_service.enabled_services + ] } resource "google_project_organization_policy" "external_ip_policy" { count = var.set_external_ip_policy ? 1 : 0 constraint = "compute.vmExternalIpAccess" - project = module.project_radlab_ds_analytics.project_id + project = local.project.project_id list_policy { allow { @@ -106,7 +134,7 @@ resource "google_project_organization_policy" "external_ip_policy" { resource "google_project_organization_policy" "shielded_vm_policy" { count = var.set_shielded_vm_policy ? 1 : 0 constraint = "compute.requireShieldedVm" - project = module.project_radlab_ds_analytics.project_id + project = local.project.project_id boolean_policy { enforced = false @@ -118,7 +146,8 @@ resource "google_project_organization_policy" "shielded_vm_policy" { resource "google_project_organization_policy" "trustedimage_project_policy" { count = var.set_trustedimage_project_policy ? 1 : 0 constraint = "compute.trustedImageProjects" - project = module.project_radlab_ds_analytics.project_id + project = local.project.project_id + list_policy { allow { values = [ @@ -129,14 +158,14 @@ resource "google_project_organization_policy" "trustedimage_project_policy" { } resource "google_service_account" "sa_p_notebook" { - project = module.project_radlab_ds_analytics.project_id - account_id = format("sa-p-notebook-%s", var.random_id) + project = local.project.project_id + account_id = format("sa-p-notebook-%s", local.random_id) display_name = "Notebooks in trusted environment" } resource "google_project_iam_member" "sa_p_notebook_permissions" { for_each = toset(local.notebook_sa_project_roles) - project = module.project_radlab_ds_analytics.project_id + project = local.project.project_id member = "serviceAccount:${google_service_account.sa_p_notebook.email}" role = each.value } @@ -149,27 +178,27 @@ resource "google_service_account_iam_member" "sa_ai_notebook_user_iam" { } resource "google_project_iam_binding" "ai_notebook_user_role1" { - project = module.project_radlab_ds_analytics.project_id + project = local.project.project_id members = var.trusted_users role = "roles/notebooks.admin" } resource "google_project_iam_binding" "ai_notebook_user_role2" { - project = module.project_radlab_ds_analytics.project_id + project = local.project.project_id members = var.trusted_users role = "roles/viewer" } resource "google_notebooks_instance" "ai_notebook" { count = var.notebook_count - project = module.project_radlab_ds_analytics.project_id + project = local.project.project_id name = "notebooks-instance-${count.index}" location = var.zone machine_type = var.machine_type vm_image { - project = "deeplearning-platform-release" - image_family = "tf-latest-cpu" + project = var.image_project + image_family = var.image_family } service_account = google_service_account.sa_p_notebook.email @@ -184,7 +213,7 @@ resource "google_notebooks_instance" "ai_notebook" { network = module.vpc_ai_notebook.network_self_link subnet = module.vpc_ai_notebook.subnets_self_links.0 - post_startup_script = "gs://radlab-solution-bucket/Data_Science_Model/samplenotebook.sh" + post_startup_script = var.startup_script labels = { module = "data-science" @@ -202,8 +231,8 @@ resource "google_notebooks_instance" "ai_notebook" { } resource "google_storage_bucket" "user_scripts_bucket" { - project = module.project_radlab_ds_analytics.project_id - name = join("", ["user-scripts-notebooks-instance-", var.random_id]) + project = local.project.project_id + name = join("", ["user-scripts-notebooks-instance-", local.random_id]) location = "US" force_destroy = true uniform_bucket_level_access = true @@ -217,7 +246,7 @@ resource "google_storage_bucket" "user_scripts_bucket" { } resource "google_storage_bucket_iam_binding" "binding" { - bucket = google_storage_bucket.user_scripts_bucket.name - role = "roles/storage.admin" + bucket = google_storage_bucket.user_scripts_bucket.name + role = "roles/storage.admin" members = var.trusted_users } diff --git a/modules/data_science/outputs.tf b/modules/data_science/outputs.tf index b716a76f..98f6dcaa 100644 --- a/modules/data_science/outputs.tf +++ b/modules/data_science/outputs.tf @@ -16,12 +16,12 @@ output "deployment_id" { description = "RADLab Module Deployment ID" - value = var.random_id + value = local.random_id } output "project-radlab-ds-analytics-id" { description = "Analytics Project ID" - value = module.project_radlab_ds_analytics.project_id + value = local.project.project_id } output "notebooks-instance-names" { diff --git a/modules/data_science/variables.tf b/modules/data_science/variables.tf index 851eae68..de573f60 100644 --- a/modules/data_science/variables.tf +++ b/modules/data_science/variables.tf @@ -31,6 +31,12 @@ variable "boot_disk_type" { default = "PD_SSD" } +variable "create_project" { + description = "Set to true if the module has to create a project. If you want to deploy in an existing project, set this variable to false." + type = bool + default = true +} + variable "domain" { description = "Display Name of Organization where GCP Resources need to get spin up" type = string @@ -49,6 +55,18 @@ variable "folder_id" { default = "" } +variable "image_family" { + description = "Image of the AI notebook." + type = string + default = "tf-latest-cpu" +} + +variable "image_project" { + description = "Google Cloud project where the image is hosted." + type = string + default = "deeplearning-platform-release" +} + variable "ip_cidr_range" { description = "Unique IP CIDR Range for AI Notebooks subnet" type = string @@ -72,10 +90,15 @@ variable "organization_id" { type = string } +variable "project_name" { + description = "Project name or ID, if it's an existing project." + type = string + default = "radlab-ds-analytics" +} variable "random_id" { description = "Adds a suffix of 4 random characters to the `project_id`" type = string - default = "" + default = null } variable "set_external_ip_policy" { @@ -96,6 +119,12 @@ variable "set_trustedimage_project_policy" { default = true } +variable "startup_script" { + description = "Startup script of the AI Notebooks." + type = string + default = "gs://radlab-solution-bucket/Data_Science_Model/samplenotebook.sh" +} + variable "trusted_users" { description = "The list of trusted users." type = set(string) From 7fe12001e777ee55cb9a1a3002277f0b83135205 Mon Sep 17 00:00:00 2001 From: Bjorn De Bakker Date: Wed, 10 Nov 2021 18:38:03 +0100 Subject: [PATCH 2/6] Add the ability to toggle the services --- modules/data_science/main.tf | 37 ++++++++++++++++++++++++++----- modules/data_science/variables.tf | 24 ++++++++++++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/modules/data_science/main.tf b/modules/data_science/main.tf index 05ec4b88..9f148c91 100644 --- a/modules/data_science/main.tf +++ b/modules/data_science/main.tf @@ -22,6 +22,18 @@ locals { ) region = join("-", [split("-", var.zone)[0], split("-", var.zone)[1]]) + network = ( + var.create_network + ? try(module.vpc_ai_notebook.0.network.network, null) + : try(data.google_compute_network.default.0, null) + ) + + subnet = ( + var.create_network + ? try(module.vpc_ai_notebook.0.subnets["${local.region}/${var.subnet_name}"], null) + : try(data.google_compute_subnetwork.default.0, null) + ) + notebook_sa_project_roles = [ "roles/compute.instanceAdmin", "roles/notebooks.admin", @@ -29,12 +41,12 @@ locals { "roles/storage.objectViewer" ] - project_services = [ + project_services = var.enable_services ? [ "compute.googleapis.com", "bigquery.googleapis.com", "notebooks.googleapis.com", "bigquerystorage.googleapis.com" - ] + ] : [] } resource "random_id" "default" { @@ -76,18 +88,31 @@ resource "google_project_service" "enabled_services" { ] } +data "google_compute_network" "default" { + count = var.create_network ? 0 : 1 + project = local.project.project_id + name = var.network_name +} + +data "google_compute_subnetwork" "default" { + count = var.create_network ? 0 : 1 + project = local.project.project_id + name = var.subnet_name +} + module "vpc_ai_notebook" { + count = var.create_network ? 1 : 0 source = "terraform-google-modules/network/google" version = "~> 3.0" project_id = local.project.project_id - network_name = "ai-notebook" + network_name = var.network_name routing_mode = "GLOBAL" description = "VPC Network created via Terraform" subnets = [ { - subnet_name = "subnet-ai-notebook" + subnet_name = var.subnet_name subnet_ip = var.ip_cidr_range subnet_region = local.region description = "Subnetwork inside *vpc-analytics* VPC network, created via Terraform" @@ -210,8 +235,8 @@ resource "google_notebooks_instance" "ai_notebook" { no_public_ip = false no_proxy_access = false - network = module.vpc_ai_notebook.network_self_link - subnet = module.vpc_ai_notebook.subnets_self_links.0 + network = local.network.self_link + subnet = local.subnet.self_link post_startup_script = var.startup_script diff --git a/modules/data_science/variables.tf b/modules/data_science/variables.tf index de573f60..f29a3f04 100644 --- a/modules/data_science/variables.tf +++ b/modules/data_science/variables.tf @@ -31,6 +31,12 @@ variable "boot_disk_type" { default = "PD_SSD" } +variable "create_network" { + description = "If the module has to be deployed in an existing network, set this variable to false." + type = bool + default = true +} + variable "create_project" { description = "Set to true if the module has to create a project. If you want to deploy in an existing project, set this variable to false." type = bool @@ -43,6 +49,12 @@ variable "domain" { default = "" } +variable "enable_services" { + description = "Enable the necessary APIs on the project. When using an existing project, this can be set to false." + type = bool + default = true +} + variable "file_path" { description = "Environment path to the respective modules (like DataScience module) which contains TF files for the same." type = string @@ -79,6 +91,12 @@ variable "machine_type" { default = "n1-standard-1" } +variable "network_name" { + description = "Name of the network to be created." + type = string + default = "ai-notebook" +} + variable "notebook_count" { description = "Number of AI Notebooks requested" type = string @@ -125,6 +143,12 @@ variable "startup_script" { default = "gs://radlab-solution-bucket/Data_Science_Model/samplenotebook.sh" } +variable "subnet_name" { + description = "Name of the subnet where to deploy the Notebooks." + type = string + default = "subnet-ai-notebook" +} + variable "trusted_users" { description = "The list of trusted users." type = set(string) From f23b3b7875abb431e4b07707b3c4c357be98db31 Mon Sep 17 00:00:00 2001 From: Mukul Gupta Date: Thu, 11 Nov 2021 15:35:32 -0800 Subject: [PATCH 3/6] [FEATURE] Adding timer to wait for Org Policy to get rolled out - Adding wait timer of 120 seconds b/w Org policies are created & AI notebook (depending on the Org Policy) starts getting created. - Also moved org policies into a separate .tf file. --- modules/data_science/main.tf | 45 +------------------- modules/data_science/orgpolicy.tf | 71 +++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 44 deletions(-) create mode 100644 modules/data_science/orgpolicy.tf diff --git a/modules/data_science/main.tf b/modules/data_science/main.tf index 9f148c91..c4f8d078 100644 --- a/modules/data_science/main.tf +++ b/modules/data_science/main.tf @@ -143,45 +143,6 @@ module "vpc_ai_notebook" { ] } -resource "google_project_organization_policy" "external_ip_policy" { - count = var.set_external_ip_policy ? 1 : 0 - constraint = "compute.vmExternalIpAccess" - project = local.project.project_id - - list_policy { - allow { - all = true - } - } -} - -# - Shielded VMs: constraints/compute.requireShieldedVm -resource "google_project_organization_policy" "shielded_vm_policy" { - count = var.set_shielded_vm_policy ? 1 : 0 - constraint = "compute.requireShieldedVm" - project = local.project.project_id - - boolean_policy { - enforced = false - } -} - -# - Define trusted image projects: constraints/compute.trustedImageProjects -# Use of images from project deeplearning-platform-release is prohibited in Argolis -resource "google_project_organization_policy" "trustedimage_project_policy" { - count = var.set_trustedimage_project_policy ? 1 : 0 - constraint = "compute.trustedImageProjects" - project = local.project.project_id - - list_policy { - allow { - values = [ - "is:projects/deeplearning-platform-release", - ] - } - } -} - resource "google_service_account" "sa_p_notebook" { project = local.project.project_id account_id = format("sa-p-notebook-%s", local.random_id) @@ -248,11 +209,7 @@ resource "google_notebooks_instance" "ai_notebook" { terraform = "true" proxy-mode = "mail" } - depends_on = [ - google_project_organization_policy.external_ip_policy, - google_project_organization_policy.shielded_vm_policy, - google_project_organization_policy.trustedimage_project_policy - ] +depends_on = [time_sleep.wait_120_seconds] } resource "google_storage_bucket" "user_scripts_bucket" { diff --git a/modules/data_science/orgpolicy.tf b/modules/data_science/orgpolicy.tf new file mode 100644 index 00000000..1dc4a940 --- /dev/null +++ b/modules/data_science/orgpolicy.tf @@ -0,0 +1,71 @@ +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +resource "google_project_organization_policy" "external_ip_policy" { + count = var.set_external_ip_policy ? 1 : 0 + constraint = "compute.vmExternalIpAccess" + project = local.project.project_id + + list_policy { + allow { + all = true + } + } + depends_on = [ + module.project_radlab_ds_analytics + ] +} + +resource "google_project_organization_policy" "shielded_vm_policy" { + count = var.set_shielded_vm_policy ? 1 : 0 + constraint = "compute.requireShieldedVm" + project = local.project.project_id + + boolean_policy { + enforced = false + } + depends_on = [ + module.project_radlab_ds_analytics + ] +} + +resource "google_project_organization_policy" "trustedimage_project_policy" { + count = var.set_trustedimage_project_policy ? 1 : 0 + constraint = "compute.trustedImageProjects" + project = local.project.project_id + + list_policy { + allow { + values = [ + "is:projects/deeplearning-platform-release", + ] + } + } + depends_on = [ + module.project_radlab_ds_analytics + ] +} + +resource "time_sleep" "wait_120_seconds" { + depends_on = [ + google_project_organization_policy.external_ip_policy, + google_project_organization_policy.shielded_vm_policy, + google_project_organization_policy.trustedimage_project_policy + ] + + create_duration = "120s" +} \ No newline at end of file From 766b7b6239c1047af7206bf9c15a8031d02463a6 Mon Sep 17 00:00:00 2001 From: Bjorn De Bakker Date: Fri, 12 Nov 2021 08:35:39 +0100 Subject: [PATCH 4/6] Adding terraform.tfvars to the list of ignored files --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4e375d36..cbb068a1 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ credentials.json .vscode/ env/ .envrc -*.iml \ No newline at end of file +*.iml +terraform.tfvars \ No newline at end of file From 45dbdb2a17c825a7996c862d9c1a45de04c147a3 Mon Sep 17 00:00:00 2001 From: Bjorn De Bakker Date: Fri, 12 Nov 2021 13:10:39 +0100 Subject: [PATCH 5/6] Sleep timer for org policies depends on whether or not they are set --- modules/data_science/main.tf | 6 ++---- modules/data_science/orgpolicy.tf | 11 +++++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/modules/data_science/main.tf b/modules/data_science/main.tf index c4f8d078..c5827a61 100644 --- a/modules/data_science/main.tf +++ b/modules/data_science/main.tf @@ -98,6 +98,7 @@ data "google_compute_subnetwork" "default" { count = var.create_network ? 0 : 1 project = local.project.project_id name = var.subnet_name + region = local.region } module "vpc_ai_notebook" { @@ -131,9 +132,6 @@ module "vpc_ai_notebook" { allow = [{ protocol = "tcp" ports = ["0-65535"] - }, { - protocol = "tcp" - ports = ["0-65535"] }] } ] @@ -209,7 +207,7 @@ resource "google_notebooks_instance" "ai_notebook" { terraform = "true" proxy-mode = "mail" } -depends_on = [time_sleep.wait_120_seconds] + depends_on = [time_sleep.wait_120_seconds] } resource "google_storage_bucket" "user_scripts_bucket" { diff --git a/modules/data_science/orgpolicy.tf b/modules/data_science/orgpolicy.tf index 1dc4a940..e93ba9e3 100644 --- a/modules/data_science/orgpolicy.tf +++ b/modules/data_science/orgpolicy.tf @@ -55,17 +55,20 @@ resource "google_project_organization_policy" "trustedimage_project_policy" { ] } } + depends_on = [ module.project_radlab_ds_analytics ] } resource "time_sleep" "wait_120_seconds" { + count = var.set_trustedimage_project_policy || var.set_shielded_vm_policy || var.set_external_ip_policy ? 1 : 0 + depends_on = [ - google_project_organization_policy.external_ip_policy, - google_project_organization_policy.shielded_vm_policy, - google_project_organization_policy.trustedimage_project_policy - ] + google_project_organization_policy.external_ip_policy, + google_project_organization_policy.shielded_vm_policy, + google_project_organization_policy.trustedimage_project_policy + ] create_duration = "120s" } \ No newline at end of file From e47dd1875f485c18eb0e89d2b936db749c7ad81f Mon Sep 17 00:00:00 2001 From: Bjorn De Bakker Date: Fri, 12 Nov 2021 13:22:33 +0100 Subject: [PATCH 6/6] Updated documentation with additional examples --- modules/data_science/README.md | 73 ++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/modules/data_science/README.md b/modules/data_science/README.md index 5715592b..ee8f306a 100644 --- a/modules/data_science/README.md +++ b/modules/data_science/README.md @@ -22,6 +22,79 @@ The lab need to be deployed by a _Cloud Admin_ persona with the following GCP ro * `Storage Object Viewer` * [OPTIONAL] `Organization Policy Administrator` +## Using Terraform module +Here are a couple of examples to use the module directly in your Terraform code, as opposed to using the RAD Lab Launcher. + +### Simple + +```hcl +module "simple" { + source = "./modules/data_science" + + billing_account_id = "123456-123456-123465" + organization_id = "12345678901" + folder_id = "1234567890" +} +``` +### Use existing project + +Make sure the identity running the Terraform code has the following IAM permissions on the project: +* `roles/compute.admin` +* `roles/resourcemanager.projectIamAdmin` +* `roles/iam.serviceAccountAdmin` +* `roles/storage.admin` +* `roles/notebooks.admin` + +This example assumes that all the necessary APIs have been enabled as well. + +````hcl +module "existing_project" { + source = "./modules/data_science" + + billing_account_id = "123456-123456-123465" + organization_id = "12345678901" + folder_id = "1234567890" + + create_project = false + project_name = "ds-project-id" + enable_services = false + + set_external_ip_policy = false + set_shielded_vm_policy = false + set_trustedimage_project_policy = false +} +```` + +### Existing network +Make sure the identity running the Terraform code has the following IAM permissions on the project: +* `roles/resourcemanager.projectIamAdmin` +* `roles/iam.serviceAccountAdmin` +* `roles/storage.admin` +* `roles/notebooks.admin` + +```hcl +module "existing_project_and_network" { + source = "./modules/data_science" + + billing_account_id = "123456-123456-123465" + organization_id = "12345678901" + folder_id = "1234567890" + + create_project = false + project_name = "ds-project-id" + enable_services = false + enable_services = false + + create_network = false + network_name = "data-science-network" + subnet_name = "data-science-subnetwork" + + set_external_ip_policy = false + set_shielded_vm_policy = false + set_trustedimage_project_policy = false +} +``` + ## Variables