Skip to content
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

Add RDB & AOF Persistence support to Memorystore for Redis Cluster #20212

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/12219.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
redis: added `persistence_config` to `google_redis_cluster`. Fixed https://github.com/hashicorp/terraform-provider-google/issues/17999
```
249 changes: 249 additions & 0 deletions google/services/redis/resource_redis_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,81 @@ resolution and up to nine fractional digits.`,
Description: `The nodeType for the Redis cluster.
If not provided, REDIS_HIGHMEM_MEDIUM will be used as default Possible values: ["REDIS_SHARED_CORE_NANO", "REDIS_HIGHMEM_MEDIUM", "REDIS_HIGHMEM_XLARGE", "REDIS_STANDARD_SMALL"]`,
},
"persistence_config": {
Type: schema.TypeList,
Computed: true,
Optional: true,
Description: `Persistence config (RDB, AOF) for the cluster.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"aof_config": {
Type: schema.TypeList,
Computed: true,
Optional: true,
Description: `AOF configuration. This field will be ignored if mode is not AOF.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"append_fsync": {
Type: schema.TypeString,
Computed: true,
Optional: true,
ValidateFunc: verify.ValidateEnum([]string{"APPEND_FSYNC_UNSPECIFIED", "NO", "EVERYSEC", "ALWAYS", ""}),
Description: `Optional. Available fsync modes.

- NO - Do not explicilty call fsync(). Rely on OS defaults.
- EVERYSEC - Call fsync() once per second in a background thread. A balance between performance and durability.
- ALWAYS - Call fsync() for earch write command. Possible values: ["APPEND_FSYNC_UNSPECIFIED", "NO", "EVERYSEC", "ALWAYS"]`,
},
},
},
},
"mode": {
Type: schema.TypeString,
Computed: true,
Optional: true,
ValidateFunc: verify.ValidateEnum([]string{"PERSISTENCE_MODE_UNSPECIFIED", "DISABLED", "RDB", "AOF", ""}),
Description: `Optional. Controls whether Persistence features are enabled. If not provided, the existing value will be used.

- DISABLED: Persistence (both backup and restore) is disabled for the cluster.
- RDB: RDB based Persistence is enabled.
- AOF: AOF based Persistence is enabled. Possible values: ["PERSISTENCE_MODE_UNSPECIFIED", "DISABLED", "RDB", "AOF"]`,
},
"rdb_config": {
Type: schema.TypeList,
Computed: true,
Optional: true,
Description: `RDB configuration. This field will be ignored if mode is not RDB.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"rdb_snapshot_period": {
Type: schema.TypeString,
Computed: true,
Optional: true,
ValidateFunc: verify.ValidateEnum([]string{"SNAPSHOT_PERIOD_UNSPECIFIED", "ONE_HOUR", "SIX_HOURS", "TWELVE_HOURS", "TWENTY_FOUR_HOURS", ""}),
Description: `Optional. Available snapshot periods for scheduling.

- ONE_HOUR: Snapshot every 1 hour.
- SIX_HOURS: Snapshot every 6 hours.
- TWELVE_HOURS: Snapshot every 12 hours.
- TWENTY_FOUR_HOURS: Snapshot every 24 hours. Possible values: ["SNAPSHOT_PERIOD_UNSPECIFIED", "ONE_HOUR", "SIX_HOURS", "TWELVE_HOURS", "TWENTY_FOUR_HOURS"]`,
},
"rdb_snapshot_start_time": {
Type: schema.TypeString,
Computed: true,
Optional: true,
Description: `The time that the first snapshot was/will be attempted, and to which
future snapshots will be aligned.
If not provided, the current time will be used.`,
},
},
},
},
},
},
},
"redis_configs": {
Type: schema.TypeMap,
Optional: true,
Expand Down Expand Up @@ -493,6 +568,12 @@ func resourceRedisClusterCreate(d *schema.ResourceData, meta interface{}) error
} else if v, ok := d.GetOkExists("redis_configs"); !tpgresource.IsEmptyValue(reflect.ValueOf(redisConfigsProp)) && (ok || !reflect.DeepEqual(v, redisConfigsProp)) {
obj["redisConfigs"] = redisConfigsProp
}
persistenceConfigProp, err := expandRedisClusterPersistenceConfig(d.Get("persistence_config"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("persistence_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(persistenceConfigProp)) && (ok || !reflect.DeepEqual(v, persistenceConfigProp)) {
obj["persistenceConfig"] = persistenceConfigProp
}
maintenancePolicyProp, err := expandRedisClusterMaintenancePolicy(d.Get("maintenance_policy"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -654,6 +735,9 @@ func resourceRedisClusterRead(d *schema.ResourceData, meta interface{}) error {
if err := d.Set("redis_configs", flattenRedisClusterRedisConfigs(res["redisConfigs"], d, config)); err != nil {
return fmt.Errorf("Error reading Cluster: %s", err)
}
if err := d.Set("persistence_config", flattenRedisClusterPersistenceConfig(res["persistenceConfig"], d, config)); err != nil {
return fmt.Errorf("Error reading Cluster: %s", err)
}
if err := d.Set("maintenance_policy", flattenRedisClusterMaintenancePolicy(res["maintenancePolicy"], d, config)); err != nil {
return fmt.Errorf("Error reading Cluster: %s", err)
}
Expand Down Expand Up @@ -710,6 +794,12 @@ func resourceRedisClusterUpdate(d *schema.ResourceData, meta interface{}) error
} else if v, ok := d.GetOkExists("redis_configs"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, redisConfigsProp)) {
obj["redisConfigs"] = redisConfigsProp
}
persistenceConfigProp, err := expandRedisClusterPersistenceConfig(d.Get("persistence_config"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("persistence_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, persistenceConfigProp)) {
obj["persistenceConfig"] = persistenceConfigProp
}
maintenancePolicyProp, err := expandRedisClusterMaintenancePolicy(d.Get("maintenance_policy"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -746,6 +836,10 @@ func resourceRedisClusterUpdate(d *schema.ResourceData, meta interface{}) error
updateMask = append(updateMask, "redisConfigs")
}

if d.HasChange("persistence_config") {
updateMask = append(updateMask, "persistenceConfig")
}

if d.HasChange("maintenance_policy") {
updateMask = append(updateMask, "maintenancePolicy")
}
Expand Down Expand Up @@ -1141,6 +1235,67 @@ func flattenRedisClusterRedisConfigs(v interface{}, d *schema.ResourceData, conf
return v
}

func flattenRedisClusterPersistenceConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["mode"] =
flattenRedisClusterPersistenceConfigMode(original["mode"], d, config)
transformed["rdb_config"] =
flattenRedisClusterPersistenceConfigRdbConfig(original["rdbConfig"], d, config)
transformed["aof_config"] =
flattenRedisClusterPersistenceConfigAofConfig(original["aofConfig"], d, config)
return []interface{}{transformed}
}
func flattenRedisClusterPersistenceConfigMode(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenRedisClusterPersistenceConfigRdbConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["rdb_snapshot_period"] =
flattenRedisClusterPersistenceConfigRdbConfigRdbSnapshotPeriod(original["rdbSnapshotPeriod"], d, config)
transformed["rdb_snapshot_start_time"] =
flattenRedisClusterPersistenceConfigRdbConfigRdbSnapshotStartTime(original["rdbSnapshotStartTime"], d, config)
return []interface{}{transformed}
}
func flattenRedisClusterPersistenceConfigRdbConfigRdbSnapshotPeriod(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenRedisClusterPersistenceConfigRdbConfigRdbSnapshotStartTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenRedisClusterPersistenceConfigAofConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["append_fsync"] =
flattenRedisClusterPersistenceConfigAofConfigAppendFsync(original["appendFsync"], d, config)
return []interface{}{transformed}
}
func flattenRedisClusterPersistenceConfigAofConfigAppendFsync(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenRedisClusterMaintenancePolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
Expand Down Expand Up @@ -1402,6 +1557,100 @@ func expandRedisClusterRedisConfigs(v interface{}, d tpgresource.TerraformResour
return m, nil
}

func expandRedisClusterPersistenceConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedMode, err := expandRedisClusterPersistenceConfigMode(original["mode"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedMode); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["mode"] = transformedMode
}

transformedRdbConfig, err := expandRedisClusterPersistenceConfigRdbConfig(original["rdb_config"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedRdbConfig); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["rdbConfig"] = transformedRdbConfig
}

transformedAofConfig, err := expandRedisClusterPersistenceConfigAofConfig(original["aof_config"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedAofConfig); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["aofConfig"] = transformedAofConfig
}

return transformed, nil
}

func expandRedisClusterPersistenceConfigMode(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandRedisClusterPersistenceConfigRdbConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedRdbSnapshotPeriod, err := expandRedisClusterPersistenceConfigRdbConfigRdbSnapshotPeriod(original["rdb_snapshot_period"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedRdbSnapshotPeriod); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["rdbSnapshotPeriod"] = transformedRdbSnapshotPeriod
}

transformedRdbSnapshotStartTime, err := expandRedisClusterPersistenceConfigRdbConfigRdbSnapshotStartTime(original["rdb_snapshot_start_time"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedRdbSnapshotStartTime); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["rdbSnapshotStartTime"] = transformedRdbSnapshotStartTime
}

return transformed, nil
}

func expandRedisClusterPersistenceConfigRdbConfigRdbSnapshotPeriod(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandRedisClusterPersistenceConfigRdbConfigRdbSnapshotStartTime(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandRedisClusterPersistenceConfigAofConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedAppendFsync, err := expandRedisClusterPersistenceConfigAofConfigAppendFsync(original["append_fsync"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedAppendFsync); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["appendFsync"] = transformedAppendFsync
}

return transformed, nil
}

func expandRedisClusterPersistenceConfigAofConfigAppendFsync(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandRedisClusterMaintenancePolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
Expand Down
Loading