istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/config/schema/codegen/common.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 codegen 16 17 import ( 18 "bytes" 19 "errors" 20 "fmt" 21 "os" 22 "os/exec" 23 "path/filepath" 24 "sort" 25 "strings" 26 "text/template" 27 28 "istio.io/istio/pilot/pkg/features" 29 "istio.io/istio/pkg/config/schema/ast" 30 "istio.io/istio/pkg/test/env" 31 ) 32 33 func Run() error { 34 inp, err := buildInputs() 35 if err != nil { 36 return err 37 } 38 39 // Include synthetic types used for XDS pushes 40 kindEntries := append([]colEntry{ 41 { 42 Resource: &ast.Resource{Identifier: "Address", Kind: "Address", Version: "internal", Group: "internal"}, 43 }, 44 { 45 Resource: &ast.Resource{Identifier: "DNSName", Kind: "DNSName", Version: "internal", Group: "internal"}, 46 }, 47 }, inp.Entries...) 48 49 sort.Slice(kindEntries, func(i, j int) bool { 50 return strings.Compare(kindEntries[i].Resource.Identifier, kindEntries[j].Resource.Identifier) < 0 51 }) 52 53 // filter to only types agent needs (to keep binary small) 54 agentEntries := []colEntry{} 55 for _, e := range inp.Entries { 56 if strings.Contains(e.Resource.ProtoPackage, "istio.io") && 57 e.Resource.Kind != "EnvoyFilter" { 58 agentEntries = append(agentEntries, e) 59 } 60 } 61 62 // add MCS types 63 gvrEntries := append([]colEntry{ 64 {Resource: &ast.Resource{Identifier: "ServiceExport", Plural: "serviceexports", Version: features.MCSAPIVersion, Group: features.MCSAPIGroup}}, 65 {Resource: &ast.Resource{Identifier: "ServiceImport", Plural: "serviceimports", Version: features.MCSAPIVersion, Group: features.MCSAPIGroup}}, 66 }, inp.Entries...) 67 68 return errors.Join( 69 writeTemplate("pkg/config/schema/gvk/resources.gen.go", gvkTemplate, map[string]any{ 70 "Entries": inp.Entries, 71 "PackageName": "gvk", 72 }), 73 writeTemplate("pkg/config/schema/gvr/resources.gen.go", gvrTemplate, map[string]any{ 74 "Entries": gvrEntries, 75 "PackageName": "gvr", 76 }), 77 writeTemplate("pilot/pkg/config/kube/crdclient/types.gen.go", crdclientTemplate, map[string]any{ 78 "Entries": inp.Entries, 79 "Packages": inp.Packages, 80 "PackageName": "crdclient", 81 }), 82 writeTemplate("pkg/config/schema/kubetypes/resources.gen.go", typesTemplate, map[string]any{ 83 "Entries": inp.Entries, 84 "Packages": inp.Packages, 85 "PackageName": "kubetypes", 86 }), 87 writeTemplate("pkg/config/schema/kubeclient/resources.gen.go", clientsTemplate, map[string]any{ 88 "Entries": inp.Entries, 89 "Packages": inp.Packages, 90 "PackageName": "kubeclient", 91 }), 92 writeTemplate("pilot/pkg/config/kube/crdclient/types.gen.go", crdclientTemplate, map[string]any{ 93 "Entries": inp.Entries, 94 "Packages": inp.Packages, 95 "PackageName": "crdclient", 96 }), 97 writeTemplate("pkg/config/schema/kind/resources.gen.go", kindTemplate, map[string]any{ 98 "Entries": kindEntries, 99 "PackageName": "kind", 100 }), 101 writeTemplate("pkg/config/schema/collections/collections.gen.go", collectionsTemplate, map[string]any{ 102 "Entries": inp.Entries, 103 "Packages": inp.Packages, 104 "PackageName": "collections", 105 "FilePrefix": "// +build !agent", 106 "CustomImport": ` "istio.io/istio/pkg/config/validation/envoyfilter"`, 107 }), 108 writeTemplate("pkg/config/schema/collections/collections.agent.gen.go", collectionsTemplate, map[string]any{ 109 "Entries": agentEntries, 110 "Packages": inp.Packages, 111 "PackageName": "collections", 112 "FilePrefix": "// +build agent", 113 "CustomImport": "", 114 }), 115 ) 116 } 117 118 func writeTemplate(path, tmpl string, i any) error { 119 t, err := applyTemplate(tmpl, i) 120 if err != nil { 121 return fmt.Errorf("apply template %v: %v", path, err) 122 } 123 dst := filepath.Join(env.IstioSrc, path) 124 if err = os.WriteFile(dst, []byte(t), os.ModePerm); err != nil { 125 return fmt.Errorf("write template %v: %v", path, err) 126 } 127 c := exec.Command("goimports", "-w", "-local", "istio.io", dst) 128 c.Stdout = os.Stdout 129 c.Stderr = os.Stderr 130 return c.Run() 131 } 132 133 func applyTemplate(tmpl string, i any) (string, error) { 134 t := template.New("tmpl").Funcs(template.FuncMap{ 135 "contains": strings.Contains, 136 }) 137 138 t2 := template.Must(t.Parse(tmpl)) 139 140 var b bytes.Buffer 141 if err := t2.Execute(&b, i); err != nil { 142 return "", err 143 } 144 145 return b.String(), nil 146 }