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  }