Skip to content

Commit

Permalink
Destroying alerts (#437)
Browse files Browse the repository at this point in the history
* Passing a non-nil slice pointer.
Note: will not work without corresponding merge to rediscloud-go-api

* Updating rediscloud-go-api to include relevant fixes

* Properly testing both alert update and deletion for global and regional
  • Loading branch information
JohnSharpe authored Oct 27, 2023
1 parent 63ed721 commit 145337a
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 15 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/RedisLabs/terraform-provider-rediscloud
go 1.19

require (
github.com/RedisLabs/rediscloud-go-api v0.5.3
github.com/RedisLabs/rediscloud-go-api v0.5.4
github.com/bflad/tfproviderlint v0.29.0
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/terraform-plugin-sdk/v2 v2.26.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/RedisLabs/rediscloud-go-api v0.5.3 h1:m2yKijrLfrNLmXBW8K7y2bfxbFXfsvnB0zVtx7JUaCo=
github.com/RedisLabs/rediscloud-go-api v0.5.3/go.mod h1:cfuU+p/rgB+TObm0cq+AkyxwXWra8JOrPLKKj+nv7lM=
github.com/RedisLabs/rediscloud-go-api v0.5.4 h1:whc+IDu74b1AcLC3/TmPmmfmrf8xIu2ufWmqVZ3qC7M=
github.com/RedisLabs/rediscloud-go-api v0.5.4/go.mod h1:cfuU+p/rgB+TObm0cq+AkyxwXWra8JOrPLKKj+nv7lM=
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,10 @@ func resourceRedisCloudActiveActiveSubscriptionDatabaseUpdate(ctx context.Contex
subscriptionMutex.Lock(subId)
defer subscriptionMutex.Unlock(subId)

var globalAlerts []*databases.UpdateAlert
// Forcibly initialise, so we have a non-nil, zero-length slice
// A pointer to a nil-slice is interpreted as empty and omitted from the json payload
//goland:noinspection GoPreferNilSlice
globalAlerts := []*databases.UpdateAlert{}
for _, alert := range d.Get("global_alert").(*schema.Set).List() {
dbAlert := alert.(map[string]interface{})

Expand Down Expand Up @@ -573,9 +576,9 @@ func resourceRedisCloudActiveActiveSubscriptionDatabaseUpdate(ctx context.Contex
}

if len(overrideAlerts) > 0 {
regionProps.Alerts = overrideAlerts
regionProps.Alerts = &overrideAlerts
} else if len(globalAlerts) > 0 {
regionProps.Alerts = globalAlerts
regionProps.Alerts = &globalAlerts
}
if len(overrideSourceIps) > 0 {
regionProps.SourceIP = overrideSourceIps
Expand Down Expand Up @@ -609,7 +612,7 @@ func resourceRedisCloudActiveActiveSubscriptionDatabaseUpdate(ctx context.Contex
SupportOSSClusterAPI: redis.Bool(d.Get("support_oss_cluster_api").(bool)),
UseExternalEndpointForOSSClusterAPI: redis.Bool(d.Get("external_endpoint_for_oss_cluster_api").(bool)),
DataEvictionPolicy: redis.String(d.Get("data_eviction").(string)),
GlobalAlerts: globalAlerts,
GlobalAlerts: &globalAlerts,
GlobalSourceIP: globalSourceIps,
Regions: regions,
}
Expand Down Expand Up @@ -692,7 +695,9 @@ func getStateAlertsFromDbRegion(dbRegion map[string]interface{}) []*databases.Up
} else if dbRegion["override_global_alert"] == nil {
return nil
}
var overrideAlerts []*databases.UpdateAlert
// Initialise to non-nil, zero-length slice.
//goland:noinspection GoPreferNilSlice
overrideAlerts := []*databases.UpdateAlert{}
for _, alert := range dbRegion["override_global_alert"].(*schema.Set).List() {
dbAlert := alert.(map[string]interface{})
overrideAlerts = append(overrideAlerts, &databases.UpdateAlert{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func TestAccResourceRedisCloudActiveActiveSubscriptionDatabase_CRUDI(t *testing.
},
),
},
// Test database is updated successfully
// Test database is updated successfully, including updates to both global and local alerts
{
Config: fmt.Sprintf(testAccResourceRedisCloudActiveActiveSubscriptionDatabaseUpdate, subscriptionName, name),
Check: resource.ComposeTestCheckFunc(
Expand All @@ -106,6 +106,9 @@ func TestAccResourceRedisCloudActiveActiveSubscriptionDatabase_CRUDI(t *testing.
resource.TestCheckResourceAttr(resourceName, "external_endpoint_for_oss_cluster_api", "true"),
resource.TestCheckResourceAttr(resourceName, "global_data_persistence", "aof-every-1-second"),
resource.TestCheckResourceAttr(resourceName, "global_password", "updated-password"),
resource.TestCheckResourceAttr(resourceName, "global_alert.#", "1"),
resource.TestCheckResourceAttr(resourceName, "global_alert.0.name", "dataset-size"),
resource.TestCheckResourceAttr(resourceName, "global_alert.0.value", "60"),

resource.TestCheckResourceAttr(resourceName, "override_region.#", "1"),
resource.TestCheckResourceAttr(resourceName, "override_region.0.name", "us-east-1"),
Expand All @@ -117,6 +120,25 @@ func TestAccResourceRedisCloudActiveActiveSubscriptionDatabase_CRUDI(t *testing.
resource.TestCheckResourceAttr(resourceName, "override_region.0.override_global_source_ips.#", "0"),
),
},
// Test database is updated, including deletion of global and local alerts
{
Config: fmt.Sprintf(testAccResourceRedisCloudActiveActiveSubscriptionDatabaseUpdateNoAlerts, subscriptionName, name),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "memory_limit_in_gb", "1"),
resource.TestCheckResourceAttr(resourceName, "support_oss_cluster_api", "true"),
resource.TestCheckResourceAttr(resourceName, "external_endpoint_for_oss_cluster_api", "true"),
resource.TestCheckResourceAttr(resourceName, "global_data_persistence", "aof-every-1-second"),
resource.TestCheckResourceAttr(resourceName, "global_password", "updated-password"),
resource.TestCheckResourceAttr(resourceName, "global_alert.#", "0"),

resource.TestCheckResourceAttr(resourceName, "override_region.#", "1"),
resource.TestCheckResourceAttr(resourceName, "override_region.0.name", "us-east-1"),
resource.TestCheckResourceAttr(resourceName, "override_region.0.override_global_data_persistence", "none"),
resource.TestCheckResourceAttr(resourceName, "override_region.0.override_global_password", "password-updated"),
resource.TestCheckResourceAttr(resourceName, "override_region.0.override_global_alert.#", "0"),
resource.TestCheckResourceAttr(resourceName, "override_region.0.override_global_source_ips.#", "0"),
),
},
// Test that that database is imported successfully
{
Config: fmt.Sprintf(testAccResourceRedisCloudActiveActiveSubscriptionDatabaseImport, subscriptionName, name),
Expand Down Expand Up @@ -261,6 +283,10 @@ resource "rediscloud_active_active_subscription_database" "example" {
global_data_persistence = "aof-every-1-second"
global_password = "updated-password"
global_source_ips = ["192.170.0.0/16"]
global_alert {
name = "dataset-size"
value = 60
}
override_region {
name = "us-east-1"
Expand All @@ -271,17 +297,37 @@ resource "rediscloud_active_active_subscription_database" "example" {
value = 41
}
}
}
`
}
`

const testAccResourceRedisCloudActiveActiveSubscriptionDatabaseUpdateNoAlerts = activeActiveSubscriptionBoilerplate + `
resource "rediscloud_active_active_subscription_database" "example" {
subscription_id = rediscloud_active_active_subscription.example.id
name = "%s"
memory_limit_in_gb = 1
support_oss_cluster_api = true
external_endpoint_for_oss_cluster_api = true
global_data_persistence = "aof-every-1-second"
global_password = "updated-password"
global_source_ips = ["192.170.0.0/16"]
override_region {
name = "us-east-1"
override_global_data_persistence = "none"
override_global_password = "password-updated"
}
}
`

// TF config for updating a database
const testAccResourceRedisCloudActiveActiveSubscriptionDatabaseImport = activeActiveSubscriptionBoilerplate + `
resource "rediscloud_active_active_subscription_database" "example" {
subscription_id = rediscloud_active_active_subscription.example.id
name = "%s"
memory_limit_in_gb = 1
}
`
}
`

const testAccResourceRedisCloudActiveActiveSubscriptionDatabaseOptionalAttributes = activeActiveSubscriptionBoilerplate + `
resource "rediscloud_active_active_subscription_database" "example" {
Expand Down
8 changes: 6 additions & 2 deletions provider/resource_rediscloud_subscription_database.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,11 @@ func resourceRedisCloudSubscriptionDatabaseUpdate(ctx context.Context, d *schema
subscriptionMutex.Lock(subId)
defer subscriptionMutex.Unlock(subId)

var alerts []*databases.UpdateAlert
// If the recommended approach is taken and there are 0 alerts, a nil-slice value is sent to the UpdateDatabase
// constructor. We instead want a non-nil (but zero length) slice to be passed forward.
//goland:noinspection GoPreferNilSlice
alerts := []*databases.UpdateAlert{}

for _, alert := range d.Get("alert").(*schema.Set).List() {
dbAlert := alert.(map[string]interface{})

Expand All @@ -561,7 +565,7 @@ func resourceRedisCloudSubscriptionDatabaseUpdate(ctx context.Context, d *schema
DataPersistence: redis.String(d.Get("data_persistence").(string)),
DataEvictionPolicy: redis.String(d.Get("data_eviction").(string)),
SourceIP: setToStringSlice(d.Get("source_ips").(*schema.Set)),
Alerts: alerts,
Alerts: &alerts,
RemoteBackup: buildBackupPlan(d.Get("remote_backup").([]interface{}), d.Get("periodic_backup_path")),
}
if len(setToStringSlice(d.Get("source_ips").(*schema.Set))) == 0 {
Expand Down
38 changes: 38 additions & 0 deletions provider/resource_rediscloud_subscription_database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ func TestAccResourceRedisCloudSubscriptionDatabase_CRUDI(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "periodic_backup_path", ""),
resource.TestCheckResourceAttr(resourceName, "external_endpoint_for_oss_cluster_api", "false"),
resource.TestCheckResourceAttr(resourceName, "password", password),
resource.TestCheckResourceAttr(resourceName, "alert.#", "1"),
resource.TestCheckResourceAttr(resourceName, "alert.0.name", "dataset-size"),
resource.TestCheckResourceAttr(resourceName, "alert.0.value", "40"),
resource.TestCheckResourceAttr(resourceName, "modules.#", "1"),
resource.TestCheckResourceAttr(resourceName, "modules.0.name", "RedisBloom"),
// Replica tests
Expand Down Expand Up @@ -107,10 +110,20 @@ func TestAccResourceRedisCloudSubscriptionDatabase_CRUDI(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "periodic_backup_path", ""),
resource.TestCheckResourceAttr(resourceName, "external_endpoint_for_oss_cluster_api", "true"),
resource.TestCheckResourceAttr(resourceName, "password", "updated-password"),
resource.TestCheckResourceAttr(resourceName, "alert.#", "1"),
resource.TestCheckResourceAttr(resourceName, "alert.0.name", "dataset-size"),
resource.TestCheckResourceAttr(resourceName, "alert.0.value", "80"),
resource.TestCheckResourceAttr(resourceName, "modules.#", "1"),
resource.TestCheckResourceAttr(resourceName, "modules.0.name", "RedisBloom"),
),
},
// Test that Alerts are deleted
{
Config: fmt.Sprintf(testAccResourceRedisCloudSubscriptionDatabaseUpdateDestroyAlerts, testCloudAccountName, name),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "alert.#", "0"),
),
},
// Test that a 32-character password is generated when no password is provided
{
Config: fmt.Sprintf(testAccResourceRedisCloudSubscriptionDatabaseNoPassword, testCloudAccountName, name),
Expand Down Expand Up @@ -365,6 +378,31 @@ resource "rediscloud_subscription_database" "example" {
]
}
`

const testAccResourceRedisCloudSubscriptionDatabaseUpdateDestroyAlerts = subscriptionBoilerplate + `
resource "rediscloud_subscription_database" "example" {
subscription_id = rediscloud_subscription.example.id
name = "example-updated"
protocol = "redis"
memory_limit_in_gb = 1
data_persistence = "aof-every-write"
data_eviction = "volatile-lru"
throughput_measurement_by = "operations-per-second"
throughput_measurement_value = 2000
password = "updated-password"
support_oss_cluster_api = true
external_endpoint_for_oss_cluster_api = true
replication = true
average_item_size_in_bytes = 0
modules = [
{
name = "RedisBloom"
}
]
}
`

const multiModulesSubscriptionBoilerplate = `
data "rediscloud_payment_method" "card" {
card_type = "Visa"
Expand Down

0 comments on commit 145337a

Please sign in to comment.