From 661af04fe80bef99d58499a51c6abc575927f690 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 May 2024 20:45:38 +0000 Subject: [PATCH 01/10] added files --- quickstart/101-ai-studio/README.md | 44 ++++++++++++++++ quickstart/101-ai-studio/connections.tf | 26 ++++++++++ quickstart/101-ai-studio/dependent.tf | 67 +++++++++++++++++++++++++ quickstart/101-ai-studio/hub-cmk.tf | 48 ++++++++++++++++++ quickstart/101-ai-studio/hub.tf | 26 ++++++++++ quickstart/101-ai-studio/main.tf | 17 +++++++ quickstart/101-ai-studio/output.tf | 16 ++++++ quickstart/101-ai-studio/project.tf | 20 ++++++++ quickstart/101-ai-studio/variables.tf | 18 +++++++ 9 files changed, 282 insertions(+) create mode 100644 quickstart/101-ai-studio/README.md create mode 100644 quickstart/101-ai-studio/connections.tf create mode 100644 quickstart/101-ai-studio/dependent.tf create mode 100644 quickstart/101-ai-studio/hub-cmk.tf create mode 100644 quickstart/101-ai-studio/hub.tf create mode 100644 quickstart/101-ai-studio/main.tf create mode 100644 quickstart/101-ai-studio/output.tf create mode 100644 quickstart/101-ai-studio/project.tf create mode 100644 quickstart/101-ai-studio/variables.tf diff --git a/quickstart/101-ai-studio/README.md b/quickstart/101-ai-studio/README.md new file mode 100644 index 00000000..579d518f --- /dev/null +++ b/quickstart/101-ai-studio/README.md @@ -0,0 +1,44 @@ +# Azure AI Studio + +This deployment configuration specifies an [Azure AI hub](https://learn.microsoft.com/en-us/azure/ai-studio/concepts/ai-resources), +and its associated resources including Azure Key Vault, Azure Storage. You can optionally provision and attach Azure Application Insights and Azure Container Registry. + +This configuration describes the minimal set of resources you require to get started with Azure AI Studio. + +## Resources + +| Terraform Resource Type | Description | +| - | - | +| `azurerm_resource_group` | The resource group all resources get deployed into. | +| `azurerm_key_vault` | An Azure Key Vault instance associated to the Azure Machine Learning workspace. | +| `azurerm_storage_account` | An Azure Storage instance associated to the Azure Machine Learning workspace. | +| `azurerm_application_insights` | An Azure Application Insights instance associated to the Azure Machine Learning workspace. | +| `azurerm_container_registry` | An Azure Container Registry instance associated to the Azure Machine Learning workspace. | + +## Variables + +| Name | Description | Default | +| ---- | ----------- | ------- | +| names | Prefix name for dependent resources. | myfirst | +| location | The Azure region used for deployments | East US | +| sku | The SKU for AI Services resources | S0 + +## Usage + +After git cloning the repo, run the following commands after having docker running on your machine. + +```bash +terraform init + +az login + +terraform plan -var names="tftemplate" -out demo.tfplan + +terraform apply "demo.tfplan" +``` + +## Common mistakes + +1. Make sure docker is running +1. Make sure to have logged into your Azure Subscription by running ```az login```. +1. Ensure that you have the correct RBAC permissions for in your subscription, hub, and project. \ No newline at end of file diff --git a/quickstart/101-ai-studio/connections.tf b/quickstart/101-ai-studio/connections.tf new file mode 100644 index 00000000..60640c44 --- /dev/null +++ b/quickstart/101-ai-studio/connections.tf @@ -0,0 +1,26 @@ +//Create an AI Services connection. +resource "azapi_resource" "AIServicesConnection" { + type = "Microsoft.MachineLearningServices/workspaces/connections@2024-04-01-preview" + name = "Default_AIServices" + parent_id = azapi_resource.hub.id + + body = jsonencode({ + properties = { + category = "AIServices", + target = jsondecode(azapi_resource.AIServicesResource.output).properties.endpoint, + authType = "AAD", // or "APIKey" + isSharedToAll = true, + metadata = { + ApiType = "Azure", + ResourceId = azapi_resource.AIServicesResource.id + } + + credentials = { + Key = "" // <- must input APIKey here + } + + } + }) + schema_validation_enabled = false + response_export_values = ["*"] +} \ No newline at end of file diff --git a/quickstart/101-ai-studio/dependent.tf b/quickstart/101-ai-studio/dependent.tf new file mode 100644 index 00000000..038af316 --- /dev/null +++ b/quickstart/101-ai-studio/dependent.tf @@ -0,0 +1,67 @@ + +resource "azurerm_resource_group" "default" { + name = "azapi-template-rg-${var.names}" + location = var.location +} + +resource "azurerm_storage_account" "default" { + name = "${var.names}storage" + location = azurerm_resource_group.default.location + resource_group_name = azurerm_resource_group.default.name + account_tier = "Standard" + account_replication_type = "GRS" + allow_nested_items_to_be_public = false +} + +resource "azurerm_key_vault" "default" { + name = "${var.names}keyvault" + location = azurerm_resource_group.default.location + resource_group_name = azurerm_resource_group.default.name + tenant_id = data.azurerm_client_config.current.tenant_id + sku_name = "standard" + purge_protection_enabled = false +} + +// AzAPI AIServices +resource "azapi_resource" "AIServicesResource"{ + type = "Microsoft.CognitiveServices/accounts@2024-01-01-preview" + name = "${var.names}AIServicesResource" + location = azurerm_resource_group.default.location + parent_id = azurerm_resource_group.default.id + + identity { + type = "SystemAssigned" + } + + body = jsonencode({ + properties = { + apiProperties = { + statisticsEnabled = false + } + } + kind = "AIServices" + sku = { + name = var.sku + } + }) + + schema_validation_enabled = false + response_export_values = ["*"] +} + +/* The following resources are OPTIONAL. +resource "azurerm_application_insights" "default" { + name = "${var.names}appinsights" + location = azurerm_resource_group.default.location + resource_group_name = azurerm_resource_group.default.name + application_type = "web" +} + +resource "azurerm_container_registry" "default" { + name = "${var.names}contreg" + resource_group_name = azurerm_resource_group.default.name + location = azurerm_resource_group.default.location + sku = "premium" + admin_enabled = true +} +*/ \ No newline at end of file diff --git a/quickstart/101-ai-studio/hub-cmk.tf b/quickstart/101-ai-studio/hub-cmk.tf new file mode 100644 index 00000000..c29c1f3e --- /dev/null +++ b/quickstart/101-ai-studio/hub-cmk.tf @@ -0,0 +1,48 @@ +/* // To enable cmk, pass in arguments to set up keyIdentifier via cmk_keyvault_key_uri. Also comment out hub.tf. + +variable "cmk_keyvault_key_uri" { + description = "Key vault uri to access the encryption key." +} + +variable "encryption_status" { + description = "Indicates whether or not the encryption is enabled for the workspace." + default = "Enabled" +} + +resource "azapi_resource" "hub" { + type = "Microsoft.MachineLearningServices/workspaces@2024-04-01" + name = "my-ai-hub" + location = azurerm_resource_group.default.location + parent_id = azurerm_resource_group.default.id + + identity { + type = "SystemAssigned" + } + + body = jsonencode({ + properties = { + description = "This is my Azure AI hub" + friendlyName = "My Hub" + storageAccount = azurerm_storage_account.default.id + keyVault = azurerm_key_vault.default.id + + /* Optional: To enable these field, the corresponding dependent resources need to be uncommented. + applicationInsight = azurerm_application_insights.default.id + containerRegistry = azurerm_container_registry.default.id + /* + + encryption = { + status = var.encryption_status + keyVaultProperties = { + keyVaultArmId = azurerm_key_vault.default.id + keyIdentifier = var.cmk_keyvault_key_uri + } + } + + } + kind = "hub" + }) + schema_validation_enabled = false +} + +*/ \ No newline at end of file diff --git a/quickstart/101-ai-studio/hub.tf b/quickstart/101-ai-studio/hub.tf new file mode 100644 index 00000000..7629f30b --- /dev/null +++ b/quickstart/101-ai-studio/hub.tf @@ -0,0 +1,26 @@ +resource "azapi_resource" "hub" { + type = "Microsoft.MachineLearningServices/workspaces@2024-04-01" + name = "my-ai-hub" + location = azurerm_resource_group.default.location + parent_id = azurerm_resource_group.default.id + + identity { + type = "SystemAssigned" + } + + body = jsonencode({ + properties = { + description = "This is my Azure AI hub" + friendlyName = "My Hub" + storageAccount = azurerm_storage_account.default.id + keyVault = azurerm_key_vault.default.id + + /* Optional: To enable these field, the corresponding dependent resources need to be uncommented. + applicationInsight = azurerm_application_insights.default.id + containerRegistry = azurerm_container_registry.default.id + */ + } + kind = "hub" + }) + schema_validation_enabled = false +} \ No newline at end of file diff --git a/quickstart/101-ai-studio/main.tf b/quickstart/101-ai-studio/main.tf new file mode 100644 index 00000000..ed091aa3 --- /dev/null +++ b/quickstart/101-ai-studio/main.tf @@ -0,0 +1,17 @@ +terraform { + required_providers { + azapi = { + source = "azure/azapi" + } + } +} + +provider "azurerm" { + features {} +} + +provider "azapi" { +} + +data "azurerm_client_config" "current" { +} \ No newline at end of file diff --git a/quickstart/101-ai-studio/output.tf b/quickstart/101-ai-studio/output.tf new file mode 100644 index 00000000..c24deefa --- /dev/null +++ b/quickstart/101-ai-studio/output.tf @@ -0,0 +1,16 @@ +output "ResourceGroup" { + value = azurerm_resource_group.default.id +} + +output "HubId" { + value = azapi_resource.hub.id +} + +output "ProjectId" { + value = azapi_resource.project.id +} + +output "endpoint" { + value = jsondecode(azapi_resource.AIServicesResource.output).properties.endpoint +} + diff --git a/quickstart/101-ai-studio/project.tf b/quickstart/101-ai-studio/project.tf new file mode 100644 index 00000000..2bcec10b --- /dev/null +++ b/quickstart/101-ai-studio/project.tf @@ -0,0 +1,20 @@ +resource "azapi_resource" "project" { + type = "Microsoft.MachineLearningServices/workspaces@2024-04-01" + name = "my-ai-project" + location = azurerm_resource_group.default.location + parent_id = azurerm_resource_group.default.id + + identity { + type = "SystemAssigned" + } + + body = jsonencode({ + properties = { + description = "This is my Azure AI PROJECT" + friendlyName = "My Project" + hubResourceId = azapi_resource.hub.id + } + kind = "project" + }) + schema_validation_enabled = false +} \ No newline at end of file diff --git a/quickstart/101-ai-studio/variables.tf b/quickstart/101-ai-studio/variables.tf new file mode 100644 index 00000000..ae636375 --- /dev/null +++ b/quickstart/101-ai-studio/variables.tf @@ -0,0 +1,18 @@ +// Names and Try are used for naming conventions in hub.tf and depende +variable "names" { + type = string + description="This variable is used to name the hub, project, and dependent resources." + default = "tftemplate" +} + +variable "location" { + type = string + description = "This is the location for all resources" + default = "East US 2" +} + +variable "sku" { + type = string + description = "The sku name of the Azure Analysis Services server to create. Choose from: B1, B2, D1, S0, S1, S2, S3, S4, S8, S9. Some skus are region specific. See https://docs.microsoft.com/en-us/azure/analysis-services/analysis-services-overview#availability-by-region" + default = "S0" +} \ No newline at end of file From c4bdeb74c01ee1106ba4d91045fbb9e4938804ed Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 May 2024 21:17:25 +0000 Subject: [PATCH 02/10] merged cmk into hub.tf --- quickstart/101-ai-studio/dependent.tf | 2 +- quickstart/101-ai-studio/hub-cmk.tf | 48 --------------------------- quickstart/101-ai-studio/hub.tf | 10 ++++++ quickstart/101-ai-studio/variables.tf | 12 ++++++- 4 files changed, 22 insertions(+), 50 deletions(-) delete mode 100644 quickstart/101-ai-studio/hub-cmk.tf diff --git a/quickstart/101-ai-studio/dependent.tf b/quickstart/101-ai-studio/dependent.tf index 038af316..50958e43 100644 --- a/quickstart/101-ai-studio/dependent.tf +++ b/quickstart/101-ai-studio/dependent.tf @@ -24,7 +24,7 @@ resource "azurerm_key_vault" "default" { // AzAPI AIServices resource "azapi_resource" "AIServicesResource"{ - type = "Microsoft.CognitiveServices/accounts@2024-01-01-preview" + type = "Microsoft.CognitiveServices/accounts@2024-04-01-preview" name = "${var.names}AIServicesResource" location = azurerm_resource_group.default.location parent_id = azurerm_resource_group.default.id diff --git a/quickstart/101-ai-studio/hub-cmk.tf b/quickstart/101-ai-studio/hub-cmk.tf deleted file mode 100644 index c29c1f3e..00000000 --- a/quickstart/101-ai-studio/hub-cmk.tf +++ /dev/null @@ -1,48 +0,0 @@ -/* // To enable cmk, pass in arguments to set up keyIdentifier via cmk_keyvault_key_uri. Also comment out hub.tf. - -variable "cmk_keyvault_key_uri" { - description = "Key vault uri to access the encryption key." -} - -variable "encryption_status" { - description = "Indicates whether or not the encryption is enabled for the workspace." - default = "Enabled" -} - -resource "azapi_resource" "hub" { - type = "Microsoft.MachineLearningServices/workspaces@2024-04-01" - name = "my-ai-hub" - location = azurerm_resource_group.default.location - parent_id = azurerm_resource_group.default.id - - identity { - type = "SystemAssigned" - } - - body = jsonencode({ - properties = { - description = "This is my Azure AI hub" - friendlyName = "My Hub" - storageAccount = azurerm_storage_account.default.id - keyVault = azurerm_key_vault.default.id - - /* Optional: To enable these field, the corresponding dependent resources need to be uncommented. - applicationInsight = azurerm_application_insights.default.id - containerRegistry = azurerm_container_registry.default.id - /* - - encryption = { - status = var.encryption_status - keyVaultProperties = { - keyVaultArmId = azurerm_key_vault.default.id - keyIdentifier = var.cmk_keyvault_key_uri - } - } - - } - kind = "hub" - }) - schema_validation_enabled = false -} - -*/ \ No newline at end of file diff --git a/quickstart/101-ai-studio/hub.tf b/quickstart/101-ai-studio/hub.tf index 7629f30b..e0389340 100644 --- a/quickstart/101-ai-studio/hub.tf +++ b/quickstart/101-ai-studio/hub.tf @@ -19,6 +19,16 @@ resource "azapi_resource" "hub" { applicationInsight = azurerm_application_insights.default.id containerRegistry = azurerm_container_registry.default.id */ + + //Optional: To enable Customer Managed Keys, the corresponding + encryption = { + status = var.encryption_status + keyVaultProperties = { + keyVaultArmId = azurerm_key_vault.default.id + keyIdentifier = var.cmk_keyvault_key_uri + } + } + } kind = "hub" }) diff --git a/quickstart/101-ai-studio/variables.tf b/quickstart/101-ai-studio/variables.tf index ae636375..b83c3120 100644 --- a/quickstart/101-ai-studio/variables.tf +++ b/quickstart/101-ai-studio/variables.tf @@ -15,4 +15,14 @@ variable "sku" { type = string description = "The sku name of the Azure Analysis Services server to create. Choose from: B1, B2, D1, S0, S1, S2, S3, S4, S8, S9. Some skus are region specific. See https://docs.microsoft.com/en-us/azure/analysis-services/analysis-services-overview#availability-by-region" default = "S0" -} \ No newline at end of file +} + +//Optional: For Customer Managed Keys, uncomment this part AND the corresponding section in hub.tf +variable "cmk_keyvault_key_uri" { + description = "Key vault uri to access the encryption key." +} + +variable "encryption_status" { + description = "Indicates whether or not the encryption is enabled for the workspace." + default = "Enabled" +} From af2f3b7866e4cc88a8be7d3bab8017a0677d17c1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 17 May 2024 20:13:17 +0000 Subject: [PATCH 03/10] fixed according to comments --- quickstart/101-ai-studio/dependent.tf | 5 +-- quickstart/101-ai-studio/hub.tf | 6 +-- quickstart/101-ai-studio/main.tf | 6 +++ quickstart/101-ai-studio/project.tf | 3 +- quickstart/101-ai-studio/variables.tf | 57 ++++++++++++++------------- 5 files changed, 41 insertions(+), 36 deletions(-) diff --git a/quickstart/101-ai-studio/dependent.tf b/quickstart/101-ai-studio/dependent.tf index 50958e43..14481aca 100644 --- a/quickstart/101-ai-studio/dependent.tf +++ b/quickstart/101-ai-studio/dependent.tf @@ -1,6 +1,6 @@ resource "azurerm_resource_group" "default" { - name = "azapi-template-rg-${var.names}" + name = "rg-${var.names}" location = var.location } @@ -24,7 +24,7 @@ resource "azurerm_key_vault" "default" { // AzAPI AIServices resource "azapi_resource" "AIServicesResource"{ - type = "Microsoft.CognitiveServices/accounts@2024-04-01-preview" + type = "Microsoft.CognitiveServices/accounts@2023-10-01-preview" name = "${var.names}AIServicesResource" location = azurerm_resource_group.default.location parent_id = azurerm_resource_group.default.id @@ -45,7 +45,6 @@ resource "azapi_resource" "AIServicesResource"{ } }) - schema_validation_enabled = false response_export_values = ["*"] } diff --git a/quickstart/101-ai-studio/hub.tf b/quickstart/101-ai-studio/hub.tf index e0389340..565ca7c1 100644 --- a/quickstart/101-ai-studio/hub.tf +++ b/quickstart/101-ai-studio/hub.tf @@ -1,5 +1,5 @@ resource "azapi_resource" "hub" { - type = "Microsoft.MachineLearningServices/workspaces@2024-04-01" + type = "Microsoft.MachineLearningServices/workspaces@2024-04-01-preview" name = "my-ai-hub" location = azurerm_resource_group.default.location parent_id = azurerm_resource_group.default.id @@ -20,7 +20,7 @@ resource "azapi_resource" "hub" { containerRegistry = azurerm_container_registry.default.id */ - //Optional: To enable Customer Managed Keys, the corresponding + /*Optional: To enable Customer Managed Keys, the corresponding encryption = { status = var.encryption_status keyVaultProperties = { @@ -28,9 +28,9 @@ resource "azapi_resource" "hub" { keyIdentifier = var.cmk_keyvault_key_uri } } + */ } kind = "hub" }) - schema_validation_enabled = false } \ No newline at end of file diff --git a/quickstart/101-ai-studio/main.tf b/quickstart/101-ai-studio/main.tf index ed091aa3..0ac01faa 100644 --- a/quickstart/101-ai-studio/main.tf +++ b/quickstart/101-ai-studio/main.tf @@ -1,5 +1,11 @@ terraform { + required_version = ">= 1.0" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">= 3.0, < 4.0" + } azapi = { source = "azure/azapi" } diff --git a/quickstart/101-ai-studio/project.tf b/quickstart/101-ai-studio/project.tf index 2bcec10b..96aee1cc 100644 --- a/quickstart/101-ai-studio/project.tf +++ b/quickstart/101-ai-studio/project.tf @@ -1,5 +1,5 @@ resource "azapi_resource" "project" { - type = "Microsoft.MachineLearningServices/workspaces@2024-04-01" + type = "Microsoft.MachineLearningServices/workspaces@2024-04-01-preview" name = "my-ai-project" location = azurerm_resource_group.default.location parent_id = azurerm_resource_group.default.id @@ -16,5 +16,4 @@ resource "azapi_resource" "project" { } kind = "project" }) - schema_validation_enabled = false } \ No newline at end of file diff --git a/quickstart/101-ai-studio/variables.tf b/quickstart/101-ai-studio/variables.tf index b83c3120..f739c12d 100644 --- a/quickstart/101-ai-studio/variables.tf +++ b/quickstart/101-ai-studio/variables.tf @@ -1,28 +1,29 @@ -// Names and Try are used for naming conventions in hub.tf and depende -variable "names" { - type = string - description="This variable is used to name the hub, project, and dependent resources." - default = "tftemplate" -} - -variable "location" { - type = string - description = "This is the location for all resources" - default = "East US 2" -} - -variable "sku" { - type = string - description = "The sku name of the Azure Analysis Services server to create. Choose from: B1, B2, D1, S0, S1, S2, S3, S4, S8, S9. Some skus are region specific. See https://docs.microsoft.com/en-us/azure/analysis-services/analysis-services-overview#availability-by-region" - default = "S0" -} - -//Optional: For Customer Managed Keys, uncomment this part AND the corresponding section in hub.tf -variable "cmk_keyvault_key_uri" { - description = "Key vault uri to access the encryption key." -} - -variable "encryption_status" { - description = "Indicates whether or not the encryption is enabled for the workspace." - default = "Enabled" -} +// Names and Try are used for naming conventions in hub.tf and depende +variable "names" { + type = string + description="This variable is used to name the hub, project, and dependent resources." + default = "tftemplate" +} + +variable "location" { + type = string + description = "This is the location for all resources" + default = "East US 2" +} + +variable "sku" { + type = string + description = "The sku name of the Azure Analysis Services server to create. Choose from: B1, B2, D1, S0, S1, S2, S3, S4, S8, S9. Some skus are region specific. See https://docs.microsoft.com/en-us/azure/analysis-services/analysis-services-overview#availability-by-region" + default = "S0" +} + +/*Optional: For Customer Managed Keys, uncomment this part AND the corresponding section in hub.tf +variable "cmk_keyvault_key_uri" { + description = "Key vault uri to access the encryption key." +} + +variable "encryption_status" { + description = "Indicates whether or not the encryption is enabled for the workspace." + default = "Enabled" +} +*/ \ No newline at end of file From 275036cf3c9eae7a4c438034c65485a697c6d987 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 17 May 2024 20:15:08 +0000 Subject: [PATCH 04/10] removed connections schema validation skip --- quickstart/101-ai-studio/connections.tf | 1 - 1 file changed, 1 deletion(-) diff --git a/quickstart/101-ai-studio/connections.tf b/quickstart/101-ai-studio/connections.tf index 60640c44..62bb753e 100644 --- a/quickstart/101-ai-studio/connections.tf +++ b/quickstart/101-ai-studio/connections.tf @@ -21,6 +21,5 @@ resource "azapi_resource" "AIServicesConnection" { } }) - schema_validation_enabled = false response_export_values = ["*"] } \ No newline at end of file From bb30e6465e1fb45e26e5b01d9ed387c3f0182a66 Mon Sep 17 00:00:00 2001 From: Andy Aviles Date: Wed, 5 Jun 2024 13:12:21 -0400 Subject: [PATCH 05/10] added in azurerm key_vault provider section in main.tf --- quickstart/101-ai-studio/main.tf | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/quickstart/101-ai-studio/main.tf b/quickstart/101-ai-studio/main.tf index 0ac01faa..c6ad21da 100644 --- a/quickstart/101-ai-studio/main.tf +++ b/quickstart/101-ai-studio/main.tf @@ -13,7 +13,16 @@ terraform { } provider "azurerm" { - features {} + features { + key_vault { + recover_soft_deleted_key_vaults = false + purge_soft_delete_on_destroy = false + purge_soft_deleted_keys_on_destroy = false + } + resource_group { + prevent_deletion_if_contains_resources = false + } + } } provider "azapi" { From d7eb1aa3cc7eb7d7a3de57f5f8c07569074a3a39 Mon Sep 17 00:00:00 2001 From: Andy Aviles Date: Mon, 17 Jun 2024 09:50:53 -0400 Subject: [PATCH 06/10] included random string suffix --- quickstart/101-ai-studio/dependent.tf | 4 ++-- quickstart/101-ai-studio/variables.tf | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/quickstart/101-ai-studio/dependent.tf b/quickstart/101-ai-studio/dependent.tf index 14481aca..9e95287e 100644 --- a/quickstart/101-ai-studio/dependent.tf +++ b/quickstart/101-ai-studio/dependent.tf @@ -5,7 +5,7 @@ resource "azurerm_resource_group" "default" { } resource "azurerm_storage_account" "default" { - name = "${var.names}storage" + name = "${var.names}storage${random_string.suffix.result}" location = azurerm_resource_group.default.location resource_group_name = azurerm_resource_group.default.name account_tier = "Standard" @@ -14,7 +14,7 @@ resource "azurerm_storage_account" "default" { } resource "azurerm_key_vault" "default" { - name = "${var.names}keyvault" + name = "${var.names}keyvault${random_string.suffix.result}" location = azurerm_resource_group.default.location resource_group_name = azurerm_resource_group.default.name tenant_id = data.azurerm_client_config.current.tenant_id diff --git a/quickstart/101-ai-studio/variables.tf b/quickstart/101-ai-studio/variables.tf index f739c12d..2a401684 100644 --- a/quickstart/101-ai-studio/variables.tf +++ b/quickstart/101-ai-studio/variables.tf @@ -17,6 +17,12 @@ variable "sku" { default = "S0" } +resource "random_string" "suffix" { + length = 4 + special = false + upper = false +} + /*Optional: For Customer Managed Keys, uncomment this part AND the corresponding section in hub.tf variable "cmk_keyvault_key_uri" { description = "Key vault uri to access the encryption key." From 757ad9785e34edcaa59c90b41387a08add7b8405 Mon Sep 17 00:00:00 2001 From: Andy Aviles Date: Wed, 19 Jun 2024 11:51:11 -0400 Subject: [PATCH 07/10] removed credentials as it was not expected --- quickstart/101-ai-studio/connections.tf | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/quickstart/101-ai-studio/connections.tf b/quickstart/101-ai-studio/connections.tf index 62bb753e..2ab70ee8 100644 --- a/quickstart/101-ai-studio/connections.tf +++ b/quickstart/101-ai-studio/connections.tf @@ -8,17 +8,12 @@ resource "azapi_resource" "AIServicesConnection" { properties = { category = "AIServices", target = jsondecode(azapi_resource.AIServicesResource.output).properties.endpoint, - authType = "AAD", // or "APIKey" + authType = "AAD", isSharedToAll = true, metadata = { ApiType = "Azure", ResourceId = azapi_resource.AIServicesResource.id } - - credentials = { - Key = "" // <- must input APIKey here - } - } }) response_export_values = ["*"] From 2f17431ec7e6ce71463b0995cd8a3c332e2b7a7b Mon Sep 17 00:00:00 2001 From: Andy Aviles Date: Fri, 21 Jun 2024 12:29:29 -0400 Subject: [PATCH 08/10] matching contributor guidelines --- quickstart/101-ai-studio/connections.tf | 20 --- quickstart/101-ai-studio/dependent.tf | 66 --------- quickstart/101-ai-studio/hub.tf | 36 ----- quickstart/101-ai-studio/main.tf | 182 ++++++++++++++++++++---- quickstart/101-ai-studio/output.tf | 5 +- quickstart/101-ai-studio/project.tf | 19 --- quickstart/101-ai-studio/providers.tf | 33 +++++ quickstart/101-ai-studio/variables.tf | 23 +-- 8 files changed, 204 insertions(+), 180 deletions(-) delete mode 100644 quickstart/101-ai-studio/connections.tf delete mode 100644 quickstart/101-ai-studio/dependent.tf delete mode 100644 quickstart/101-ai-studio/hub.tf delete mode 100644 quickstart/101-ai-studio/project.tf create mode 100644 quickstart/101-ai-studio/providers.tf diff --git a/quickstart/101-ai-studio/connections.tf b/quickstart/101-ai-studio/connections.tf deleted file mode 100644 index 2ab70ee8..00000000 --- a/quickstart/101-ai-studio/connections.tf +++ /dev/null @@ -1,20 +0,0 @@ -//Create an AI Services connection. -resource "azapi_resource" "AIServicesConnection" { - type = "Microsoft.MachineLearningServices/workspaces/connections@2024-04-01-preview" - name = "Default_AIServices" - parent_id = azapi_resource.hub.id - - body = jsonencode({ - properties = { - category = "AIServices", - target = jsondecode(azapi_resource.AIServicesResource.output).properties.endpoint, - authType = "AAD", - isSharedToAll = true, - metadata = { - ApiType = "Azure", - ResourceId = azapi_resource.AIServicesResource.id - } - } - }) - response_export_values = ["*"] -} \ No newline at end of file diff --git a/quickstart/101-ai-studio/dependent.tf b/quickstart/101-ai-studio/dependent.tf deleted file mode 100644 index 9e95287e..00000000 --- a/quickstart/101-ai-studio/dependent.tf +++ /dev/null @@ -1,66 +0,0 @@ - -resource "azurerm_resource_group" "default" { - name = "rg-${var.names}" - location = var.location -} - -resource "azurerm_storage_account" "default" { - name = "${var.names}storage${random_string.suffix.result}" - location = azurerm_resource_group.default.location - resource_group_name = azurerm_resource_group.default.name - account_tier = "Standard" - account_replication_type = "GRS" - allow_nested_items_to_be_public = false -} - -resource "azurerm_key_vault" "default" { - name = "${var.names}keyvault${random_string.suffix.result}" - location = azurerm_resource_group.default.location - resource_group_name = azurerm_resource_group.default.name - tenant_id = data.azurerm_client_config.current.tenant_id - sku_name = "standard" - purge_protection_enabled = false -} - -// AzAPI AIServices -resource "azapi_resource" "AIServicesResource"{ - type = "Microsoft.CognitiveServices/accounts@2023-10-01-preview" - name = "${var.names}AIServicesResource" - location = azurerm_resource_group.default.location - parent_id = azurerm_resource_group.default.id - - identity { - type = "SystemAssigned" - } - - body = jsonencode({ - properties = { - apiProperties = { - statisticsEnabled = false - } - } - kind = "AIServices" - sku = { - name = var.sku - } - }) - - response_export_values = ["*"] -} - -/* The following resources are OPTIONAL. -resource "azurerm_application_insights" "default" { - name = "${var.names}appinsights" - location = azurerm_resource_group.default.location - resource_group_name = azurerm_resource_group.default.name - application_type = "web" -} - -resource "azurerm_container_registry" "default" { - name = "${var.names}contreg" - resource_group_name = azurerm_resource_group.default.name - location = azurerm_resource_group.default.location - sku = "premium" - admin_enabled = true -} -*/ \ No newline at end of file diff --git a/quickstart/101-ai-studio/hub.tf b/quickstart/101-ai-studio/hub.tf deleted file mode 100644 index 565ca7c1..00000000 --- a/quickstart/101-ai-studio/hub.tf +++ /dev/null @@ -1,36 +0,0 @@ -resource "azapi_resource" "hub" { - type = "Microsoft.MachineLearningServices/workspaces@2024-04-01-preview" - name = "my-ai-hub" - location = azurerm_resource_group.default.location - parent_id = azurerm_resource_group.default.id - - identity { - type = "SystemAssigned" - } - - body = jsonencode({ - properties = { - description = "This is my Azure AI hub" - friendlyName = "My Hub" - storageAccount = azurerm_storage_account.default.id - keyVault = azurerm_key_vault.default.id - - /* Optional: To enable these field, the corresponding dependent resources need to be uncommented. - applicationInsight = azurerm_application_insights.default.id - containerRegistry = azurerm_container_registry.default.id - */ - - /*Optional: To enable Customer Managed Keys, the corresponding - encryption = { - status = var.encryption_status - keyVaultProperties = { - keyVaultArmId = azurerm_key_vault.default.id - keyIdentifier = var.cmk_keyvault_key_uri - } - } - */ - - } - kind = "hub" - }) -} \ No newline at end of file diff --git a/quickstart/101-ai-studio/main.tf b/quickstart/101-ai-studio/main.tf index c6ad21da..ca348732 100644 --- a/quickstart/101-ai-studio/main.tf +++ b/quickstart/101-ai-studio/main.tf @@ -1,32 +1,160 @@ -terraform { - required_version = ">= 1.0" - - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = ">= 3.0, < 4.0" - } - azapi = { - source = "azure/azapi" - } - } +resource "random_pet" "rg_name" { + prefix = var.resource_group_name_prefix } -provider "azurerm" { - features { - key_vault { - recover_soft_deleted_key_vaults = false - purge_soft_delete_on_destroy = false - purge_soft_deleted_keys_on_destroy = false - } - resource_group { - prevent_deletion_if_contains_resources = false - } - } -} - -provider "azapi" { +// RESOURCE GROUP +resource "azurerm_resource_group" "rg" { + location = var.resource_group_location + name = random_pet.rg_name.id } data "azurerm_client_config" "current" { -} \ No newline at end of file +} + +// STORAGE ACCOUNT +resource "azurerm_storage_account" "default" { + name = "${var.prefix}storage${random_string.suffix.result}" + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + account_tier = "Standard" + account_replication_type = "GRS" + allow_nested_items_to_be_public = false +} + +// KEY VAULT +resource "azurerm_key_vault" "default" { + name = "${var.prefix}keyvault${random_string.suffix.result}" + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + tenant_id = data.azurerm_client_config.current.tenant_id + sku_name = "standard" + purge_protection_enabled = false +} + +// AzAPI AIServices +resource "azapi_resource" "AIServicesResource"{ + type = "Microsoft.CognitiveServices/accounts@2023-10-01-preview" + name = "AIServicesResource${random_string.suffix.result}" + location = azurerm_resource_group.rg.location + parent_id = azurerm_resource_group.rg.id + + identity { + type = "SystemAssigned" + } + + body = jsonencode({ + name = "AIServicesResource${random_string.suffix.result}" + properties = { + //restore = true + customSubDomainName = "${random_string.suffix.result}domain" + apiProperties = { + statisticsEnabled = false + } + } + kind = "AIServices" + sku = { + name = var.sku + } + }) + + response_export_values = ["*"] +} + +// Azure AI Hub +resource "azapi_resource" "hub" { + type = "Microsoft.MachineLearningServices/workspaces@2024-04-01-preview" + name = "${random_pet.rg_name.id}-aih" + location = azurerm_resource_group.rg.location + parent_id = azurerm_resource_group.rg.id + + identity { + type = "SystemAssigned" + } + + body = jsonencode({ + properties = { + description = "This is my Azure AI hub" + friendlyName = "My Hub" + storageAccount = azurerm_storage_account.default.id + keyVault = azurerm_key_vault.default.id + + /* Optional: To enable these field, the corresponding dependent resources need to be uncommented. + applicationInsight = azurerm_application_insights.default.id + containerRegistry = azurerm_container_registry.default.id + */ + + /*Optional: To enable Customer Managed Keys, the corresponding + encryption = { + status = var.encryption_status + keyVaultProperties = { + keyVaultArmId = azurerm_key_vault.default.id + keyIdentifier = var.cmk_keyvault_key_uri + } + } + */ + + } + kind = "hub" + }) +} + +// Azure AI Project +resource "azapi_resource" "project" { + type = "Microsoft.MachineLearningServices/workspaces@2024-04-01-preview" + name = "my-ai-project${random_string.suffix.result}" + location = azurerm_resource_group.rg.location + parent_id = azurerm_resource_group.rg.id + + identity { + type = "SystemAssigned" + } + + body = jsonencode({ + properties = { + description = "This is my Azure AI PROJECT" + friendlyName = "My Project" + hubResourceId = azapi_resource.hub.id + } + kind = "project" + }) +} + +// AzAPI AI Services Connection +resource "azapi_resource" "AIServicesConnection" { + type = "Microsoft.MachineLearningServices/workspaces/connections@2024-04-01-preview" + name = "Default_AIServices${random_string.suffix.result}" + parent_id = azapi_resource.hub.id + + body = jsonencode({ + properties = { + category = "AIServices", + target = jsondecode(azapi_resource.AIServicesResource.output).properties.endpoint, + authType = "AAD", + isSharedToAll = true, + metadata = { + ApiType = "Azure", + ResourceId = azapi_resource.AIServicesResource.id + } + } + }) + response_export_values = ["*"] +} + +/* The following resources are OPTIONAL. +// APPLICATION INSIGHTS +resource "azurerm_application_insights" "default" { + name = "${var.prefix}appinsights${random_string.suffix.result}" + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + application_type = "web" +} + +// CONTAINER REGISTRY +resource "azurerm_container_registry" "default" { + name = "${var.prefix}contreg${random_string.suffix.result}" + resource_group_name = azurerm_resource_group.rg.name + location = azurerm_resource_group.rg.location + sku = "premium" + admin_enabled = true +} +*/ \ No newline at end of file diff --git a/quickstart/101-ai-studio/output.tf b/quickstart/101-ai-studio/output.tf index c24deefa..ae3666a1 100644 --- a/quickstart/101-ai-studio/output.tf +++ b/quickstart/101-ai-studio/output.tf @@ -1,5 +1,5 @@ output "ResourceGroup" { - value = azurerm_resource_group.default.id + value = azurerm_resource_group.rg.id } output "HubId" { @@ -12,5 +12,4 @@ output "ProjectId" { output "endpoint" { value = jsondecode(azapi_resource.AIServicesResource.output).properties.endpoint -} - +} \ No newline at end of file diff --git a/quickstart/101-ai-studio/project.tf b/quickstart/101-ai-studio/project.tf deleted file mode 100644 index 96aee1cc..00000000 --- a/quickstart/101-ai-studio/project.tf +++ /dev/null @@ -1,19 +0,0 @@ -resource "azapi_resource" "project" { - type = "Microsoft.MachineLearningServices/workspaces@2024-04-01-preview" - name = "my-ai-project" - location = azurerm_resource_group.default.location - parent_id = azurerm_resource_group.default.id - - identity { - type = "SystemAssigned" - } - - body = jsonencode({ - properties = { - description = "This is my Azure AI PROJECT" - friendlyName = "My Project" - hubResourceId = azapi_resource.hub.id - } - kind = "project" - }) -} \ No newline at end of file diff --git a/quickstart/101-ai-studio/providers.tf b/quickstart/101-ai-studio/providers.tf new file mode 100644 index 00000000..f802a369 --- /dev/null +++ b/quickstart/101-ai-studio/providers.tf @@ -0,0 +1,33 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~>3.0" + } + azapi = { + source = "azure/azapi" + } + random = { + source = "hashicorp/random" + version = "~>3.0" + } + } +} + +provider "azurerm" { + features { + key_vault { + recover_soft_deleted_key_vaults = false + purge_soft_delete_on_destroy = false + purge_soft_deleted_keys_on_destroy = false + } + resource_group { + prevent_deletion_if_contains_resources = false + } + } +} + +provider "azapi" { +} \ No newline at end of file diff --git a/quickstart/101-ai-studio/variables.tf b/quickstart/101-ai-studio/variables.tf index 2a401684..8d6d2484 100644 --- a/quickstart/101-ai-studio/variables.tf +++ b/quickstart/101-ai-studio/variables.tf @@ -1,14 +1,19 @@ -// Names and Try are used for naming conventions in hub.tf and depende -variable "names" { - type = string - description="This variable is used to name the hub, project, and dependent resources." - default = "tftemplate" +variable "resource_group_location" { + type = string + default = "eastus" + description = "Location of the resource group." } -variable "location" { +variable "resource_group_name_prefix" { + type = string + default = "rg" + description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription." +} + +variable "prefix" { type = string - description = "This is the location for all resources" - default = "East US 2" + description="This variable is used to name the hub, project, and dependent resources." + default = "ai" } variable "sku" { @@ -23,7 +28,7 @@ resource "random_string" "suffix" { upper = false } -/*Optional: For Customer Managed Keys, uncomment this part AND the corresponding section in hub.tf +/*Optional: For Customer Managed Keys, uncomment this part AND the corresponding section in main.tf variable "cmk_keyvault_key_uri" { description = "Key vault uri to access the encryption key." } From 85af378d987b5aa00fc8bb041ca3fd16bb19ccf4 Mon Sep 17 00:00:00 2001 From: Andy Aviles Date: Fri, 21 Jun 2024 13:35:30 -0400 Subject: [PATCH 09/10] renamed outputs.tf --- quickstart/101-ai-studio/{output.tf => outputs.tf} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename quickstart/101-ai-studio/{output.tf => outputs.tf} (100%) diff --git a/quickstart/101-ai-studio/output.tf b/quickstart/101-ai-studio/outputs.tf similarity index 100% rename from quickstart/101-ai-studio/output.tf rename to quickstart/101-ai-studio/outputs.tf From 29e04061467005e3b69acb833cf6283ab16b8127 Mon Sep 17 00:00:00 2001 From: Andy Aviles Date: Wed, 10 Jul 2024 11:44:01 -0400 Subject: [PATCH 10/10] updated outputs and variables used --- quickstart/101-ai-studio/README.md | 9 +++++---- quickstart/101-ai-studio/outputs.tf | 8 ++------ 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/quickstart/101-ai-studio/README.md b/quickstart/101-ai-studio/README.md index 579d518f..19df45c4 100644 --- a/quickstart/101-ai-studio/README.md +++ b/quickstart/101-ai-studio/README.md @@ -19,9 +19,10 @@ This configuration describes the minimal set of resources you require to get sta | Name | Description | Default | | ---- | ----------- | ------- | -| names | Prefix name for dependent resources. | myfirst | -| location | The Azure region used for deployments | East US | -| sku | The SKU for AI Services resources | S0 +| `resource_group_name_prefix` | Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription. | rg | +| `resource_group_location` | Location of the resource group. | eastus | +| `prefix` | This variable is used to name the hub, project, and dependent resources. | ai | +| `sku` | The SKU for AI Services resources | S0 ## Usage @@ -32,7 +33,7 @@ terraform init az login -terraform plan -var names="tftemplate" -out demo.tfplan +terraform plan -out demo.tfplan terraform apply "demo.tfplan" ``` diff --git a/quickstart/101-ai-studio/outputs.tf b/quickstart/101-ai-studio/outputs.tf index ae3666a1..3c3f6c5f 100644 --- a/quickstart/101-ai-studio/outputs.tf +++ b/quickstart/101-ai-studio/outputs.tf @@ -1,12 +1,8 @@ -output "ResourceGroup" { +output "resource_group_name" { value = azurerm_resource_group.rg.id } -output "HubId" { - value = azapi_resource.hub.id -} - -output "ProjectId" { +output "workspace_name" { value = azapi_resource.project.id }