-
Notifications
You must be signed in to change notification settings - Fork 277
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support Redis database advanced configuration. (#1037)
- Loading branch information
1 parent
2e99b4a
commit 8042b83
Showing
5 changed files
with
374 additions
and
1 deletion.
There are no files selected for viewing
248 changes: 248 additions & 0 deletions
248
digitalocean/database/resource_database_redis_config.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
package database | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log" | ||
|
||
"github.com/digitalocean/godo" | ||
"github.com/digitalocean/terraform-provider-digitalocean/digitalocean/config" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" | ||
) | ||
|
||
func ResourceDigitalOceanDatabaseRedisConfig() *schema.Resource { | ||
return &schema.Resource{ | ||
CreateContext: resourceDigitalOceanDatabaseRedisConfigCreate, | ||
ReadContext: resourceDigitalOceanDatabaseRedisConfigRead, | ||
UpdateContext: resourceDigitalOceanDatabaseRedisConfigUpdate, | ||
DeleteContext: resourceDigitalOceanDatabaseRedisConfigDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: resourceDigitalOceanDatabaseRedisConfigImport, | ||
}, | ||
Schema: map[string]*schema.Schema{ | ||
"cluster_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validation.NoZeroValues, | ||
}, | ||
|
||
"maxmemory_policy": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
|
||
"pubsub_client_output_buffer_limit": { | ||
Type: schema.TypeInt, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
|
||
"number_of_databases": { | ||
Type: schema.TypeInt, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
|
||
"io_threads": { | ||
Type: schema.TypeInt, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
|
||
"lfu_log_factor": { | ||
Type: schema.TypeInt, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
|
||
"lfu_decay_time": { | ||
Type: schema.TypeInt, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
|
||
"ssl": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
|
||
"timeout": { | ||
Type: schema.TypeInt, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
|
||
"notify_keyspace_events": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
|
||
"persistence": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
ValidateFunc: validation.StringInSlice( | ||
[]string{ | ||
"off", | ||
"rdb", | ||
}, | ||
true, | ||
), | ||
}, | ||
|
||
"acl_channels_default": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
ValidateFunc: validation.StringInSlice( | ||
[]string{ | ||
"allchannels", | ||
"resetchannels", | ||
}, | ||
true, | ||
), | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceDigitalOceanDatabaseRedisConfigCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
client := meta.(*config.CombinedConfig).GodoClient() | ||
clusterID := d.Get("cluster_id").(string) | ||
|
||
err := updateRedisConfig(ctx, d, client) | ||
if err != nil { | ||
return diag.Errorf("Error updating Redis configuration: %s", err) | ||
} | ||
|
||
d.SetId(makeDatabaseRedisConfigID(clusterID)) | ||
|
||
return resourceDigitalOceanDatabaseRedisConfigRead(ctx, d, meta) | ||
} | ||
|
||
func resourceDigitalOceanDatabaseRedisConfigUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
client := meta.(*config.CombinedConfig).GodoClient() | ||
err := updateRedisConfig(ctx, d, client) | ||
if err != nil { | ||
return diag.Errorf("Error updating Redis configuration: %s", err) | ||
} | ||
|
||
return resourceDigitalOceanDatabaseRedisConfigRead(ctx, d, meta) | ||
} | ||
|
||
func updateRedisConfig(ctx context.Context, d *schema.ResourceData, client *godo.Client) error { | ||
clusterID := d.Get("cluster_id").(string) | ||
|
||
opts := &godo.RedisConfig{} | ||
|
||
if v, ok := d.GetOk("maxmemory_policy"); ok { | ||
opts.RedisMaxmemoryPolicy = godo.PtrTo(v.(string)) | ||
} | ||
|
||
if v, ok := d.GetOk("pubsub_client_output_buffer_limit"); ok { | ||
opts.RedisPubsubClientOutputBufferLimit = godo.PtrTo(v.(int)) | ||
} | ||
|
||
if v, ok := d.GetOk("number_of_databases"); ok { | ||
opts.RedisNumberOfDatabases = godo.PtrTo(v.(int)) | ||
} | ||
|
||
if v, ok := d.GetOk("io_threads"); ok { | ||
opts.RedisIOThreads = godo.PtrTo(v.(int)) | ||
} | ||
|
||
if v, ok := d.GetOk("lfu_log_factor"); ok { | ||
opts.RedisLFULogFactor = godo.PtrTo(v.(int)) | ||
} | ||
|
||
if v, ok := d.GetOk("lfu_decay_time"); ok { | ||
opts.RedisLFUDecayTime = godo.PtrTo(v.(int)) | ||
} | ||
|
||
if v, ok := d.GetOkExists("ssl"); ok { | ||
opts.RedisSSL = godo.PtrTo(v.(bool)) | ||
} | ||
|
||
if v, ok := d.GetOk("timeout"); ok { | ||
opts.RedisTimeout = godo.PtrTo(v.(int)) | ||
} | ||
|
||
if v, ok := d.GetOk("notify_keyspace_events"); ok { | ||
opts.RedisNotifyKeyspaceEvents = godo.PtrTo(v.(string)) | ||
} | ||
|
||
if v, ok := d.GetOk("persistence"); ok { | ||
opts.RedisPersistence = godo.PtrTo(v.(string)) | ||
} | ||
|
||
if v, ok := d.GetOk("acl_channels_default"); ok { | ||
opts.RedisACLChannelsDefault = godo.PtrTo(v.(string)) | ||
} | ||
|
||
log.Printf("[DEBUG] Redis configuration: %s", godo.Stringify(opts)) | ||
_, err := client.Databases.UpdateRedisConfig(ctx, clusterID, opts) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceDigitalOceanDatabaseRedisConfigRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
client := meta.(*config.CombinedConfig).GodoClient() | ||
clusterID := d.Get("cluster_id").(string) | ||
|
||
config, resp, err := client.Databases.GetRedisConfig(ctx, clusterID) | ||
if err != nil { | ||
if resp != nil && resp.StatusCode == 404 { | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
return diag.Errorf("Error retrieving Redis configuration: %s", err) | ||
} | ||
|
||
d.Set("maxmemory_policy", config.RedisMaxmemoryPolicy) | ||
d.Set("pubsub_client_output_buffer_limit", config.RedisPubsubClientOutputBufferLimit) | ||
d.Set("number_of_databases", config.RedisNumberOfDatabases) | ||
d.Set("io_threads", config.RedisIOThreads) | ||
d.Set("lfu_log_factor", config.RedisLFULogFactor) | ||
d.Set("lfu_decay_time", config.RedisLFUDecayTime) | ||
d.Set("ssl", config.RedisSSL) | ||
d.Set("timeout", config.RedisTimeout) | ||
d.Set("notify_keyspace_events", config.RedisNotifyKeyspaceEvents) | ||
d.Set("persistence", config.RedisPersistence) | ||
d.Set("acl_channels_default", config.RedisACLChannelsDefault) | ||
|
||
return nil | ||
} | ||
|
||
func resourceDigitalOceanDatabaseRedisConfigDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
d.SetId("") | ||
warn := []diag.Diagnostic{ | ||
{ | ||
Severity: diag.Warning, | ||
Summary: "digitalocean_database_redis_config removed from state", | ||
Detail: "Database configurations are only removed from state when destroyed. The remote configuration is not unset.", | ||
}, | ||
} | ||
return warn | ||
} | ||
|
||
func resourceDigitalOceanDatabaseRedisConfigImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { | ||
clusterID := d.Id() | ||
d.SetId(makeDatabaseRedisConfigID(clusterID)) | ||
d.Set("cluster_id", clusterID) | ||
|
||
return []*schema.ResourceData{d}, nil | ||
} | ||
|
||
func makeDatabaseRedisConfigID(clusterID string) string { | ||
return fmt.Sprintf("%s/redis-config", clusterID) | ||
} |
62 changes: 62 additions & 0 deletions
62
digitalocean/database/resource_database_redis_config_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package database_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/digitalocean/terraform-provider-digitalocean/digitalocean/acceptance" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
) | ||
|
||
func TestAccDigitalOceanDatabaseRedisConfig_Basic(t *testing.T) { | ||
name := acceptance.RandomTestName() | ||
dbConfig := fmt.Sprintf(testAccCheckDigitalOceanDatabaseClusterRedis, name, "7") | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { acceptance.TestAccPreCheck(t) }, | ||
ProviderFactories: acceptance.TestAccProviderFactories, | ||
CheckDestroy: testAccCheckDigitalOceanDatabaseClusterDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: fmt.Sprintf(testAccCheckDigitalOceanDatabaseRedisConfigConfigBasic, dbConfig, "noeviction", 3600, "KA"), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttr( | ||
"digitalocean_database_redis_config.foobar", "maxmemory_policy", "noeviction"), | ||
resource.TestCheckResourceAttr( | ||
"digitalocean_database_redis_config.foobar", "timeout", "3600"), | ||
resource.TestCheckResourceAttr( | ||
"digitalocean_database_redis_config.foobar", "notify_keyspace_events", "KA"), | ||
resource.TestCheckResourceAttr( | ||
"digitalocean_database_redis_config.foobar", "ssl", "true"), | ||
resource.TestCheckResourceAttr( | ||
"digitalocean_database_redis_config.foobar", "persistence", "rdb"), | ||
), | ||
}, | ||
{ | ||
Config: fmt.Sprintf(testAccCheckDigitalOceanDatabaseRedisConfigConfigBasic, dbConfig, "allkeys-lru", 600, "KEA"), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttr( | ||
"digitalocean_database_redis_config.foobar", "maxmemory_policy", "allkeys-lru"), | ||
resource.TestCheckResourceAttr( | ||
"digitalocean_database_redis_config.foobar", "timeout", "600"), | ||
resource.TestCheckResourceAttr( | ||
"digitalocean_database_redis_config.foobar", "notify_keyspace_events", "KEA"), | ||
resource.TestCheckResourceAttr( | ||
"digitalocean_database_redis_config.foobar", "ssl", "true"), | ||
resource.TestCheckResourceAttr( | ||
"digitalocean_database_redis_config.foobar", "persistence", "rdb"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
const testAccCheckDigitalOceanDatabaseRedisConfigConfigBasic = ` | ||
%s | ||
resource "digitalocean_database_redis_config" "foobar" { | ||
cluster_id = digitalocean_database_cluster.foobar.id | ||
maxmemory_policy = "%s" | ||
timeout = %d | ||
notify_keyspace_events = "%s" | ||
}` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
--- | ||
page_title: "DigitalOcean: digitalocean_database_redis_config" | ||
--- | ||
|
||
# digitalocean\_database\_redis\_config | ||
|
||
Provides a virtual resource that can be used to change advanced configuration | ||
options for a DigitalOcean managed Redis database cluster. | ||
|
||
-> **Note** Redis configurations are only removed from state when destroyed. The remote configuration is not unset. | ||
|
||
## Example Usage | ||
|
||
```hcl | ||
resource "digitalocean_database_redis_config" "example" { | ||
cluster_id = digitalocean_database_cluster.example.id | ||
maxmemory_policy = "allkeys-lru" | ||
notify_keyspace_events = "KEA" | ||
timeout = 90 | ||
} | ||
resource "digitalocean_database_cluster" "example" { | ||
name = "example-redis-cluster" | ||
engine = "redis" | ||
version = "7" | ||
size = "db-s-1vcpu-1gb" | ||
region = "nyc1" | ||
node_count = 1 | ||
} | ||
``` | ||
|
||
|
||
## Argument Reference | ||
|
||
The following arguments are supported. See the [DigitalOcean API documentation](https://docs.digitalocean.com/reference/api/api-reference/#operation/databases_patch_config) | ||
for additional details on each option. | ||
|
||
|
||
* `cluster_id` - (Required) The ID of the target Redis cluster. | ||
* `maxmemory_policy` - (Optional) A string specifying the desired eviction policy for the Redis cluster.Supported values are: `noeviction`, `allkeys-lru`, `allkeys-random`, `volatile-lru`, `volatile-random`, `volatile-ttl` | ||
* `pubsub_client_output_buffer_limit` - (Optional) The output buffer limit for pub/sub clients in MB. The value is the hard limit, the soft limit is 1/4 of the hard limit. When setting the limit, be mindful of the available memory in the selected service plan. | ||
* `number_of_databases` - (Optional) The number of Redis databases. Changing this will cause a restart of Redis service. | ||
* `io_threads` - (Optional) The Redis IO thread count. | ||
* `lfu_log_factor` - (Optional) The counter logarithm factor for volatile-lfu and allkeys-lfu maxmemory policies. | ||
* `lfu_decay_time` - (Optional) The LFU maxmemory policy counter decay time in minutes. | ||
* `ssl` - (Optional) A boolean indicating whether to require SSL to access Redis. | ||
* `timeout` - (Optional) The Redis idle connection timeout in seconds. | ||
* `notify_keyspace_events` - (Optional) The `notify-keyspace-events` option. Requires at least `K` or `E`. | ||
* `persistence` - (Optional) When persistence is `rdb`, Redis does RDB dumps each 10 minutes if any key is changed. Also RDB dumps are done according to backup schedule for backup purposes. When persistence is `off`, no RDB dumps and backups are done, so data can be lost at any moment if service is restarted for any reason, or if service is powered off. Also service can't be forked. | ||
* `acl_channels_default` - (Optional) Determines default pub/sub channels' ACL for new users if an ACL is not supplied. When this option is not defined, `allchannels` is assumed to keep backward compatibility. This option doesn't affect Redis' `acl-pubsub-default` configuration. Supported values are: `allchannels` and `resetchannels` | ||
|
||
## Attributes Reference | ||
|
||
All above attributes are exported. If an attribute was set outside of Terraform, it will be computed. | ||
|
||
## Import | ||
|
||
A Redis database cluster's configuration can be imported using the `id` the parent cluster, e.g. | ||
|
||
``` | ||
terraform import digitalocean_database_redis_config.example 245bcfd0-7f31-4ce6-a2bc-475a116cca97 | ||
``` |