-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
azurerm_mongo_cluster
- Supports connection_strings
#28880
base: main
Are you sure you want to change the base?
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -6,6 +6,7 @@ package mongocluster | |||||||||||||||||||||
import ( | ||||||||||||||||||||||
"context" | ||||||||||||||||||||||
"fmt" | ||||||||||||||||||||||
"net/url" | ||||||||||||||||||||||
"regexp" | ||||||||||||||||||||||
"time" | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
@@ -14,7 +15,6 @@ import ( | |||||||||||||||||||||
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" | ||||||||||||||||||||||
"github.com/hashicorp/go-azure-helpers/resourcemanager/location" | ||||||||||||||||||||||
"github.com/hashicorp/go-azure-sdk/resource-manager/mongocluster/2024-07-01/mongoclusters" | ||||||||||||||||||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||||||||||||||||||||||
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk" | ||||||||||||||||||||||
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" | ||||||||||||||||||||||
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" | ||||||||||||||||||||||
|
@@ -27,22 +27,29 @@ var _ sdk.ResourceWithUpdate = MongoClusterResource{} | |||||||||||||||||||||
var _ sdk.ResourceWithCustomizeDiff = MongoClusterResource{} | ||||||||||||||||||||||
|
||||||||||||||||||||||
type MongoClusterResourceModel struct { | ||||||||||||||||||||||
Name string `tfschema:"name"` | ||||||||||||||||||||||
ResourceGroupName string `tfschema:"resource_group_name"` | ||||||||||||||||||||||
Location string `tfschema:"location"` | ||||||||||||||||||||||
AdministratorUserName string `tfschema:"administrator_username"` | ||||||||||||||||||||||
AdministratorPassword string `tfschema:"administrator_password"` | ||||||||||||||||||||||
CreateMode string `tfschema:"create_mode"` | ||||||||||||||||||||||
ShardCount int64 `tfschema:"shard_count"` | ||||||||||||||||||||||
SourceLocation string `tfschema:"source_location"` | ||||||||||||||||||||||
SourceServerId string `tfschema:"source_server_id"` | ||||||||||||||||||||||
ComputeTier string `tfschema:"compute_tier"` | ||||||||||||||||||||||
HighAvailabilityMode string `tfschema:"high_availability_mode"` | ||||||||||||||||||||||
PublicNetworkAccess string `tfschema:"public_network_access"` | ||||||||||||||||||||||
PreviewFeatures []string `tfschema:"preview_features"` | ||||||||||||||||||||||
StorageSizeInGb int64 `tfschema:"storage_size_in_gb"` | ||||||||||||||||||||||
Tags map[string]string `tfschema:"tags"` | ||||||||||||||||||||||
Version string `tfschema:"version"` | ||||||||||||||||||||||
Name string `tfschema:"name"` | ||||||||||||||||||||||
ResourceGroupName string `tfschema:"resource_group_name"` | ||||||||||||||||||||||
Location string `tfschema:"location"` | ||||||||||||||||||||||
AdministratorUserName string `tfschema:"administrator_username"` | ||||||||||||||||||||||
AdministratorPassword string `tfschema:"administrator_password"` | ||||||||||||||||||||||
CreateMode string `tfschema:"create_mode"` | ||||||||||||||||||||||
ShardCount int64 `tfschema:"shard_count"` | ||||||||||||||||||||||
SourceLocation string `tfschema:"source_location"` | ||||||||||||||||||||||
SourceServerId string `tfschema:"source_server_id"` | ||||||||||||||||||||||
ComputeTier string `tfschema:"compute_tier"` | ||||||||||||||||||||||
HighAvailabilityMode string `tfschema:"high_availability_mode"` | ||||||||||||||||||||||
PublicNetworkAccess string `tfschema:"public_network_access"` | ||||||||||||||||||||||
PreviewFeatures []string `tfschema:"preview_features"` | ||||||||||||||||||||||
StorageSizeInGb int64 `tfschema:"storage_size_in_gb"` | ||||||||||||||||||||||
ConnectionStrings []MongoClusterConnectionString `tfschema:"connection_strings"` | ||||||||||||||||||||||
Tags map[string]string `tfschema:"tags"` | ||||||||||||||||||||||
Version string `tfschema:"version"` | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
type MongoClusterConnectionString struct { | ||||||||||||||||||||||
ConnectionString string `tfschema:"connection_string"` | ||||||||||||||||||||||
Description string `tfschema:"description"` | ||||||||||||||||||||||
Name string `tfschema:"name"` | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
func (r MongoClusterResource) ModelObject() interface{} { | ||||||||||||||||||||||
|
@@ -57,12 +64,12 @@ func (r MongoClusterResource) ResourceType() string { | |||||||||||||||||||||
return "azurerm_mongo_cluster" | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
func (r MongoClusterResource) Arguments() map[string]*schema.Schema { | ||||||||||||||||||||||
return map[string]*schema.Schema{ | ||||||||||||||||||||||
func (r MongoClusterResource) Arguments() map[string]*pluginsdk.Schema { | ||||||||||||||||||||||
return map[string]*pluginsdk.Schema{ | ||||||||||||||||||||||
"name": { | ||||||||||||||||||||||
ForceNew: true, | ||||||||||||||||||||||
Required: true, | ||||||||||||||||||||||
Type: schema.TypeString, | ||||||||||||||||||||||
Type: pluginsdk.TypeString, | ||||||||||||||||||||||
ValidateFunc: validation.StringMatch( | ||||||||||||||||||||||
regexp.MustCompile(`^[a-z\d]([-a-z\d]{1,38}[a-z\d])$`), | ||||||||||||||||||||||
"`name` must be between 3 and 40 characters. It can contain only lowercase letters, numbers, and hyphens (-). It must start and end with a lowercase letter or number.", | ||||||||||||||||||||||
|
@@ -74,15 +81,15 @@ func (r MongoClusterResource) Arguments() map[string]*schema.Schema { | |||||||||||||||||||||
"location": commonschema.Location(), | ||||||||||||||||||||||
|
||||||||||||||||||||||
"administrator_username": { | ||||||||||||||||||||||
Type: schema.TypeString, | ||||||||||||||||||||||
Type: pluginsdk.TypeString, | ||||||||||||||||||||||
Optional: true, | ||||||||||||||||||||||
ForceNew: true, | ||||||||||||||||||||||
ValidateFunc: validation.StringIsNotEmpty, | ||||||||||||||||||||||
RequiredWith: []string{"administrator_password"}, | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
|
||||||||||||||||||||||
"create_mode": { | ||||||||||||||||||||||
Type: schema.TypeString, | ||||||||||||||||||||||
Type: pluginsdk.TypeString, | ||||||||||||||||||||||
Optional: true, | ||||||||||||||||||||||
ForceNew: true, | ||||||||||||||||||||||
Default: string(mongoclusters.CreateModeDefault), | ||||||||||||||||||||||
|
@@ -94,24 +101,24 @@ func (r MongoClusterResource) Arguments() map[string]*schema.Schema { | |||||||||||||||||||||
}, | ||||||||||||||||||||||
|
||||||||||||||||||||||
"preview_features": { | ||||||||||||||||||||||
Type: schema.TypeList, | ||||||||||||||||||||||
Type: pluginsdk.TypeList, | ||||||||||||||||||||||
Optional: true, | ||||||||||||||||||||||
ForceNew: true, | ||||||||||||||||||||||
Elem: &schema.Schema{ | ||||||||||||||||||||||
Type: schema.TypeString, | ||||||||||||||||||||||
Elem: &pluginsdk.Schema{ | ||||||||||||||||||||||
Type: pluginsdk.TypeString, | ||||||||||||||||||||||
ValidateFunc: validation.StringInSlice(mongoclusters.PossibleValuesForPreviewFeature(), false), | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
|
||||||||||||||||||||||
"shard_count": { | ||||||||||||||||||||||
Type: schema.TypeInt, | ||||||||||||||||||||||
Type: pluginsdk.TypeInt, | ||||||||||||||||||||||
Optional: true, | ||||||||||||||||||||||
ValidateFunc: validation.IntAtLeast(1), | ||||||||||||||||||||||
ForceNew: true, | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
|
||||||||||||||||||||||
"source_location": { | ||||||||||||||||||||||
Type: schema.TypeString, | ||||||||||||||||||||||
Type: pluginsdk.TypeString, | ||||||||||||||||||||||
Optional: true, | ||||||||||||||||||||||
ForceNew: true, | ||||||||||||||||||||||
StateFunc: location.StateFunc, | ||||||||||||||||||||||
|
@@ -121,22 +128,22 @@ func (r MongoClusterResource) Arguments() map[string]*schema.Schema { | |||||||||||||||||||||
}, | ||||||||||||||||||||||
|
||||||||||||||||||||||
"source_server_id": { | ||||||||||||||||||||||
Type: schema.TypeString, | ||||||||||||||||||||||
Type: pluginsdk.TypeString, | ||||||||||||||||||||||
Optional: true, | ||||||||||||||||||||||
ForceNew: true, | ||||||||||||||||||||||
ValidateFunc: mongoclusters.ValidateMongoClusterID, | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
|
||||||||||||||||||||||
"administrator_password": { | ||||||||||||||||||||||
Type: schema.TypeString, | ||||||||||||||||||||||
Type: pluginsdk.TypeString, | ||||||||||||||||||||||
Optional: true, | ||||||||||||||||||||||
Sensitive: true, | ||||||||||||||||||||||
ValidateFunc: validation.StringIsNotEmpty, | ||||||||||||||||||||||
RequiredWith: []string{"administrator_username"}, | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
|
||||||||||||||||||||||
"compute_tier": { | ||||||||||||||||||||||
Type: schema.TypeString, | ||||||||||||||||||||||
Type: pluginsdk.TypeString, | ||||||||||||||||||||||
Optional: true, | ||||||||||||||||||||||
ValidateFunc: validation.StringInSlice([]string{ | ||||||||||||||||||||||
"Free", | ||||||||||||||||||||||
|
@@ -150,7 +157,7 @@ func (r MongoClusterResource) Arguments() map[string]*schema.Schema { | |||||||||||||||||||||
}, | ||||||||||||||||||||||
|
||||||||||||||||||||||
"high_availability_mode": { | ||||||||||||||||||||||
Type: schema.TypeString, | ||||||||||||||||||||||
Type: pluginsdk.TypeString, | ||||||||||||||||||||||
Optional: true, | ||||||||||||||||||||||
ValidateFunc: validation.StringInSlice([]string{ | ||||||||||||||||||||||
// Confirmed with service team the `SameZone` is currently not supported. | ||||||||||||||||||||||
|
@@ -160,22 +167,22 @@ func (r MongoClusterResource) Arguments() map[string]*schema.Schema { | |||||||||||||||||||||
}, | ||||||||||||||||||||||
|
||||||||||||||||||||||
"public_network_access": { | ||||||||||||||||||||||
Type: schema.TypeString, | ||||||||||||||||||||||
Type: pluginsdk.TypeString, | ||||||||||||||||||||||
Optional: true, | ||||||||||||||||||||||
Default: string(mongoclusters.PublicNetworkAccessEnabled), | ||||||||||||||||||||||
ValidateFunc: validation.StringInSlice(mongoclusters.PossibleValuesForPublicNetworkAccess(), false), | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
|
||||||||||||||||||||||
"storage_size_in_gb": { | ||||||||||||||||||||||
Type: schema.TypeInt, | ||||||||||||||||||||||
Type: pluginsdk.TypeInt, | ||||||||||||||||||||||
Optional: true, | ||||||||||||||||||||||
ValidateFunc: validation.IntBetween(32, 16384), | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
|
||||||||||||||||||||||
"tags": commonschema.Tags(), | ||||||||||||||||||||||
|
||||||||||||||||||||||
"version": { | ||||||||||||||||||||||
Type: schema.TypeString, | ||||||||||||||||||||||
Type: pluginsdk.TypeString, | ||||||||||||||||||||||
Optional: true, | ||||||||||||||||||||||
ValidateFunc: validation.StringInSlice([]string{ | ||||||||||||||||||||||
"5.0", | ||||||||||||||||||||||
|
@@ -186,8 +193,30 @@ func (r MongoClusterResource) Arguments() map[string]*schema.Schema { | |||||||||||||||||||||
} | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
func (r MongoClusterResource) Attributes() map[string]*schema.Schema { | ||||||||||||||||||||||
return map[string]*schema.Schema{} | ||||||||||||||||||||||
func (r MongoClusterResource) Attributes() map[string]*pluginsdk.Schema { | ||||||||||||||||||||||
return map[string]*pluginsdk.Schema{ | ||||||||||||||||||||||
"connection_strings": { | ||||||||||||||||||||||
Type: pluginsdk.TypeList, | ||||||||||||||||||||||
Sensitive: true, | ||||||||||||||||||||||
Computed: true, | ||||||||||||||||||||||
Elem: &pluginsdk.Resource{ | ||||||||||||||||||||||
Schema: map[string]*pluginsdk.Schema{ | ||||||||||||||||||||||
"name": { | ||||||||||||||||||||||
Type: pluginsdk.TypeString, | ||||||||||||||||||||||
Computed: true, | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
"description": { | ||||||||||||||||||||||
Type: pluginsdk.TypeString, | ||||||||||||||||||||||
Computed: true, | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
"connection_string": { | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To avoid confusion around There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||||||
Type: pluginsdk.TypeString, | ||||||||||||||||||||||
Computed: true, | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
} | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
func (r MongoClusterResource) Create() sdk.ResourceFunc { | ||||||||||||||||||||||
|
@@ -452,6 +481,14 @@ func (r MongoClusterResource) Read() sdk.ResourceFunc { | |||||||||||||||||||||
state.Tags = pointer.From(model.Tags) | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
csResp, err := client.ListConnectionStrings(ctx, *id) | ||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||
return fmt.Errorf("listing connection string for %s: %+v", *id, err) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||||||
} | ||||||||||||||||||||||
if model := csResp.Model; model != nil { | ||||||||||||||||||||||
state.ConnectionStrings = flattenMongoClusterConnectionString(model.ConnectionStrings, state.AdministratorUserName, state.AdministratorPassword) | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
return metadata.Encode(&state) | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
@@ -570,3 +607,41 @@ func flattenMongoClusterPreviewFeatures(input *[]mongoclusters.PreviewFeature) [ | |||||||||||||||||||||
|
||||||||||||||||||||||
return results | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
func flattenMongoClusterConnectionString(input *[]mongoclusters.ConnectionString, userName, userPassword string) []MongoClusterConnectionString { | ||||||||||||||||||||||
if input == nil { | ||||||||||||||||||||||
return nil | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
results := make([]MongoClusterConnectionString, 0) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||||||
for _, cs := range *input { | ||||||||||||||||||||||
var name string | ||||||||||||||||||||||
if cs.Name != nil { | ||||||||||||||||||||||
name = *cs.Name | ||||||||||||||||||||||
} | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||||||
|
||||||||||||||||||||||
var description string | ||||||||||||||||||||||
if cs.Description != nil { | ||||||||||||||||||||||
description = *cs.Description | ||||||||||||||||||||||
} | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||||||
|
||||||||||||||||||||||
var connectionString string | ||||||||||||||||||||||
if cs.ConnectionString != nil { | ||||||||||||||||||||||
connectionString = *cs.ConnectionString | ||||||||||||||||||||||
} | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||||||
|
||||||||||||||||||||||
// Password can be empty if it isn't available in the state file (e.g. during import). | ||||||||||||||||||||||
// In this case, we simply leave the placeholder unchanged. | ||||||||||||||||||||||
if userPassword != "" { | ||||||||||||||||||||||
connectionString = regexp.MustCompile(`<user>:<password>`).ReplaceAllString(connectionString, url.UserPassword(userName, userPassword).String()) | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
results = append(results, MongoClusterConnectionString{ | ||||||||||||||||||||||
Name: name, | ||||||||||||||||||||||
Description: description, | ||||||||||||||||||||||
ConnectionString: connectionString, | ||||||||||||||||||||||
}) | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
return results | ||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,9 +36,12 @@ func testAccMongoCluster_basic(t *testing.T) { | |
Config: r.basic(data), | ||
Check: acceptance.ComposeTestCheckFunc( | ||
check.That(data.ResourceName).ExistsInAzure(r), | ||
check.That(data.ResourceName).Key("connection_strings.0.connection_string").HasValue( | ||
fmt.Sprintf(`mongodb+srv://adminTerraform:QAZwsx123basic@acctest-mc%d.mongocluster.cosmos.azure.com/?tls=true&authMechanism=SCRAM-SHA-256&retrywrites=false&maxIdleTimeMS=120000`, | ||
data.RandomInteger)), | ||
), | ||
}, | ||
data.ImportStep("administrator_password", "create_mode"), | ||
data.ImportStep("administrator_password", "create_mode", "connection_strings.0.connection_string"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We'll need to add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
}) | ||
} | ||
|
||
|
@@ -134,19 +137,12 @@ func (r MongoClusterResource) basic(data acceptance.TestData) string { | |
return fmt.Sprintf(` | ||
%s | ||
|
||
resource "random_password" "test" { | ||
length = 8 | ||
numeric = true | ||
upper = true | ||
lower = true | ||
} | ||
|
||
resource "azurerm_mongo_cluster" "test" { | ||
name = "acctest-mc%d" | ||
resource_group_name = azurerm_resource_group.test.name | ||
location = azurerm_resource_group.test.location | ||
administrator_username = "adminTerraform" | ||
administrator_password = random_password.test.result | ||
administrator_password = "QAZwsx123basic" | ||
shard_count = "1" | ||
compute_tier = "Free" | ||
high_availability_mode = "Disabled" | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -111,6 +111,18 @@ In addition to the Arguments listed above - the following Attributes are exporte | |||||
|
||||||
* `id` - The ID of the MongoDB Cluster. | ||||||
|
||||||
* `connection_strings` - The list of `connection_strings` blocks as defined below. | ||||||
|
||||||
--- | ||||||
|
||||||
A `connection_strings` exports the following: | ||||||
|
||||||
* `name` - The name of the connection string. | ||||||
|
||||||
* `description` - The description of the connection string. | ||||||
|
||||||
* `connection_string` - The Mongo Cluster connection string. The `<user>:<password>` place holder returned from API will be replaced by the real `administrator_username` and `administrator_password` if available in the state. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||
|
||||||
## Timeouts | ||||||
|
||||||
The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should change this to
connection_string
because otherwise it'll look like the following in state asA plural
connection_strings
signifies multiple connection strings in a single block rather than one connection string per block.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mbfrahry This one is a read only attribute, I assume we shall keep it plural as the user can only reference them like:
azurerm_mongo_cluster.example.connection_strings.x
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhh good call! That makes sense to me! Thank you for walking me through that