Skip to content

Commit

Permalink
chore: move GetRawConfigForKey function to meta package (#2514)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mia-Cross authored Apr 11, 2024
1 parent b565b53 commit 617f33a
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 75 deletions.
64 changes: 64 additions & 0 deletions internal/meta/extractors.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ package meta

import (
"net/http"
"strconv"
"strings"

"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/scaleway/scaleway-sdk-go/scw"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/zonal"
Expand Down Expand Up @@ -96,3 +100,63 @@ func ExtractScwClient(m interface{}) *scw.Client {
func ExtractHTTPClient(m interface{}) *http.Client {
return m.(*Meta).HTTPClient()
}

func getKeyInRawConfigMap(rawConfig map[string]cty.Value, key string, ty cty.Type) (interface{}, bool) {
if key == "" {
return rawConfig, false
}
// We split the key into its elements
keys := strings.Split(key, ".")

// We look at the first element's type
if value, ok := rawConfig[keys[0]]; ok {
switch {
case value.Type().IsListType():
// If it's a list and the second element of the key is an index, we look for the value in the list at the given index
if index, err := strconv.Atoi(keys[1]); err == nil {
return getKeyInRawConfigMap(value.AsValueSlice()[index].AsValueMap(), strings.Join(keys[2:], ""), ty)
}
// If it's a list and the second element of the key is '#', we look for the value in the list's first element
return getKeyInRawConfigMap(value.AsValueSlice()[0].AsValueMap(), strings.Join(keys[2:], ""), ty)

case value.Type().IsMapType():
// If it's a map, we look for the value in the map
return getKeyInRawConfigMap(value.AsValueMap(), strings.Join(keys[1:], ""), ty)

case value.Type().IsPrimitiveType():
// If it's a primitive type (bool, string, number), we convert the value to the expected type given as parameter before returning it
switch ty {
case cty.String:
if value.IsNull() {
return nil, false
}
return value.AsString(), true
case cty.Bool:
if value.IsNull() {
return false, false
}
if value.True() {
return true, true
}
return false, true
case cty.Number:
if value.IsNull() {
return nil, false
}
valueInt, _ := value.AsBigFloat().Int64()
return valueInt, true
}
}
}
return nil, false
}

// GetRawConfigForKey returns the value for a specific key in the user's raw configuration, which can be useful on resources' update
// The value for the key to look for must be a primitive type (bool, string, number) and the expected type of the value should be passed as the ty parameter
func GetRawConfigForKey(d *schema.ResourceData, key string, ty cty.Type) (interface{}, bool) {
rawConfig := d.GetRawConfig()
if rawConfig.IsNull() {
return nil, false
}
return getKeyInRawConfigMap(rawConfig.AsValueMap(), key, ty)
}
3 changes: 2 additions & 1 deletion internal/services/lb/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/scaleway/terraform-provider-scaleway/v2/internal/dsf"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/zonal"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/meta"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/verify"
)
Expand Down Expand Up @@ -619,7 +620,7 @@ func resourceLbBackendUpdate(ctx context.Context, d *schema.ResourceData, m inte
updateHCRequest.TCPConfig = expandLbHCTCP(d.Get("health_check_tcp"))
}

_, healthCheckPortSetByUser := getRawConfigForKey(d, "health_check_port", cty.Number)
_, healthCheckPortSetByUser := meta.GetRawConfigForKey(d, "health_check_port", cty.Number)
if d.HasChange("forward_port") && !healthCheckPortSetByUser {
updateHCRequest.Port = int32(d.Get("forward_port").(int))
}
Expand Down
61 changes: 0 additions & 61 deletions internal/services/lb/helpers_lb.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"fmt"
"net"
"reflect"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -178,66 +177,6 @@ func normalizeIPSubnet(ip string) string {
return ip
}

// getRawConfigForKey returns the value for a specific key in the user's raw configuration, which can be useful on resources' update
// The value for the key to look for must be a primitive type (bool, string, number) and the expected type of the value should be passed as the ty parameter
func getRawConfigForKey(d *schema.ResourceData, key string, ty cty.Type) (interface{}, bool) {
rawConfig := d.GetRawConfig()
if rawConfig.IsNull() {
return nil, false
}
return GetKeyInRawConfigMap(rawConfig.AsValueMap(), key, ty)
}

func GetKeyInRawConfigMap(rawConfig map[string]cty.Value, key string, ty cty.Type) (interface{}, bool) {
if key == "" {
return rawConfig, false
}
// We split the key into its elements
keys := strings.Split(key, ".")

// We look at the first element's type
if value, ok := rawConfig[keys[0]]; ok {
switch {
case value.Type().IsListType():
// If it's a list and the second element of the key is an index, we look for the value in the list at the given index
if index, err := strconv.Atoi(keys[1]); err == nil {
return GetKeyInRawConfigMap(value.AsValueSlice()[index].AsValueMap(), strings.Join(keys[2:], ""), ty)
}
// If it's a list and the second element of the key is '#', we look for the value in the list's first element
return GetKeyInRawConfigMap(value.AsValueSlice()[0].AsValueMap(), strings.Join(keys[2:], ""), ty)

case value.Type().IsMapType():
// If it's a map, we look for the value in the map
return GetKeyInRawConfigMap(value.AsValueMap(), strings.Join(keys[1:], ""), ty)

case value.Type().IsPrimitiveType():
// If it's a primitive type (bool, string, number), we convert the value to the expected type given as parameter before returning it
switch ty {
case cty.String:
if value.IsNull() {
return nil, false
}
return value.AsString(), true
case cty.Bool:
if value.IsNull() {
return false, false
}
if value.True() {
return true, true
}
return false, true
case cty.Number:
if value.IsNull() {
return nil, false
}
valueInt, _ := value.AsBigFloat().Int64()
return valueInt, true
}
}
}
return nil, false
}

func customizeDiffLBIPIDs(_ context.Context, diff *schema.ResourceDiff, _ interface{}) error {
oldIPIDs, newIPIDs := diff.GetChange("ip_ids")
oldIPIDsSet := make(map[string]struct{})
Expand Down
18 changes: 5 additions & 13 deletions internal/services/rdb/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,19 +94,11 @@ func getIPConfigCreate(d *schema.ResourceData, ipFieldName string) (ipamConfig *

// getIPConfigUpdate forces the provider to read the user's config instead of checking the state, because "enable_ipam" is not readable from the API
func getIPConfigUpdate(d *schema.ResourceData, ipFieldName string) (ipamConfig *bool, staticConfig *string) {
if rawConfig := d.GetRawConfig(); !rawConfig.IsNull() {
pnRawConfig := rawConfig.AsValueMap()["private_network"].AsValueSlice()[0].AsValueMap()
if !pnRawConfig["enable_ipam"].IsNull() {
if pnRawConfig["enable_ipam"].False() {
ipamConfig = scw.BoolPtr(false)
} else {
ipamConfig = scw.BoolPtr(true)
}
}
if !pnRawConfig[ipFieldName].IsNull() {
value := pnRawConfig[ipFieldName].AsString()
staticConfig = &value
}
if ipamConfigI, _ := meta.GetRawConfigForKey(d, "private_network.#.enable_ipam", cty.Bool); ipamConfigI != nil {
ipamConfig = types.ExpandBoolPtr(ipamConfigI)
}
if staticConfigI, _ := meta.GetRawConfigForKey(d, "private_network.#."+ipFieldName, cty.String); staticConfigI != nil {
staticConfig = types.ExpandStringPtr(staticConfigI)
}
return ipamConfig, staticConfig
}
Expand Down

0 comments on commit 617f33a

Please sign in to comment.