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

feat(dbaas): add Valkey support, deprecate Redis #683

Merged
merged 1 commit into from
Nov 14, 2024
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@ See updating [Changelog example here](https://keepachangelog.com/en/1.0.0/)

- upcloud_managed_object_storage_bucket resource for managing buckets in managed object storage services.
- upcloud_server: `index` field to `network_interfaces`.
- upcloud_managed_database_valkey: add support for Valkey.

### Changed

- upcloud_managed_database_\*: Update available properties to match listing provided by the API, see [#626](https://github.com/UpCloudLtd/terraform-provider-upcloud/pull/626) for details.
- upcloud_server: When modifying `network_interfaces`, match configured network interfaces to the server's actual network interfaces by `index` and `ip_address` (in addition to list order). This is to avoid public and utility network interfaces being re-assigned when the interfaces are re-ordered or when interface is removed from middle of the list. This might result to inaccurate diffs in the Terraform plan when interfaces are re-ordered or when interface is removed from middle of the list. We recommend explicitly setting the value for `index` in configuration, when interfaces are re-ordered or when interface is removed from middle of the list.

### Deprecated

- upcloud_managed_database_redis: Redis is deprecated in favor of Valkey. Please use Valkey for new key value store instances.

## [5.14.0] - 2024-10-28

### Changed
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.22
toolchain go1.22.5

require (
github.com/UpCloudLtd/upcloud-go-api/v8 v8.11.0
github.com/UpCloudLtd/upcloud-go-api/v8 v8.12.0
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/go-retryablehttp v0.7.7
github.com/hashicorp/go-uuid v1.0.3
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/ProtonMail/go-crypto v1.1.0-alpha.0 h1:nHGfwXmFvJrSR9xu8qL7BkO4DqTHXE9N5vPhgY2I+j0=
github.com/ProtonMail/go-crypto v1.1.0-alpha.0/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/UpCloudLtd/upcloud-go-api/v8 v8.11.0 h1:2eQLOlx+s5GlmUcyD9aihuYtWb0eC+dyZl3biu8Lb+8=
github.com/UpCloudLtd/upcloud-go-api/v8 v8.11.0/go.mod h1:bFnrOkfsDDmsb94nnBV5eSQjjsfDnwAzLnCt9+b4t/4=
github.com/UpCloudLtd/upcloud-go-api/v8 v8.12.0 h1:l4pOiBdNvpmZdQukGUqoEBIngFxvFWsNq8WnfHSzPJI=
github.com/UpCloudLtd/upcloud-go-api/v8 v8.12.0/go.mod h1:bFnrOkfsDDmsb94nnBV5eSQjjsfDnwAzLnCt9+b4t/4=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
Expand Down
173 changes: 167 additions & 6 deletions internal/service/database/data_source_sessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,27 @@ func DataSourceSessionsPostgreSQL() *schema.Resource {

func DataSourceSessionsRedis() *schema.Resource {
return &schema.Resource{
Description: "Current sessions of a Redis managed database",
ReadContext: dataSourceSessionsRedisRead,
Description: utils.DescriptionWithDeprecationWarning(redisDeprecationMessage, "Current sessions of a Redis managed database"),
DeprecationMessage: redisDeprecationMessage,
ReadContext: dataSourceSessionsRedisRead,
Schema: utils.JoinSchemas(
schemaDataSourceSessionsCommon(),
schemaDataSourceSessionsRedis(),
),
}
}

func DataSourceSessionsValkey() *schema.Resource {
return &schema.Resource{
Description: "Current sessions of a Valkey managed database",
ReadContext: dataSourceSessionsValkeyRead,
Schema: utils.JoinSchemas(
schemaDataSourceSessionsCommon(),
schemaDataSourceSessionsValkey(),
),
}
}

func schemaDataSourceSessionsCommon() map[string]*schema.Schema {
return map[string]*schema.Schema{
"limit": {
Expand Down Expand Up @@ -111,6 +123,18 @@ func schemaDataSourceSessionsRedis() map[string]*schema.Schema {
}
}

func schemaDataSourceSessionsValkey() map[string]*schema.Schema {
return map[string]*schema.Schema{
"sessions": {
Description: "Current sessions",
Type: schema.TypeSet,
Optional: true,
Computed: true,
Elem: schemaDatabaseSessionValkey(),
},
}
}

func schemaDatabaseSessionMySQL() *schema.Resource {
return &schema.Resource{
Description: "MySQL session",
Expand Down Expand Up @@ -372,6 +396,102 @@ func schemaDatabaseSessionRedis() *schema.Resource {
}
}

func schemaDatabaseSessionValkey() *schema.Resource {
return &schema.Resource{
Description: "Valkey session",
Schema: map[string]*schema.Schema{
"active_channel_subscriptions": {
Description: "Number of active channel subscriptions",
Type: schema.TypeInt,
Computed: true,
},
"active_database": {
Description: "Current database ID",
Type: schema.TypeString,
Computed: true,
},
"active_pattern_matching_channel_subscriptions": {
Description: "Number of pattern matching subscriptions.",
Type: schema.TypeInt,
Computed: true,
},
"application_name": {
Description: "Name of the application that is connected to this service.",
Type: schema.TypeString,
Computed: true,
},
"client_addr": {
Description: "Number of pattern matching subscriptions.",
Type: schema.TypeString,
Computed: true,
},
"connection_age": {
Description: "Total duration of the connection in nanoseconds.",
Type: schema.TypeInt,
Computed: true,
},
"connection_idle": {
Description: "Idle time of the connection in nanoseconds.",
Type: schema.TypeInt,
Computed: true,
},
"flags": {
Description: "A set containing flags' descriptions.",
Type: schema.TypeSet,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Computed: true,
},
"flags_raw": {
Description: "Client connection flags in raw string format.",
Type: schema.TypeString,
Computed: true,
},
"id": {
Description: "Process ID of this session.",
Type: schema.TypeString,
Computed: true,
},
"multi_exec_commands": {
Description: "Number of commands in a MULTI/EXEC context.",
Type: schema.TypeInt,
Computed: true,
},
"output_buffer": {
Description: "Output buffer length.",
Type: schema.TypeInt,
Computed: true,
},
"output_buffer_memory": {
Description: "Output buffer memory usage.",
Type: schema.TypeInt,
Computed: true,
},
"output_list_length": {
Description: "Output list length (replies are queued in this list when the buffer is full).",
Type: schema.TypeInt,
Computed: true,
},
"query": {
Description: "The last executed command.",
Type: schema.TypeString,
Computed: true,
},
"query_buffer": {
Description: "Query buffer length (0 means no query pending).",
Type: schema.TypeInt,
Computed: true,
},
"query_buffer_free": {
Description: "Free space of the query buffer (0 means the buffer is full).",
Type: schema.TypeInt,
Computed: true,
},
},
}
}

func dataSourceSessionsMySQLRead(ctx context.Context, d *schema.ResourceData, meta interface{}) (diags diag.Diagnostics) {
return dataSourceSessionsRead(ctx, d, meta, upcloud.ManagedDatabaseServiceTypeMySQL)
}
Expand All @@ -381,7 +501,11 @@ func dataSourceSessionsPostgreSQLRead(ctx context.Context, d *schema.ResourceDat
}

func dataSourceSessionsRedisRead(ctx context.Context, d *schema.ResourceData, meta interface{}) (diags diag.Diagnostics) {
return dataSourceSessionsRead(ctx, d, meta, upcloud.ManagedDatabaseServiceTypeRedis)
return dataSourceSessionsRead(ctx, d, meta, upcloud.ManagedDatabaseServiceTypeRedis) //nolint:staticcheck // To be removed when Redis support has been removed
}

func dataSourceSessionsValkeyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) (diags diag.Diagnostics) {
return dataSourceSessionsRead(ctx, d, meta, upcloud.ManagedDatabaseServiceTypeValkey)
}

func dataSourceSessionsRead(ctx context.Context, d *schema.ResourceData, meta interface{}, serviceType upcloud.ManagedDatabaseServiceType) (diags diag.Diagnostics) {
Expand Down Expand Up @@ -426,8 +550,13 @@ func dataSourceSessionsRead(ctx context.Context, d *schema.ResourceData, meta in
if err := d.Set("sessions", buildSessionsPostgreSQL(sessions.PostgreSQL)); err != nil {
return diag.FromErr(err)
}
case upcloud.ManagedDatabaseServiceTypeRedis:
err := d.Set("sessions", buildSessionsRedis(sessions.Redis))
case upcloud.ManagedDatabaseServiceTypeRedis: //nolint:staticcheck // To be removed when Redis support has been removed
err := d.Set("sessions", buildSessionsRedis(sessions.Redis)) //nolint:staticcheck // To be removed when Redis support has been removed
if err != nil {
return diag.FromErr(err)
}
case upcloud.ManagedDatabaseServiceTypeValkey:
err := d.Set("sessions", buildSessionsValkey(sessions.Valkey))
if err != nil {
return diag.FromErr(err)
}
Expand Down Expand Up @@ -495,7 +624,39 @@ func buildSessionsPostgreSQL(sessions []upcloud.ManagedDatabaseSessionPostgreSQL
return maps
}

func buildSessionsRedis(sessions []upcloud.ManagedDatabaseSessionRedis) []map[string]interface{} {
func buildSessionsRedis(sessions []upcloud.ManagedDatabaseSessionRedis) []map[string]interface{} { //nolint:staticcheck // To be removed when Redis support has been removed
maps := make([]map[string]interface{}, 0)

if len(sessions) == 0 {
return maps
}

for _, session := range sessions {
maps = append(maps, map[string]interface{}{
"active_channel_subscriptions": session.ActiveChannelSubscriptions,
"active_database": session.ActiveDatabase,
"active_pattern_matching_channel_subscriptions": session.ActivePatternMatchingChannelSubscriptions,
"application_name": session.ApplicationName,
"client_addr": session.ClientAddr,
"connection_age": session.ConnectionAge.Nanoseconds(),
"connection_idle": session.ConnectionIdle.Nanoseconds(),
"flags": session.Flags,
"flags_raw": session.FlagsRaw,
"id": session.Id,
"multi_exec_commands": session.MultiExecCommands,
"output_buffer": session.OutputBuffer,
"output_buffer_memory": session.OutputBufferMemory,
"output_list_length": session.OutputListLength,
"query": session.Query,
"query_buffer": session.QueryBuffer,
"query_buffer_free": session.QueryBufferFree,
})
}

return maps
}

func buildSessionsValkey(sessions []upcloud.ManagedDatabaseSessionValkey) []map[string]interface{} {
maps := make([]map[string]interface{}, 0)

if len(sessions) == 0 {
Expand Down
3 changes: 2 additions & 1 deletion internal/service/database/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ func TestDatabaseProperties(t *testing.T) {
upcloud.ManagedDatabaseServiceTypeMySQL,
upcloud.ManagedDatabaseServiceTypeOpenSearch,
upcloud.ManagedDatabaseServiceTypePostgreSQL,
upcloud.ManagedDatabaseServiceTypeRedis,
upcloud.ManagedDatabaseServiceTypeRedis, //nolint:staticcheck // To be removed when Redis support has been removed
upcloud.ManagedDatabaseServiceTypeValkey,
}

for _, dbType := range dbTypes {
Expand Down
3 changes: 2 additions & 1 deletion internal/service/database/properties/properties_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ func getTypes() []upcloud.ManagedDatabaseServiceType {
upcloud.ManagedDatabaseServiceTypeMySQL,
upcloud.ManagedDatabaseServiceTypeOpenSearch,
upcloud.ManagedDatabaseServiceTypePostgreSQL,
upcloud.ManagedDatabaseServiceTypeRedis,
upcloud.ManagedDatabaseServiceTypeRedis, //nolint:staticcheck // To be removed when Redis support has been removed
upcloud.ManagedDatabaseServiceTypeValkey,
}
}

Expand Down
17 changes: 10 additions & 7 deletions internal/service/database/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

const redisDeprecationMessage string = "Redis is deprecated in favor of Valkey. Please use Valkey for new key value store instances."

func ResourceRedis() *schema.Resource {
return &schema.Resource{
Description: serviceDescription("Redis"),
CreateContext: resourceRedisCreate,
ReadContext: resourceRedisRead,
UpdateContext: resourceRedisUpdate,
DeleteContext: resourceDatabaseDelete,
Description: utils.DescriptionWithDeprecationWarning(redisDeprecationMessage, serviceDescription("Redis")),
DeprecationMessage: redisDeprecationMessage,
CreateContext: resourceRedisCreate,
ReadContext: resourceRedisRead,
UpdateContext: resourceRedisUpdate,
DeleteContext: resourceDatabaseDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Expand All @@ -28,7 +31,7 @@ func ResourceRedis() *schema.Resource {
}

func resourceRedisCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
if err := d.Set("type", string(upcloud.ManagedDatabaseServiceTypeRedis)); err != nil {
if err := d.Set("type", string(upcloud.ManagedDatabaseServiceTypeRedis)); err != nil { //nolint:staticcheck // To be removed when Redis support has been removed
return diag.FromErr(err)
}

Expand Down Expand Up @@ -63,7 +66,7 @@ func schemaRedisEngine() map[string]*schema.Schema {
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: properties.GetSchemaMap(upcloud.ManagedDatabaseServiceTypeRedis),
Schema: properties.GetSchemaMap(upcloud.ManagedDatabaseServiceTypeRedis), //nolint:staticcheck // To be removed when Redis support has been removed
},
},
}
Expand Down
Loading
Loading