...
1
16
17 package resource
18
19 import (
20 "fmt"
21 "strings"
22
23 "k8s.io/apimachinery/pkg/runtime/schema"
24 "k8s.io/client-go/dynamic"
25 "k8s.io/client-go/openapi"
26 "k8s.io/client-go/openapi3"
27 "k8s.io/kube-openapi/pkg/spec3"
28 "k8s.io/kube-openapi/pkg/validation/spec"
29 )
30
31 var _ Verifier = &queryParamVerifierV3{}
32
33
34
35
36
37
38 func NewQueryParamVerifierV3(dynamicClient dynamic.Interface, oapiClient openapi.Client, queryParam VerifiableQueryParam) Verifier {
39 return &queryParamVerifierV3{
40 finder: NewCRDFinder(CRDFromDynamic(dynamicClient)),
41 root: openapi3.NewRoot(oapiClient),
42 queryParam: queryParam,
43 }
44 }
45
46
47
48
49 type queryParamVerifierV3 struct {
50 finder CRDFinder
51 root openapi3.Root
52 queryParam VerifiableQueryParam
53 }
54
55 var namespaceGVK = schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Namespace"}
56
57
58
59
60
61
62 func (v *queryParamVerifierV3) HasSupport(gvk schema.GroupVersionKind) error {
63 if (gvk == schema.GroupVersionKind{Version: "v1", Kind: "List"}) {
64 return NewParamUnsupportedError(gvk, v.queryParam)
65 }
66 gvSpec, err := v.root.GVSpec(gvk.GroupVersion())
67 if err == nil {
68 return supportsQueryParamV3(gvSpec, gvk, v.queryParam)
69 }
70 if _, isErr := err.(*openapi3.GroupVersionNotFoundError); !isErr {
71 return err
72 }
73
74
75 if found, _ := v.finder.HasCRD(gvk.GroupKind()); found {
76 namespaceSpec, err := v.root.GVSpec(namespaceGVK.GroupVersion())
77 if err != nil {
78
79 return err
80 }
81 return supportsQueryParamV3(namespaceSpec, namespaceGVK, v.queryParam)
82 }
83 return NewParamUnsupportedError(gvk, v.queryParam)
84 }
85
86
87
88 func hasGVKExtensionV3(extensions spec.Extensions, gvk schema.GroupVersionKind) bool {
89 var oapiGVK map[string]string
90 err := extensions.GetObject("x-kubernetes-group-version-kind", &oapiGVK)
91 if err != nil {
92 return false
93 }
94 if oapiGVK["group"] == gvk.Group &&
95 oapiGVK["version"] == gvk.Version &&
96 oapiGVK["kind"] == gvk.Kind {
97 return true
98 }
99 return false
100 }
101
102
103
104
105
106
107
108 func supportsQueryParamV3(doc *spec3.OpenAPI, gvk schema.GroupVersionKind, queryParam VerifiableQueryParam) error {
109 if doc == nil || doc.Paths == nil {
110 return fmt.Errorf("Invalid OpenAPI V3 document")
111 }
112 for _, path := range doc.Paths.Paths {
113
114 if path == nil {
115 continue
116 }
117 op := path.PathProps.Patch
118 if op == nil {
119 continue
120 }
121
122 if !hasGVKExtensionV3(op.VendorExtensible.Extensions, gvk) {
123 continue
124 }
125
126
127 for _, param := range op.OperationProps.Parameters {
128 if param.ParameterProps.Name == string(queryParam) && param.In == "query" {
129 return nil
130 }
131
132
133 if ref := param.Refable.Ref.Ref.String(); strings.HasPrefix(ref, "#/parameters/") && doc.Components != nil {
134 k := strings.TrimPrefix(ref, "#/parameters/")
135 if globalParam, ok := doc.Components.Parameters[k]; ok && globalParam != nil {
136 if globalParam.In == "query" && globalParam.Name == string(queryParam) {
137 return nil
138 }
139 }
140 }
141 }
142 return NewParamUnsupportedError(gvk, queryParam)
143 }
144 return fmt.Errorf("Path not found for GVK (%s) in OpenAPI V3 doc", gvk)
145 }
146
View as plain text