| // Copyright Istio Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package codegen |
| |
| import ( |
| "fmt" |
| "sort" |
| "strings" |
| ) |
| |
| import ( |
| "github.com/apache/dubbo-go-pixiu/pkg/config/schema/ast" |
| "github.com/apache/dubbo-go-pixiu/pkg/util/sets" |
| ) |
| |
| const staticResourceTemplate = ` |
| // GENERATED FILE -- DO NOT EDIT |
| // |
| |
| package {{.PackageName}} |
| |
| import ( |
| "github.com/apache/dubbo-go-pixiu/pkg/config" |
| ) |
| |
| var ( |
| {{- range .Entries }} |
| {{.Type}} = config.GroupVersionKind{Group: "{{.Resource.Group}}", Version: "{{.Resource.Version}}", Kind: "{{.Resource.Kind}}"} |
| {{- end }} |
| ) |
| ` |
| |
| const staticCollectionsTemplate = ` |
| {{- .FilePrefix}} |
| // GENERATED FILE -- DO NOT EDIT |
| // |
| |
| package {{.PackageName}} |
| |
| import ( |
| "github.com/apache/dubbo-go-pixiu/pkg/config/schema/collection" |
| "github.com/apache/dubbo-go-pixiu/pkg/config/schema/resource" |
| "github.com/apache/dubbo-go-pixiu/pkg/config/validation" |
| "reflect" |
| {{- range .Packages}} |
| {{.ImportName}} "{{.PackageName}}" |
| {{- end}} |
| ) |
| |
| var ( |
| {{ range .Entries }} |
| {{ commentBlock (wordWrap (printf "%s %s" .Collection.VariableName .Collection.Description) 70) 1 }} |
| {{ .Collection.VariableName }} = collection.Builder { |
| Name: "{{ .Collection.Name }}", |
| VariableName: "{{ .Collection.VariableName }}", |
| Resource: resource.Builder { |
| Group: "{{ .Resource.Group }}", |
| Kind: "{{ .Resource.Kind }}", |
| Plural: "{{ .Resource.Plural }}", |
| Version: "{{ .Resource.Version }}", |
| Proto: "{{ .Resource.Proto }}", |
| {{- if ne .Resource.StatusProto "" }}StatusProto: "{{ .Resource.StatusProto }}",{{end}} |
| ReflectType: {{ .Type }}, |
| {{- if ne .StatusType "" }}StatusType: {{ .StatusType }}, {{end}} |
| ProtoPackage: "{{ .Resource.ProtoPackage }}", |
| {{- if ne "" .Resource.StatusProtoPackage}}StatusPackage: "{{ .Resource.StatusProtoPackage }}", {{end}} |
| ClusterScoped: {{ .Resource.ClusterScoped }}, |
| ValidateProto: validation.{{ .Resource.Validate }}, |
| }.MustBuild(), |
| }.MustBuild() |
| {{ end }} |
| |
| // All contains all collections in the system. |
| All = collection.NewSchemasBuilder(). |
| {{- range .Entries }} |
| MustAdd({{ .Collection.VariableName }}). |
| {{- end }} |
| Build() |
| |
| // Istio contains only Istio collections. |
| Istio = collection.NewSchemasBuilder(). |
| {{- range .Entries }} |
| {{- if (hasPrefix .Collection.Name "istio/") }} |
| MustAdd({{ .Collection.VariableName }}). |
| {{- end}} |
| {{- end }} |
| Build() |
| |
| // Kube contains only kubernetes collections. |
| Kube = collection.NewSchemasBuilder(). |
| {{- range .Entries }} |
| {{- if (hasPrefix .Collection.Name "k8s/") }} |
| MustAdd({{ .Collection.VariableName }}). |
| {{- end }} |
| {{- end }} |
| Build() |
| |
| // Builtin contains only native Kubernetes collections. This differs from Kube, which has |
| // Kubernetes controlled CRDs |
| Builtin = collection.NewSchemasBuilder(). |
| {{- range .Entries }} |
| {{- if .Collection.Builtin }} |
| MustAdd({{ .Collection.VariableName }}). |
| {{- end }} |
| {{- end }} |
| Build() |
| |
| // Pilot contains only collections used by Pilot. |
| Pilot = collection.NewSchemasBuilder(). |
| {{- range .Entries }} |
| {{- if .Collection.Pilot }} |
| MustAdd({{ .Collection.VariableName }}). |
| {{- end}} |
| {{- end }} |
| Build() |
| |
| // PilotGatewayAPI contains only collections used by Pilot, including experimental Service Api. |
| PilotGatewayAPI = collection.NewSchemasBuilder(). |
| {{- range .Entries }} |
| {{- if or (.Collection.Pilot) (hasPrefix .Collection.Name "k8s/gateway_api") }} |
| MustAdd({{ .Collection.VariableName }}). |
| {{- end}} |
| {{- end }} |
| Build() |
| |
| // Deprecated contains only collections used by that will soon be used by nothing. |
| Deprecated = collection.NewSchemasBuilder(). |
| {{- range .Entries }} |
| {{- if .Collection.Deprecated }} |
| MustAdd({{ .Collection.VariableName }}). |
| {{- end}} |
| {{- end }} |
| Build() |
| ) |
| ` |
| |
| type colEntry struct { |
| Collection *ast.Collection |
| Resource *ast.Resource |
| Type string |
| StatusType string |
| } |
| |
| func WriteGvk(packageName string, m *ast.Metadata) (string, error) { |
| entries := make([]colEntry, 0, len(m.Collections)) |
| customNames := map[string]string{ |
| "k8s/gateway_api/v1alpha2/gateways": "KubernetesGateway", |
| } |
| for _, c := range m.Collections { |
| r := m.FindResourceForGroupKind(c.Group, c.Kind) |
| if r == nil { |
| return "", fmt.Errorf("failed to find resource (%s/%s) for collection %s", c.Group, c.Kind, c.Name) |
| } |
| |
| name := r.Kind |
| if cn, f := customNames[c.Name]; f { |
| name = cn |
| } |
| entries = append(entries, colEntry{ |
| Type: name, |
| Resource: r, |
| }) |
| } |
| |
| sort.Slice(entries, func(i, j int) bool { |
| return strings.Compare(entries[i].Type, entries[j].Type) < 0 |
| }) |
| |
| context := struct { |
| Entries []colEntry |
| PackageName string |
| }{ |
| Entries: entries, |
| PackageName: packageName, |
| } |
| |
| // Calculate the Go packages that needs to be imported for the proto types to be registered. |
| return applyTemplate(staticResourceTemplate, context) |
| } |
| |
| type packageImport struct { |
| PackageName string |
| ImportName string |
| } |
| |
| // StaticCollections generates a Go file for static-importing Proto packages, so that they get registered statically. |
| func StaticCollections(packageName string, m *ast.Metadata, filter func(name string) bool, prefix string) (string, error) { |
| entries := make([]colEntry, 0, len(m.Collections)) |
| for _, c := range m.Collections { |
| if !filter(c.Name) { |
| continue |
| } |
| r := m.FindResourceForGroupKind(c.Group, c.Kind) |
| if r == nil { |
| return "", fmt.Errorf("failed to find resource (%s/%s) for collection %s", c.Group, c.Kind, c.Name) |
| } |
| |
| spl := strings.Split(r.Proto, ".") |
| tname := spl[len(spl)-1] |
| stat := strings.Split(r.StatusProto, ".") |
| statName := stat[len(stat)-1] |
| e := colEntry{ |
| Collection: c, |
| Resource: r, |
| Type: fmt.Sprintf("reflect.TypeOf(&%s.%s{}).Elem()", toImport(r.ProtoPackage), tname), |
| } |
| if r.StatusProtoPackage != "" { |
| e.StatusType = fmt.Sprintf("reflect.TypeOf(&%s.%s{}).Elem()", toImport(r.StatusProtoPackage), statName) |
| } |
| entries = append(entries, e) |
| } |
| // Single instance and sort names |
| names := sets.New() |
| |
| for _, r := range m.Resources { |
| if r.ProtoPackage != "" { |
| names.Insert(r.ProtoPackage) |
| } |
| if r.StatusProtoPackage != "" { |
| names.Insert(r.StatusProtoPackage) |
| } |
| } |
| |
| packages := make([]packageImport, 0, names.Len()) |
| for p := range names { |
| packages = append(packages, packageImport{p, toImport(p)}) |
| } |
| sort.Slice(packages, func(i, j int) bool { |
| return strings.Compare(packages[i].PackageName, packages[j].PackageName) < 0 |
| }) |
| |
| sort.Slice(entries, func(i, j int) bool { |
| return strings.Compare(entries[i].Collection.Name, entries[j].Collection.Name) < 0 |
| }) |
| |
| context := struct { |
| Entries []colEntry |
| PackageName string |
| FilePrefix string |
| Packages []packageImport |
| }{ |
| Entries: entries, |
| PackageName: packageName, |
| Packages: packages, |
| FilePrefix: prefix, |
| } |
| |
| // Calculate the Go packages that needs to be imported for the proto types to be registered. |
| return applyTemplate(staticCollectionsTemplate, context) |
| } |
| |
| func toImport(p string) string { |
| return strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(p, "/", ""), ".", ""), "-", "") |
| } |