| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 main |
| |
| import ( |
| "bytes" |
| "flag" |
| "fmt" |
| "go/format" |
| "log" |
| "os" |
| "path/filepath" |
| "sort" |
| "strings" |
| "text/template" |
| |
| "google.golang.org/protobuf/reflect/protoreflect" |
| "google.golang.org/protobuf/reflect/protoregistry" |
| |
| _ "github.com/apache/dubbo-admin/api/mesh/v1alpha1" |
| ) |
| |
| // resourceTemplate for creating a Dubbo Resource. |
| var resourceTemplate = template.Must(template.New("dubbo-resource").Parse(` |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| // Generated by tools/resourcegen |
| // Run "make generate" to update this file. |
| |
| {{ $pkg := printf "%sproto" .Package }} |
| {{ $tk := "` + "`" + `" }} |
| |
| // nolint:whitespace |
| package v1alpha1 |
| |
| import ( |
| "encoding/json" |
| |
| "google.golang.org/protobuf/proto" |
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
| k8sruntime "k8s.io/apimachinery/pkg/runtime" |
| |
| {{ $pkg }} "github.com/apache/dubbo-admin/api/{{ .Package }}/v1alpha1" |
| "github.com/apache/dubbo-admin/pkg/core/logger" |
| coremodel "github.com/apache/dubbo-admin/pkg/core/resource/model" |
| ) |
| {{range .Resources}} |
| |
| const {{.Name}}Kind coremodel.ResourceKind = "{{.Name}}" |
| |
| func init() { |
| coremodel.RegisterResourceSchema({{.Name}}Kind, New{{.Name}}Resource) |
| } |
| |
| type {{.Name}}Resource struct { |
| |
| metav1.TypeMeta {{ $tk }}json:",inline"{{ $tk }} |
| |
| metav1.ObjectMeta {{ $tk }}json:"metadata,omitempty"{{ $tk }} |
| |
| // Mesh is the name of the dubbo mesh this resource belongs to. |
| // It may be omitted for cluster-scoped resources. |
| Mesh string {{ $tk }}json:"mesh,omitempty"{{ $tk }} |
| |
| // Spec is the specification of the Dubbo {{ .ProtoType }} resource. |
| Spec *{{$pkg}}.{{.Name}} {{ $tk }}json:"spec,omitempty"{{ $tk }} |
| |
| // Status is the status of the Dubbo {{.Name}} resource. |
| Status {{.Name}}ResourceStatus {{ $tk }}json:"status,omitempty"{{ $tk }} |
| } |
| |
| type {{.Name}}ResourceStatus struct { |
| // define resource-specific status here |
| } |
| |
| type {{.Name}}ResourceList struct { |
| metav1.TypeMeta {{ $tk }}json:",inline"{{ $tk }} |
| metav1.ListMeta {{ $tk }}json:"metadata,omitempty"{{ $tk }} |
| Items []{{.Name}}Resource {{ $tk }}json:"items"{{ $tk }} |
| } |
| |
| func (r *{{.Name}}Resource) ResourceKind() coremodel.ResourceKind { |
| return {{.Name}}Kind |
| } |
| |
| func (r *{{.Name}}Resource) MeshName() string { |
| return r.Mesh |
| } |
| |
| func (r *{{.Name}}Resource) ResourceKey() string { |
| return coremodel.BuildResourceKey(r.Mesh, r.Name) |
| } |
| |
| func (r *{{.Name}}Resource) ResourceMeta() metav1.ObjectMeta { |
| return r.ObjectMeta |
| } |
| |
| func (r *{{.Name}}Resource) ResourceSpec() coremodel.ResourceSpec { |
| return r.Spec |
| } |
| func (r *{{.Name}}Resource) DeepCopyObject() k8sruntime.Object { |
| if r == nil { |
| return nil |
| } |
| |
| out := &{{.Name}}Resource{ |
| TypeMeta: r.TypeMeta, |
| Mesh: r.Mesh, |
| Status: r.Status, |
| } |
| |
| r.ObjectMeta.DeepCopyInto(&out.ObjectMeta) |
| |
| if r.Spec != nil { |
| spec, ok := proto.Clone(r.Spec).(*{{ $pkg }}.{{.Name}}) |
| if !ok { |
| logger.Warnf("failed to clone spec %v, spec is not conformed to %s", r.Spec, r.ResourceKind()) |
| return out |
| } |
| out.Spec = spec |
| } |
| |
| return out |
| } |
| |
| func (r *{{.Name}}Resource) String() string { |
| jsonStr, err := json.Marshal(r) |
| if err != nil { |
| logger.Errorf("failed to encode {{.Name}}Resource: %s to json, err: %w", r.ResourceKey(), err) |
| return "" |
| } |
| return string(jsonStr) |
| } |
| |
| func New{{.Name}}ResourceWithAttributes(name string, mesh string) *{{.Name}}Resource{ |
| return &{{.Name}}Resource{ |
| TypeMeta: metav1.TypeMeta{ |
| Kind: string({{.Name}}Kind), |
| APIVersion: "v1alpha1", |
| }, |
| ObjectMeta: metav1.ObjectMeta{ |
| Name: name, |
| Labels: map[string]string{}, |
| }, |
| Mesh: mesh, |
| } |
| } |
| |
| func New{{.Name}}Resource() coremodel.Resource { |
| return &{{.Name}}Resource{ |
| TypeMeta: metav1.TypeMeta{ |
| Kind: string({{.Name}}Kind), |
| APIVersion: "v1alpha1", |
| }, |
| } |
| } |
| |
| |
| {{- end }} {{/* Resources */}} |
| `)) |
| |
| // ProtoMessageFunc ... |
| type ProtoMessageFunc func(protoreflect.MessageType) bool |
| |
| // OnDubboResourceMessage ... |
| func OnDubboResourceMessage(pkg string, f ProtoMessageFunc) ProtoMessageFunc { |
| return func(m protoreflect.MessageType) bool { |
| r := DubboResourceForMessage(m.Descriptor()) |
| if r == nil { |
| return true |
| } |
| |
| fullname := string(m.Descriptor().FullName()) |
| if strings.Contains(fullname, "legacy") { |
| log.Printf("Skipping message: %s", fullname) |
| return true |
| } |
| if r.Package == pkg { |
| return f(m) |
| } |
| |
| return true |
| } |
| } |
| |
| func main() { |
| var pkg string |
| var outputDir string |
| |
| flag.StringVar(&pkg, "package", "", "the name of the package to generate: (mesh, system)") |
| flag.StringVar(&outputDir, "output", "", "the directory to write generated files") |
| flag.Parse() |
| |
| switch pkg { |
| case "mesh", "system": |
| default: |
| log.Fatalf("package %s is not supported", pkg) |
| } |
| |
| if err := os.MkdirAll(outputDir, 0755); err != nil { |
| log.Fatalf("failed to create output dir: %v", err) |
| } |
| |
| var types []protoreflect.MessageType |
| protoregistry.GlobalTypes.RangeMessages( |
| OnDubboResourceMessage(pkg, func(m protoreflect.MessageType) bool { |
| types = append(types, m) |
| return true |
| })) |
| |
| // Sort by name so the output is deterministic. |
| sort.Slice(types, func(i, j int) bool { |
| return types[i].Descriptor().FullName() < types[j].Descriptor().FullName() |
| }) |
| |
| var resources []ResourceInfo |
| for _, t := range types { |
| resourceInfo := ToResourceInfo(t.Descriptor()) |
| resources = append(resources, resourceInfo) |
| } |
| |
| for _, resource := range resources { |
| var buf bytes.Buffer |
| if err := resourceTemplate.Execute(&buf, struct { |
| Package string |
| Resources []ResourceInfo |
| }{ |
| Package: pkg, |
| Resources: []ResourceInfo{resource}, |
| }); err != nil { |
| log.Fatalf("template error for %s: %s", resource.Name, err) |
| } |
| |
| out, err := format.Source(buf.Bytes()) |
| if err != nil { |
| log.Fatalf("format error for %s: %s", resource.Name, err) |
| } |
| |
| filename := filepath.Join(outputDir, fmt.Sprintf("%s_types.go", strings.ToLower(resource.Name))) |
| if err := os.WriteFile(filename, out, 0644); err != nil { |
| log.Fatalf("write file error for %s: %s", filename, err) |
| } |
| |
| log.Printf("Generated: %s", filename) |
| } |
| } |