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

rds: Improve version/instance data sources #35698

Merged
merged 23 commits into from
Feb 9, 2024
Merged
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a0bc51b
rds/cluster: Improve tests
YakDriver Feb 7, 2024
c93e7aa
rds/consts: Fix mispelling
YakDriver Feb 7, 2024
65fa729
Add changelog
YakDriver Feb 7, 2024
68c626f
rds/cluster: Revise tests to improve data source use
YakDriver Feb 7, 2024
8cfa741
rds/consts: Add main preferred instance classes
YakDriver Feb 7, 2024
4836a41
rds/engine_version: Update search options and functionality
YakDriver Feb 7, 2024
5b211d3
rds/engine_version: Update tests for new functionality
YakDriver Feb 7, 2024
2dc9a5b
rds/orderable_instance: Add new functionality
YakDriver Feb 7, 2024
6045f1f
rds/orderable_instance: Update tests for new functionality
YakDriver Feb 7, 2024
63bdc08
docs/rds: Update engine_version docs for changes
YakDriver Feb 7, 2024
1f3fca6
docs/rds: Update orderable_instance docs for changes
YakDriver Feb 7, 2024
1776cf5
Update go.mod
YakDriver Feb 7, 2024
2bf3115
rds/neptune: Small corrections
YakDriver Feb 8, 2024
794a7a6
rds: Post-rebase cleanup
YakDriver Feb 8, 2024
f8d8463
rds/cluster: Fix tests
YakDriver Feb 8, 2024
433a7f9
aws/rds: Tweak tests
YakDriver Feb 8, 2024
588bbb2
rds: Clean up some lint
YakDriver Feb 8, 2024
53920bd
rds/instance: Fix test linting
YakDriver Feb 8, 2024
76c90e4
rds: Fix minor issues
YakDriver Feb 8, 2024
2ca0e35
rds/instance: Remove extra comment
YakDriver Feb 8, 2024
3c49d41
rds/consts: Remove unused
YakDriver Feb 8, 2024
c0a95af
rds: Make code more readable
YakDriver Feb 9, 2024
6154e5f
rds/orderable_instance: Improve performance
YakDriver Feb 9, 2024
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
196 changes: 145 additions & 51 deletions internal/service/rds/orderable_instance_data_source.go
Original file line number Diff line number Diff line change
@@ -5,7 +5,9 @@ package rds

import (
"context"
"sort"

"github.com/YakDriver/go-version"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
@@ -48,6 +50,11 @@ func DataSourceOrderableInstance() *schema.Resource {
Computed: true,
},

"engine_latest_version": {
Type: schema.TypeBool,
Optional: true,
},

"license_model": {
Type: schema.TypeString,
Optional: true,
@@ -120,15 +127,23 @@ func DataSourceOrderableInstance() *schema.Resource {
"supported_engine_modes": {
Type: schema.TypeList,
Computed: true,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},

"supported_network_types": {
Type: schema.TypeList,
Computed: true,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},

"supports_clusters": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},

"supports_enhanced_monitoring": {
Type: schema.TypeBool,
Optional: true,
@@ -159,6 +174,12 @@ func DataSourceOrderableInstance() *schema.Resource {
Computed: true,
},

"supports_multi_az": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},

"supports_performance_insights": {
Type: schema.TypeBool,
Optional: true,
@@ -230,6 +251,12 @@ func dataSourceOrderableInstanceRead(ctx context.Context, d *schema.ResourceData
}
}

if v, ok := d.GetOk("supports_clusters"); ok {
if aws.BoolValue(instanceOption.SupportsClusters) != v.(bool) {
continue
}
}

if v, ok := d.GetOk("supports_enhanced_monitoring"); ok {
if aws.BoolValue(instanceOption.SupportsEnhancedMonitoring) != v.(bool) {
continue
@@ -260,6 +287,12 @@ func dataSourceOrderableInstanceRead(ctx context.Context, d *schema.ResourceData
}
}

if v, ok := d.GetOk("supports_multi_az"); ok {
if aws.BoolValue(instanceOption.MultiAZCapable) != v.(bool) {
continue
}
}

if v, ok := d.GetOk("supports_performance_insights"); ok {
if aws.BoolValue(instanceOption.SupportsPerformanceInsights) != v.(bool) {
continue
@@ -282,6 +315,7 @@ func dataSourceOrderableInstanceRead(ctx context.Context, d *schema.ResourceData
}
return !lastPage
})

if err != nil {
return sdkdiag.AppendErrorf(diags, "reading RDS Orderable DB Instance Options: %s", err)
}
@@ -290,94 +324,142 @@ func dataSourceOrderableInstanceRead(ctx context.Context, d *schema.ResourceData
return sdkdiag.AppendErrorf(diags, "no RDS Orderable DB Instance Options found matching criteria; try different search")
}

// preferred classes/versions
var found *rds.OrderableDBInstanceOption
l := d.Get("preferred_instance_classes").([]interface{})
v := d.Get("preferred_engine_versions").([]interface{})
if len(l) > 0 && len(v) > 0 {
for _, elem := range l {
preferredInstanceClass, ok := elem.(string)
if l := d.Get("supported_engine_modes").([]interface{}); len(l) > 0 {
var matches []*rds.OrderableDBInstanceOption

if !ok {
continue
for _, allClass := range instanceClassResults {
searchedModes:
for _, pref := range l {
for _, mode := range allClass.SupportedEngineModes {
if aws.StringValue(mode) == pref {
matches = append(matches, allClass)
break searchedModes
}
}
}
}

for _, ver := range v {
preferredEngineVersion, ok := ver.(string)
if len(matches) == 0 {
return sdkdiag.AppendErrorf(diags, "no RDS Orderable DB Instance Options found matching supported_engine_modes: %v", l)
}

if !ok {
continue
}
instanceClassResults = matches
}

for _, instanceClassResult := range instanceClassResults {
if preferredInstanceClass == aws.StringValue(instanceClassResult.DBInstanceClass) &&
preferredEngineVersion == aws.StringValue(instanceClassResult.EngineVersion) {
found = instanceClassResult
break
}
}
if l := d.Get("supported_network_types").([]interface{}); len(l) > 0 {
var matches []*rds.OrderableDBInstanceOption

if found != nil {
break
for _, allClass := range instanceClassResults {
searchedNetworks:
for _, pref := range l {
for _, netType := range allClass.SupportedNetworkTypes {
if aws.StringValue(netType) == pref {
matches = append(matches, allClass)
break searchedNetworks
}
}
}
}

if found != nil {
break
}
if len(matches) == 0 {
return sdkdiag.AppendErrorf(diags, "no RDS Orderable DB Instance Options found matching supported_network_types: %v", l)
}
} else if len(l) > 0 {
for _, elem := range l {
preferredInstanceClass, ok := elem.(string)

if !ok {
continue
}
instanceClassResults = matches
}

for _, instanceClassResult := range instanceClassResults {
if preferredInstanceClass == aws.StringValue(instanceClassResult.DBInstanceClass) {
found = instanceClassResult
break
prefSearch := false

if l := d.Get("preferred_engine_versions").([]interface{}); len(l) > 0 {
var matches []*rds.OrderableDBInstanceOption

for _, prefVer := range l {
for _, allClass := range instanceClassResults {
if aws.StringValue(allClass.EngineVersion) == prefVer {
matches = append(matches, allClass)
}
// keeping all the instance classes to ensure we can match any preferred instance classes
}
}

if found != nil {
break
}
if len(matches) == 0 {
return sdkdiag.AppendErrorf(diags, "no RDS Orderable DB Instance Options found matching preferred_engine_versions: %v", l)
}
} else if len(v) > 0 {
for _, ver := range v {
preferredEngineVersion, ok := ver.(string)

if !ok {
continue
}
prefSearch = true
instanceClassResults = matches
}

latestVersion := d.Get("engine_latest_version").(bool)

if l := d.Get("preferred_instance_classes").([]interface{}); len(l) > 0 {
var matches []*rds.OrderableDBInstanceOption

for _, instanceClassResult := range instanceClassResults {
if preferredEngineVersion == aws.StringValue(instanceClassResult.EngineVersion) {
found = instanceClassResult
for _, prefClass := range l {
for _, allClass := range instanceClassResults {
if aws.StringValue(allClass.DBInstanceClass) == prefClass {
matches = append(matches, allClass)
}

if !latestVersion && len(matches) > 0 {
break
}

// otherwise, get all the instance classes that match the *first* preferred class (and any other criteria)
}

if found != nil {
// if we have a match, we can stop searching
if len(matches) > 0 {
break
}
}

if len(matches) == 0 {
return sdkdiag.AppendErrorf(diags, "no RDS Orderable DB Instance Options found matching preferred_instance_classes: %v", l)
}

prefSearch = true
instanceClassResults = matches
}

if found == nil && len(instanceClassResults) > 1 {
return sdkdiag.AppendErrorf(diags, "multiple RDS DB Instance Classes (%v) match the criteria; try a different search", instanceClassResults)
var found *rds.OrderableDBInstanceOption

if latestVersion && prefSearch {
sortInstanceClassesByVersion(instanceClassResults)
found = instanceClassResults[len(instanceClassResults)-1]
}

/*
fmt.Printf("instanceClassResults:\n")
for _, instanceClassResult := range instanceClassResults {
fmt.Printf("class: %s, version: %s\n", aws.StringValue(instanceClassResult.DBInstanceClass), aws.StringValue(instanceClassResult.EngineVersion))
}
*/

if found == nil && len(instanceClassResults) > 0 && prefSearch {
found = instanceClassResults[0]
}

if found == nil && len(instanceClassResults) == 1 {
found = instanceClassResults[0]
}

if found == nil && len(instanceClassResults) > 4 {
// there can be a LOT(!!) of results, so if there are more than this, only include the search criteria
return sdkdiag.AppendErrorf(diags, "multiple (%d) RDS DB Instance Classes match the criteria; try a different search: %+v\nPreferred instance classes: %+v\nPreferred engine versions: %+v", len(instanceClassResults), input, d.Get("preferred_instance_classes"), d.Get("preferred_engine_versions"))
}

if found == nil && len(instanceClassResults) > 1 {
// there can be a lot of results, so if there are a few, include the results and search criteria
return sdkdiag.AppendErrorf(diags, "multiple (%d) RDS DB Instance Classes (%v) match the criteria; try a different search: %+v\nPreferred instance classes: %+v\nPreferred engine versions: %+v", len(instanceClassResults), instanceClassResults, input, d.Get("preferred_instance_classes"), d.Get("preferred_engine_versions"))
}

if found == nil {
return sdkdiag.AppendErrorf(diags, "no RDS DB Instance Classes match the criteria; try a different search")
}

//fmt.Printf("found: %s, %s\n", aws.StringValue(found.DBInstanceClass), aws.StringValue(found.EngineVersion))

d.SetId(aws.StringValue(found.DBInstanceClass))
d.Set("availability_zone_group", found.AvailabilityZoneGroup)
var availabilityZones []string
@@ -401,15 +483,27 @@ func dataSourceOrderableInstanceRead(ctx context.Context, d *schema.ResourceData
d.Set("storage_type", found.StorageType)
d.Set("supported_engine_modes", aws.StringValueSlice(found.SupportedEngineModes))
d.Set("supported_network_types", aws.StringValueSlice(found.SupportedNetworkTypes))
d.Set("supports_clusters", found.SupportsClusters)
d.Set("supports_enhanced_monitoring", found.SupportsEnhancedMonitoring)
d.Set("supports_global_databases", found.SupportsGlobalDatabases)
d.Set("supports_iam_database_authentication", found.SupportsIAMDatabaseAuthentication)
d.Set("supports_iops", found.SupportsIops)
d.Set("supports_kerberos_authentication", found.SupportsKerberosAuthentication)
d.Set("supports_multi_az", found.MultiAZCapable)
d.Set("supports_performance_insights", found.SupportsPerformanceInsights)
d.Set("supports_storage_autoscaling", found.SupportsStorageAutoscaling)
d.Set("supports_storage_encryption", found.SupportsStorageEncryption)
d.Set("vpc", found.Vpc)

return diags
}

func sortInstanceClassesByVersion(ic []*rds.OrderableDBInstanceOption) {
if len(ic) < 2 {
return
}

sort.Slice(ic, func(i, j int) bool {
return version.LessThan(aws.StringValue(ic[i].EngineVersion), aws.StringValue(ic[j].EngineVersion))
})
}