-
Notifications
You must be signed in to change notification settings - Fork 0
/
jsonpath_renderer.go
153 lines (138 loc) · 5.15 KB
/
jsonpath_renderer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package structemplate
import (
"fmt"
"reflect"
"strconv"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// RenderJsonPathParams 为一个Unstructured对象渲染一组JsonPath param
func RenderJsonPathParams(objsMap map[schema.GroupVersionKind][]*unstructured.Unstructured, paramsDef []TemplateDynamicParam, valuesMap map[string]interface{}) error {
var err error = nil
for _, param := range paramsDef {
if param.ParamType != ParamTypeJsonPath {
// skip non-JsonPath type params
continue
}
// for every inject target object set value of that json path
for _, gvkTarget := range param.ValueInjectTargets {
value, exist := valuesMap[param.ParamCode]
if !exist {
value = param.Default
}
if value == nil {
if param.Optional {
continue
}
return errors.New("必填参数缺失:" + param.ParamCode)
}
err = RenderObjsWithOneJsonPathParam(objsMap[gvkTarget.TargetGVK], ¶m, &gvkTarget, value)
if err != nil {
break
}
}
}
return err
}
func RenderObjsWithOneJsonPathParam(objs []*unstructured.Unstructured, paramDef *TemplateDynamicParam, paramPath *JsonPathParamTarget, value interface{}) error {
var err error = nil
for _, obj := range objs {
if err = RenderJsonPathParamForUnstructuredObj(obj, paramDef, paramPath, value); err != nil {
break
}
}
return err
}
// RenderJsonPathParamForUnstructuredObj 为一个Unstructured Object渲染一个参数,自动识别label selector并过滤
func RenderJsonPathParamForUnstructuredObj(obj *unstructured.Unstructured, paramDef *TemplateDynamicParam, paramPath *JsonPathParamTarget, value interface{}) error {
// 处理数组元素追加模式
if paramDef.AppendArray {
if err := AppendArrayField(obj, paramPath.ParamJsonPath, value); err != nil {
return err
}
return nil
}
// 处理MapKV追加模式
if len(paramDef.MapKey) > 0 {
if err := AppendMapForUnstructuredObj(obj, paramPath.ParamJsonPath, paramDef.MapKey, value); err != nil {
return err
}
return nil
}
// 处理一般属性设置模式
if err := SetValueOfUnstructredObj(obj, paramPath.ParamJsonPath, value); err != nil {
return err
}
return nil
}
// AppendArrayField 为指定Unstructured对象的数组类型字段增加值
// *将自动判断keyPath指定对象是否为数组类型,或为空时自动创建数组
// *若keyPath位置的值不是数组类型,则抛出错误
func AppendArrayField(obj *unstructured.Unstructured, keyPath string, value interface{}) error {
return SetNestedField(obj.Object, keyPath, value, true)
// kp := parseKeyPath(keyPath)
// subObj, exists, err := unstructured.NestedFieldNoCopy(obj.Object, kp...)
// if err != nil {
// return err
// }
// if !exists {
// // 全新字段,创建数组直接设置
// unstructured.SetNestedField(obj.Object, []interface{}{value}, kp...)
// } else {
// // 检查数据类型为slice
// t := reflect.TypeOf(subObj)
// switch t.Kind() {
// case reflect.Slice, reflect.Array:
// subObj, ok := subObj.([]interface{})
// if !ok {
// return errors.New("转换目标字段为slice出错:" + keyPath)
// }
// newSli := append(subObj, value)
// // 重新替换
// return SetNestedField(obj.Object, kp[:len(kp)-1], newSli, true)
// default:
// return errors.New("目标字段不是slice或array")
// }
// }
// return nil
}
// SetValueOfUnstructredObj 为指定的Unstructured对象在keyPath指定的位置上设置任意值
// keyPath: `.spec.name1.name2` 格式的json path表达式
// value: 需要设置的任意值
//
// 为Unstructured对象指定属性设置指定value,不支持嵌套map中使用带'.'的key
func SetValueOfUnstructredObj(obj *unstructured.Unstructured, jsonPathKey string, value interface{}) error {
return AppendMapForUnstructuredObj(obj, jsonPathKey, "", value)
}
// AppendMapForUnstructuredObj 为Unstructured对象指定属性设置指定value,针对map对象添加属性支持带有'.'的key
func AppendMapForUnstructuredObj(obj *unstructured.Unstructured, mapParamJsonPathKey string, key string, value interface{}) error {
processFunc := func(targetValue interface{}) error {
// 完成参数设定
// 解析jsonPath表达式 e.g. `.metadata.namespace` --> []string{"metadata", "namespace"}
// jsonPathArr := parseKeyPath(mapParamJsonPathKey)
// if len(key) > 0 {
// jsonPathArr = append(jsonPathArr, key)
// }
return SetNestedField(obj.Object, fmt.Sprintf("%s.%s", mapParamJsonPathKey, key), targetValue, false)
}
safeValue := reflect.ValueOf(value)
switch safeValue.Kind() {
case reflect.Slice:
genericSlice := make([]interface{}, safeValue.Len())
for i := 0; i < safeValue.Len(); i++ {
genericSlice[i] = safeValue.Index(i).Interface()
}
return processFunc(genericSlice)
case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint8, reflect.Int, reflect.Int16, reflect.Int32, reflect.Int8:
intV, err := strconv.ParseInt(fmt.Sprintf("%d", value), 10, 64)
if err != nil {
return errors.Wrap(err, "整数型参数解析出错")
}
return processFunc(intV)
case reflect.Float32, reflect.Float64:
return processFunc(value.(float64))
default:
return processFunc(value)
}
}