Skip to content

Commit

Permalink
Merge pull request #220 from kingsoftcloud/trunk
Browse files Browse the repository at this point in the history
Trunk
  • Loading branch information
notone0010 authored Jul 5, 2024
2 parents 4735f55 + 975dda6 commit 32b0c50
Show file tree
Hide file tree
Showing 21 changed files with 3,153 additions and 404 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 1.16.0 (Jul 05, 2024)

FEATURES:

- - **New Resource:** `ksyun_kce_cluster_attachment` KCE集群添加新节点
- - **New Resource:** `ksyun_kce_cluster_attach_existence` KCE集群添加已有节点 替换 `ksyun_kce_worker`
- - **New Resource:** `ksyun_kce_cluster` KCE集群支持创建多机型节点,支持托管集群

## 1.15.7 (May 28, 2024)

IMPROVEMENTS:
Expand Down
227 changes: 226 additions & 1 deletion ksyun/internal/pkg/helper/helper.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package helper

import (
"fmt"
"log"
"reflect"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/mitchellh/mapstructure"
)

// GetSchemaListHeadMap returns string key map if argument is MaxItem: 1 List Type
Expand All @@ -13,7 +16,16 @@ func GetSchemaListHeadMap(d *schema.ResourceData, key string) (result map[string
if !ok {
return
}
interfaces, ok := v.([]interface{})
var (
interfaces []interface{}
)
switch v.(type) {
case []interface{}:
interfaces = v.([]interface{})
case *schema.Set:
interfaces = v.(*schema.Set).List()
}

if !ok || len(interfaces) == 0 {
ok = false
return
Expand All @@ -23,6 +35,44 @@ func GetSchemaListHeadMap(d *schema.ResourceData, key string) (result map[string
return
}

func GetSchemaSingerMapWithKey(d *schema.ResourceData, key string) (result map[string]interface{}, ok bool) {
v, ok := d.GetOk(key)
if !ok {
return
}
result, ok = v.(map[string]interface{})
return
}

func GetSchemaMapListWithKey(d *schema.ResourceData, key string) (result []map[string]interface{}, ok bool) {
v, ok := d.GetOk(key)
if !ok {
return
}
var (
interfaces []interface{}
)
switch v.(type) {
case []interface{}:
interfaces = v.([]interface{})
case *schema.Set:
interfaces = v.(*schema.Set).List()
}

if !ok || len(interfaces) == 0 {
ok = false
return
}
for _, inter := range interfaces {
if v, ok := inter.(map[string]interface{}); !ok {
return nil, ok
} else {
result = append(result, v)
}
}
return
}

func StringBoolean(s bool) string {
if s {
return "True"
Expand Down Expand Up @@ -106,6 +156,9 @@ func ConvertMapKey2Underline(m map[string]interface{}) map[string]interface{} {

func IsEmpty(v interface{}) bool {
value := reflect.ValueOf(v)
if !value.IsValid() {
return true
}
if value.Kind() == reflect.Ptr || value.Kind() == reflect.Interface {
if value.IsNil() {
return true
Expand Down Expand Up @@ -151,3 +204,175 @@ func MapCopy(m map[string]interface{}) (map[string]interface{}, bool) {
}
return n, true
}

func GetDiffMap(base map[string]interface{}, targets ...map[string]interface{}) (diff map[string]interface{}) {
if len(targets) == 0 {
return base
}
var (
isDiff bool
)

diff = make(map[string]interface{}, len(base))
for _, target := range targets {
diff, isDiff = diffMap(base, target)
if isDiff {
return diff
}
}
return

}

func diffMap(base map[string]interface{}, target map[string]interface{}) (diff map[string]interface{}, isDiff bool) {
diff = make(map[string]interface{})
for k, v := range base {
if tv, ok := target[k]; ok {
if !reflect.DeepEqual(v, tv) {
isDiff = true
}

diff[k] = tv
} else {
diff[k] = v
}
}
return
}

func MapstructureFiller(i interface{}, o interface{}, tag string) (err error) {
defer func() {
if r := recover(); r != nil {
log.Println("MapstructureFiller panic recovered: ", r)
err = fmt.Errorf("MapstructureFiller panic recovered: %v", r)
}
}()

oVal := reflect.ValueOf(o)
if oVal.Kind() != reflect.Ptr {
return fmt.Errorf("o must be a pointer")
}
// it's basic convert
convertConfig := &mapstructure.DecoderConfig{
IgnoreUntaggedFields: true,
ZeroFields: false,
WeaklyTypedInput: true,
Metadata: nil,
Result: o,
}

// convertConfig.DecodeHook = decodeHookFunc()

if tag != "" {
convertConfig.TagName = tag
}

decoder, err := mapstructure.NewDecoder(convertConfig)
if err != nil {
return err
}
if err := decoder.Decode(i); err != nil {
return err
}

if tag == "" {
return nil
}

sVal := reflect.ValueOf(i)
switch sVal.Kind() {
case reflect.Struct:
oMap := o.(*map[string]interface{})
// specify to custom type such as list, filter
for j := 0; j < sVal.NumField(); j++ {
fieldType := sVal.Type().Field(j)
fieldVal := sVal.Field(j)

mapstructureTag := fieldType.Tag.Get(tag)
tagList := strings.Split(mapstructureTag, ",")
var (
tagKind string
tagName string
)
tagName = tagList[0]
if tagName == "" {
continue
}

if isZeroOfUnderlyingType(fieldVal.Interface()) {
delete(*oMap, tagName)
continue
}

switch fieldType.Type.Kind() {
case reflect.Slice:
if fieldVal.Len() == 0 {
break
}
tempList := make([]interface{}, 0, fieldVal.Len())
for k := 0; k < fieldVal.Len(); k++ {
if fieldVal.Index(k).Kind() == reflect.Struct {
tempMap := make(map[string]interface{})

err = MapstructureFiller(fieldVal.Index(k).Interface(), &tempMap, tag)
if err != nil {
return err
}
tempList = append(tempList, tempMap)
}

}
if len(tempList) > 0 {
(*oMap)[tagName] = tempList
}

}

if len(tagList) > 1 {
tagKind = tagList[1]
}

switch tagKind {
case "tf-list":
if IsEmpty((*oMap)[tagName]) || reflect.ValueOf((*oMap)[tagName]).Kind() == reflect.Slice {
continue
}
(*oMap)[tagName] = []interface{}{(*oMap)[tagName]}
}
}

}

return nil
}

func decodeHookFunc() mapstructure.DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
if f.Kind() == reflect.String && t.Kind() == reflect.Bool {
return data, nil
}

result := make(map[string]interface{})

// 遍历struct的所有字段
val := reflect.ValueOf(data)
for i := 0; i < val.NumField(); i++ {
valueField := val.Field(i)
typeField := val.Type().Field(i)

// 检查字段是否为空值(这里只检查了基本类型和字符串,你可能需要扩展以处理其他类型)
if isZeroOfUnderlyingType(valueField.Interface()) {
continue // 忽略空值
}

// 使用字段名作为map的键,字段值作为map的值
result[typeField.Name] = valueField.Interface()
}

return result, nil
}
}

func isZeroOfUnderlyingType(x interface{}) bool {
return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
}
60 changes: 60 additions & 0 deletions ksyun/internal/pkg/helper/helper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package helper

import (
"testing"

"github.com/terraform-providers/terraform-provider-ksyun/ksyun/internal/structor/v1/kce"
)

func TestMapstructureFiller(t *testing.T) {
var (
dd *kce.DataDisk
)

var val map[string]interface{}
advanced := kce.AdvancedSetting{
DataDisk: dd,
PreUserScript: "adds",
UserScript: "sdasad",
Schedulable: false,
Label: []kce.Label{{Key: "tf_assembly_kce", Value: "advanced_setting"}},
ExtraArg: &kce.ExtraArg{
Kubelet: []string{"custom_arg"},
},
ContainerRuntime: "containerd",
ContainerPath: "/data/containerd",
DockerPath: "/data/docker",
ContainerLogMaxFiles: 0,
ContainerLogMaxSize: 0,
Taint: []kce.Taint{
{Key: "key1", Value: "value1", Effect: "effect1"},
{Key: "key2", Value: "value2", Effect: "effect2"},
},
}
err := MapstructureFiller(advanced, &val, "tf-schema")
if err != nil {
t.Errorf("MapstructureFiller() error = %v", err)
return
}
t.Logf("val = %v", val)

}

func TestGetDiffMap(t *testing.T) {
a := map[string]interface{}{
"a": "c",
"v": "v",
"c": "c",
"d": "d",
}
b := map[string]interface{}{
"a": "a",
"v": "v",
"c": "c",
"d": "d",
"e": "e",
}

diff := GetDiffMap(a, b)
t.Logf("diff: %+v", diff)
}
Loading

0 comments on commit 32b0c50

Please sign in to comment.