blob: 9270d26320be3a3976cf3c0b415382e87b1cc2d8 [file] [log] [blame]
Matthias Andreas Benkard832a54e2019-01-29 09:27:38 +01001/*
2Copyright 2018 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package generators
18
19import (
20 "fmt"
21 "io"
22
23 "k8s.io/kube-openapi/pkg/generators/rules"
24
25 "github.com/golang/glog"
26 "k8s.io/gengo/types"
27)
28
29// apiLinter is the framework hosting mutliple API rules and recording API rule
30// violations
31type apiLinter struct {
32 // API rules that implement APIRule interface and output API rule violations
33 rules []APIRule
34 violations []apiViolation
35}
36
37// newAPILinter creates an apiLinter object with API rules in package rules. Please
38// add APIRule here when new API rule is implemented.
39func newAPILinter() *apiLinter {
40 return &apiLinter{
41 rules: []APIRule{
42 &rules.NamesMatch{},
43 },
44 }
45}
46
47// apiViolation uniquely identifies single API rule violation
48type apiViolation struct {
49 // Name of rule from APIRule.Name()
50 rule string
51
52 packageName string
53 typeName string
54
55 // Optional: name of field that violates API rule. Empty fieldName implies that
56 // the entire type violates the rule.
57 field string
58}
59
60// APIRule is the interface for validating API rule on Go types
61type APIRule interface {
62 // Validate evaluates API rule on type t and returns a list of field names in
63 // the type that violate the rule. Empty field name [""] implies the entire
64 // type violates the rule.
65 Validate(t *types.Type) ([]string, error)
66
67 // Name returns the name of APIRule
68 Name() string
69}
70
71// validate runs all API rules on type t and records any API rule violation
72func (l *apiLinter) validate(t *types.Type) error {
73 for _, r := range l.rules {
74 glog.V(5).Infof("validating API rule %v for type %v", r.Name(), t)
75 fields, err := r.Validate(t)
76 if err != nil {
77 return err
78 }
79 for _, field := range fields {
80 l.violations = append(l.violations, apiViolation{
81 rule: r.Name(),
82 packageName: t.Name.Package,
83 typeName: t.Name.Name,
84 field: field,
85 })
86 }
87 }
88 return nil
89}
90
91// report prints any API rule violation to writer w and returns error if violation exists
92func (l *apiLinter) report(w io.Writer) error {
93 for _, v := range l.violations {
94 fmt.Fprintf(w, "API rule violation: %s,%s,%s,%s\n", v.rule, v.packageName, v.typeName, v.field)
95 }
96 if len(l.violations) > 0 {
97 return fmt.Errorf("API rule violations exist")
98 }
99 return nil
100}