Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: convert ip_filter values into the target type
Browse files Browse the repository at this point in the history
byashimov committed May 10, 2024
1 parent 878fdb2 commit 267b9c0
Showing 4 changed files with 128 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -11,6 +11,8 @@ nav_order: 1

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

- Fix `ip_filter`, `ip_filter_string`, and `ip_filter_object` crash when receive an unexpected type

## [4.17.0] - 2024-05-07

- Fix `aiven_kafka_connector` fails to create resource with 201 error
5 changes: 4 additions & 1 deletion internal/sdkprovider/userconfig/converters/converters.go
Original file line number Diff line number Diff line change
@@ -363,7 +363,10 @@ func flatten(kind userConfigType, name string, d *schema.ResourceData, dto map[s
prefix := fmt.Sprintf("%s.0.", key)

// Renames ip_filter to ip_filter_object
renameAliasesToTfo(kind, name, dto, d)
err := renameAliasesToTfo(kind, name, dto, d)
if err != nil {
return err
}

// Copies "create only" fields from the original config.
// Like admin_password, that is received only on POST request when service is created.
67 changes: 65 additions & 2 deletions internal/sdkprovider/userconfig/converters/utils.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package converters

import (
"encoding/json"
"fmt"
"reflect"
"strings"
@@ -37,22 +38,84 @@ type resourceData interface {
// renameAliasesToTfo renames aliases to TF object
// Must sort keys to rename from bottom to top.
// Otherwise, might not find the deepest key if parent key is renamed
func renameAliasesToTfo(kind userConfigType, name string, dto map[string]any, d resourceData) {
func renameAliasesToTfo(kind userConfigType, name string, dto map[string]any, d resourceData) error {
prefix := userConfigKey(kind, name) + ".0."
m := getFieldMapping(kind, name)

for _, to := range sortKeys(m) {
from := m[to]

if strings.HasSuffix(to, "_string") || strings.HasSuffix(to, "_object") {
// If resource doesn't have this field, then ignores (uses original)
path := strings.ReplaceAll(to, "/", ".0.")
_, ok := d.GetOk(fmt.Sprintf("%s.0.%s", userConfigKey(kind, name), path))
_, ok := d.GetOk(prefix + path)
if !ok {
continue
}
}

renameAlias(dto, from, to)
}

// Converts ip_filter list into an expected by the config type
return convertIpFilter(dto)
}

// ipFilterMistyped reverse types: string to map, map to string
// Unmarshalled with no errors when ip_filter has type missmatch
type ipFilterMistyped struct {
IpFilter []map[string]string `json:"ip_filter"`

Check failure on line 67 in internal/sdkprovider/userconfig/converters/utils.go

GitHub Actions / make_lint

ST1003: struct field IpFilter should be IPFilter (stylecheck)
IpFilterString []map[string]string `json:"ip_filter_string"`

Check failure on line 68 in internal/sdkprovider/userconfig/converters/utils.go

GitHub Actions / make_lint

ST1003: struct field IpFilterString should be IPFilterString (stylecheck)
IpFilterObject []string `json:"ip_filter_object"`

Check failure on line 69 in internal/sdkprovider/userconfig/converters/utils.go

GitHub Actions / make_lint

ST1003: struct field IpFilterObject should be IPFilterObject (stylecheck)
}

// convertIpFilter converts a list of ip_filter objects into a list of strings and vice versa
func convertIpFilter(dto map[string]any) error {

Check failure on line 73 in internal/sdkprovider/userconfig/converters/utils.go

GitHub Actions / make_lint

ST1003: func convertIpFilter should be convertIPFilter (stylecheck)
b, err := json.Marshal(dto)
if err != nil {
return err
}

var r ipFilterMistyped
err = json.Unmarshal(b, &r)
if err != nil {
// Marshaling went wrong, nothing to fix
return nil

Check failure on line 83 in internal/sdkprovider/userconfig/converters/utils.go

GitHub Actions / make_lint

error is not nil (line 80) but it returns nil (nilerr)
}

// Converting went smooth.
// Which means either there is no ip_filter at all, or it has an invalid type

// Converts objects into strings
if len(r.IpFilterObject) > 0 {
mapList := make([]map[string]string, 0)
for _, v := range r.IpFilterObject {
mapList = append(mapList, map[string]string{"network": v})
}

dto["ip_filter_object"] = mapList
return nil
}

// Converts strings into objects
strList := make([]string, 0)
for _, v := range append(r.IpFilter, r.IpFilterString...) {
strList = append(strList, v["network"])
}

if len(strList) == 0 {
// Nothing to do here
return nil
}

// Chooses which key to set values
strKey := "ip_filter"
if len(r.IpFilterString) > 0 {
strKey = "ip_filter_string"
}

dto[strKey] = strList
return nil
}

// renameAlias renames ip_filter_string to ip_filter
58 changes: 57 additions & 1 deletion internal/sdkprovider/userconfig/converters/utils_test.go
Original file line number Diff line number Diff line change
@@ -172,6 +172,60 @@ func TestRenameAliasesToTfo(t *testing.T) {
dto: `{"pg": {"pg_stat_statements.track": 0}}`,
tfo: newResourceDataMock(),
},
{
serviceType: "thanos",
name: "ip_filter gets a list of objects",
expected: `{"ip_filter": ["0.0.0.0/0"]}`,
dto: `{"ip_filter": [{"network": "0.0.0.0/0"}]}`,
tfo: newResourceDataMock(
newResourceDataKV("thanos_user_config.0.ip_filter", []string{"0.0.0.0/0"}),
),
},
{
serviceType: "thanos",
name: "ip_filter_string gets a list of objects",
expected: `{"ip_filter_string": ["0.0.0.0/0"]}`,
dto: `{"ip_filter": [{"network": "0.0.0.0/0"}]}`,
tfo: newResourceDataMock(
newResourceDataKV("thanos_user_config.0.ip_filter_string", []string{"0.0.0.0/0"}),
),
},
{
serviceType: "thanos",
name: "ip_filter_object gets a list of strings",
expected: `{"ip_filter_object": [{"network": "0.0.0.0/0"}]}`,
dto: `{"ip_filter": ["0.0.0.0/0"]}`,
tfo: newResourceDataMock(
newResourceDataKV("thanos_user_config.0.ip_filter_object", []map[string]string{{"network": "0.0.0.0/0"}}),
),
},
{
serviceType: "thanos",
name: "ip_filter_object empty list",
expected: `{"ip_filter_object": []}`,
dto: `{"ip_filter": []}`,
tfo: newResourceDataMock(
newResourceDataKV("thanos_user_config.0.ip_filter_object", []map[string]string{}),
),
},
{
serviceType: "thanos",
name: "ip_filter_string empty list",
expected: `{"ip_filter_string": []}`,
dto: `{"ip_filter": []}`,
tfo: newResourceDataMock(
newResourceDataKV("thanos_user_config.0.ip_filter_string", []string{}),
),
},
{
serviceType: "thanos",
name: "ip_filter empty list",
expected: `{"ip_filter": []}`,
dto: `{"ip_filter": []}`,
tfo: newResourceDataMock(
newResourceDataKV("thanos_user_config.0.ip_filter", []string{}),
),
},
}

reSpaces := regexp.MustCompile(`\s+`)
@@ -181,7 +235,9 @@ func TestRenameAliasesToTfo(t *testing.T) {
err := json.Unmarshal([]byte(opt.dto), &m)
require.NoError(t, err)

renameAliasesToTfo(ServiceUserConfig, opt.serviceType, m, opt.tfo)
err = renameAliasesToTfo(ServiceUserConfig, opt.serviceType, m, opt.tfo)
require.NoError(t, err)

b, err := json.Marshal(&m)
require.NoError(t, err)
assert.Equal(t, reSpaces.ReplaceAllString(opt.expected, ""), string(b))

0 comments on commit 267b9c0

Please sign in to comment.