From dd42877721c7175762d8113c8ef4eac9d8cbaad6 Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Sat, 7 Dec 2024 09:13:21 +0100 Subject: [PATCH 1/4] [Feature] Allow to use GCP SA in `databricks_credential` (storage only) Right now it's only possible to use it only for `purpose = "STORAGE"`. --- catalog/resource_credential.go | 7 ++++++- docs/resources/credential.md | 26 +++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/catalog/resource_credential.go b/catalog/resource_credential.go index 4cf77e319e..72f1ea5da1 100644 --- a/catalog/resource_credential.go +++ b/catalog/resource_credential.go @@ -11,7 +11,8 @@ import ( var credentialSchema = common.StructToSchema(catalog.CredentialInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { - var alofServiceCreds = []string{"aws_iam_role", "azure_managed_identity", "azure_service_principal"} + var alofServiceCreds = []string{"aws_iam_role", "azure_managed_identity", "azure_service_principal", + "databricks_gcp_service_account"} for _, cred := range alofServiceCreds { common.CustomizeSchemaPath(m, cred).SetExactlyOneOf(alofServiceCreds) } @@ -25,6 +26,10 @@ var credentialSchema = common.StructToSchema(catalog.CredentialInfo{}, common.CustomizeSchemaPath(m, computed).SetComputed() } + common.CustomizeSchemaPath(m, "databricks_gcp_service_account").SetComputed() + common.CustomizeSchemaPath(m, "databricks_gcp_service_account", "email").SetComputed() + common.CustomizeSchemaPath(m, "databricks_gcp_service_account", "credential_id").SetComputed() + common.CustomizeSchemaPath(m, "databricks_gcp_service_account", "private_key_id").SetComputed() common.MustSchemaPath(m, "aws_iam_role", "external_id").Computed = true common.MustSchemaPath(m, "aws_iam_role", "unity_catalog_iam_arn").Computed = true common.MustSchemaPath(m, "azure_managed_identity", "credential_id").Computed = true diff --git a/docs/resources/credential.md b/docs/resources/credential.md index e612e9f89e..f56ec07fe2 100644 --- a/docs/resources/credential.md +++ b/docs/resources/credential.md @@ -50,7 +50,26 @@ resource "databricks_credential" "external_mi" { } resource "databricks_grants" "external_creds" { - credential = databricks_credential.external.id + credential = databricks_credential.external_mi.id + grant { + principal = "Data Engineers" + privileges = ["ACCESS"] + } +} +``` + +For GCP + +```hcl +resource "databricks_credential" "external_gcp_sa" { + name = "gcp_sa_credential" + databricks_gcp_service_account {} + purpose = "SERVICE" + comment = "GCP SA credential managed by TF" +} + +resource "databricks_grants" "external_creds" { + credential = databricks_credential.external_gcp_sa.id grant { principal = "Data Engineers" privileges = ["ACCESS"] @@ -87,6 +106,11 @@ The following arguments are required: - `application_id` - The application ID of the application registration within the referenced AAD tenant - `client_secret` - The client secret generated for the above app ID in AAD. **This field is redacted on output** +`databricks_gcp_service_account` optional configuration block for creating a Databricks-managed GCP Service Account. Only applicable when purpose is `STORAGE`: + +- `email` (output only) - The email of the GCP service account created, to be granted access to relevant buckets. + + ## Attribute Reference In addition to all arguments above, the following attributes are exported: From b6df8bebdb2e035a8014018fb080af3a158f38d2 Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Tue, 10 Dec 2024 06:31:09 +0100 Subject: [PATCH 2/4] add integration test --- internal/acceptance/credential_test.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/internal/acceptance/credential_test.go b/internal/acceptance/credential_test.go index efbd492318..aae1534964 100644 --- a/internal/acceptance/credential_test.go +++ b/internal/acceptance/credential_test.go @@ -10,7 +10,7 @@ func TestUcAccCredential(t *testing.T) { UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_credential" "external" { - name = "cred-{var.RANDOM}" + name = "service-cred-{var.RANDOM}" aws_iam_role { role_arn = "{env.TEST_METASTORE_DATA_ACCESS_ARN}" } @@ -19,6 +19,18 @@ func TestUcAccCredential(t *testing.T) { comment = "Managed by TF" }`, }) + } else if isGcp(t) { + UnityWorkspaceLevel(t, Step{ + // TODO: update purpose to SERVICE when it's released + Template: ` + resource "databricks_credential" "external" { + name = "storage-cred-{var.RANDOM}" + databricks_gcp_service_account {} + purpose = "STORAGE" + skip_validation = true + comment = "Managed by TF" + }`, + }) } } From 9fd889bc311b8b65f17cde36c6afd2a4fbfaaebd Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Thu, 12 Dec 2024 15:50:27 +0100 Subject: [PATCH 3/4] Address review comments --- docs/resources/credential.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/resources/credential.md b/docs/resources/credential.md index f56ec07fe2..6642c6cb4f 100644 --- a/docs/resources/credential.md +++ b/docs/resources/credential.md @@ -58,13 +58,13 @@ resource "databricks_grants" "external_creds" { } ``` -For GCP +For GCP (only applicable when purpose is `STORAGE`) ```hcl resource "databricks_credential" "external_gcp_sa" { name = "gcp_sa_credential" databricks_gcp_service_account {} - purpose = "SERVICE" + purpose = "STORAGE" comment = "GCP SA credential managed by TF" } From 697cf3a21490862503c30c2bb96bbd7c1bb9963b Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Thu, 12 Dec 2024 15:57:29 +0100 Subject: [PATCH 4/4] fix acceptance test --- internal/acceptance/credential_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/acceptance/credential_test.go b/internal/acceptance/credential_test.go index aae1534964..80e3cb5b8f 100644 --- a/internal/acceptance/credential_test.go +++ b/internal/acceptance/credential_test.go @@ -19,7 +19,7 @@ func TestUcAccCredential(t *testing.T) { comment = "Managed by TF" }`, }) - } else if isGcp(t) { + } else if IsGcp(t) { UnityWorkspaceLevel(t, Step{ // TODO: update purpose to SERVICE when it's released Template: `