Skip to content

Commit be53c0a

Browse files
feat: Add azure attributes in federated database instance resource (#3484)
* feat: Azure Support in CloudProviderConfig for mongodbatlas_federated_database_instance * Add flattenAzureCloudProviderConfig function to handle Azure configuration * test: add Azure cloud provider acceptance test for federated DB instance test: add Azure cloud provider acceptance test for federated database resource * refactor(test): Remove duplicate local implementation to use shared test functionality on Azure Cloud Provider Missing refactor * Add changelog * Move helper function under test functions for better organization * Change order of parameters to match formatting options * Remove extra linebreak * Add Azure var IDs for Data Federation testing to be used in CI * Remove unnecessary data source for Azure config test reusability * Refactor flattenCloudProviderConfig functions to accept schema.ResourceData * Add data source for azure attribute * Add clarification comments to address change in schema attribute * refactor: Extract schema definition for cloudProviderConfig field into its own function to be able to reuse it in multiple places * Address PR comment suggestion * Add resource_schema file * Modify schema fields to handle test_s3_bucket field on data source * Correct cloud provider data source being used for test on azure config * Update changelog to reflect addition of data sources for azure cloud provider config
1 parent 58e2c9f commit be53c0a

10 files changed

+251
-162
lines changed

.changelog/3484.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
```release-note:enhancement
2+
resource/mongodbatlas_federated_database_instance: Adds `azure` attribute to allow the creation of federated databases with Azure cloud provider configuration
3+
```
4+
5+
```release-note:enhancement
6+
data-source/mongodbatlas_federated_database_instance: Adds `azure` attribute to support reading federated databases with Azure cloud provider configuration
7+
```
8+
9+
```release-note:enhancement
10+
data-source/mongodbatlas_federated_database_instances: Adds `azure` attribute to support reading federated databases with Azure cloud provider configuration
11+
```

.github/workflows/acceptance-tests-runner.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,9 @@ jobs:
774774
MONGODB_ATLAS_FEDERATED_ISSUER_URI: ${{ inputs.mongodb_atlas_federated_issuer_uri }}
775775
MONGODB_ATLAS_FEDERATED_ORG_ID: ${{ inputs.mongodb_atlas_federated_org_id }}
776776
MONGODB_ATLAS_FEDERATED_SETTINGS_ASSOCIATED_DOMAIN: ${{ inputs.mongodb_atlas_federated_settings_associated_domain }}
777+
AZURE_ATLAS_APP_ID: ${{ inputs.azure_atlas_app_id }}
778+
AZURE_SERVICE_PRINCIPAL_ID: ${{ inputs.azure_service_principal_id }}
779+
AZURE_TENANT_ID: ${{ inputs.azure_tenant_id }}
777780
AWS_S3_BUCKET: ${{ secrets.aws_s3_bucket_federation }}
778781
AWS_REGION: ${{ inputs.aws_region_federation }}
779782
AWS_ACCESS_KEY_ID: ${{ secrets.aws_access_key_id }}

internal/service/cloudprovideraccess/data_source_cloud_provider_access_setup.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func DataSourceSetup() *schema.Resource {
2222
"provider_name": {
2323
Type: schema.TypeString,
2424
Required: true,
25-
ValidateFunc: validation.StringInSlice([]string{"AWS"}, false),
25+
ValidateFunc: validation.StringInSlice([]string{"AWS", "AZURE"}, false),
2626
},
2727
"role_id": {
2828
Type: schema.TypeString,

internal/service/cloudprovideraccess/resource_cloud_provider_access_setup_test.go

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ func TestAccCloudProviderAccessSetupAWS_basic(t *testing.T) {
1717
resource.ParallelTest(t, *basicSetupTestCase(t))
1818
}
1919

20+
const (
21+
cloudProviderAzureDataSource = `
22+
data "mongodbatlas_cloud_provider_access_setup" "test" {
23+
project_id = mongodbatlas_cloud_provider_access_setup.test.project_id
24+
provider_name = "AZURE"
25+
role_id = mongodbatlas_cloud_provider_access_setup.test.role_id
26+
}
27+
`
28+
)
29+
2030
func TestAccCloudProviderAccessSetupAzure_basic(t *testing.T) {
2131
var (
2232
resourceName = "mongodbatlas_cloud_provider_access_setup.test"
@@ -26,13 +36,12 @@ func TestAccCloudProviderAccessSetupAzure_basic(t *testing.T) {
2636
tenantID = os.Getenv("AZURE_TENANT_ID")
2737
projectID = acc.ProjectIDExecution(t)
2838
)
29-
3039
resource.ParallelTest(t, resource.TestCase{
3140
PreCheck: func() { acc.PreCheckCloudProviderAccessAzure(t) },
3241
ProtoV6ProviderFactories: acc.TestAccProviderV6Factories,
3342
Steps: []resource.TestStep{
3443
{
35-
Config: configSetupAzure(projectID, atlasAzureAppID, servicePrincipalID, tenantID),
44+
Config: acc.ConfigSetupAzure(projectID, atlasAzureAppID, servicePrincipalID, tenantID) + cloudProviderAzureDataSource,
3645
Check: resource.ComposeAggregateTestCheckFunc(
3746
checkExists(resourceName),
3847
resource.TestCheckResourceAttrSet(resourceName, "role_id"),
@@ -104,26 +113,6 @@ func configSetupAWS(projectID string) string {
104113
`, projectID)
105114
}
106115

107-
func configSetupAzure(projectID, atlasAzureAppID, servicePrincipalID, tenantID string) string {
108-
return fmt.Sprintf(`
109-
resource "mongodbatlas_cloud_provider_access_setup" "test" {
110-
project_id = %[1]q
111-
provider_name = "AZURE"
112-
azure_config {
113-
atlas_azure_app_id = %[2]q
114-
service_principal_id = %[3]q
115-
tenant_id = %[4]q
116-
}
117-
}
118-
119-
data "mongodbatlas_cloud_provider_access_setup" "test" {
120-
project_id = mongodbatlas_cloud_provider_access_setup.test.project_id
121-
provider_name = "AWS"
122-
role_id = mongodbatlas_cloud_provider_access_setup.test.role_id
123-
}
124-
`, projectID, atlasAzureAppID, servicePrincipalID, tenantID)
125-
}
126-
127116
func checkExists(resourceName string) resource.TestCheckFunc {
128117
return func(s *terraform.State) error {
129118
rs, ok := s.RootModule().Resources[resourceName]

internal/service/federateddatabaseinstance/data_source_federated_database_instance.go

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -33,47 +33,7 @@ func DataSource() *schema.Resource {
3333
Type: schema.TypeString,
3434
},
3535
},
36-
"cloud_provider_config": {
37-
Type: schema.TypeList,
38-
MaxItems: 1,
39-
Computed: true,
40-
Optional: true,
41-
Elem: &schema.Resource{
42-
Schema: map[string]*schema.Schema{
43-
"aws": {
44-
Type: schema.TypeList,
45-
MaxItems: 1,
46-
Computed: true,
47-
Optional: true,
48-
Elem: &schema.Resource{
49-
Schema: map[string]*schema.Schema{
50-
"role_id": {
51-
Type: schema.TypeString,
52-
Computed: true,
53-
},
54-
"test_s3_bucket": {
55-
Type: schema.TypeString,
56-
Computed: true,
57-
Optional: true,
58-
},
59-
"iam_assumed_role_arn": {
60-
Type: schema.TypeString,
61-
Computed: true,
62-
},
63-
"iam_user_arn": {
64-
Type: schema.TypeString,
65-
Computed: true,
66-
},
67-
"external_id": {
68-
Type: schema.TypeString,
69-
Computed: true,
70-
},
71-
},
72-
},
73-
},
74-
},
75-
},
76-
},
36+
"cloud_provider_config": cloudProviderConfig(true),
7737
"data_process_region": {
7838
Type: schema.TypeList,
7939
Computed: true,

internal/service/federateddatabaseinstance/data_source_federated_database_instances.go

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -45,47 +45,7 @@ func PluralDataSource() *schema.Resource {
4545
Type: schema.TypeString,
4646
},
4747
},
48-
"cloud_provider_config": {
49-
Type: schema.TypeList,
50-
MaxItems: 1,
51-
Computed: true,
52-
Optional: true,
53-
Elem: &schema.Resource{
54-
Schema: map[string]*schema.Schema{
55-
"aws": {
56-
Type: schema.TypeList,
57-
MaxItems: 1,
58-
Computed: true,
59-
Optional: true,
60-
Elem: &schema.Resource{
61-
Schema: map[string]*schema.Schema{
62-
"role_id": {
63-
Type: schema.TypeString,
64-
Computed: true,
65-
},
66-
"test_s3_bucket": {
67-
Type: schema.TypeString,
68-
Computed: true,
69-
Optional: true,
70-
},
71-
"iam_assumed_role_arn": {
72-
Type: schema.TypeString,
73-
Computed: true,
74-
},
75-
"iam_user_arn": {
76-
Type: schema.TypeString,
77-
Computed: true,
78-
},
79-
"external_id": {
80-
Type: schema.TypeString,
81-
Computed: true,
82-
},
83-
},
84-
},
85-
},
86-
},
87-
},
88-
},
48+
"cloud_provider_config": cloudProviderConfig(true),
8949
"data_process_region": {
9050
Type: schema.TypeList,
9151
Computed: true,

internal/service/federateddatabaseinstance/resource_federated_database_instance.go

Lines changed: 43 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -53,45 +53,8 @@ func Resource() *schema.Resource {
5353
Type: schema.TypeString,
5454
},
5555
},
56-
"cloud_provider_config": {
57-
Type: schema.TypeList,
58-
MaxItems: 1,
59-
Computed: true,
60-
Optional: true,
61-
Elem: &schema.Resource{
62-
Schema: map[string]*schema.Schema{
63-
"aws": {
64-
Type: schema.TypeList,
65-
MaxItems: 1,
66-
Required: true,
67-
Elem: &schema.Resource{
68-
Schema: map[string]*schema.Schema{
69-
"role_id": {
70-
Type: schema.TypeString,
71-
Required: true,
72-
},
73-
"test_s3_bucket": {
74-
Type: schema.TypeString,
75-
Required: true,
76-
},
77-
"iam_assumed_role_arn": {
78-
Type: schema.TypeString,
79-
Computed: true,
80-
},
81-
"iam_user_arn": {
82-
Type: schema.TypeString,
83-
Computed: true,
84-
},
85-
"external_id": {
86-
Type: schema.TypeString,
87-
Computed: true,
88-
},
89-
},
90-
},
91-
},
92-
},
93-
},
94-
},
56+
// Optional-only behavior from the API, but keeping O+C to avoid behavior changes.
57+
"cloud_provider_config": cloudProviderConfig(false),
9558
"data_process_region": {
9659
Type: schema.TypeList,
9760
MaxItems: 1,
@@ -708,7 +671,8 @@ func newUrls(urlsFromConfig []any) *[]string {
708671
func newCloudProviderConfig(d *schema.ResourceData) *admin.DataLakeCloudProviderConfig {
709672
if cloudProvider, ok := d.Get("cloud_provider_config").([]any); ok && len(cloudProvider) == 1 {
710673
return &admin.DataLakeCloudProviderConfig{
711-
Aws: newAWSConfig(cloudProvider),
674+
Aws: newAWSConfig(cloudProvider),
675+
Azure: newAzureConfig(cloudProvider),
712676
}
713677
}
714678

@@ -724,6 +688,14 @@ func newAWSConfig(cloudProvider []any) *admin.DataLakeAWSCloudProviderConfig {
724688
return nil
725689
}
726690

691+
func newAzureConfig(cloudProvider []any) *admin.DataFederationAzureCloudProviderConfig {
692+
if azure, ok := cloudProvider[0].(map[string]any)["azure"].([]any); ok && len(azure) == 1 {
693+
azureSchema := azure[0].(map[string]any)
694+
return admin.NewDataFederationAzureCloudProviderConfig(azureSchema["role_id"].(string))
695+
}
696+
return nil
697+
}
698+
727699
func newDataProcessRegion(d *schema.ResourceData) *admin.DataLakeDataProcessRegion {
728700
if dataProcessRegion, ok := d.Get("data_process_region").([]any); ok && len(dataProcessRegion) == 1 {
729701
return &admin.DataLakeDataProcessRegion{
@@ -740,8 +712,18 @@ func flattenCloudProviderConfig(d *schema.ResourceData, cloudProviderConfig *adm
740712
return nil
741713
}
742714

743-
aws := cloudProviderConfig.GetAws()
715+
return []map[string]any{
716+
{
717+
"aws": flattenAWSCloudProviderConfig(d, cloudProviderConfig.Aws),
718+
"azure": flattenAzureCloudProviderConfig(cloudProviderConfig.Azure),
719+
},
720+
}
721+
}
744722

723+
func flattenAWSCloudProviderConfig(d *schema.ResourceData, aws *admin.DataLakeAWSCloudProviderConfig) []map[string]any {
724+
if aws == nil {
725+
return nil
726+
}
745727
awsOut := []map[string]any{
746728
{
747729
"role_id": aws.GetRoleId(),
@@ -751,29 +733,33 @@ func flattenCloudProviderConfig(d *schema.ResourceData, cloudProviderConfig *adm
751733
},
752734
}
753735

754-
currentCloudProviderConfig, ok := d.Get("cloud_provider_config").([]any)
755-
if !ok || len(currentCloudProviderConfig) == 0 {
756-
return []map[string]any{
757-
{
758-
"aws": &awsOut,
759-
},
760-
}
761-
}
762-
// test_s3_bucket is not part of the API response
763-
if currentAWS, ok := currentCloudProviderConfig[0].(map[string]any)["aws"].([]any); ok {
764-
if testS3Bucket, ok := currentAWS[0].(map[string]any)["test_s3_bucket"].(string); ok {
765-
awsOut[0]["test_s3_bucket"] = testS3Bucket
766-
return []map[string]any{
767-
{
768-
"aws": &awsOut,
769-
},
736+
// Optionally add test_s3_bucket if present in the config
737+
if currentCloudProviderConfig, ok := d.Get("cloud_provider_config").([]any); ok && len(currentCloudProviderConfig) > 0 {
738+
if currentAWS, ok := currentCloudProviderConfig[0].(map[string]any)["aws"].([]any); ok && len(currentAWS) > 0 {
739+
if testS3Bucket, ok := currentAWS[0].(map[string]any)["test_s3_bucket"].(string); ok && testS3Bucket != "" {
740+
awsOut[0]["test_s3_bucket"] = testS3Bucket
770741
}
771742
}
772743
}
773744

774745
return awsOut
775746
}
776747

748+
func flattenAzureCloudProviderConfig(azure *admin.DataFederationAzureCloudProviderConfig) []map[string]any {
749+
if azure == nil {
750+
return nil
751+
}
752+
753+
return []map[string]any{
754+
{
755+
"role_id": azure.GetRoleId(),
756+
"atlas_app_id": azure.GetAtlasAppId(),
757+
"service_principal_id": azure.GetServicePrincipalId(),
758+
"tenant_id": azure.GetTenantId(),
759+
},
760+
}
761+
}
762+
777763
func flattenDataProcessRegion(processRegion *admin.DataLakeDataProcessRegion) []map[string]any {
778764
if processRegion == nil || (processRegion.Region == "" && processRegion.CloudProvider == "") {
779765
return nil

0 commit comments

Comments
 (0)