| /* |
| * 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 schema |
| |
| import ( |
| "fmt" |
| |
| "github.com/apache/dubbo-kubernetes/pkg/core/schema/ast" |
| "github.com/apache/dubbo-kubernetes/pkg/core/schema/collection" |
| "github.com/apache/dubbo-kubernetes/pkg/core/schema/resource" |
| resource2 "github.com/apache/dubbo-kubernetes/pkg/core/tools/resource" |
| "github.com/apache/dubbo-kubernetes/pkg/core/validation" |
| "github.com/google/go-cmp/cmp" |
| ) |
| |
| type Metadata struct { |
| collections collection.Schemas |
| } |
| |
| // AllCollections is all known collections |
| func (m *Metadata) AllCollections() collection.Schemas { return m.collections } |
| |
| func (m *Metadata) Equal(o *Metadata) bool { |
| return cmp.Equal(m.collections, o.collections) |
| } |
| |
| // ParseAndBuild parses the given metadata file and returns the strongly typed schema. |
| func ParseAndBuild(yamlText string) (*Metadata, error) { |
| mast, err := ast.Parse(yamlText) |
| if err != nil { |
| return nil, err |
| } |
| |
| return Build(mast) |
| } |
| |
| // Build strongly-typed Metadata from parsed AST. |
| func Build(astm *ast.Metadata) (*Metadata, error) { |
| resourceKey := func(group, kind string) string { |
| return group + "/" + kind |
| } |
| |
| resources := make(map[string]resource.Schema) |
| for i, ar := range astm.Resources { |
| if ar.Kind == "" { |
| return nil, fmt.Errorf("resource %d missing type", i) |
| } |
| if ar.Plural == "" { |
| return nil, fmt.Errorf("resource %d missing type", i) |
| } |
| if ar.Version == "" { |
| return nil, fmt.Errorf("resource %d missing type", i) |
| } |
| if ar.Proto == "" { |
| return nil, fmt.Errorf("resource %d missing type", i) |
| } |
| if ar.Validate == "" { |
| validateFn := "Validate" + resource2.CamelCase(ar.Kind) |
| if !validation.IsValidateFunc(validateFn) { |
| validateFn = "EmptyValidate" |
| } |
| ar.Validate = validateFn |
| } |
| validateFn := validation.GetValidateFunc(ar.Validate) |
| if validateFn == nil { |
| return nil, fmt.Errorf("failed locating proto validation function %s", ar.Validate) |
| } |
| |
| r := resource.Builder{ |
| ClusterScoped: ar.ClusterScoped, |
| Kind: ar.Kind, |
| Plural: ar.Plural, |
| Group: ar.Group, |
| Version: ar.Version, |
| Proto: ar.Proto, |
| ValidateProto: validateFn, |
| }.BuildNoValidate() |
| |
| key := resourceKey(ar.Group, ar.Kind) |
| if _, ok := resources[key]; ok { |
| return nil, fmt.Errorf("found duplicate resource for resource (%s)", key) |
| } |
| resources[key] = r |
| } |
| |
| cBuilder := collection.NewSchemasBuilder() |
| for _, c := range astm.Collections { |
| key := resourceKey(c.Group, c.Kind) |
| r, found := resources[key] |
| if !found { |
| return nil, fmt.Errorf("failed locating resource (%s) for collection %s", key, c.Name) |
| } |
| |
| s, err := collection.Builder{ |
| Name: c.Name, |
| Resource: r, |
| }.Build() |
| if err != nil { |
| return nil, err |
| } |
| |
| if err = cBuilder.Add(s); err != nil { |
| return nil, err |
| } |
| } |
| |
| collections := cBuilder.Build() |
| |
| return &Metadata{ |
| collections: collections, |
| }, nil |
| } |