diff --git a/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go b/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go index b5e0ad7e3a42..21ef2d20b629 100644 --- a/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go +++ b/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go @@ -917,6 +917,11 @@ func azureBlobStorageDataSchema() *schema.Resource { }, Description: ` Workload Identity Details used to authenticate API requests to Azure.`, }, + "private_network_service": { + Type: schema.TypeString, + Optional: true, + Description: `Service Directory Service used as the endpoint for transfers from a customer-managed VPC. Format: projects/{projectId}/locations/{location}/namespaces/{namespace}/services/{service}`, + }, }, } } @@ -1782,6 +1787,7 @@ func expandAzureBlobStorageData(azureBlobStorageDatas []interface{}) *storagetra AzureCredentials: expandAzureCredentials(azureBlobStorageData["azure_credentials"].([]interface{})), CredentialsSecret: azureBlobStorageData["credentials_secret"].(string), FederatedIdentityConfig: expandAzureFederatedIdentifyConfig(azureBlobStorageData["federated_identity_config"].([]interface{})), + PrivateNetworkService: azureBlobStorageData["private_network_service"].(string), } } @@ -1793,6 +1799,7 @@ func flattenAzureBlobStorageData(azureBlobStorageData *storagetransfer.AzureBlob "azure_credentials": flattenAzureCredentials(d), "federated_identity_config": flattenAzureFederatedIdentifyConfig(d), "credentials_secret": azureBlobStorageData.CredentialsSecret, + "private_network_service": azureBlobStorageData.PrivateNetworkService, } return []map[string]interface{}{data} diff --git a/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job_meta.yaml b/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job_meta.yaml index 9bf9ba4ae234..ac10b9a1d31f 100644 --- a/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job_meta.yaml +++ b/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job_meta.yaml @@ -70,6 +70,7 @@ fields: - api_field: 'transferSpec.azureBlobStorageDataSource.federatedIdentityConfig.clientId' - api_field: 'transferSpec.azureBlobStorageDataSource.federatedIdentityConfig.tenantId' - api_field: 'transferSpec.azureBlobStorageDataSource.path' + - api_field: 'transferSpec.azureBlobStorageDataSource.privateNetworkService' - api_field: 'transferSpec.azureBlobStorageDataSource.storageAccount' - api_field: 'transferSpec.awsS3CompatibleDataSource.bucketName' - api_field: 'transferSpec.awsS3CompatibleDataSource.path' diff --git a/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job_test.go b/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job_test.go index b54c9259a32b..7fa3d91d1dc6 100644 --- a/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job_test.go +++ b/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job_test.go @@ -666,6 +666,61 @@ func TestAccStorageTransferJob_awsS3CompatibleDataSource(t *testing.T) { }) } +func TestAccStorageTransferJob_azureBlobStorageDataSourcePrivateNetwork(t *testing.T) { + t.Parallel() + + project := envvar.GetTestProjectFromEnv() + testDataSinkName := acctest.RandString(t, 10) + suffix := acctest.RandString(t, 10) + namespaceId := "tf-test-sts-azure-" + suffix + serviceIdA := "tf-test-sts-azure-svc-a-" + suffix + serviceIdB := "tf-test-sts-azure-svc-b-" + suffix + location := "us-central1" + expectedPNSA := fmt.Sprintf("projects/%s/locations/%s/namespaces/%s/services/%s", project, location, namespaceId, serviceIdA) + expectedPNSB := fmt.Sprintf("projects/%s/locations/%s/namespaces/%s/services/%s", project, location, namespaceId, serviceIdB) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccStorageTransferJobDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccStorageTransferJob_azureBlobStorageDataSourcePrivateNetwork(project, testDataSinkName, namespaceId, serviceIdA, serviceIdB, location, "a"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr( + "google_storage_transfer_job.transfer_job", + "transfer_spec.0.azure_blob_storage_data_source.0.private_network_service", + expectedPNSA, + ), + ), + }, + { + ResourceName: "google_storage_transfer_job.transfer_job", + ImportState: true, + ImportStateVerify: true, + // azure_credentials is input-only on the API and not returned on Read. + ImportStateVerifyIgnore: []string{"transfer_spec.0.azure_blob_storage_data_source.0.azure_credentials"}, + }, + { + Config: testAccStorageTransferJob_azureBlobStorageDataSourcePrivateNetwork(project, testDataSinkName, namespaceId, serviceIdA, serviceIdB, location, "b"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr( + "google_storage_transfer_job.transfer_job", + "transfer_spec.0.azure_blob_storage_data_source.0.private_network_service", + expectedPNSB, + ), + ), + }, + { + ResourceName: "google_storage_transfer_job.transfer_job", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"transfer_spec.0.azure_blob_storage_data_source.0.azure_credentials"}, + }, + }, + }) +} + func TestAccStorageTransferJob_transferManifest(t *testing.T) { t.Parallel() @@ -3035,6 +3090,85 @@ resource "google_storage_transfer_job" "transfer_job" { `, project, dataSourceBucketName, dataSinkBucketName, transferJobDescription, manifestObjectName) } +func testAccStorageTransferJob_azureBlobStorageDataSourcePrivateNetwork(project, dataSinkBucketName, namespaceId, serviceIdA, serviceIdB, location, which string) string { + pnsRef := "google_service_directory_service.sts_azure_a.id" + if which == "b" { + pnsRef = "google_service_directory_service.sts_azure_b.id" + } + return fmt.Sprintf(` +data "google_storage_transfer_project_service_account" "default" { + project = "%[1]s" +} + +resource "google_storage_bucket" "data_sink" { + name = "%[2]s" + project = "%[1]s" + location = "US" + force_destroy = true +} + +resource "google_storage_bucket_iam_member" "data_sink" { + bucket = google_storage_bucket.data_sink.name + role = "roles/storage.admin" + member = "serviceAccount:${data.google_storage_transfer_project_service_account.default.email}" +} + +resource "google_service_directory_namespace" "sts_azure" { + project = "%[1]s" + namespace_id = "%[3]s" + location = "%[6]s" +} + +resource "google_service_directory_service" "sts_azure_a" { + service_id = "%[4]s" + namespace = google_service_directory_namespace.sts_azure.id +} + +resource "google_service_directory_service" "sts_azure_b" { + service_id = "%[5]s" + namespace = google_service_directory_namespace.sts_azure.id +} + +resource "google_storage_transfer_job" "transfer_job" { + description = "Azure source with private network service" + project = "%[1]s" + + transfer_spec { + azure_blob_storage_data_source { + storage_account = "examplestorageaccount" + container = "example-container" + path = "foo/bar/" + azure_credentials { + sas_token = "fakesastoken" + } + private_network_service = %[7]s + } + gcs_data_sink { + bucket_name = google_storage_bucket.data_sink.name + path = "foo/bar/" + } + } + + schedule { + schedule_start_date { + year = 2024 + month = 1 + day = 1 + } + schedule_end_date { + year = 2024 + month = 1 + day = 1 + } + } + + depends_on = [ + google_storage_bucket_iam_member.data_sink, + ] +} +`, project, dataSinkBucketName, namespaceId, serviceIdA, serviceIdB, location, pnsRef) +} + func testAccStorageTransferJob_withoutTransferManifest(project, dataSourceBucketName, dataSinkBucketName, transferJobDescription string) string { return fmt.Sprintf(` data "google_storage_transfer_project_service_account" "default" { diff --git a/mmv1/third_party/terraform/website/docs/r/storage_transfer_job.html.markdown b/mmv1/third_party/terraform/website/docs/r/storage_transfer_job.html.markdown index a004ac000ab8..45b8df4fb385 100644 --- a/mmv1/third_party/terraform/website/docs/r/storage_transfer_job.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/storage_transfer_job.html.markdown @@ -333,6 +333,8 @@ The `aws_access_key` block supports: * `federated_identity_config` - (Optional) Federated identity config of a user registered Azure application. Structure [documented below](#nested_federated_identity_config). +* `private_network_service` - (Optional) Service Directory Service to be used as the endpoint for transfers from a customer-managed VPC. Format: `projects/{projectId}/locations/{location}/namespaces/{namespace}/services/{service}`. + The `azure_credentials` block supports: * `sas_token` - (Required) Azure shared access signature. See [Grant limited access to Azure Storage resources using shared access signatures (SAS)](https://docs.microsoft.com/en-us/azure/storage/common/storage-sas-overview).