github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/util/strategicpatch/types.go (about) 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 "github.com/spotmaxtech/k8s-apimachinery-v0260/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 }