istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/util/yml/parts.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 "regexp" 19 "strings" 20 21 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 "sigs.k8s.io/yaml" 23 ) 24 25 const ( 26 joinSeparator = "\n---\n" 27 ) 28 29 // Split where the '---' appears at the very beginning of a line. This will avoid 30 // accidentally splitting in cases where yaml resources contain nested yaml (which 31 // is indented). 32 var splitRegex = regexp.MustCompile(`(^|\n)---`) 33 34 // SplitYamlByKind splits the given YAML into parts indexed by kind. 35 func SplitYamlByKind(content string) map[string]string { 36 cfgs := SplitString(content) 37 result := map[string]string{} 38 for _, cfg := range cfgs { 39 var typeMeta metav1.TypeMeta 40 if e := yaml.Unmarshal([]byte(cfg), &typeMeta); e != nil { 41 // Ignore invalid parts. This most commonly happens when it's empty or contains only comments. 42 continue 43 } 44 result[typeMeta.Kind] = JoinString(result[typeMeta.Kind], cfg) 45 } 46 return result 47 } 48 49 // SplitYamlByKind splits the given YAML into parts indexed by kind. 50 func GetMetadata(content string) []metav1.ObjectMeta { 51 cfgs := SplitString(content) 52 result := []metav1.ObjectMeta{} 53 for _, cfg := range cfgs { 54 var m metav1.ObjectMeta 55 if e := yaml.Unmarshal([]byte(cfg), &m); e != nil { 56 // Ignore invalid parts. This most commonly happens when it's empty or contains only comments. 57 continue 58 } 59 result = append(result, m) 60 } 61 return result 62 } 63 64 // SplitString splits the given yaml doc if it's multipart document. 65 func SplitString(yamlText string) []string { 66 out := make([]string, 0) 67 parts := splitRegex.Split(yamlText, -1) 68 for _, part := range parts { 69 part := strings.TrimSpace(part) 70 if len(part) > 0 { 71 out = append(out, part) 72 } 73 } 74 return out 75 } 76 77 // JoinString joins the given yaml parts into a single multipart document. 78 func JoinString(parts ...string) string { 79 // Assume that each part is already a multi-document. Split and trim each part, 80 // if necessary. 81 toJoin := make([]string, 0, len(parts)) 82 for _, part := range parts { 83 toJoin = append(toJoin, SplitString(part)...) 84 } 85 86 return strings.Join(toJoin, joinSeparator) 87 }