Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / k8s.io / apimachinery / pkg / util / strategicpatch / types.go
1 /*
2 Copyright 2017 The Kubernetes Authors.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 package strategicpatch
18
19 import (
20         "errors"
21         "strings"
22
23         "k8s.io/apimachinery/pkg/util/mergepatch"
24         openapi "k8s.io/kube-openapi/pkg/util/proto"
25 )
26
27 const (
28         patchStrategyOpenapiextensionKey = "x-kubernetes-patch-strategy"
29         patchMergeKeyOpenapiextensionKey = "x-kubernetes-patch-merge-key"
30 )
31
32 type LookupPatchItem interface {
33         openapi.SchemaVisitor
34
35         Error() error
36         Path() *openapi.Path
37 }
38
39 type kindItem struct {
40         key          string
41         path         *openapi.Path
42         err          error
43         patchmeta    PatchMeta
44         subschema    openapi.Schema
45         hasVisitKind bool
46 }
47
48 func NewKindItem(key string, path *openapi.Path) *kindItem {
49         return &kindItem{
50                 key:  key,
51                 path: path,
52         }
53 }
54
55 var _ LookupPatchItem = &kindItem{}
56
57 func (item *kindItem) Error() error {
58         return item.err
59 }
60
61 func (item *kindItem) Path() *openapi.Path {
62         return item.path
63 }
64
65 func (item *kindItem) VisitPrimitive(schema *openapi.Primitive) {
66         item.err = errors.New("expected kind, but got primitive")
67 }
68
69 func (item *kindItem) VisitArray(schema *openapi.Array) {
70         item.err = errors.New("expected kind, but got slice")
71 }
72
73 func (item *kindItem) VisitMap(schema *openapi.Map) {
74         item.err = errors.New("expected kind, but got map")
75 }
76
77 func (item *kindItem) VisitReference(schema openapi.Reference) {
78         if !item.hasVisitKind {
79                 schema.SubSchema().Accept(item)
80         }
81 }
82
83 func (item *kindItem) VisitKind(schema *openapi.Kind) {
84         subschema, ok := schema.Fields[item.key]
85         if !ok {
86                 item.err = FieldNotFoundError{Path: schema.GetPath().String(), Field: item.key}
87                 return
88         }
89
90         mergeKey, patchStrategies, err := parsePatchMetadata(subschema.GetExtensions())
91         if err != nil {
92                 item.err = err
93                 return
94         }
95         item.patchmeta = PatchMeta{
96                 patchStrategies: patchStrategies,
97                 patchMergeKey:   mergeKey,
98         }
99         item.subschema = subschema
100 }
101
102 type sliceItem struct {
103         key          string
104         path         *openapi.Path
105         err          error
106         patchmeta    PatchMeta
107         subschema    openapi.Schema
108         hasVisitKind bool
109 }
110
111 func NewSliceItem(key string, path *openapi.Path) *sliceItem {
112         return &sliceItem{
113                 key:  key,
114                 path: path,
115         }
116 }
117
118 var _ LookupPatchItem = &sliceItem{}
119
120 func (item *sliceItem) Error() error {
121         return item.err
122 }
123
124 func (item *sliceItem) Path() *openapi.Path {
125         return item.path
126 }
127
128 func (item *sliceItem) VisitPrimitive(schema *openapi.Primitive) {
129         item.err = errors.New("expected slice, but got primitive")
130 }
131
132 func (item *sliceItem) VisitArray(schema *openapi.Array) {
133         if !item.hasVisitKind {
134                 item.err = errors.New("expected visit kind first, then visit array")
135         }
136         subschema := schema.SubType
137         item.subschema = subschema
138 }
139
140 func (item *sliceItem) VisitMap(schema *openapi.Map) {
141         item.err = errors.New("expected slice, but got map")
142 }
143
144 func (item *sliceItem) VisitReference(schema openapi.Reference) {
145         if !item.hasVisitKind {
146                 schema.SubSchema().Accept(item)
147         } else {
148                 item.subschema = schema.SubSchema()
149         }
150 }
151
152 func (item *sliceItem) VisitKind(schema *openapi.Kind) {
153         subschema, ok := schema.Fields[item.key]
154         if !ok {
155                 item.err = FieldNotFoundError{Path: schema.GetPath().String(), Field: item.key}
156                 return
157         }
158
159         mergeKey, patchStrategies, err := parsePatchMetadata(subschema.GetExtensions())
160         if err != nil {
161                 item.err = err
162                 return
163         }
164         item.patchmeta = PatchMeta{
165                 patchStrategies: patchStrategies,
166                 patchMergeKey:   mergeKey,
167         }
168         item.hasVisitKind = true
169         subschema.Accept(item)
170 }
171
172 func parsePatchMetadata(extensions map[string]interface{}) (string, []string, error) {
173         ps, foundPS := extensions[patchStrategyOpenapiextensionKey]
174         var patchStrategies []string
175         var mergeKey, patchStrategy string
176         var ok bool
177         if foundPS {
178                 patchStrategy, ok = ps.(string)
179                 if ok {
180                         patchStrategies = strings.Split(patchStrategy, ",")
181                 } else {
182                         return "", nil, mergepatch.ErrBadArgType(patchStrategy, ps)
183                 }
184         }
185         mk, foundMK := extensions[patchMergeKeyOpenapiextensionKey]
186         if foundMK {
187                 mergeKey, ok = mk.(string)
188                 if !ok {
189                         return "", nil, mergepatch.ErrBadArgType(mergeKey, mk)
190                 }
191         }
192         return mergeKey, patchStrategies, nil
193 }