Skip to content

Commit

Permalink
feat: add disaster_recovery integration type
Browse files Browse the repository at this point in the history
  • Loading branch information
byashimov committed Dec 5, 2024
1 parent 579949a commit 9914c69
Show file tree
Hide file tree
Showing 21 changed files with 124 additions and 35 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ nav_order: 1
<!-- Always keep the following header in place: -->
<!--## [MAJOR.MINOR.PATCH] - YYYY-MM-DD -->

## [MAJOR.MINOR.PATCH] - YYYY-MM-DD -->

- Add `disaster_recovery` service integration type support

## [4.30.0] - 2024-12-05

- Add `aiven_kafka_native_acl` resource
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/cassandra.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ Optional:

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration
- `source_service_name` (String) Name of the source service


Expand Down
4 changes: 2 additions & 2 deletions docs/resources/clickhouse.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ Optional:

Required:

- `integration_type` (String) Type of the service integration. Supported integrations are `clickhouse_kafka` and `clickhouse_postgresql`.
- `source_service_name` (String) Name of the source service.
- `integration_type` (String) Type of the service integration
- `source_service_name` (String) Name of the source service


<a id="nestedblock--tag"></a>
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/dragonfly.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ Optional:

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration
- `source_service_name` (String) Name of the source service


Expand Down
2 changes: 1 addition & 1 deletion docs/resources/flink.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ Optional:

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration
- `source_service_name` (String) Name of the source service


Expand Down
2 changes: 1 addition & 1 deletion docs/resources/grafana.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ Optional:

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration
- `source_service_name` (String) Name of the source service


Expand Down
2 changes: 1 addition & 1 deletion docs/resources/kafka.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ Optional:

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration
- `source_service_name` (String) Name of the source service


Expand Down
2 changes: 1 addition & 1 deletion docs/resources/kafka_connect.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ Optional:

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration
- `source_service_name` (String) Name of the source service


Expand Down
2 changes: 1 addition & 1 deletion docs/resources/kafka_mirrormaker.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ Optional:

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration
- `source_service_name` (String) Name of the source service


Expand Down
2 changes: 1 addition & 1 deletion docs/resources/m3aggregator.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ Optional:

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration
- `source_service_name` (String) Name of the source service


Expand Down
2 changes: 1 addition & 1 deletion docs/resources/m3db.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ Required:

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration
- `source_service_name` (String) Name of the source service


Expand Down
2 changes: 1 addition & 1 deletion docs/resources/mysql.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ Optional:

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration. The possible values are `read_replica`.
- `source_service_name` (String) Name of the source service


Expand Down
2 changes: 1 addition & 1 deletion docs/resources/opensearch.md
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ Optional:

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration
- `source_service_name` (String) Name of the source service


Expand Down
2 changes: 1 addition & 1 deletion docs/resources/pg.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ Optional:

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration. The possible values are `read_replica` and `disaster_recovery`.
- `source_service_name` (String) Name of the source service


Expand Down
2 changes: 1 addition & 1 deletion docs/resources/redis.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ Optional:

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration
- `source_service_name` (String) Name of the source service


Expand Down
2 changes: 1 addition & 1 deletion docs/resources/thanos.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ resource "aiven_thanos" "example_thanos" {

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration
- `source_service_name` (String) Name of the source service


Expand Down
2 changes: 1 addition & 1 deletion docs/resources/valkey.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ resource "aiven_valkey" "example_valkey" {

Required:

- `integration_type` (String) Type of the service integration. The only supported value at the moment is `read_replica`
- `integration_type` (String) Type of the service integration
- `source_service_name` (String) Name of the source service


Expand Down
2 changes: 1 addition & 1 deletion internal/acctest/acctest.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ const (
DefaultResourceNamePrefix = "test-acc"

// DefaultRandomSuffixLength is the default length of the random suffix used in acceptance tests.
DefaultRandomSuffixLength = 10
DefaultRandomSuffixLength = 6
)

func RandStr() string {
Expand Down
54 changes: 39 additions & 15 deletions internal/schemautil/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
"slices"
"strconv"
"strings"
"time"
Expand All @@ -19,6 +20,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"

"github.com/aiven/terraform-provider-aiven/internal/common"
"github.com/aiven/terraform-provider-aiven/internal/schemautil/userconfig"
"github.com/aiven/terraform-provider-aiven/internal/sdkprovider/userconfig/converters"
)

Expand Down Expand Up @@ -71,9 +73,31 @@ var TechEmailsResourceSchema = &schema.Resource{
func ServiceCommonSchemaWithUserConfig(kind string) map[string]*schema.Schema {
s := ServiceCommonSchema()
converters.SetUserConfig(converters.ServiceUserConfig, kind, s)

// Assigns the integration types that are allowed to be set when creating a service
integrations := getBootstrapIntegrationTypes(kind)
if len(integrations) > 0 {
r := s[serviceIntegrationsKey].Elem.(*schema.Resource)
r.Schema["integration_type"].Description = userconfig.Desc(r.Schema["integration_type"].Description).PossibleValuesString(FlattenToString(integrations)...).Build()
}

return s
}

// getBootstrapIntegrationTypes returns the integration types that are allowed to be set when creating a service.
func getBootstrapIntegrationTypes(kind string) []service.IntegrationType {
list := make([]service.IntegrationType, 0)
if kind == ServiceTypePG || kind == ServiceTypeMySQL {
list = append(list, service.IntegrationTypeReadReplica)
}

if kind == ServiceTypePG {
list = append(list, service.IntegrationTypeDisasterRecovery)
}

return list
}

func ServiceCommonSchema() map[string]*schema.Schema {
return map[string]*schema.Schema{
"project": CommonSchemaProjectReference,
Expand Down Expand Up @@ -222,7 +246,7 @@ func ServiceCommonSchema() map[string]*schema.Schema {
"integration_type": {
Type: schema.TypeString,
Required: true,
Description: "Type of the service integration. The only supported value at the moment is `read_replica`",
Description: "Type of the service integration",
},
},
},
Expand Down Expand Up @@ -521,7 +545,7 @@ func ResourceServiceUpdate(ctx context.Context, d *schema.ResourceData, m interf
return nil
}

if len(getIntegrationsForTerraform(s.ServiceIntegrations, service.IntegrationTypeAutoscaler)) == 0 {
if len(flattenIntegrations(s.ServiceIntegrations, service.IntegrationTypeAutoscaler)) == 0 {
diskSpace, err := getDiskSpaceFromStateOrDiff(ctx, d, client)
if err != nil {
return diag.Errorf("error getting default disc space: %s", err)
Expand Down Expand Up @@ -614,18 +638,18 @@ func getTechnicalEmailsForTerraform(s *service.ServiceGetOut) *schema.Set {
return schema.NewSet(schema.HashResource(TechEmailsResourceSchema), techEmails)
}

func getIntegrationsForTerraform(integrations []service.ServiceIntegrationOut, integrationType service.IntegrationType) []map[string]interface{} {
var filteredIntegrations []map[string]interface{}
for _, integration := range integrations {
if integration.IntegrationType == integrationType {
integrationMap := map[string]interface{}{
"integration_type": integration.IntegrationType,
"source_service_name": integration.SourceService,
}
filteredIntegrations = append(filteredIntegrations, integrationMap)
// flattenIntegrations converts the service integrations into a list of maps
func flattenIntegrations(integrations []service.ServiceIntegrationOut, kinds ...service.IntegrationType) []map[string]interface{} {
result := make([]map[string]any, 0)
for _, v := range integrations {
if slices.Contains(kinds, v.IntegrationType) {
result = append(result, map[string]any{
"integration_type": v.IntegrationType,
"source_service_name": v.SourceService,
})
}
}
return filteredIntegrations
return result
}

func ResourceServiceDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
Expand Down Expand Up @@ -776,9 +800,9 @@ func copyServicePropertiesFromAPIResponseToTerraform(
return fmt.Errorf("cannot set `components` : %w", err)
}

// Handle read_replica service integrations
readReplicaIntegrations := getIntegrationsForTerraform(s.ServiceIntegrations, service.IntegrationTypeReadReplica)
if err := d.Set("service_integrations", readReplicaIntegrations); err != nil {
// Handle service integrations
integrations := flattenIntegrations(s.ServiceIntegrations, getBootstrapIntegrationTypes(serviceType)...)
if err := d.Set(serviceIntegrationsKey, integrations); err != nil {
return err
}

Expand Down
10 changes: 8 additions & 2 deletions internal/schemautil/wait.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/aiven/go-client-codegen/handler/staticip"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/samber/lo"

"github.com/aiven/terraform-provider-aiven/internal/common"
)
Expand Down Expand Up @@ -257,8 +258,13 @@ func backupsReady(s *service.ServiceGetOut) bool {
// No backups for read replicas type of service
// See https://github.com/aiven/terraform-provider-aiven/pull/172
for _, i := range s.ServiceIntegrations {
if i.IntegrationType == "read_replica" && *i.DestService == s.ServiceName {
return true
switch i.IntegrationType {
case service.IntegrationTypeReadReplica, service.IntegrationTypeDisasterRecovery:
// fixme: disaster recovery will have a backup eventually,
// remove this when BE is ready
if lo.FromPtr(i.DestService) == s.ServiceName {
return true
}
}
}

Expand Down
55 changes: 55 additions & 0 deletions internal/sdkprovider/service/pg/pg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1088,3 +1088,58 @@ func testAccCheckAivenServicePGAttributes(n string) resource.TestCheckFunc {
return nil
}
}

func TestAccAivenServicePG_disaster_recovery(t *testing.T) {
primaryName := "aiven_pg.primary"
secondaryName := "aiven_pg.secondary"
projectName := os.Getenv("AIVEN_PROJECT_NAME")
randStr := acc.RandStr()
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acc.TestAccPreCheck(t) },
ProtoV6ProviderFactories: acc.TestProtoV6ProviderFactories,
CheckDestroy: acc.TestAccCheckAivenServiceResourceDestroy,
Steps: []resource.TestStep{
{
Config: testAccPGServiceResourceDisasterRecovery(projectName, randStr),
Check: resource.ComposeTestCheckFunc(
acc.TestAccCheckAivenServiceCommonAttributes(primaryName),
acc.TestAccCheckAivenServiceCommonAttributes(secondaryName),
// One service integration should be created
resource.TestCheckResourceAttr(secondaryName, "service_integrations.#", "1"),
// Which is of type disaster_recovery
resource.TestCheckTypeSetElemNestedAttrs(secondaryName, "service_integrations.*", map[string]string{
"integration_type": "disaster_recovery",
"source_service_name": "test-acc-primary-" + randStr,
}),
),
},
},
})
}

func testAccPGServiceResourceDisasterRecovery(project, randStr string) string {
return fmt.Sprintf(`
resource "aiven_pg" "primary" {
project = "%[1]s"
cloud_name = "google-europe-west1"
plan = "startup-4"
service_name = "test-acc-primary-%[2]s"
maintenance_window_dow = "monday"
maintenance_window_time = "10:00:00"
}
resource "aiven_pg" "secondary" {
project = aiven_pg.primary.project
cloud_name = "google-europe-west1"
plan = "startup-4"
service_name = "test-acc-secondary-%[2]s"
maintenance_window_dow = "monday"
maintenance_window_time = "10:00:00"
service_integrations {
integration_type = "disaster_recovery"
source_service_name = "test-acc-primary-%[2]s"
}
}
`, project, randStr)
}

0 comments on commit 9914c69

Please sign in to comment.