Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
teowa committed Sep 15, 2023
1 parent 691192d commit 05aa71a
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 39 deletions.
1 change: 1 addition & 0 deletions internal/services/appconfiguration/app_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func resourceConfigurationStoreReplicaHash(input interface{}) int {
var buf bytes.Buffer
if rawData, ok := input.(map[string]interface{}); ok {
buf.WriteString(rawData["name"].(string))
buf.WriteString(rawData["location"].(string))
}
return pluginsdk.HashString(buf.String())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,8 @@ func dataSourceAppConfiguration() *pluginsdk.Resource {
},

"replica": {
Type: pluginsdk.TypeSet,
Type: pluginsdk.TypeList,
Computed: true,
Set: resourceConfigurationStoreReplicaHash,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"name": {
Expand Down
57 changes: 25 additions & 32 deletions internal/services/appconfiguration/app_configuration_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"github.com/hashicorp/go-azure-sdk/resource-manager/appconfiguration/2023-03-01/replicas"
"github.com/hashicorp/go-azure-sdk/sdk/client"
"github.com/hashicorp/go-azure-sdk/sdk/client/pollers"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/appconfiguration/validate"
Expand Down Expand Up @@ -145,13 +144,7 @@ func resourceAppConfiguration() *pluginsdk.Resource {
Required: true,
ValidateFunc: validate.ConfigurationStoreReplicaName,
},
"location": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: location.EnhancedValidate,
StateFunc: location.StateFunc,
DiffSuppressFunc: location.DiffSuppressFunc,
},
"location": commonschema.LocationWithoutForceNew(),
"endpoint": {
Type: pluginsdk.TypeString,
Computed: true,
Expand Down Expand Up @@ -357,21 +350,14 @@ func resourceAppConfigurationCreate(d *pluginsdk.ResourceData, meta interface{})
}
meta.(*clients.Client).AppConfiguration.AddToCache(resourceId, *resp.Model.Properties.Endpoint)

expandedReplicas, err := expandAppConfigurationReplicas(d.Get("replica").(*schema.Set).List(), name, location)
expandedReplicas, err := expandAppConfigurationReplicas(d.Get("replica").(*pluginsdk.Set).List(), name, location)
if err != nil {
return fmt.Errorf("expanding `replica`: %+v", err)
}

replicaClient := meta.(*clients.Client).AppConfiguration.ReplicasClient
for _, replica := range expandedReplicas {
replicaId := replicas.NewReplicaID(subscriptionId, resourceGroup, name, *replica.Name)

existingReplica, err := replicaClient.Get(ctx, replicaId)
if err != nil {
if !response.WasNotFound(existingReplica.HttpResponse) {
return fmt.Errorf("retrieving %s: %+v", replicaId, err)
}
}
for _, replica := range *expandedReplicas {
replicaId := replicas.NewReplicaID(resourceId.SubscriptionId, resourceId.ResourceGroupName, resourceId.ConfigurationStoreName, *replica.Name)

if err := replicaClient.CreateThenPoll(ctx, replicaId, replica); err != nil {
return fmt.Errorf("creating %s: %+v", replicaId, err)
Expand Down Expand Up @@ -502,7 +488,8 @@ func resourceAppConfigurationUpdate(d *pluginsdk.ResourceData, meta interface{})
for _, newReplica := range newReplicas.(*pluginsdk.Set).List() {
newReplicaMap := newReplica.(map[string]interface{})

if strings.EqualFold(oldReplicaMap["name"].(string), newReplicaMap["name"].(string)) && strings.EqualFold(oldReplicaMap["location"].(string), newReplicaMap["location"].(string)) {
if strings.EqualFold(oldReplicaMap["name"].(string), newReplicaMap["name"].(string)) &&
strings.EqualFold(location.Normalize(oldReplicaMap["location"].(string)), location.Normalize(newReplicaMap["location"].(string))) {
isRemoved = false
break
}
Expand All @@ -517,13 +504,13 @@ func resourceAppConfigurationUpdate(d *pluginsdk.ResourceData, meta interface{})
return err
}

expandedReplicas, err := expandAppConfigurationReplicas(d.Get("replica").(*schema.Set).List(), id.ConfigurationStoreName, location.Normalize(existing.Model.Location))
expandedReplicas, err := expandAppConfigurationReplicas(d.Get("replica").(*pluginsdk.Set).List(), id.ConfigurationStoreName, location.Normalize(existing.Model.Location))
if err != nil {
return fmt.Errorf("expanding `replica`: %+v", err)
}

// check if a replica has been added or an existing one changed its location, (re)create it
for _, replica := range expandedReplicas {
for _, replica := range *expandedReplicas {
replicaId := replicas.NewReplicaID(id.SubscriptionId, id.ResourceGroupName, id.ConfigurationStoreName, *replica.Name)

existingReplica, err := replicaClient.Get(ctx, replicaId)
Expand All @@ -534,7 +521,7 @@ func resourceAppConfigurationUpdate(d *pluginsdk.ResourceData, meta interface{})
}

if !response.WasNotFound(existingReplica.HttpResponse) {
continue
return fmt.Errorf("updating %s: replica %s already exists", *id, replicaId)
}

if err = replicaClient.CreateThenPoll(ctx, replicaId, replica); err != nil {
Expand Down Expand Up @@ -786,30 +773,36 @@ func expandAppConfigurationEncryption(input []interface{}) *configurationstores.
return result
}

func expandAppConfigurationReplicas(input []interface{}, configurationStoreName, configurationStoreLocation string) ([]replicas.Replica, error) {
func expandAppConfigurationReplicas(input []interface{}, configurationStoreName, configurationStoreLocation string) (*[]replicas.Replica, error) {
result := make([]replicas.Replica, 0)

locationSet := map[string]interface{}{
configurationStoreLocation: nil,
// check if there are duplicated replica names or locations
// location cannot be same as original configuration store and other replicas
const placeholder = ""
locationSet := map[string]string{
configurationStoreLocation: placeholder,
}
replicaNameSet := map[string]interface{}{}
replicaNameSet := map[string]struct{}{}

for _, v := range input {
replica := v.(map[string]interface{})
replicaName := replica["name"].(string)
replicaLocation := location.Normalize(replica["location"].(string))

if _, ok := locationSet[replicaLocation]; ok {
return result, fmt.Errorf("replica location %q is duplicated in configuration store %q location", replicaLocation, configurationStoreName)
if name, ok := locationSet[replicaLocation]; ok {
if name == placeholder {
return nil, fmt.Errorf("replica %q location %q is duplicated with original configuration store %q", replicaName, replicaLocation, configurationStoreName)
}
return nil, fmt.Errorf("replica %q location %q is duplicated with replica %q", replicaName, replicaLocation, name)
}
locationSet[replicaLocation] = nil
locationSet[replicaLocation] = replicaName

if _, ok := replicaNameSet[replicaName]; ok {
return result, fmt.Errorf("replica name %q is duplicated", replicaName)
return nil, fmt.Errorf("replica name %q is duplicated", replicaName)
}

if len(replicaName)+len(configurationStoreName) > 60 {
return result, fmt.Errorf("replica name %q is too long, the total length of replica name and configuration store name should be greater than 60", replicaName)
return nil, fmt.Errorf("replica name %q is too long, the total length of replica name and configuration store name should be greater than 60", replicaName)
}

result = append(result, replicas.Replica{
Expand All @@ -818,7 +811,7 @@ func expandAppConfigurationReplicas(input []interface{}, configurationStoreName,
})
}

return result, nil
return &result, nil
}

func flattenAppConfigurationAccessKeys(values []configurationstores.ApiKey) flattenedAccessKeys {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,13 @@ func TestAccAppConfiguration_replicaUpdate(t *testing.T) {
),
},
data.ImportStep(),
{
Config: r.replicaUpdatedSwitch(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.complete(data),
Check: acceptance.ComposeTestCheckFunc(
Expand Down Expand Up @@ -547,6 +554,36 @@ resource "azurerm_app_configuration" "test" {
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.Locations.Ternary, data.Locations.Secondary)
}

func (AppConfigurationResource) replicaUpdatedSwitch(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-appconfig-%d"
location = "%s"
}
resource "azurerm_app_configuration" "test" {
name = "testaccappconf%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
sku = "standard"
replica {
name = "replica1"
location = "%s"
}
replica {
name = "replica2"
location = "%s"
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.Locations.Ternary, data.Locations.Secondary)
}

func (r AppConfigurationResource) requiresImport(data acceptance.TestData) string {
template := r.standard(data)
return fmt.Sprintf(`
Expand Down
2 changes: 1 addition & 1 deletion website/docs/d/app_configuration.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ A `replica` block exports the following:

* `location` - The supported Azure location where the replica exists.

* `name` - (Optional) The name of the replica.
* `name` - The name of the replica.


---
Expand Down
8 changes: 4 additions & 4 deletions website/docs/r/app_configuration.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,9 @@ An `identity` block supports the following:

A `replica` block supports the following:

* `location` - (Required) Specifies the supported Azure location where the replica exists.
* `location` - (Required) Specifies the supported Azure location where the replica exists. Changing this forces a new replica to be created.

* `name` - (Optional) Specifies the name of the replica. Changing this forces a new replica to be created.
* `name` - (Required) Specifies the name of the replica. Changing this forces a new replica to be created.

---

Expand Down Expand Up @@ -237,9 +237,9 @@ An `identity` block exports the following:

A `replica` block exports the following:

* `id` - The replica ID.
* `id` - The ID of the App Configuration Replica.

* `endpoint` - The URL of the replica.
* `endpoint` - The URL of the App Configuration Replica.

---

Expand Down

0 comments on commit 05aa71a

Please sign in to comment.