istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/util/yml/apply.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package yml 16 17 import ( 18 "fmt" 19 "reflect" 20 21 appsv1 "k8s.io/api/apps/v1" 22 "k8s.io/apimachinery/pkg/util/strategicpatch" 23 "sigs.k8s.io/yaml" 24 25 "istio.io/istio/pkg/test" 26 "istio.io/istio/pkg/test/util/tmpl" 27 ) 28 29 // ApplyNamespace applies the given namespaces to the resources in the yamlText if not set. 30 func ApplyNamespace(yamlText, ns string) (string, error) { 31 chunks := SplitString(yamlText) 32 33 toJoin := make([]string, 0, len(chunks)) 34 for _, chunk := range chunks { 35 chunk, err := applyNamespace(chunk, ns) 36 if err != nil { 37 return "", err 38 } 39 toJoin = append(toJoin, chunk) 40 } 41 42 result := JoinString(toJoin...) 43 return result, nil 44 } 45 46 // ApplyPullSecrets applies the given pullsecret to the deployment resource 47 func ApplyPullSecret(deploymentYaml string, pullSecret string) (string, error) { 48 var deploymentMerge appsv1.Deployment 49 50 mainYaml, err := yaml.YAMLToJSON([]byte(deploymentYaml)) 51 if err != nil { 52 return "", fmt.Errorf("yamlToJSON error in base: %s\n%s", err, mainYaml) 53 } 54 55 patchYaml := tmpl.MustEvaluate(` 56 spec: 57 template: 58 spec: 59 imagePullSecrets: 60 - name: {{.pullSecret}} 61 `, map[string]string{"pullSecret": pullSecret}) 62 63 overlayYaml, err := yaml.YAMLToJSON([]byte(patchYaml)) 64 if err != nil { 65 return "", fmt.Errorf("yamlToJSON error in overlay: %s\n%s", err, overlayYaml) 66 } 67 68 merged, err := strategicpatch.StrategicMergePatch(mainYaml, overlayYaml, &deploymentMerge) 69 if err != nil { 70 return "", fmt.Errorf("json merge error (%s) for base object: \n%s\n override object: \n%s", err, mainYaml, overlayYaml) 71 } 72 73 resYaml, err := yaml.JSONToYAML(merged) 74 if err != nil { 75 return "", fmt.Errorf("jsonToYAML error (%s) for merged object: \n%s", err, merged) 76 } 77 return string(resYaml), nil 78 } 79 80 // MustApplyNamespace applies the given namespaces to the resources in the yamlText if not set. 81 func MustApplyNamespace(t test.Failer, yamlText, ns string) string { 82 y, err := ApplyNamespace(yamlText, ns) 83 if err != nil { 84 t.Fatalf("ApplyNamespace: %v for text %v", err, yamlText) 85 } 86 return y 87 } 88 89 func ApplyAnnotation(yamlText, k, v string) (string, error) { 90 m := make(map[string]any) 91 if err := yaml.Unmarshal([]byte(yamlText), &m); err != nil { 92 return "", err 93 } 94 95 meta, err := ensureChildMap(m, "metadata") 96 if err != nil { 97 return "", err 98 } 99 if meta["annotations"] != nil { 100 meta["annotations"].(map[string]string)[k] = v 101 } else { 102 an := map[string]string{k: v} 103 meta["annotations"] = an 104 } 105 106 by, err := yaml.Marshal(m) 107 if err != nil { 108 return "", err 109 } 110 111 return string(by), nil 112 } 113 114 func applyNamespace(yamlText, ns string) (string, error) { 115 m := make(map[string]any) 116 if err := yaml.Unmarshal([]byte(yamlText), &m); err != nil { 117 return "", err 118 } 119 120 meta, err := ensureChildMap(m, "metadata") 121 if err != nil { 122 return "", err 123 } 124 if meta["namespace"] != nil && meta["namespace"] != "" { 125 return yamlText, nil 126 } 127 meta["namespace"] = ns 128 129 by, err := yaml.Marshal(m) 130 if err != nil { 131 return "", err 132 } 133 134 return string(by), nil 135 } 136 137 func ensureChildMap(m map[string]any, name string) (map[string]any, error) { 138 c, ok := m[name] 139 if !ok { 140 c = make(map[string]any) 141 } 142 143 cm, ok := c.(map[string]any) 144 if !ok { 145 return nil, fmt.Errorf("child %q field is not a map: %v", name, reflect.TypeOf(c)) 146 } 147 148 return cm, nil 149 }