diff --git a/go.mod b/go.mod index 1829a233fb9b..d01ee7baaf27 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a // indirect k8s.io/klog v0.3.1 k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 - sigs.k8s.io/controller-runtime v0.2.0-beta.2 + sigs.k8s.io/controller-runtime v0.2.0-beta.3 sigs.k8s.io/controller-tools v0.2.0-beta.2.0.20190610175510-203d8e8ab133 sigs.k8s.io/testing_frameworks v0.1.2-0.20190130140139-57f07443c2d4 ) diff --git a/go.sum b/go.sum index 94f60856cfe9..e3f79412faec 100644 --- a/go.sum +++ b/go.sum @@ -21,8 +21,6 @@ github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMx github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/appscode/jsonpatch v0.0.0-20190108182946-7c0e3b262f30 h1:Kn3rqvbUFqSepE2OqVu0Pn1CbDw9IuMlONapol0zuwk= -github.com/appscode/jsonpatch v0.0.0-20190108182946-7c0e3b262f30/go.mod h1:4AJxUpXUhv4N+ziTvIcWWXgeorXpxPZOfk9HdEVr96M= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4= @@ -36,9 +34,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/evanphx/json-patch v4.0.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.1.0+incompatible h1:K1MDoo4AZ4wU0GIU/fPmtZg7VpzLjCxu+UwBD1FvwOc= -github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= +github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -222,6 +219,8 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190501045030-23463209683d h1:D7DVZUZEUgsSIDTivnUtVeGfN5AvhDIKtdIZAqx0ieE= golang.org/x/tools v0.0.0-20190501045030-23463209683d/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +gomodules.xyz/jsonpatch/v2 v2.0.0 h1:OyHbl+7IOECpPKfVK42oFr6N7+Y2dR+Jsb/IiDV3hOo= +gomodules.xyz/jsonpatch/v2 v2.0.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= google.golang.org/api v0.3.1 h1:oJra/lMfmtm13/rgY/8i3MzjFWYXvQIAKjQ3HqofMk8= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -276,8 +275,8 @@ k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c h1:3KSCztE7gPitlZmWbNwue/ k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 h1:VBM/0P5TWxwk+Nw6Z+lAw3DKgO76g90ETOiA6rfLV1Y= k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -sigs.k8s.io/controller-runtime v0.2.0-beta.2 h1:hOWldx1qmGI9TsU+uUsq1xTgVmUV7AZo08VAYX0dwGI= -sigs.k8s.io/controller-runtime v0.2.0-beta.2/go.mod h1:TSH2R0nSz4WAlUUlNnOFcOR/VUhfwBLlmtq2X6AiQCA= +sigs.k8s.io/controller-runtime v0.2.0-beta.3 h1:K3dddu6/pOVORH2dBOnEbXif6R80oSDa4y/t1jhoh8s= +sigs.k8s.io/controller-runtime v0.2.0-beta.3/go.mod h1:HweyYKQ8fBuzdu2bdaeBJvsFgAi/OqBBnrVGXcqKhME= sigs.k8s.io/controller-tools v0.2.0-beta.2.0.20190610175510-203d8e8ab133 h1:snHWE0FBZKrXqKguv+fz6SrtTtXTc5iYxWzhycBAygE= sigs.k8s.io/controller-tools v0.2.0-beta.2.0.20190610175510-203d8e8ab133/go.mod h1:gC5UAnK1jbxWnDaqTi0yxKIsRsRwshzeRtTUGbM9vos= sigs.k8s.io/testing_frameworks v0.1.1 h1:cP2l8fkA3O9vekpy5Ks8mmA0NW/F7yBdXf8brkWhVrs= diff --git a/vendor/github.com/appscode/jsonpatch/.gitignore b/vendor/github.com/appscode/jsonpatch/.gitignore deleted file mode 100644 index 0e9448e05286..000000000000 --- a/vendor/github.com/appscode/jsonpatch/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof - -.idea/ diff --git a/vendor/github.com/appscode/jsonpatch/.travis.yml b/vendor/github.com/appscode/jsonpatch/.travis.yml deleted file mode 100644 index 92f2439d7449..000000000000 --- a/vendor/github.com/appscode/jsonpatch/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: go -go: - - 1.x - - tip - -env: - - GO111MODULE=on - -script: - - go test -v diff --git a/vendor/github.com/appscode/jsonpatch/README.md b/vendor/github.com/appscode/jsonpatch/README.md deleted file mode 100644 index bbbf72921faf..000000000000 --- a/vendor/github.com/appscode/jsonpatch/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# jsonpatch - -[![Build Status](https://travis-ci.org/appscode/jsonpatch.svg?branch=master)](https://travis-ci.org/appscode/jsonpatch) -[![Go Report Card](https://goreportcard.com/badge/appscode/jsonpatch "Go Report Card")](https://goreportcard.com/report/appscode/jsonpatch) -[![GoDoc](https://godoc.org/github.com/appscode/jsonpatch?status.svg "GoDoc")](https://godoc.org/github.com/appscode/jsonpatch) - -As per http://jsonpatch.com JSON Patch is specified in RFC 6902 from the IETF. - -JSON Patch allows you to generate JSON that describes changes you want to make to a document, so you don't have to send the whole doc. JSON Patch format is supported by HTTP PATCH method, allowing for standards based partial updates via REST APIs. - -```console -go get github.com/appscode/jsonpatch -``` - -I tried some of the other "jsonpatch" go implementations, but none of them could diff two json documents and -generate format like jsonpatch.com specifies. Here's an example of the patch format: - -```json -[ - { "op": "replace", "path": "/baz", "value": "boo" }, - { "op": "add", "path": "/hello", "value": ["world"] }, - { "op": "remove", "path": "/foo"} -] - -``` -The API is super simple - -## example - -```go -package main - -import ( - "fmt" - "github.com/appscode/jsonpatch" -) - -var simpleA = `{"a":100, "b":200, "c":"hello"}` -var simpleB = `{"a":100, "b":200, "c":"goodbye"}` - -func main() { - patch, e := jsonpatch.CreatePatch([]byte(simpleA), []byte(simpleA)) - if e != nil { - fmt.Printf("Error creating JSON patch:%v", e) - return - } - for _, operation := range patch { - fmt.Printf("%s\n", operation.Json()) - } -} -``` - -This code needs more tests, as it's a highly recursive, type-fiddly monster. It's not a lot of code, but it has to deal with a lot of complexity. diff --git a/vendor/github.com/appscode/jsonpatch/go.mod b/vendor/github.com/appscode/jsonpatch/go.mod deleted file mode 100644 index 458d129ec903..000000000000 --- a/vendor/github.com/appscode/jsonpatch/go.mod +++ /dev/null @@ -1,8 +0,0 @@ -module github.com/appscode/jsonpatch - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/evanphx/json-patch v4.0.0+incompatible - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/testify v1.2.2 -) diff --git a/vendor/github.com/appscode/jsonpatch/go.sum b/vendor/github.com/appscode/jsonpatch/go.sum deleted file mode 100644 index 0972e0e1a992..000000000000 --- a/vendor/github.com/appscode/jsonpatch/go.sum +++ /dev/null @@ -1,8 +0,0 @@ -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/evanphx/json-patch v4.0.0+incompatible h1:xregGRMLBeuRcwiOTHRCsPPuzCQlqhxUPbqdw+zNkLc= -github.com/evanphx/json-patch v4.0.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= diff --git a/vendor/github.com/evanphx/json-patch/BUILD.bazel b/vendor/github.com/evanphx/json-patch/BUILD.bazel index 95b6cbca8cb3..b7755e478b64 100644 --- a/vendor/github.com/evanphx/json-patch/BUILD.bazel +++ b/vendor/github.com/evanphx/json-patch/BUILD.bazel @@ -3,10 +3,12 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ + "errors.go", "merge.go", "patch.go", ], importmap = "sigs.k8s.io/cluster-api/vendor/github.com/evanphx/json-patch", importpath = "github.com/evanphx/json-patch", visibility = ["//visibility:public"], + deps = ["//vendor/github.com/pkg/errors:go_default_library"], ) diff --git a/vendor/github.com/evanphx/json-patch/README.md b/vendor/github.com/evanphx/json-patch/README.md index a711d7961b37..9c7f87f7ceaa 100644 --- a/vendor/github.com/evanphx/json-patch/README.md +++ b/vendor/github.com/evanphx/json-patch/README.md @@ -28,10 +28,15 @@ go get -u github.com/evanphx/json-patch # Configuration -There is a single global configuration variable `jsonpatch.SupportNegativeIndices'. This -defaults to `true` and enables the non-standard practice of allowing negative indices -to mean indices starting at the end of an array. This functionality can be disabled -by setting `jsonpatch.SupportNegativeIndices = false`. +* There is a global configuration variable `jsonpatch.SupportNegativeIndices`. + This defaults to `true` and enables the non-standard practice of allowing + negative indices to mean indices starting at the end of an array. This + functionality can be disabled by setting `jsonpatch.SupportNegativeIndices = + false`. + +* There is a global configuration variable `jsonpatch.AccumulatedCopySizeLimit`, + which limits the total size increase in bytes caused by "copy" operations in a + patch. It defaults to 0, which means there is no limit. ## Create and apply a merge patch Given both an original JSON document and a modified JSON document, you can create diff --git a/vendor/github.com/evanphx/json-patch/errors.go b/vendor/github.com/evanphx/json-patch/errors.go new file mode 100644 index 000000000000..75304b4437c1 --- /dev/null +++ b/vendor/github.com/evanphx/json-patch/errors.go @@ -0,0 +1,38 @@ +package jsonpatch + +import "fmt" + +// AccumulatedCopySizeError is an error type returned when the accumulated size +// increase caused by copy operations in a patch operation has exceeded the +// limit. +type AccumulatedCopySizeError struct { + limit int64 + accumulated int64 +} + +// NewAccumulatedCopySizeError returns an AccumulatedCopySizeError. +func NewAccumulatedCopySizeError(l, a int64) *AccumulatedCopySizeError { + return &AccumulatedCopySizeError{limit: l, accumulated: a} +} + +// Error implements the error interface. +func (a *AccumulatedCopySizeError) Error() string { + return fmt.Sprintf("Unable to complete the copy, the accumulated size increase of copy is %d, exceeding the limit %d", a.accumulated, a.limit) +} + +// ArraySizeError is an error type returned when the array size has exceeded +// the limit. +type ArraySizeError struct { + limit int + size int +} + +// NewArraySizeError returns an ArraySizeError. +func NewArraySizeError(l, s int) *ArraySizeError { + return &ArraySizeError{limit: l, size: s} +} + +// Error implements the error interface. +func (a *ArraySizeError) Error() string { + return fmt.Sprintf("Unable to create array of size %d, limit is %d", a.size, a.limit) +} diff --git a/vendor/github.com/evanphx/json-patch/patch.go b/vendor/github.com/evanphx/json-patch/patch.go index f26b6824b6d5..1b5f95e61123 100644 --- a/vendor/github.com/evanphx/json-patch/patch.go +++ b/vendor/github.com/evanphx/json-patch/patch.go @@ -6,6 +6,8 @@ import ( "fmt" "strconv" "strings" + + "github.com/pkg/errors" ) const ( @@ -14,7 +16,23 @@ const ( eAry ) -var SupportNegativeIndices bool = true +var ( + // SupportNegativeIndices decides whether to support non-standard practice of + // allowing negative indices to mean indices starting at the end of an array. + // Default to true. + SupportNegativeIndices bool = true + // AccumulatedCopySizeLimit limits the total size increase in bytes caused by + // "copy" operations in a patch. + AccumulatedCopySizeLimit int64 = 0 +) + +var ( + ErrTestFailed = errors.New("test failed") + ErrMissing = errors.New("missing value") + ErrUnknownType = errors.New("unknown object type") + ErrInvalid = errors.New("invalid state detected") + ErrInvalidIndex = errors.New("invalid index referenced") +) type lazyNode struct { raw *json.RawMessage @@ -23,10 +41,11 @@ type lazyNode struct { which int } -type operation map[string]*json.RawMessage +// Operation is a single JSON-Patch step, such as a single 'add' operation. +type Operation map[string]*json.RawMessage -// Patch is an ordered collection of operations. -type Patch []operation +// Patch is an ordered collection of Operations. +type Patch []Operation type partialDoc map[string]*lazyNode type partialArray []*lazyNode @@ -51,7 +70,7 @@ func (n *lazyNode) MarshalJSON() ([]byte, error) { case eAry: return json.Marshal(n.ary) default: - return nil, fmt.Errorf("Unknown type") + return nil, ErrUnknownType } } @@ -63,13 +82,27 @@ func (n *lazyNode) UnmarshalJSON(data []byte) error { return nil } +func deepCopy(src *lazyNode) (*lazyNode, int, error) { + if src == nil { + return nil, 0, nil + } + a, err := src.MarshalJSON() + if err != nil { + return nil, 0, err + } + sz := len(a) + ra := make(json.RawMessage, sz) + copy(ra, a) + return newLazyNode(&ra), sz, nil +} + func (n *lazyNode) intoDoc() (*partialDoc, error) { if n.which == eDoc { return &n.doc, nil } if n.raw == nil { - return nil, fmt.Errorf("Unable to unmarshal nil pointer as partial document") + return nil, ErrInvalid } err := json.Unmarshal(*n.raw, &n.doc) @@ -88,7 +121,7 @@ func (n *lazyNode) intoAry() (*partialArray, error) { } if n.raw == nil { - return nil, fmt.Errorf("Unable to unmarshal nil pointer as partial array") + return nil, ErrInvalid } err := json.Unmarshal(*n.raw, &n.ary) @@ -205,7 +238,8 @@ func (n *lazyNode) equal(o *lazyNode) bool { return true } -func (o operation) kind() string { +// Kind reads the "op" field of the Operation. +func (o Operation) Kind() string { if obj, ok := o["op"]; ok && obj != nil { var op string @@ -221,39 +255,41 @@ func (o operation) kind() string { return "unknown" } -func (o operation) path() string { +// Path reads the "path" field of the Operation. +func (o Operation) Path() (string, error) { if obj, ok := o["path"]; ok && obj != nil { var op string err := json.Unmarshal(*obj, &op) if err != nil { - return "unknown" + return "unknown", err } - return op + return op, nil } - return "unknown" + return "unknown", errors.Wrapf(ErrMissing, "operation missing path field") } -func (o operation) from() string { +// From reads the "from" field of the Operation. +func (o Operation) From() (string, error) { if obj, ok := o["from"]; ok && obj != nil { var op string err := json.Unmarshal(*obj, &op) if err != nil { - return "unknown" + return "unknown", err } - return op + return op, nil } - return "unknown" + return "unknown", errors.Wrapf(ErrMissing, "operation, missing from field") } -func (o operation) value() *lazyNode { +func (o Operation) value() *lazyNode { if obj, ok := o["value"]; ok { return newLazyNode(obj) } @@ -261,6 +297,23 @@ func (o operation) value() *lazyNode { return nil } +// ValueInterface decodes the operation value into an interface. +func (o Operation) ValueInterface() (interface{}, error) { + if obj, ok := o["value"]; ok && obj != nil { + var v interface{} + + err := json.Unmarshal(*obj, &v) + + if err != nil { + return nil, err + } + + return v, nil + } + + return nil, errors.Wrapf(ErrMissing, "operation, missing value field") +} + func isArray(buf []byte) bool { Loop: for _, c := range buf { @@ -337,42 +390,21 @@ func (d *partialDoc) get(key string) (*lazyNode, error) { func (d *partialDoc) remove(key string) error { _, ok := (*d)[key] if !ok { - return fmt.Errorf("Unable to remove nonexistent key: %s", key) + return errors.Wrapf(ErrMissing, "Unable to remove nonexistent key: %s", key) } delete(*d, key) return nil } +// set should only be used to implement the "replace" operation, so "key" must +// be an already existing index in "d". func (d *partialArray) set(key string, val *lazyNode) error { - if key == "-" { - *d = append(*d, val) - return nil - } - idx, err := strconv.Atoi(key) if err != nil { return err } - - sz := len(*d) - if idx+1 > sz { - sz = idx + 1 - } - - ary := make([]*lazyNode, sz) - - cur := *d - - copy(ary, cur) - - if idx >= len(ary) { - return fmt.Errorf("Unable to access invalid index: %d", idx) - } - - ary[idx] = val - - *d = ary + (*d)[idx] = val return nil } @@ -384,20 +416,22 @@ func (d *partialArray) add(key string, val *lazyNode) error { idx, err := strconv.Atoi(key) if err != nil { - return err + return errors.Wrapf(err, "value was not a proper array index: '%s'", key) } - ary := make([]*lazyNode, len(*d)+1) + sz := len(*d) + 1 + + ary := make([]*lazyNode, sz) cur := *d if idx >= len(ary) { - return fmt.Errorf("Unable to access invalid index: %d", idx) + return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx) } if SupportNegativeIndices { if idx < -len(ary) { - return fmt.Errorf("Unable to access invalid index: %d", idx) + return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx) } if idx < 0 { @@ -421,7 +455,7 @@ func (d *partialArray) get(key string) (*lazyNode, error) { } if idx >= len(*d) { - return nil, fmt.Errorf("Unable to access invalid index: %d", idx) + return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx) } return (*d)[idx], nil @@ -436,12 +470,12 @@ func (d *partialArray) remove(key string) error { cur := *d if idx >= len(cur) { - return fmt.Errorf("Unable to access invalid index: %d", idx) + return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx) } if SupportNegativeIndices { if idx < -len(cur) { - return fmt.Errorf("Unable to access invalid index: %d", idx) + return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx) } if idx < 0 { @@ -459,131 +493,189 @@ func (d *partialArray) remove(key string) error { } -func (p Patch) add(doc *container, op operation) error { - path := op.path() +func (p Patch) add(doc *container, op Operation) error { + path, err := op.Path() + if err != nil { + return errors.Wrapf(ErrMissing, "add operation failed to decode path") + } con, key := findObject(doc, path) if con == nil { - return fmt.Errorf("jsonpatch add operation does not apply: doc is missing path: \"%s\"", path) + return errors.Wrapf(ErrMissing, "add operation does not apply: doc is missing path: \"%s\"", path) } - return con.add(key, op.value()) + err = con.add(key, op.value()) + if err != nil { + return errors.Wrapf(err, "error in add for path: '%s'", path) + } + + return nil } -func (p Patch) remove(doc *container, op operation) error { - path := op.path() +func (p Patch) remove(doc *container, op Operation) error { + path, err := op.Path() + if err != nil { + return errors.Wrapf(ErrMissing, "remove operation failed to decode path") + } con, key := findObject(doc, path) if con == nil { - return fmt.Errorf("jsonpatch remove operation does not apply: doc is missing path: \"%s\"", path) + return errors.Wrapf(ErrMissing, "remove operation does not apply: doc is missing path: \"%s\"", path) + } + + err = con.remove(key) + if err != nil { + return errors.Wrapf(err, "error in remove for path: '%s'", path) } - return con.remove(key) + return nil } -func (p Patch) replace(doc *container, op operation) error { - path := op.path() +func (p Patch) replace(doc *container, op Operation) error { + path, err := op.Path() + if err != nil { + return errors.Wrapf(err, "replace operation failed to decode path") + } con, key := findObject(doc, path) if con == nil { - return fmt.Errorf("jsonpatch replace operation does not apply: doc is missing path: %s", path) + return errors.Wrapf(ErrMissing, "replace operation does not apply: doc is missing path: %s", path) } _, ok := con.get(key) if ok != nil { - return fmt.Errorf("jsonpatch replace operation does not apply: doc is missing key: %s", path) + return errors.Wrapf(ErrMissing, "replace operation does not apply: doc is missing key: %s", path) + } + + err = con.set(key, op.value()) + if err != nil { + return errors.Wrapf(err, "error in remove for path: '%s'", path) } - return con.set(key, op.value()) + return nil } -func (p Patch) move(doc *container, op operation) error { - from := op.from() +func (p Patch) move(doc *container, op Operation) error { + from, err := op.From() + if err != nil { + return errors.Wrapf(err, "move operation failed to decode from") + } con, key := findObject(doc, from) if con == nil { - return fmt.Errorf("jsonpatch move operation does not apply: doc is missing from path: %s", from) + return errors.Wrapf(ErrMissing, "move operation does not apply: doc is missing from path: %s", from) } val, err := con.get(key) if err != nil { - return err + return errors.Wrapf(err, "error in move for path: '%s'", key) } err = con.remove(key) if err != nil { - return err + return errors.Wrapf(err, "error in move for path: '%s'", key) } - path := op.path() + path, err := op.Path() + if err != nil { + return errors.Wrapf(err, "move operation failed to decode path") + } con, key = findObject(doc, path) if con == nil { - return fmt.Errorf("jsonpatch move operation does not apply: doc is missing destination path: %s", path) + return errors.Wrapf(ErrMissing, "move operation does not apply: doc is missing destination path: %s", path) + } + + err = con.add(key, val) + if err != nil { + return errors.Wrapf(err, "error in move for path: '%s'", path) } - return con.set(key, val) + return nil } -func (p Patch) test(doc *container, op operation) error { - path := op.path() +func (p Patch) test(doc *container, op Operation) error { + path, err := op.Path() + if err != nil { + return errors.Wrapf(err, "test operation failed to decode path") + } con, key := findObject(doc, path) if con == nil { - return fmt.Errorf("jsonpatch test operation does not apply: is missing path: %s", path) + return errors.Wrapf(ErrMissing, "test operation does not apply: is missing path: %s", path) } val, err := con.get(key) - if err != nil { - return err + return errors.Wrapf(err, "error in test for path: '%s'", path) } if val == nil { if op.value().raw == nil { return nil } - return fmt.Errorf("Testing value %s failed", path) + return errors.Wrapf(ErrTestFailed, "testing value %s failed", path) } else if op.value() == nil { - return fmt.Errorf("Testing value %s failed", path) + return errors.Wrapf(ErrTestFailed, "testing value %s failed", path) } if val.equal(op.value()) { return nil } - return fmt.Errorf("Testing value %s failed", path) + return errors.Wrapf(ErrTestFailed, "testing value %s failed", path) } -func (p Patch) copy(doc *container, op operation) error { - from := op.from() +func (p Patch) copy(doc *container, op Operation, accumulatedCopySize *int64) error { + from, err := op.From() + if err != nil { + return errors.Wrapf(err, "copy operation failed to decode from") + } con, key := findObject(doc, from) if con == nil { - return fmt.Errorf("jsonpatch copy operation does not apply: doc is missing from path: %s", from) + return errors.Wrapf(ErrMissing, "copy operation does not apply: doc is missing from path: %s", from) } val, err := con.get(key) if err != nil { - return err + return errors.Wrapf(err, "error in copy for from: '%s'", from) } - path := op.path() + path, err := op.Path() + if err != nil { + return errors.Wrapf(ErrMissing, "copy operation failed to decode path") + } con, key = findObject(doc, path) if con == nil { - return fmt.Errorf("jsonpatch copy operation does not apply: doc is missing destination path: %s", path) + return errors.Wrapf(ErrMissing, "copy operation does not apply: doc is missing destination path: %s", path) + } + + valCopy, sz, err := deepCopy(val) + if err != nil { + return errors.Wrapf(err, "error while performing deep copy") + } + + (*accumulatedCopySize) += int64(sz) + if AccumulatedCopySizeLimit > 0 && *accumulatedCopySize > AccumulatedCopySizeLimit { + return NewAccumulatedCopySizeError(AccumulatedCopySizeLimit, *accumulatedCopySize) + } + + err = con.add(key, valCopy) + if err != nil { + return errors.Wrapf(err, "error while adding value during copy") } - return con.set(key, val) + return nil } // Equal indicates if 2 JSON documents have the same structural equality. @@ -636,8 +728,10 @@ func (p Patch) ApplyIndent(doc []byte, indent string) ([]byte, error) { err = nil + var accumulatedCopySize int64 + for _, op := range p { - switch op.kind() { + switch op.Kind() { case "add": err = p.add(&pd, op) case "remove": @@ -649,9 +743,9 @@ func (p Patch) ApplyIndent(doc []byte, indent string) ([]byte, error) { case "test": err = p.test(&pd, op) case "copy": - err = p.copy(&pd, op) + err = p.copy(&pd, op, &accumulatedCopySize) default: - err = fmt.Errorf("Unexpected kind: %s", op.kind()) + err = fmt.Errorf("Unexpected kind: %s", op.Kind()) } if err != nil { diff --git a/vendor/github.com/appscode/jsonpatch/BUILD.bazel b/vendor/gomodules.xyz/jsonpatch/v2/BUILD.bazel similarity index 56% rename from vendor/github.com/appscode/jsonpatch/BUILD.bazel rename to vendor/gomodules.xyz/jsonpatch/v2/BUILD.bazel index 31dd99df64b7..19d937231989 100644 --- a/vendor/github.com/appscode/jsonpatch/BUILD.bazel +++ b/vendor/gomodules.xyz/jsonpatch/v2/BUILD.bazel @@ -3,7 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = ["jsonpatch.go"], - importmap = "sigs.k8s.io/cluster-api/vendor/github.com/appscode/jsonpatch", - importpath = "github.com/appscode/jsonpatch", + importmap = "sigs.k8s.io/cluster-api/vendor/gomodules.xyz/jsonpatch/v2", + importpath = "gomodules.xyz/jsonpatch/v2", visibility = ["//visibility:public"], ) diff --git a/vendor/github.com/appscode/jsonpatch/LICENSE b/vendor/gomodules.xyz/jsonpatch/v2/LICENSE similarity index 100% rename from vendor/github.com/appscode/jsonpatch/LICENSE rename to vendor/gomodules.xyz/jsonpatch/v2/LICENSE diff --git a/vendor/gomodules.xyz/jsonpatch/v2/go.mod b/vendor/gomodules.xyz/jsonpatch/v2/go.mod new file mode 100644 index 000000000000..b5eaf830ebc4 --- /dev/null +++ b/vendor/gomodules.xyz/jsonpatch/v2/go.mod @@ -0,0 +1,9 @@ +module gomodules.xyz/jsonpatch/v2 + +go 1.12 + +require ( + github.com/evanphx/json-patch v4.5.0+incompatible + github.com/pkg/errors v0.8.1 // indirect + github.com/stretchr/testify v1.3.0 +) diff --git a/vendor/gomodules.xyz/jsonpatch/v2/go.sum b/vendor/gomodules.xyz/jsonpatch/v2/go.sum new file mode 100644 index 000000000000..d8f9ffe1c94a --- /dev/null +++ b/vendor/gomodules.xyz/jsonpatch/v2/go.sum @@ -0,0 +1,11 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= +github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= diff --git a/vendor/github.com/appscode/jsonpatch/jsonpatch.go b/vendor/gomodules.xyz/jsonpatch/v2/jsonpatch.go similarity index 97% rename from vendor/github.com/appscode/jsonpatch/jsonpatch.go rename to vendor/gomodules.xyz/jsonpatch/v2/jsonpatch.go index 3e698949e579..e7cb7d6da50e 100644 --- a/vendor/github.com/appscode/jsonpatch/jsonpatch.go +++ b/vendor/gomodules.xyz/jsonpatch/v2/jsonpatch.go @@ -58,8 +58,8 @@ func NewPatch(operation, path string, value interface{}) Operation { // // An error will be returned if any of the two documents are invalid. func CreatePatch(a, b []byte) ([]Operation, error) { - aI := map[string]interface{}{} - bI := map[string]interface{}{} + var aI interface{} + var bI interface{} err := json.Unmarshal(a, &aI) if err != nil { return nil, errBadJSONDoc @@ -68,7 +68,7 @@ func CreatePatch(a, b []byte) ([]Operation, error) { if err != nil { return nil, errBadJSONDoc } - return diff(aI, bI, "", []Operation{}) + return handleValues(aI, bI, "", []Operation{}) } // Returns true if the values matches (must be json types) @@ -326,7 +326,7 @@ func backtrace(s, t []interface{}, p string, i int, j int, matrix [][]int) []Ope return append([]Operation{op}, backtrace(s, t, p, i-1, j-1, matrix)...) } - p2, _ := handleValues(s[j-1], t[j-1], makePath(p, i-1), []Operation{}) + p2, _ := handleValues(s[i-1], t[j-1], makePath(p, i-1), []Operation{}) return append(p2, backtrace(s, t, p, i-1, j-1, matrix)...) } if i > 0 && j > 0 && matrix[i-1][j-1] == matrix[i][j] { diff --git a/vendor/modules.txt b/vendor/modules.txt index 03c061762e01..443d6f175667 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -13,8 +13,6 @@ github.com/Azure/go-autorest/autorest/date github.com/Azure/go-autorest/logger # github.com/Azure/go-autorest/tracing v0.1.0 github.com/Azure/go-autorest/tracing -# github.com/appscode/jsonpatch v0.0.0-20190108182946-7c0e3b262f30 -github.com/appscode/jsonpatch # github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 github.com/beorn7/perks/quantile # github.com/census-instrumentation/opencensus-proto v0.2.0 @@ -28,7 +26,7 @@ github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1 github.com/davecgh/go-spew/spew # github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go -# github.com/evanphx/json-patch v4.1.0+incompatible +# github.com/evanphx/json-patch v4.5.0+incompatible github.com/evanphx/json-patch # github.com/go-logr/logr v0.1.0 github.com/go-logr/logr @@ -249,6 +247,8 @@ golang.org/x/tools/go/ast/astutil golang.org/x/tools/internal/module golang.org/x/tools/go/internal/gcimporter golang.org/x/tools/internal/fastwalk +# gomodules.xyz/jsonpatch/v2 v2.0.0 +gomodules.xyz/jsonpatch/v2 # google.golang.org/api v0.3.1 google.golang.org/api/support/bundler # google.golang.org/appengine v1.4.0 @@ -648,7 +648,7 @@ k8s.io/utils/pointer k8s.io/utils/integer k8s.io/utils/buffer k8s.io/utils/trace -# sigs.k8s.io/controller-runtime v0.2.0-beta.2 +# sigs.k8s.io/controller-runtime v0.2.0-beta.3 sigs.k8s.io/controller-runtime/pkg/client sigs.k8s.io/controller-runtime/pkg/client/config sigs.k8s.io/controller-runtime/pkg/manager @@ -668,7 +668,6 @@ sigs.k8s.io/controller-runtime/pkg/metrics sigs.k8s.io/controller-runtime/pkg/recorder sigs.k8s.io/controller-runtime/pkg/runtime/inject sigs.k8s.io/controller-runtime/pkg/webhook -sigs.k8s.io/controller-runtime/pkg/webhook/conversion sigs.k8s.io/controller-runtime/pkg/envtest sigs.k8s.io/controller-runtime/pkg/manager/signals sigs.k8s.io/controller-runtime/pkg/log @@ -682,7 +681,6 @@ sigs.k8s.io/controller-runtime/pkg/cache/internal sigs.k8s.io/controller-runtime/pkg/webhook/admission sigs.k8s.io/controller-runtime/pkg/webhook/internal/certwatcher sigs.k8s.io/controller-runtime/pkg/webhook/internal/metrics -sigs.k8s.io/controller-runtime/pkg/conversion sigs.k8s.io/controller-runtime/pkg/envtest/printer sigs.k8s.io/controller-runtime/pkg/internal/controller/metrics sigs.k8s.io/controller-runtime/pkg/internal/objectutil diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/client/options.go b/vendor/sigs.k8s.io/controller-runtime/pkg/client/options.go index 46ddf66f9781..395ce7838f28 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/client/options.go +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/client/options.go @@ -101,7 +101,6 @@ type DeleteOptions struct { // AsDeleteOptions returns these options as a metav1.DeleteOptions. // This may mutate the Raw field. func (o *DeleteOptions) AsDeleteOptions() *metav1.DeleteOptions { - if o == nil { return &metav1.DeleteOptions{} } @@ -309,7 +308,6 @@ type UpdateOptions struct { // AsUpdateOptions returns these options as a metav1.UpdateOptions. // This may mutate the Raw field. func (o *UpdateOptions) AsUpdateOptions() *metav1.UpdateOptions { - if o == nil { return &metav1.UpdateOptions{} } diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/conversion/BUILD.bazel b/vendor/sigs.k8s.io/controller-runtime/pkg/conversion/BUILD.bazel deleted file mode 100644 index b037c13017a0..000000000000 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/conversion/BUILD.bazel +++ /dev/null @@ -1,10 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["conversion.go"], - importmap = "sigs.k8s.io/cluster-api/vendor/sigs.k8s.io/controller-runtime/pkg/conversion", - importpath = "sigs.k8s.io/controller-runtime/pkg/conversion", - visibility = ["//visibility:public"], - deps = ["//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library"], -) diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/conversion/conversion.go b/vendor/sigs.k8s.io/controller-runtime/pkg/conversion/conversion.go deleted file mode 100644 index da32ab48e4b6..000000000000 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/conversion/conversion.go +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright 2019 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -/* -Package conversion provides interface definitions that an API Type needs to -implement for it to be supported by the generic conversion webhook handler -defined under pkg/webhook/conversion. -*/ -package conversion - -import "k8s.io/apimachinery/pkg/runtime" - -// Convertible defines capability of a type to convertible i.e. it can be converted to/from a hub type. -type Convertible interface { - runtime.Object - ConvertTo(dst Hub) error - ConvertFrom(src Hub) error -} - -// Hub marks that a given type is the hub type for conversion. This means that -// all conversions will first convert to the hub type, then convert from the hub -// type to the destination type. All types besides the hub type should implement -// Convertible. -type Hub interface { - runtime.Object - Hub() -} diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/envtest/server.go b/vendor/sigs.k8s.io/controller-runtime/pkg/envtest/server.go index 2cfedd1e066c..7c4d8cfff720 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/envtest/server.go +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/envtest/server.go @@ -90,7 +90,7 @@ type Environment struct { // UseExisting indicates that this environments should use an // existing kubeconfig, instead of trying to stand up a new control plane. // This is useful in cases that need aggregated API servers and the like. - UseExistingCluster bool + UseExistingCluster *bool // ControlPlaneStartTimeout is the maximum duration each controlplane component // may take to start. It defaults to the KUBEBUILDER_CONTROLPLANE_START_TIMEOUT @@ -113,7 +113,7 @@ type Environment struct { // Stop stops a running server func (te *Environment) Stop() error { - if te.UseExistingCluster { + if te.useExistingCluster() { return nil } return te.ControlPlane.Stop() @@ -130,11 +130,7 @@ func (te Environment) getAPIServerFlags() []string { // Start starts a local Kubernetes server and updates te.ApiserverPort with the port it is listening on func (te *Environment) Start() (*rest.Config, error) { - if !te.UseExistingCluster { - // Check USE_EXISTING_CLUSTER env then - te.UseExistingCluster = strings.ToLower(os.Getenv(envUseExistingCluster)) == "true" - } - if te.UseExistingCluster { + if te.useExistingCluster() { log.V(1).Info("using existing cluster") if te.Config == nil { // we want to allow people to pass in their own config, so @@ -256,3 +252,10 @@ func (te *Environment) defaultTimeouts() error { } return nil } + +func (te *Environment) useExistingCluster() bool { + if te.UseExistingCluster == nil { + return strings.ToLower(os.Getenv(envUseExistingCluster)) == "true" + } + return *te.UseExistingCluster +} diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/manager/BUILD.bazel b/vendor/sigs.k8s.io/controller-runtime/pkg/manager/BUILD.bazel index d0d71f7c276a..fb4e56739e8b 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/manager/BUILD.bazel +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/manager/BUILD.bazel @@ -31,6 +31,5 @@ go_library( "//vendor/sigs.k8s.io/controller-runtime/pkg/recorder:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/runtime/inject:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/webhook:go_default_library", - "//vendor/sigs.k8s.io/controller-runtime/pkg/webhook/conversion:go_default_library", ], ) diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/manager/internal.go b/vendor/sigs.k8s.io/controller-runtime/pkg/manager/internal.go index 45803ef32f81..19857bdd0350 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/manager/internal.go +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/manager/internal.go @@ -38,7 +38,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/recorder" "sigs.k8s.io/controller-runtime/pkg/runtime/inject" "sigs.k8s.io/controller-runtime/pkg/webhook" - "sigs.k8s.io/controller-runtime/pkg/webhook/conversion" ) const ( @@ -218,7 +217,6 @@ func (cm *controllerManager) GetWebhookServer() *webhook.Server { Port: cm.port, Host: cm.host, } - cm.webhookServer.Register("/convert", &conversion.Webhook{}) if err := cm.Add(cm.webhookServer); err != nil { panic("unable to add webhookServer to the controller manager") } @@ -361,7 +359,16 @@ func (cm *controllerManager) startLeaderElection() (err error) { return err } + ctx, cancel := context.WithCancel(context.Background()) + go func() { + select { + case <-cm.internalStop: + cancel() + case <-ctx.Done(): + } + }() + // Start the leader elector process - go l.Run(context.Background()) + go l.Run(ctx) return nil } diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/BUILD.bazel b/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/BUILD.bazel index 256f841cd9d8..aaf80606a3fd 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/BUILD.bazel +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/BUILD.bazel @@ -7,15 +7,16 @@ go_library( "doc.go", "listener.go", "registry.go", + "workqueue.go", ], importmap = "sigs.k8s.io/cluster-api/vendor/sigs.k8s.io/controller-runtime/pkg/metrics", importpath = "sigs.k8s.io/controller-runtime/pkg/metrics", visibility = ["//visibility:public"], deps = [ "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", "//vendor/k8s.io/client-go/tools/metrics:go_default_library", "//vendor/k8s.io/client-go/util/workqueue:go_default_library", + "//vendor/sigs.k8s.io/controller-runtime/pkg/internal/log:go_default_library", ], ) diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/client_go_adapter.go b/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/client_go_adapter.go index 3b2c316280e5..dd9e50b3fdbe 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/client_go_adapter.go +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/client_go_adapter.go @@ -20,23 +20,9 @@ import ( "net/url" "time" - "k8s.io/apimachinery/pkg/util/runtime" - "github.com/prometheus/client_golang/prometheus" reflectormetrics "k8s.io/client-go/tools/cache" clientmetrics "k8s.io/client-go/tools/metrics" - workqueuemetrics "k8s.io/client-go/util/workqueue" -) - -const ( - workQueueSubsystem = "workqueue" - depthKey = "depth" - addsKey = "adds_total" - queueLatencyKey = "queue_duration_seconds" - workDurationKey = "work_duration_seconds" - unfinishedWorkKey = "unfinished_work_seconds" - longestRunningProcessorKey = "longest_running_processor_seconds" - retriesKey = "retries_total" ) // this file contains setup logic to initialize the myriad of places @@ -117,62 +103,11 @@ var ( Name: "last_resource_version", Help: "Last resource version seen for the reflectors", }, []string{"name"}) - - // workqueue metrics - - depth = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Subsystem: workQueueSubsystem, - Name: depthKey, - Help: "Current depth of workqueue", - }, []string{"name"}) - - adds = prometheus.NewCounterVec(prometheus.CounterOpts{ - Subsystem: workQueueSubsystem, - Name: addsKey, - Help: "Total number of adds handled by workqueue", - }, []string{"name"}) - - latency = prometheus.NewHistogramVec(prometheus.HistogramOpts{ - Subsystem: workQueueSubsystem, - Name: queueLatencyKey, - Help: "How long in seconds an item stays in workqueue before being requested.", - Buckets: prometheus.ExponentialBuckets(10e-9, 10, 10), - }, []string{"name"}) - - workDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{ - Subsystem: workQueueSubsystem, - Name: workDurationKey, - Help: "How long in seconds processing an item from workqueue takes.", - Buckets: prometheus.ExponentialBuckets(10e-9, 10, 10), - }, []string{"name"}) - - unfinishedWork = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Subsystem: workQueueSubsystem, - Name: unfinishedWorkKey, - Help: "How many seconds of work has done that " + - "is in progress and hasn't been observed by work_duration. Large " + - "values indicate stuck threads. One can deduce the number of stuck " + - "threads by observing the rate at which this increases.", - }, []string{"name"}) - - longestRunning = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Subsystem: workQueueSubsystem, - Name: longestRunningProcessorKey, - Help: "How many seconds has the longest running " + - "processor for workqueue been running.", - }, []string{"name"}) - - retries = prometheus.NewCounterVec(prometheus.CounterOpts{ - Subsystem: workQueueSubsystem, - Name: retriesKey, - Help: "Total number of retries handled by workqueue", - }, []string{"name"}) ) func init() { registerClientMetrics() registerReflectorMetrics() - registerWorkqueueMetrics() } // registerClientMetrics sets up the client latency metrics from client-go @@ -199,19 +134,6 @@ func registerReflectorMetrics() { reflectormetrics.SetReflectorMetricsProvider(reflectorMetricsProvider{}) } -// registerWorkQueueMetrics sets up workqueue (other reconcile) metrics -func registerWorkqueueMetrics() { - Registry.MustRegister(depth) - Registry.MustRegister(adds) - Registry.MustRegister(latency) - Registry.MustRegister(workDuration) - Registry.MustRegister(retries) - Registry.MustRegister(longestRunning) - Registry.MustRegister(unfinishedWork) - - workqueuemetrics.SetProvider(workqueueMetricsProvider{}) -} - // this section contains adapters, implementations, and other sundry organic, artisinally // hand-crafted syntax trees required to convince client-go that it actually wants to let // someone use its metrics. @@ -273,114 +195,3 @@ func (reflectorMetricsProvider) NewItemsInWatchMetric(name string) reflectormetr func (reflectorMetricsProvider) NewLastResourceVersionMetric(name string) reflectormetrics.GaugeMetric { return lastResourceVersion.WithLabelValues(name) } - -// Workqueue metrics (method #3 for client-go metrics), -// copied (more-or-less directly) from k8s.io/kubernetes setup code -// (which isn't anywhere in an easily-importable place). -// TODO(directxman12): stop "cheating" and calling histograms summaries when we pull in the latest deps - -type workqueueMetricsProvider struct{} - -func (workqueueMetricsProvider) NewDepthMetric(name string) workqueuemetrics.GaugeMetric { - return depth.WithLabelValues(name) -} - -func (workqueueMetricsProvider) NewAddsMetric(name string) workqueuemetrics.CounterMetric { - return adds.WithLabelValues(name) -} - -func (workqueueMetricsProvider) NewLatencyMetric(name string) workqueuemetrics.HistogramMetric { - return latency.WithLabelValues(name) -} - -func (workqueueMetricsProvider) NewWorkDurationMetric(name string) workqueuemetrics.HistogramMetric { - return workDuration.WithLabelValues(name) -} - -func (workqueueMetricsProvider) NewUnfinishedWorkSecondsMetric(name string) workqueuemetrics.SettableGaugeMetric { - return unfinishedWork.WithLabelValues(name) -} - -func (workqueueMetricsProvider) NewLongestRunningProcessorSecondsMetric(name string) workqueuemetrics.SettableGaugeMetric { - return longestRunning.WithLabelValues(name) -} - -func (workqueueMetricsProvider) NewRetriesMetric(name string) workqueuemetrics.CounterMetric { - return retries.WithLabelValues(name) -} - -func (workqueueMetricsProvider) NewDeprecatedDepthMetric(name string) workqueuemetrics.GaugeMetric { - depth := prometheus.NewGauge(prometheus.GaugeOpts{ - Subsystem: name, - Name: "depth", - Help: "Current depth of workqueue: " + name, - }) - runtime.HandleError(Registry.Register(depth)) - return depth -} - -func (workqueueMetricsProvider) NewDeprecatedAddsMetric(name string) workqueuemetrics.CounterMetric { - adds := prometheus.NewCounter(prometheus.CounterOpts{ - Subsystem: name, - Name: "adds", - Help: "Total number of adds handled by workqueue: " + name, - }) - runtime.HandleError(Registry.Register(adds)) - return adds -} - -func (workqueueMetricsProvider) NewDeprecatedLatencyMetric(name string) workqueuemetrics.SummaryMetric { - latency := prometheus.NewSummary(prometheus.SummaryOpts{ - Subsystem: name, - Name: "queue_latency", - Help: "How long an item stays in workqueue" + name + " before being requested.", - ConstLabels: prometheus.Labels{"name": name}, - }) - runtime.HandleError(Registry.Register(latency)) - return latency -} - -func (workqueueMetricsProvider) NewDeprecatedWorkDurationMetric(name string) workqueuemetrics.SummaryMetric { - workDuration := prometheus.NewSummary(prometheus.SummaryOpts{ - Subsystem: name, - Name: "work_duration", - Help: "How long processing an item from workqueue" + name + " takes.", - ConstLabels: prometheus.Labels{"name": name}, - }) - runtime.HandleError(Registry.Register(workDuration)) - return workDuration -} - -func (workqueueMetricsProvider) NewDeprecatedUnfinishedWorkSecondsMetric(name string) workqueuemetrics.SettableGaugeMetric { - unfinishedWork := prometheus.NewGauge(prometheus.GaugeOpts{ - Subsystem: name, - Name: "unfinished_work_seconds", - Help: "How many seconds of work " + name + " has done that " + - "is in progress and hasn't been observed by work_duration. Large " + - "values indicate stuck threads. One can deduce the number of stuck " + - "threads by observing the rate at which this increases.", - }) - runtime.HandleError(Registry.Register(unfinishedWork)) - return unfinishedWork -} - -func (workqueueMetricsProvider) NewDeprecatedLongestRunningProcessorMicrosecondsMetric(name string) workqueuemetrics.SettableGaugeMetric { - longestRunning := prometheus.NewGauge(prometheus.GaugeOpts{ - Subsystem: name, - Name: "longest_running_processor_microseconds", - Help: "How many microseconds has the longest running " + - "processor for " + name + " been running.", - }) - runtime.HandleError(Registry.Register(longestRunning)) - return longestRunning -} - -func (workqueueMetricsProvider) NewDeprecatedRetriesMetric(name string) workqueuemetrics.CounterMetric { - retries := prometheus.NewCounter(prometheus.CounterOpts{ - Subsystem: name, - Name: "retries", - Help: "Total number of retries handled by workqueue: " + name, - }) - runtime.HandleError(Registry.Register(retries)) - return retries -} diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/workqueue.go b/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/workqueue.go new file mode 100644 index 000000000000..6381f0c14a45 --- /dev/null +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/workqueue.go @@ -0,0 +1,173 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package metrics + +import ( + "github.com/prometheus/client_golang/prometheus" + "k8s.io/client-go/util/workqueue" + logf "sigs.k8s.io/controller-runtime/pkg/internal/log" +) + +var log = logf.RuntimeLog.WithName("metrics") + +// This file is copied and adapted from k8s.io/kubernetes/pkg/util/workqueue/prometheus +// which registers metrics to the default prometheus Registry. We require very +// similar functionality, but must register metrics to a different Registry. + +func init() { + workqueue.SetProvider(workqueueMetricsProvider{}) +} + +func registerWorkqueueMetric(c prometheus.Collector, name, queue string) { + if err := Registry.Register(c); err != nil { + log.Error(err, "failed to register metric", "name", name, "queue", queue) + } +} + +type workqueueMetricsProvider struct{} + +func (workqueueMetricsProvider) NewDepthMetric(queue string) workqueue.GaugeMetric { + const name = "workqueue_depth" + m := prometheus.NewGauge(prometheus.GaugeOpts{ + Name: name, + Help: "Current depth of workqueue", + ConstLabels: prometheus.Labels{"name": queue}, + }) + registerWorkqueueMetric(m, name, queue) + return m +} + +func (workqueueMetricsProvider) NewAddsMetric(queue string) workqueue.CounterMetric { + const name = "workqueue_adds_total" + m := prometheus.NewCounter(prometheus.CounterOpts{ + Name: name, + Help: "Total number of adds handled by workqueue", + ConstLabels: prometheus.Labels{"name": queue}, + }) + registerWorkqueueMetric(m, name, queue) + return m +} + +func (workqueueMetricsProvider) NewLatencyMetric(queue string) workqueue.HistogramMetric { + const name = "workqueue_queue_duration_seconds" + m := prometheus.NewHistogram(prometheus.HistogramOpts{ + Name: name, + Help: "How long in seconds an item stays in workqueue before being requested.", + ConstLabels: prometheus.Labels{"name": queue}, + Buckets: prometheus.ExponentialBuckets(10e-9, 10, 10), + }) + registerWorkqueueMetric(m, name, queue) + return m +} + +func (workqueueMetricsProvider) NewWorkDurationMetric(queue string) workqueue.HistogramMetric { + const name = "workqueue_work_duration_seconds" + m := prometheus.NewHistogram(prometheus.HistogramOpts{ + Name: name, + Help: "How long in seconds processing an item from workqueue takes.", + ConstLabels: prometheus.Labels{"name": queue}, + Buckets: prometheus.ExponentialBuckets(10e-9, 10, 10), + }) + registerWorkqueueMetric(m, name, queue) + return m +} + +func (workqueueMetricsProvider) NewUnfinishedWorkSecondsMetric(queue string) workqueue.SettableGaugeMetric { + const name = "workqueue_unfinished_work_seconds" + m := prometheus.NewGauge(prometheus.GaugeOpts{ + Name: name, + Help: "How many seconds of work has done that " + + "is in progress and hasn't been observed by work_duration. Large " + + "values indicate stuck threads. One can deduce the number of stuck " + + "threads by observing the rate at which this increases.", + ConstLabels: prometheus.Labels{"name": queue}, + }) + registerWorkqueueMetric(m, name, queue) + return m +} + +func (workqueueMetricsProvider) NewLongestRunningProcessorSecondsMetric(queue string) workqueue.SettableGaugeMetric { + const name = "workqueue_longest_running_processor_seconds" + m := prometheus.NewGauge(prometheus.GaugeOpts{ + Name: name, + Help: "How many seconds has the longest running " + + "processor for workqueue been running.", + ConstLabels: prometheus.Labels{"name": queue}, + }) + registerWorkqueueMetric(m, name, queue) + return m +} + +func (workqueueMetricsProvider) NewRetriesMetric(queue string) workqueue.CounterMetric { + const name = "workqueue_retries_total" + m := prometheus.NewCounter(prometheus.CounterOpts{ + Name: name, + Help: "Total number of retries handled by workqueue", + ConstLabels: prometheus.Labels{"name": queue}, + }) + registerWorkqueueMetric(m, name, queue) + return m +} + +// TODO(abursavich): Remove the following deprecated metrics when they are +// removed from k8s.io/client-go/util/workqueue. + +func (workqueueMetricsProvider) NewDeprecatedLongestRunningProcessorMicrosecondsMetric(queue string) workqueue.SettableGaugeMetric { + const name = "workqueue_longest_running_processor_microseconds" + m := prometheus.NewGauge(prometheus.GaugeOpts{ + Name: name, + Help: "(Deprecated) How many microseconds has the longest running " + + "processor for workqueue been running.", + ConstLabels: prometheus.Labels{"name": queue}, + }) + registerWorkqueueMetric(m, name, queue) + return m +} + +// NOTE: The following deprecated metrics are noops because they were never +// included in controller-runtime. + +func (workqueueMetricsProvider) NewDeprecatedDepthMetric(queue string) workqueue.GaugeMetric { + return noopMetric{} +} + +func (workqueueMetricsProvider) NewDeprecatedAddsMetric(queue string) workqueue.CounterMetric { + return noopMetric{} +} + +func (workqueueMetricsProvider) NewDeprecatedLatencyMetric(queue string) workqueue.SummaryMetric { + return noopMetric{} +} + +func (workqueueMetricsProvider) NewDeprecatedWorkDurationMetric(queue string) workqueue.SummaryMetric { + return noopMetric{} +} + +func (workqueueMetricsProvider) NewDeprecatedUnfinishedWorkSecondsMetric(queue string) workqueue.SettableGaugeMetric { + return noopMetric{} +} + +func (workqueueMetricsProvider) NewDeprecatedRetriesMetric(queue string) workqueue.CounterMetric { + return noopMetric{} +} + +type noopMetric struct{} + +func (noopMetric) Inc() {} +func (noopMetric) Dec() {} +func (noopMetric) Set(float64) {} +func (noopMetric) Observe(float64) {} diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/BUILD.bazel b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/BUILD.bazel index 9e98626b4c5c..592604f43aa2 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/BUILD.bazel +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/BUILD.bazel @@ -11,7 +11,7 @@ go_library( importpath = "sigs.k8s.io/controller-runtime/pkg/webhook", visibility = ["//visibility:public"], deps = [ - "//vendor/github.com/appscode/jsonpatch:go_default_library", + "//vendor/gomodules.xyz/jsonpatch/v2:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/internal/log:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/runtime/inject:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission:go_default_library", diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/BUILD.bazel b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/BUILD.bazel index eab2a4c4e234..755d50a7b605 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/BUILD.bazel +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/BUILD.bazel @@ -17,8 +17,8 @@ go_library( importpath = "sigs.k8s.io/controller-runtime/pkg/webhook/admission", visibility = ["//visibility:public"], deps = [ - "//vendor/github.com/appscode/jsonpatch:go_default_library", "//vendor/github.com/go-logr/logr:go_default_library", + "//vendor/gomodules.xyz/jsonpatch/v2:go_default_library", "//vendor/k8s.io/api/admission/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/multi.go b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/multi.go index a65be69f68d1..2ffdb57b0091 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/multi.go +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/multi.go @@ -22,7 +22,7 @@ import ( "fmt" "net/http" - "github.com/appscode/jsonpatch" + "gomodules.xyz/jsonpatch/v2" admissionv1beta1 "k8s.io/api/admission/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/runtime/inject" diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/response.go b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/response.go index bb625ed0d3c6..da8e3367889c 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/response.go +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/response.go @@ -19,7 +19,7 @@ package admission import ( "net/http" - "github.com/appscode/jsonpatch" + "gomodules.xyz/jsonpatch/v2" admissionv1beta1 "k8s.io/api/admission/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/webhook.go b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/webhook.go index 2f6cd9a88fda..9804aa9ba0f5 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/webhook.go +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/admission/webhook.go @@ -21,8 +21,8 @@ import ( "errors" "net/http" - "github.com/appscode/jsonpatch" "github.com/go-logr/logr" + "gomodules.xyz/jsonpatch/v2" admissionv1beta1 "k8s.io/api/admission/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/alias.go b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/alias.go index 27ed60ad183e..276784efb28c 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/alias.go +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/alias.go @@ -17,7 +17,7 @@ limitations under the License. package webhook import ( - "github.com/appscode/jsonpatch" + "gomodules.xyz/jsonpatch/v2" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/conversion/BUILD.bazel b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/conversion/BUILD.bazel deleted file mode 100644 index af871c5398ea..000000000000 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/conversion/BUILD.bazel +++ /dev/null @@ -1,22 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "conversion.go", - "decoder.go", - ], - importmap = "sigs.k8s.io/cluster-api/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/conversion", - importpath = "sigs.k8s.io/controller-runtime/pkg/webhook/conversion", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", - "//vendor/sigs.k8s.io/controller-runtime/pkg/conversion:go_default_library", - "//vendor/sigs.k8s.io/controller-runtime/pkg/log:go_default_library", - ], -) diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/conversion/conversion.go b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/conversion/conversion.go deleted file mode 100644 index 7a74a14892f4..000000000000 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/conversion/conversion.go +++ /dev/null @@ -1,320 +0,0 @@ -/* -Copyright 2019 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -/* -Package conversion provides implementation for CRD conversion webhook that implements handler for version conversion requests for types that are convertible. - -See pkg/conversion for interface definitions required to ensure an API Type is convertible. -*/ -package conversion - -import ( - "encoding/json" - "fmt" - "net/http" - - apix "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/controller-runtime/pkg/conversion" - logf "sigs.k8s.io/controller-runtime/pkg/log" -) - -var ( - log = logf.Log.WithName("conversion-webhook") -) - -// Webhook implements a CRD conversion webhook HTTP handler. -type Webhook struct { - scheme *runtime.Scheme - decoder *Decoder -} - -// InjectScheme injects a scheme into the webhook, in order to construct a Decoder. -func (wh *Webhook) InjectScheme(s *runtime.Scheme) error { - var err error - wh.scheme = s - wh.decoder, err = NewDecoder(s) - if err != nil { - return err - } - - return nil -} - -// ensure Webhook implements http.Handler -var _ http.Handler = &Webhook{} - -func (wh *Webhook) ServeHTTP(w http.ResponseWriter, r *http.Request) { - convertReview := &apix.ConversionReview{} - err := json.NewDecoder(r.Body).Decode(convertReview) - if err != nil { - log.Error(err, "failed to read conversion request") - w.WriteHeader(http.StatusBadRequest) - return - } - - // TODO(droot): may be move the conversion logic to a separate module to - // decouple it from the http layer ? - resp, err := wh.handleConvertRequest(convertReview.Request) - if err != nil { - log.Error(err, "failed to convert", "request", convertReview.Request.UID) - convertReview.Response = errored(err) - } else { - convertReview.Response = resp - } - convertReview.Response.UID = convertReview.Request.UID - convertReview.Request = nil - - err = json.NewEncoder(w).Encode(convertReview) - if err != nil { - log.Error(err, "failed to write response") - return - } -} - -// handles a version conversion request. -func (wh *Webhook) handleConvertRequest(req *apix.ConversionRequest) (*apix.ConversionResponse, error) { - if req == nil { - return nil, fmt.Errorf("conversion request is nil") - } - var objects []runtime.RawExtension - - for _, obj := range req.Objects { - src, gvk, err := wh.decoder.Decode(obj.Raw) - if err != nil { - return nil, err - } - dst, err := wh.allocateDstObject(req.DesiredAPIVersion, gvk.Kind) - if err != nil { - return nil, err - } - err = wh.convertObject(src, dst) - if err != nil { - return nil, err - } - objects = append(objects, runtime.RawExtension{Object: dst}) - } - return &apix.ConversionResponse{ - UID: req.UID, - ConvertedObjects: objects, - Result: metav1.Status{ - Status: metav1.StatusSuccess, - }, - }, nil -} - -// convertObject will convert given a src object to dst object. -// Note(droot): couldn't find a way to reduce the cyclomatic complexity under 10 -// without compromising readability, so disabling gocyclo linter -func (wh *Webhook) convertObject(src, dst runtime.Object) error { - srcGVK := src.GetObjectKind().GroupVersionKind() - dstGVK := dst.GetObjectKind().GroupVersionKind() - - if srcGVK.GroupKind() != dstGVK.GroupKind() { - return fmt.Errorf("src %T and dst %T does not belong to same API Group", src, dst) - } - - if srcGVK == dstGVK { - return fmt.Errorf("conversion is not allowed between same type %T", src) - } - - srcIsHub, dstIsHub := isHub(src), isHub(dst) - srcIsConvertible, dstIsConvertible := isConvertible(src), isConvertible(dst) - - switch { - case srcIsHub && dstIsConvertible: - return dst.(conversion.Convertible).ConvertFrom(src.(conversion.Hub)) - case dstIsHub && srcIsConvertible: - return src.(conversion.Convertible).ConvertTo(dst.(conversion.Hub)) - case srcIsConvertible && dstIsConvertible: - return wh.convertViaHub(src.(conversion.Convertible), dst.(conversion.Convertible)) - default: - return fmt.Errorf("%T is not convertible to %T", src, dst) - } -} - -func (wh *Webhook) convertViaHub(src, dst conversion.Convertible) error { - hub, err := wh.getHub(src) - if err != nil { - return err - } - - if hub == nil { - return fmt.Errorf("%s does not have any Hub defined", src) - } - - err = src.ConvertTo(hub) - if err != nil { - return fmt.Errorf("%T failed to convert to hub version %T : %v", src, hub, err) - } - - err = dst.ConvertFrom(hub) - if err != nil { - return fmt.Errorf("%T failed to convert from hub version %T : %v", dst, hub, err) - } - - return nil -} - -// getHub returns an instance of the Hub for passed-in object's group/kind. -func (wh *Webhook) getHub(obj runtime.Object) (conversion.Hub, error) { - gvks, _, err := wh.scheme.ObjectKinds(obj) - if err != nil { - return nil, fmt.Errorf("error retriving object kinds for given object : %v", err) - } - - var hub conversion.Hub - var isHub, hubFoundAlready bool - for _, gvk := range gvks { - instance, err := wh.scheme.New(gvk) - if err != nil { - return nil, fmt.Errorf("failed to allocate an instance for gvk %v %v", gvk, err) - } - if hub, isHub = instance.(conversion.Hub); isHub { - if hubFoundAlready { - return nil, fmt.Errorf("multiple hub version defined for %T", obj) - } - hubFoundAlready = true - } - } - return hub, nil -} - -// allocateDstObject returns an instance for a given GVK. -func (wh *Webhook) allocateDstObject(apiVersion, kind string) (runtime.Object, error) { - gvk := schema.FromAPIVersionAndKind(apiVersion, kind) - - obj, err := wh.scheme.New(gvk) - if err != nil { - return obj, err - } - - t, err := meta.TypeAccessor(obj) - if err != nil { - return obj, err - } - - t.SetAPIVersion(apiVersion) - t.SetKind(kind) - - return obj, nil -} - -// CheckConvertibility determines if given type is convertible or not. For a type -// to be convertible, the group-kind needs to have a Hub type defined and all -// non-hub types must be able to convert to/from Hub. -func CheckConvertibility(scheme *runtime.Scheme, obj runtime.Object) error { - var hubs, spokes, nonSpokes []runtime.Object - - gvks, _, err := scheme.ObjectKinds(obj) - if err != nil { - return fmt.Errorf("error retriving object kinds for given object : %v", err) - } - - for _, gvk := range gvks { - instance, err := scheme.New(gvk) - if err != nil { - return fmt.Errorf("failed to allocate an instance for gvk %v %v", gvk, err) - } - - if isHub(instance) { - hubs = append(hubs, instance) - continue - } - - if !isConvertible(instance) { - nonSpokes = append(nonSpokes, instance) - continue - } - - spokes = append(spokes, instance) - } - - if len(gvks) == 1 { - return nil // single version - } - - if len(hubs) == 0 && len(spokes) == 0 { - // multiple version detected with no conversion implementation. This is - // true for multi-version built-in types. - return nil - } - - if len(hubs) == 1 && len(nonSpokes) == 0 { // convertible - spokeVersions := []string{} - for _, sp := range spokes { - spokeVersions = append(spokeVersions, sp.GetObjectKind().GroupVersionKind().String()) - } - log.V(1).Info("conversion enabled for kind", "kind", - gvks[0].GroupKind(), "hub", hubs[0], "spokes", spokeVersions) - return nil - } - - return PartialImplementationError{ - hubs: hubs, - nonSpokes: nonSpokes, - spokes: spokes, - } -} - -// PartialImplementationError represents an error due to partial conversion -// implementation such as hub without spokes, multiple hubs or spokes without hub. -type PartialImplementationError struct { - gvk schema.GroupVersionKind - hubs []runtime.Object - nonSpokes []runtime.Object - spokes []runtime.Object -} - -func (e PartialImplementationError) Error() string { - if len(e.hubs) == 0 { - return fmt.Sprintf("no hub defined for gvk %s", e.gvk) - } - if len(e.hubs) > 1 { - return fmt.Sprintf("multiple(%d) hubs defined for group-kind '%s' ", - len(e.hubs), e.gvk.GroupKind()) - } - if len(e.nonSpokes) > 0 { - return fmt.Sprintf("%d inconvertible types detected for group-kind '%s'", - len(e.nonSpokes), e.gvk.GroupKind()) - } - return "" -} - -// isHub determines if passed-in object is a Hub or not. -func isHub(obj runtime.Object) bool { - _, yes := obj.(conversion.Hub) - return yes -} - -// isConvertible determines if passed-in object is a convertible. -func isConvertible(obj runtime.Object) bool { - _, yes := obj.(conversion.Convertible) - return yes -} - -// helper to construct error response. -func errored(err error) *apix.ConversionResponse { - return &apix.ConversionResponse{ - Result: metav1.Status{ - Status: metav1.StatusFailure, - Message: err.Error(), - }, - } -} diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/conversion/decoder.go b/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/conversion/decoder.go deleted file mode 100644 index 8a145cd97880..000000000000 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/webhook/conversion/decoder.go +++ /dev/null @@ -1,31 +0,0 @@ -package conversion - -import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/runtime/serializer" -) - -// Decoder knows how to decode the contents of a CRD version conversion -// request into a concrete object. -// TODO(droot): consider reusing decoder from admission pkg for this. -type Decoder struct { - codecs serializer.CodecFactory -} - -// NewDecoder creates a Decoder given the runtime.Scheme -func NewDecoder(scheme *runtime.Scheme) (*Decoder, error) { - return &Decoder{codecs: serializer.NewCodecFactory(scheme)}, nil -} - -// Decode decodes the inlined object. -func (d *Decoder) Decode(content []byte) (runtime.Object, *schema.GroupVersionKind, error) { - deserializer := d.codecs.UniversalDeserializer() - return deserializer.Decode(content, nil, nil) -} - -// DecodeInto decodes the inlined object in the into the passed-in runtime.Object. -func (d *Decoder) DecodeInto(content []byte, into runtime.Object) error { - deserializer := d.codecs.UniversalDeserializer() - return runtime.DecodeInto(deserializer, content, into) -}