diff --git a/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_compare.go b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_compare.go index 094b90f..903f3e6 100644 --- a/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_compare.go +++ b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_compare.go @@ -5,9 +5,10 @@ import ( "compress/gzip" "encoding/base64" "io/ioutil" - "sync" "github.com/pkg/errors" + "github.com/rancher/wrangler/pkg/data/convert" + patch2 "github.com/rancher/wrangler/pkg/patch" "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/api/meta" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -19,23 +20,12 @@ import ( "k8s.io/apimachinery/pkg/util/jsonmergepatch" "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/client-go/dynamic" - "k8s.io/client-go/kubernetes/scheme" ) const ( LabelApplied = "objectset.rio.cattle.io/applied" ) -var ( - patchCache = map[schema.GroupVersionKind]patchCacheEntry{} - patchCacheLock = sync.Mutex{} -) - -type patchCacheEntry struct { - patchType types.PatchType - lookup strategicpatch.LookupPatchMeta -} - func prepareObjectForCreate(gvk schema.GroupVersionKind, obj runtime.Object) (runtime.Object, error) { serialized, err := json.Marshal(obj) if err != nil { @@ -68,7 +58,7 @@ func prepareObjectForCreate(gvk schema.GroupVersionKind, obj runtime.Object) (ru } func originalAndModified(gvk schema.GroupVersionKind, oldMetadata v1.Object, newObject runtime.Object) ([]byte, []byte, error) { - original, err := getOriginal(gvk, oldMetadata) + original, err := getOriginalBytes(gvk, oldMetadata) if err != nil { return nil, nil, err } @@ -99,7 +89,7 @@ func emptyMaps(data map[string]interface{}, keys ...string) bool { return false } - data = toMapInterface(value) + data = convert.ToMapInterface(value) } return true @@ -148,7 +138,6 @@ func applyPatch(gvk schema.GroupVersionKind, reconciler Reconciler, patcher Patc if err != nil { return false, err } - current, err := json.Marshal(oldObject) if err != nil { return false, err @@ -172,12 +161,18 @@ func applyPatch(gvk schema.GroupVersionKind, reconciler Reconciler, patcher Patc return false, nil } + logrus.Debugf("DesiredSet - Patch %s %s/%s for %s -- [%s, %s, %s, %s]", gvk, oldMetadata.GetNamespace(), oldMetadata.GetName(), debugID, patch, original, modified, current) + if reconciler != nil { newObject, err := prepareObjectForCreate(gvk, newObject) if err != nil { return false, err } - handled, err := reconciler(oldObject, newObject) + originalObject, err := getOriginalObject(gvk, oldMetadata) + if err != nil { + return false, err + } + handled, err := reconciler(originalObject, newObject) if err != nil { return false, err } @@ -186,9 +181,6 @@ func applyPatch(gvk schema.GroupVersionKind, reconciler Reconciler, patcher Patc } } - logrus.Debugf("DesiredSet - Patch %s %s/%s for %s -- [%s, %s, %s, %s]", gvk, oldMetadata.GetNamespace(), oldMetadata.GetName(), debugID, - patch, original, modified, current) - logrus.Debugf("DesiredSet - Updated %s %s/%s for %s -- %s %s", gvk, oldMetadata.GetNamespace(), oldMetadata.GetName(), debugID, patchType, patch) _, err = patcher(oldMetadata.GetNamespace(), oldMetadata.GetName(), patchType, patch) @@ -216,7 +208,7 @@ func removeCreationTimestamp(data map[string]interface{}) bool { return false } - data = toMapInterface(metadata) + data = convert.ToMapInterface(metadata) if _, ok := data["creationTimestamp"]; ok { delete(data, "creationTimestamp") return true @@ -225,10 +217,10 @@ func removeCreationTimestamp(data map[string]interface{}) bool { return false } -func getOriginal(gvk schema.GroupVersionKind, obj v1.Object) ([]byte, error) { +func getOriginalObject(gvk schema.GroupVersionKind, obj v1.Object) (runtime.Object, error) { original := appliedFromAnnotation(obj.GetAnnotations()[LabelApplied]) if len(original) == 0 { - return []byte("{}"), nil + return nil, nil } mapObj := map[string]interface{}{} @@ -238,16 +230,19 @@ func getOriginal(gvk schema.GroupVersionKind, obj v1.Object) ([]byte, error) { } removeCreationTimestamp(mapObj) - - u := &unstructured.Unstructured{ + return prepareObjectForCreate(gvk, &unstructured.Unstructured{ Object: mapObj, - } + }) +} - objCopy, err := prepareObjectForCreate(gvk, u) +func getOriginalBytes(gvk schema.GroupVersionKind, obj v1.Object) ([]byte, error) { + objCopy, err := getOriginalObject(gvk, obj) if err != nil { return nil, err } - + if objCopy == nil { + return []byte("{}"), nil + } return json.Marshal(objCopy) } @@ -295,7 +290,7 @@ func doPatch(gvk schema.GroupVersionKind, original, modified, current []byte) (t var patch []byte var lookupPatchMeta strategicpatch.LookupPatchMeta - patchType, lookupPatchMeta, err := getPatchStyle(gvk) + patchType, lookupPatchMeta, err := patch2.GetMergeStyle(gvk) if err != nil { return patchType, nil, err } @@ -312,46 +307,3 @@ func doPatch(gvk schema.GroupVersionKind, original, modified, current []byte) (t return patchType, patch, err } - -func getPatchStyle(gvk schema.GroupVersionKind) (types.PatchType, strategicpatch.LookupPatchMeta, error) { - var ( - patchType types.PatchType - lookupPatchMeta strategicpatch.LookupPatchMeta - ) - - patchCacheLock.Lock() - entry, ok := patchCache[gvk] - patchCacheLock.Unlock() - - if ok { - return entry.patchType, entry.lookup, nil - } - - versionedObject, err := scheme.Scheme.New(gvk) - - if runtime.IsNotRegisteredError(err) { - patchType = types.MergePatchType - } else if err != nil { - return patchType, nil, err - } else { - patchType = types.StrategicMergePatchType - lookupPatchMeta, err = strategicpatch.NewPatchMetaFromStruct(versionedObject) - if err != nil { - return patchType, nil, err - } - } - - patchCacheLock.Lock() - patchCache[gvk] = patchCacheEntry{ - patchType: patchType, - lookup: lookupPatchMeta, - } - patchCacheLock.Unlock() - - return patchType, lookupPatchMeta, nil -} - -func toMapInterface(obj interface{}) map[string]interface{} { - v, _ := obj.(map[string]interface{}) - return v -} diff --git a/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_crud.go b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_crud.go index fe91a4a..610e9a6 100644 --- a/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_crud.go +++ b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_crud.go @@ -51,8 +51,8 @@ func (o *desiredSet) get(nsed bool, namespace, name string, client dynamic.Names return client.Get(name, v1.GetOptions{}) } -func (o *desiredSet) delete(nsed bool, namespace, name string, client dynamic.NamespaceableResourceInterface) error { - if o.noDelete { +func (o *desiredSet) delete(nsed bool, namespace, name string, client dynamic.NamespaceableResourceInterface, force bool) error { + if o.noDelete && !force { return nil } opts := &v1.DeleteOptions{ diff --git a/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_process.go b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_process.go index e62b41a..da5cd29 100644 --- a/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_process.go +++ b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_process.go @@ -239,8 +239,8 @@ func (o *desiredSet) process(debugID string, set labels.Selector, gvk schema.Gro logrus.Debugf("DesiredSet - Created %s %s for %s", gvk, k, debugID) } - deleteF := func(k objectset.ObjectKey) { - if err := o.delete(nsed, k.Namespace, k.Name, client); err != nil { + deleteF := func(k objectset.ObjectKey, force bool) { + if err := o.delete(nsed, k.Namespace, k.Name, client, force); err != nil { o.err(errors.Wrapf(err, "failed to delete %s %s for %s", k, gvk, debugID)) return } @@ -250,7 +250,7 @@ func (o *desiredSet) process(debugID string, set labels.Selector, gvk schema.Gro updateF := func(k objectset.ObjectKey) { err := o.compareObjects(gvk, patcher, client, debugID, existing[k], objs[k], len(toCreate) > 0 || len(toDelete) > 0) if err == ErrReplace { - deleteF(k) + deleteF(k, true) o.err(fmt.Errorf("DesiredSet - Replace Wait %s %s for %s", gvk, k, debugID)) } else if err != nil { o.err(errors.Wrapf(err, "failed to update %s %s for %s", k, gvk, debugID)) @@ -266,7 +266,7 @@ func (o *desiredSet) process(debugID string, set labels.Selector, gvk schema.Gro } for _, k := range toDelete { - deleteF(k) + deleteF(k, false) } } diff --git a/vendor/github.com/rancher/wrangler/pkg/broadcast/generic.go b/vendor/github.com/rancher/wrangler/pkg/broadcast/generic.go new file mode 100644 index 0000000..ec1096c --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/broadcast/generic.go @@ -0,0 +1,83 @@ +package broadcast + +import ( + "context" + "sync" +) + +type ConnectFunc func() (chan interface{}, error) + +type Broadcaster struct { + sync.Mutex + running bool + subs map[chan interface{}]struct{} +} + +func (b *Broadcaster) Subscribe(ctx context.Context, connect ConnectFunc) (chan interface{}, error) { + b.Lock() + defer b.Unlock() + + if !b.running { + if err := b.start(connect); err != nil { + return nil, err + } + } + + sub := make(chan interface{}, 100) + if b.subs == nil { + b.subs = map[chan interface{}]struct{}{} + } + b.subs[sub] = struct{}{} + go func() { + <-ctx.Done() + b.unsub(sub, true) + }() + + return sub, nil +} + +func (b *Broadcaster) unsub(sub chan interface{}, lock bool) { + if lock { + b.Lock() + } + if _, ok := b.subs[sub]; ok { + close(sub) + delete(b.subs, sub) + } + if lock { + b.Unlock() + } +} + +func (b *Broadcaster) start(connect ConnectFunc) error { + c, err := connect() + if err != nil { + return err + } + + go b.stream(c) + b.running = true + return nil +} + +func (b *Broadcaster) stream(input chan interface{}) { + for item := range input { + b.Lock() + for sub := range b.subs { + select { + case sub <- item: + default: + // Slow consumer, drop + go b.unsub(sub, true) + } + } + b.Unlock() + } + + b.Lock() + for sub := range b.subs { + b.unsub(sub, false) + } + b.running = false + b.Unlock() +} diff --git a/vendor/github.com/rancher/wrangler/pkg/condition/condition.go b/vendor/github.com/rancher/wrangler/pkg/condition/condition.go index 8b5bf87..8f8e6cf 100644 --- a/vendor/github.com/rancher/wrangler/pkg/condition/condition.go +++ b/vendor/github.com/rancher/wrangler/pkg/condition/condition.go @@ -4,16 +4,16 @@ import ( "reflect" "time" - "k8s.io/apimachinery/pkg/runtime" + "github.com/sirupsen/logrus" ) type Cond string -func (c Cond) GetStatus(obj runtime.Object) string { +func (c Cond) GetStatus(obj interface{}) string { return getStatus(obj, string(c)) } -func (c Cond) SetError(obj runtime.Object, reason string, err error) { +func (c Cond) SetError(obj interface{}, reason string, err error) { if err == nil { c.True(obj) c.Message(obj, "") @@ -28,7 +28,7 @@ func (c Cond) SetError(obj runtime.Object, reason string, err error) { c.Reason(obj, reason) } -func (c Cond) MatchesError(obj runtime.Object, reason string, err error) bool { +func (c Cond) MatchesError(obj interface{}, reason string, err error) bool { if err == nil { return c.IsTrue(obj) && c.GetMessage(obj) == "" && @@ -42,11 +42,11 @@ func (c Cond) MatchesError(obj runtime.Object, reason string, err error) bool { c.GetReason(obj) == reason } -func (c Cond) SetStatus(obj runtime.Object, status string) { +func (c Cond) SetStatus(obj interface{}, status string) { setStatus(obj, string(c), status) } -func (c Cond) SetStatusBool(obj runtime.Object, val bool) { +func (c Cond) SetStatusBool(obj interface{}, val bool) { if val { setStatus(obj, string(c), "True") } else { @@ -54,52 +54,52 @@ func (c Cond) SetStatusBool(obj runtime.Object, val bool) { } } -func (c Cond) True(obj runtime.Object) { +func (c Cond) True(obj interface{}) { setStatus(obj, string(c), "True") } -func (c Cond) IsTrue(obj runtime.Object) bool { +func (c Cond) IsTrue(obj interface{}) bool { return getStatus(obj, string(c)) == "True" } -func (c Cond) False(obj runtime.Object) { +func (c Cond) False(obj interface{}) { setStatus(obj, string(c), "False") } -func (c Cond) IsFalse(obj runtime.Object) bool { +func (c Cond) IsFalse(obj interface{}) bool { return getStatus(obj, string(c)) == "False" } -func (c Cond) Unknown(obj runtime.Object) { +func (c Cond) Unknown(obj interface{}) { setStatus(obj, string(c), "Unknown") } -func (c Cond) IsUnknown(obj runtime.Object) bool { +func (c Cond) IsUnknown(obj interface{}) bool { return getStatus(obj, string(c)) == "Unknown" } -func (c Cond) LastUpdated(obj runtime.Object, ts string) { +func (c Cond) LastUpdated(obj interface{}, ts string) { setTS(obj, string(c), ts) } -func (c Cond) GetLastUpdated(obj runtime.Object) string { +func (c Cond) GetLastUpdated(obj interface{}) string { return getTS(obj, string(c)) } -func (c Cond) CreateUnknownIfNotExists(obj runtime.Object) { +func (c Cond) CreateUnknownIfNotExists(obj interface{}) { condSlice := getValue(obj, "Status", "Conditions") - cond := findCond(condSlice, string(c)) + cond := findCond(obj, condSlice, string(c)) if cond == nil { c.Unknown(obj) } } -func (c Cond) Reason(obj runtime.Object, reason string) { +func (c Cond) Reason(obj interface{}, reason string) { cond := findOrCreateCond(obj, string(c)) getFieldValue(cond, "Reason").SetString(reason) } -func (c Cond) GetReason(obj runtime.Object) string { +func (c Cond) GetReason(obj interface{}) string { cond := findOrNotCreateCond(obj, string(c)) if cond == nil { return "" @@ -107,18 +107,18 @@ func (c Cond) GetReason(obj runtime.Object) string { return getFieldValue(*cond, "Reason").String() } -func (c Cond) SetMessageIfBlank(obj runtime.Object, message string) { +func (c Cond) SetMessageIfBlank(obj interface{}, message string) { if c.GetMessage(obj) == "" { c.Message(obj, message) } } -func (c Cond) Message(obj runtime.Object, message string) { +func (c Cond) Message(obj interface{}, message string) { cond := findOrCreateCond(obj, string(c)) setValue(cond, "Message", message) } -func (c Cond) GetMessage(obj runtime.Object) string { +func (c Cond) GetMessage(obj interface{}) string { cond := findOrNotCreateCond(obj, string(c)) if cond == nil { return "" @@ -167,12 +167,15 @@ func setValue(cond reflect.Value, fieldName, newValue string) { func findOrNotCreateCond(obj interface{}, condName string) *reflect.Value { condSlice := getValue(obj, "Status", "Conditions") - return findCond(condSlice, condName) + return findCond(obj, condSlice, condName) } func findOrCreateCond(obj interface{}, condName string) reflect.Value { condSlice := getValue(obj, "Status", "Conditions") - cond := findCond(condSlice, condName) + if !condSlice.IsValid() { + condSlice = getValue(obj, "Conditions") + } + cond := findCond(obj, condSlice, condName) if cond != nil { return *cond } @@ -181,10 +184,16 @@ func findOrCreateCond(obj interface{}, condName string) reflect.Value { newCond.FieldByName("Type").SetString(condName) newCond.FieldByName("Status").SetString("Unknown") condSlice.Set(reflect.Append(condSlice, newCond)) - return *findCond(condSlice, condName) + return *findCond(obj, condSlice, condName) } -func findCond(val reflect.Value, name string) *reflect.Value { +func findCond(obj interface{}, val reflect.Value, name string) *reflect.Value { + defer func() { + if recover() != nil { + logrus.Fatalf("failed to find .Status.Conditions field on %v", reflect.TypeOf(obj)) + } + }() + for i := 0; i < val.Len(); i++ { cond := val.Index(i) typeVal := getFieldValue(cond, "Type") diff --git a/vendor/github.com/rancher/wrangler/pkg/generic/controller.go b/vendor/github.com/rancher/wrangler/pkg/generic/controller.go index f723b0a..4608875 100644 --- a/vendor/github.com/rancher/wrangler/pkg/generic/controller.go +++ b/vendor/github.com/rancher/wrangler/pkg/generic/controller.go @@ -199,7 +199,7 @@ func (c *Controller) enqueue(obj interface{}) { utilruntime.HandleError(err) return } - c.workqueue.AddRateLimited(key) + c.workqueue.Add(key) } func (c *Controller) handleObject(obj interface{}) { diff --git a/vendor/github.com/rancher/wrangler/pkg/gvk/detect.go b/vendor/github.com/rancher/wrangler/pkg/gvk/detect.go new file mode 100644 index 0000000..a8c16b8 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/gvk/detect.go @@ -0,0 +1,19 @@ +package gvk + +import ( + "encoding/json" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func Detect(obj []byte) (schema.GroupVersionKind, bool, error) { + partial := v1.PartialObjectMetadata{} + if err := json.Unmarshal(obj, &partial); err != nil { + return schema.GroupVersionKind{}, false, err + } + + result := partial.GetObjectKind().GroupVersionKind() + ok := result.Kind != "" && result.Version != "" + return result, ok, nil +} diff --git a/vendor/github.com/rancher/wrangler/pkg/gvk/get.go b/vendor/github.com/rancher/wrangler/pkg/gvk/get.go index ba7449d..3392c54 100644 --- a/vendor/github.com/rancher/wrangler/pkg/gvk/get.go +++ b/vendor/github.com/rancher/wrangler/pkg/gvk/get.go @@ -3,6 +3,7 @@ package gvk import ( "fmt" + "github.com/pkg/errors" "github.com/rancher/wrangler/pkg/schemes" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -16,11 +17,11 @@ func Get(obj runtime.Object) (schema.GroupVersionKind, error) { gvks, _, err := schemes.All.ObjectKinds(obj) if err != nil { - return schema.GroupVersionKind{}, err + return schema.GroupVersionKind{}, errors.Wrapf(err, "failed to find gvk for %T, you may need to import the wrangler generated controller package", obj) } if len(gvks) == 0 { - return schema.GroupVersionKind{}, fmt.Errorf("failed to find gvk for %v", obj.GetObjectKind()) + return schema.GroupVersionKind{}, fmt.Errorf("failed to find gvk for %T", obj) } return gvks[0], nil diff --git a/vendor/github.com/rancher/wrangler/pkg/objectset/objectset.go b/vendor/github.com/rancher/wrangler/pkg/objectset/objectset.go index 6f6ab5f..f295497 100644 --- a/vendor/github.com/rancher/wrangler/pkg/objectset/objectset.go +++ b/vendor/github.com/rancher/wrangler/pkg/objectset/objectset.go @@ -5,6 +5,7 @@ import ( "reflect" "sort" + "github.com/pkg/errors" "github.com/rancher/wrangler/pkg/gvk" "github.com/rancher/wrangler/pkg/merr" @@ -97,7 +98,7 @@ func (o *ObjectSet) add(obj runtime.Object) { gvk, err := o.objects.Add(obj) if err != nil { - o.err(fmt.Errorf("failed to add %v", obj)) + o.err(errors.Wrapf(err, "failed to add %T", obj)) return } diff --git a/vendor/github.com/rancher/wrangler/pkg/patch/apply.go b/vendor/github.com/rancher/wrangler/pkg/patch/apply.go new file mode 100644 index 0000000..b7c7a60 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/patch/apply.go @@ -0,0 +1,57 @@ +package patch + +import ( + "encoding/json" + "fmt" + + jsonpatch "github.com/evanphx/json-patch" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/strategicpatch" +) + +func Apply(original, patch []byte) ([]byte, error) { + style, metadata, err := GetPatchStyle(original, patch) + if err != nil { + return nil, err + } + + switch style { + case types.JSONPatchType: + return applyJSONPatch(original, patch) + case types.MergePatchType: + return applyMergePatch(original, patch) + case types.StrategicMergePatchType: + return applyStrategicMergePatch(original, patch, metadata) + default: + return nil, fmt.Errorf("invalid patch") + } +} + +func applyStrategicMergePatch(original, patch []byte, lookup strategicpatch.LookupPatchMeta) ([]byte, error) { + originalMap := map[string]interface{}{} + patchMap := map[string]interface{}{} + if err := json.Unmarshal(original, &originalMap); err != nil { + return nil, err + } + if err := json.Unmarshal(patch, &patchMap); err != nil { + return nil, err + } + patchedMap, err := strategicpatch.StrategicMergeMapPatch(originalMap, patchMap, lookup) + if err != nil { + return nil, err + } + return json.Marshal(patchedMap) +} + +func applyMergePatch(original, patch []byte) ([]byte, error) { + return jsonpatch.MergePatch(original, patch) +} + +func applyJSONPatch(original, patch []byte) ([]byte, error) { + jsonPatch, err := jsonpatch.DecodePatch(patch) + if err != nil { + return nil, err + } + + return jsonPatch.Apply(original) +} diff --git a/vendor/github.com/rancher/wrangler/pkg/patch/style.go b/vendor/github.com/rancher/wrangler/pkg/patch/style.go new file mode 100644 index 0000000..eaa8d21 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/patch/style.go @@ -0,0 +1,79 @@ +package patch + +import ( + "sync" + + "github.com/rancher/wrangler/pkg/gvk" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/strategicpatch" + "k8s.io/client-go/kubernetes/scheme" +) + +var ( + patchCache = map[schema.GroupVersionKind]patchCacheEntry{} + patchCacheLock = sync.Mutex{} +) + +type patchCacheEntry struct { + patchType types.PatchType + lookup strategicpatch.LookupPatchMeta +} + +func isJSONPatch(patch []byte) bool { + // a JSON patch is a list + return len(patch) > 0 && patch[0] == '[' +} + +func GetPatchStyle(original, patch []byte) (types.PatchType, strategicpatch.LookupPatchMeta, error) { + if isJSONPatch(patch) { + return types.JSONPatchType, nil, nil + } + gvk, ok, err := gvk.Detect(original) + if err != nil { + return "", nil, err + } + if !ok { + return types.MergePatchType, nil, nil + } + return GetMergeStyle(gvk) +} + +func GetMergeStyle(gvk schema.GroupVersionKind) (types.PatchType, strategicpatch.LookupPatchMeta, error) { + var ( + patchType types.PatchType + lookupPatchMeta strategicpatch.LookupPatchMeta + ) + + patchCacheLock.Lock() + entry, ok := patchCache[gvk] + patchCacheLock.Unlock() + + if ok { + return entry.patchType, entry.lookup, nil + } + + versionedObject, err := scheme.Scheme.New(gvk) + + if runtime.IsNotRegisteredError(err) { + patchType = types.MergePatchType + } else if err != nil { + return patchType, nil, err + } else { + patchType = types.StrategicMergePatchType + lookupPatchMeta, err = strategicpatch.NewPatchMetaFromStruct(versionedObject) + if err != nil { + return patchType, nil, err + } + } + + patchCacheLock.Lock() + patchCache[gvk] = patchCacheEntry{ + patchType: patchType, + lookup: lookupPatchMeta, + } + patchCacheLock.Unlock() + + return patchType, lookupPatchMeta, nil +} diff --git a/vendor/github.com/rancher/wrangler/pkg/schemas/reflection.go b/vendor/github.com/rancher/wrangler/pkg/schemas/reflection.go index 4acfbe2..1b665e8 100644 --- a/vendor/github.com/rancher/wrangler/pkg/schemas/reflection.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/reflection.go @@ -70,7 +70,18 @@ func (s *Schemas) Import(obj interface{}, externalOverrides ...interface{}) (*Sc types = append(types, reflect.TypeOf(override)) } - return s.importType(reflect.TypeOf(obj), types...) + var ( + v = reflect.ValueOf(obj) + t reflect.Type + ) + + if v.Kind() == reflect.Ptr { + t = v.Elem().Type() + } else { + t = v.Type() + } + + return s.importType(t, types...) } func (s *Schemas) newSchemaFromType(t reflect.Type, typeName string) (*Schema, error) { @@ -245,6 +256,8 @@ func (s *Schemas) readFields(schema *Schema, t reflect.Type) error { schemaField := Field{ CodeName: field.Name, + Create: true, + Update: true, } fieldType := field.Type diff --git a/vendor/github.com/rancher/wrangler/pkg/summary/summarizers.go b/vendor/github.com/rancher/wrangler/pkg/summary/summarizers.go index 6bdf871..58cf238 100644 --- a/vendor/github.com/rancher/wrangler/pkg/summary/summarizers.go +++ b/vendor/github.com/rancher/wrangler/pkg/summary/summarizers.go @@ -44,11 +44,13 @@ var ( "Saved": "saving", "Updated": "updating", "Updating": "updating", + "Upgraded": "upgrading", "Waiting": "waiting", "InitialRolesPopulated": "activating", "ScalingActive": "pending", "AbleToScale": "pending", "RunCompleted": "running", + "Processed": "processed", } // True == error diff --git a/vendor/github.com/rancher/wrangler/pkg/summary/summary.go b/vendor/github.com/rancher/wrangler/pkg/summary/summary.go index 0857f9b..e32b638 100644 --- a/vendor/github.com/rancher/wrangler/pkg/summary/summary.go +++ b/vendor/github.com/rancher/wrangler/pkg/summary/summary.go @@ -14,6 +14,25 @@ type Summary struct { Message []string } +func dedupMessage(messages []string) []string { + if len(messages) <= 1 { + return messages + } + + seen := map[string]bool{} + var result []string + + for _, message := range messages { + if seen[message] { + continue + } + seen[message] = true + result = append(result, message) + } + + return result +} + func Summarize(unstr *unstructured.Unstructured) Summary { var ( obj data.Object @@ -35,5 +54,6 @@ func Summarize(unstr *unstructured.Unstructured) Summary { } summary.State = strings.ToLower(summary.State) + summary.Message = dedupMessage(summary.Message) return summary } diff --git a/vendor/k8s.io/client-go/metadata/metadatainformer/informer.go b/vendor/k8s.io/client-go/dynamic/dynamicinformer/informer.go similarity index 61% rename from vendor/k8s.io/client-go/metadata/metadatainformer/informer.go rename to vendor/k8s.io/client-go/dynamic/dynamicinformer/informer.go index 4c9efed..42520a9 100644 --- a/vendor/k8s.io/client-go/metadata/metadatainformer/informer.go +++ b/vendor/k8s.io/client-go/dynamic/dynamicinformer/informer.go @@ -14,31 +14,32 @@ See the License for the specific language governing permissions and limitations under the License. */ -package metadatainformer +package dynamicinformer import ( "sync" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/dynamic/dynamiclister" "k8s.io/client-go/informers" - "k8s.io/client-go/metadata" - "k8s.io/client-go/metadata/metadatalister" "k8s.io/client-go/tools/cache" ) -// NewSharedInformerFactory constructs a new instance of metadataSharedInformerFactory for all namespaces. -func NewSharedInformerFactory(client metadata.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewFilteredSharedInformerFactory(client, defaultResync, metav1.NamespaceAll, nil) +// NewDynamicSharedInformerFactory constructs a new instance of dynamicSharedInformerFactory for all namespaces. +func NewDynamicSharedInformerFactory(client dynamic.Interface, defaultResync time.Duration) DynamicSharedInformerFactory { + return NewFilteredDynamicSharedInformerFactory(client, defaultResync, metav1.NamespaceAll, nil) } -// NewFilteredSharedInformerFactory constructs a new instance of metadataSharedInformerFactory. +// NewFilteredDynamicSharedInformerFactory constructs a new instance of dynamicSharedInformerFactory. // Listers obtained via this factory will be subject to the same filters as specified here. -func NewFilteredSharedInformerFactory(client metadata.Interface, defaultResync time.Duration, namespace string, tweakListOptions TweakListOptionsFunc) SharedInformerFactory { - return &metadataSharedInformerFactory{ +func NewFilteredDynamicSharedInformerFactory(client dynamic.Interface, defaultResync time.Duration, namespace string, tweakListOptions TweakListOptionsFunc) DynamicSharedInformerFactory { + return &dynamicSharedInformerFactory{ client: client, defaultResync: defaultResync, namespace: namespace, @@ -48,8 +49,8 @@ func NewFilteredSharedInformerFactory(client metadata.Interface, defaultResync t } } -type metadataSharedInformerFactory struct { - client metadata.Interface +type dynamicSharedInformerFactory struct { + client dynamic.Interface defaultResync time.Duration namespace string @@ -61,9 +62,9 @@ type metadataSharedInformerFactory struct { tweakListOptions TweakListOptionsFunc } -var _ SharedInformerFactory = &metadataSharedInformerFactory{} +var _ DynamicSharedInformerFactory = &dynamicSharedInformerFactory{} -func (f *metadataSharedInformerFactory) ForResource(gvr schema.GroupVersionResource) informers.GenericInformer { +func (f *dynamicSharedInformerFactory) ForResource(gvr schema.GroupVersionResource) informers.GenericInformer { f.lock.Lock() defer f.lock.Unlock() @@ -73,14 +74,14 @@ func (f *metadataSharedInformerFactory) ForResource(gvr schema.GroupVersionResou return informer } - informer = NewFilteredMetadataInformer(f.client, gvr, f.namespace, f.defaultResync, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) + informer = NewFilteredDynamicInformer(f.client, gvr, f.namespace, f.defaultResync, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) f.informers[key] = informer return informer } // Start initializes all requested informers. -func (f *metadataSharedInformerFactory) Start(stopCh <-chan struct{}) { +func (f *dynamicSharedInformerFactory) Start(stopCh <-chan struct{}) { f.lock.Lock() defer f.lock.Unlock() @@ -93,7 +94,7 @@ func (f *metadataSharedInformerFactory) Start(stopCh <-chan struct{}) { } // WaitForCacheSync waits for all started informers' cache were synced. -func (f *metadataSharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[schema.GroupVersionResource]bool { +func (f *dynamicSharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[schema.GroupVersionResource]bool { informers := func() map[schema.GroupVersionResource]cache.SharedIndexInformer { f.lock.Lock() defer f.lock.Unlock() @@ -114,9 +115,9 @@ func (f *metadataSharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) return res } -// NewFilteredMetadataInformer constructs a new informer for a metadata type. -func NewFilteredMetadataInformer(client metadata.Interface, gvr schema.GroupVersionResource, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions TweakListOptionsFunc) informers.GenericInformer { - return &metadataInformer{ +// NewFilteredDynamicInformer constructs a new informer for a dynamic type. +func NewFilteredDynamicInformer(client dynamic.Interface, gvr schema.GroupVersionResource, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions TweakListOptionsFunc) informers.GenericInformer { + return &dynamicInformer{ gvr: gvr, informer: cache.NewSharedIndexInformer( &cache.ListWatch{ @@ -133,24 +134,24 @@ func NewFilteredMetadataInformer(client metadata.Interface, gvr schema.GroupVers return client.Resource(gvr).Namespace(namespace).Watch(options) }, }, - &metav1.PartialObjectMetadata{}, + &unstructured.Unstructured{}, resyncPeriod, indexers, ), } } -type metadataInformer struct { +type dynamicInformer struct { informer cache.SharedIndexInformer gvr schema.GroupVersionResource } -var _ informers.GenericInformer = &metadataInformer{} +var _ informers.GenericInformer = &dynamicInformer{} -func (d *metadataInformer) Informer() cache.SharedIndexInformer { +func (d *dynamicInformer) Informer() cache.SharedIndexInformer { return d.informer } -func (d *metadataInformer) Lister() cache.GenericLister { - return metadatalister.NewRuntimeObjectShim(metadatalister.New(d.informer.GetIndexer(), d.gvr)) +func (d *dynamicInformer) Lister() cache.GenericLister { + return dynamiclister.NewRuntimeObjectShim(dynamiclister.New(d.informer.GetIndexer(), d.gvr)) } diff --git a/vendor/k8s.io/client-go/metadata/metadatainformer/interface.go b/vendor/k8s.io/client-go/dynamic/dynamicinformer/interface.go similarity index 86% rename from vendor/k8s.io/client-go/metadata/metadatainformer/interface.go rename to vendor/k8s.io/client-go/dynamic/dynamicinformer/interface.go index 732e565..083977c 100644 --- a/vendor/k8s.io/client-go/metadata/metadatainformer/interface.go +++ b/vendor/k8s.io/client-go/dynamic/dynamicinformer/interface.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package metadatainformer +package dynamicinformer import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -22,8 +22,8 @@ import ( "k8s.io/client-go/informers" ) -// SharedInformerFactory provides access to a shared informer and lister for dynamic client -type SharedInformerFactory interface { +// DynamicSharedInformerFactory provides access to a shared informer and lister for dynamic client +type DynamicSharedInformerFactory interface { Start(stopCh <-chan struct{}) ForResource(gvr schema.GroupVersionResource) informers.GenericInformer WaitForCacheSync(stopCh <-chan struct{}) map[schema.GroupVersionResource]bool diff --git a/vendor/k8s.io/client-go/metadata/metadatalister/interface.go b/vendor/k8s.io/client-go/dynamic/dynamiclister/interface.go similarity index 76% rename from vendor/k8s.io/client-go/metadata/metadatalister/interface.go rename to vendor/k8s.io/client-go/dynamic/dynamiclister/interface.go index bb35485..c39cbee 100644 --- a/vendor/k8s.io/client-go/metadata/metadatalister/interface.go +++ b/vendor/k8s.io/client-go/dynamic/dynamiclister/interface.go @@ -14,19 +14,19 @@ See the License for the specific language governing permissions and limitations under the License. */ -package metadatalister +package dynamiclister import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" ) // Lister helps list resources. type Lister interface { // List lists all resources in the indexer. - List(selector labels.Selector) (ret []*metav1.PartialObjectMetadata, err error) + List(selector labels.Selector) (ret []*unstructured.Unstructured, err error) // Get retrieves a resource from the indexer with the given name - Get(name string) (*metav1.PartialObjectMetadata, error) + Get(name string) (*unstructured.Unstructured, error) // Namespace returns an object that can list and get resources in a given namespace. Namespace(namespace string) NamespaceLister } @@ -34,7 +34,7 @@ type Lister interface { // NamespaceLister helps list and get resources. type NamespaceLister interface { // List lists all resources in the indexer for a given namespace. - List(selector labels.Selector) (ret []*metav1.PartialObjectMetadata, err error) + List(selector labels.Selector) (ret []*unstructured.Unstructured, err error) // Get retrieves a resource from the indexer for a given namespace and name. - Get(name string) (*metav1.PartialObjectMetadata, error) + Get(name string) (*unstructured.Unstructured, error) } diff --git a/vendor/k8s.io/client-go/metadata/metadatalister/lister.go b/vendor/k8s.io/client-go/dynamic/dynamiclister/lister.go similarity index 61% rename from vendor/k8s.io/client-go/metadata/metadatalister/lister.go rename to vendor/k8s.io/client-go/dynamic/dynamiclister/lister.go index faeccc0..a50fc47 100644 --- a/vendor/k8s.io/client-go/metadata/metadatalister/lister.go +++ b/vendor/k8s.io/client-go/dynamic/dynamiclister/lister.go @@ -14,40 +14,40 @@ See the License for the specific language governing permissions and limitations under the License. */ -package metadatalister +package dynamiclister import ( "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/tools/cache" ) -var _ Lister = &metadataLister{} -var _ NamespaceLister = &metadataNamespaceLister{} +var _ Lister = &dynamicLister{} +var _ NamespaceLister = &dynamicNamespaceLister{} -// metadataLister implements the Lister interface. -type metadataLister struct { +// dynamicLister implements the Lister interface. +type dynamicLister struct { indexer cache.Indexer gvr schema.GroupVersionResource } // New returns a new Lister. func New(indexer cache.Indexer, gvr schema.GroupVersionResource) Lister { - return &metadataLister{indexer: indexer, gvr: gvr} + return &dynamicLister{indexer: indexer, gvr: gvr} } // List lists all resources in the indexer. -func (l *metadataLister) List(selector labels.Selector) (ret []*metav1.PartialObjectMetadata, err error) { +func (l *dynamicLister) List(selector labels.Selector) (ret []*unstructured.Unstructured, err error) { err = cache.ListAll(l.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*metav1.PartialObjectMetadata)) + ret = append(ret, m.(*unstructured.Unstructured)) }) return ret, err } // Get retrieves a resource from the indexer with the given name -func (l *metadataLister) Get(name string) (*metav1.PartialObjectMetadata, error) { +func (l *dynamicLister) Get(name string) (*unstructured.Unstructured, error) { obj, exists, err := l.indexer.GetByKey(name) if err != nil { return nil, err @@ -55,31 +55,31 @@ func (l *metadataLister) Get(name string) (*metav1.PartialObjectMetadata, error) if !exists { return nil, errors.NewNotFound(l.gvr.GroupResource(), name) } - return obj.(*metav1.PartialObjectMetadata), nil + return obj.(*unstructured.Unstructured), nil } // Namespace returns an object that can list and get resources from a given namespace. -func (l *metadataLister) Namespace(namespace string) NamespaceLister { - return &metadataNamespaceLister{indexer: l.indexer, namespace: namespace, gvr: l.gvr} +func (l *dynamicLister) Namespace(namespace string) NamespaceLister { + return &dynamicNamespaceLister{indexer: l.indexer, namespace: namespace, gvr: l.gvr} } -// metadataNamespaceLister implements the NamespaceLister interface. -type metadataNamespaceLister struct { +// dynamicNamespaceLister implements the NamespaceLister interface. +type dynamicNamespaceLister struct { indexer cache.Indexer namespace string gvr schema.GroupVersionResource } // List lists all resources in the indexer for a given namespace. -func (l *metadataNamespaceLister) List(selector labels.Selector) (ret []*metav1.PartialObjectMetadata, err error) { +func (l *dynamicNamespaceLister) List(selector labels.Selector) (ret []*unstructured.Unstructured, err error) { err = cache.ListAllByNamespace(l.indexer, l.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*metav1.PartialObjectMetadata)) + ret = append(ret, m.(*unstructured.Unstructured)) }) return ret, err } // Get retrieves a resource from the indexer for a given namespace and name. -func (l *metadataNamespaceLister) Get(name string) (*metav1.PartialObjectMetadata, error) { +func (l *dynamicNamespaceLister) Get(name string) (*unstructured.Unstructured, error) { obj, exists, err := l.indexer.GetByKey(l.namespace + "/" + name) if err != nil { return nil, err @@ -87,5 +87,5 @@ func (l *metadataNamespaceLister) Get(name string) (*metav1.PartialObjectMetadat if !exists { return nil, errors.NewNotFound(l.gvr.GroupResource(), name) } - return obj.(*metav1.PartialObjectMetadata), nil + return obj.(*unstructured.Unstructured), nil } diff --git a/vendor/k8s.io/client-go/metadata/metadatalister/shim.go b/vendor/k8s.io/client-go/dynamic/dynamiclister/shim.go similarity index 66% rename from vendor/k8s.io/client-go/metadata/metadatalister/shim.go rename to vendor/k8s.io/client-go/dynamic/dynamiclister/shim.go index f31c607..92a5f54 100644 --- a/vendor/k8s.io/client-go/metadata/metadatalister/shim.go +++ b/vendor/k8s.io/client-go/dynamic/dynamiclister/shim.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package metadatalister +package dynamiclister import ( "k8s.io/apimachinery/pkg/labels" @@ -22,22 +22,22 @@ import ( "k8s.io/client-go/tools/cache" ) -var _ cache.GenericLister = &metadataListerShim{} -var _ cache.GenericNamespaceLister = &metadataNamespaceListerShim{} +var _ cache.GenericLister = &dynamicListerShim{} +var _ cache.GenericNamespaceLister = &dynamicNamespaceListerShim{} -// metadataListerShim implements the cache.GenericLister interface. -type metadataListerShim struct { +// dynamicListerShim implements the cache.GenericLister interface. +type dynamicListerShim struct { lister Lister } // NewRuntimeObjectShim returns a new shim for Lister. // It wraps Lister so that it implements cache.GenericLister interface func NewRuntimeObjectShim(lister Lister) cache.GenericLister { - return &metadataListerShim{lister: lister} + return &dynamicListerShim{lister: lister} } // List will return all objects across namespaces -func (s *metadataListerShim) List(selector labels.Selector) (ret []runtime.Object, err error) { +func (s *dynamicListerShim) List(selector labels.Selector) (ret []runtime.Object, err error) { objs, err := s.lister.List(selector) if err != nil { return nil, err @@ -51,24 +51,24 @@ func (s *metadataListerShim) List(selector labels.Selector) (ret []runtime.Objec } // Get will attempt to retrieve assuming that name==key -func (s *metadataListerShim) Get(name string) (runtime.Object, error) { +func (s *dynamicListerShim) Get(name string) (runtime.Object, error) { return s.lister.Get(name) } -func (s *metadataListerShim) ByNamespace(namespace string) cache.GenericNamespaceLister { - return &metadataNamespaceListerShim{ +func (s *dynamicListerShim) ByNamespace(namespace string) cache.GenericNamespaceLister { + return &dynamicNamespaceListerShim{ namespaceLister: s.lister.Namespace(namespace), } } -// metadataNamespaceListerShim implements the NamespaceLister interface. +// dynamicNamespaceListerShim implements the NamespaceLister interface. // It wraps NamespaceLister so that it implements cache.GenericNamespaceLister interface -type metadataNamespaceListerShim struct { +type dynamicNamespaceListerShim struct { namespaceLister NamespaceLister } // List will return all objects in this namespace -func (ns *metadataNamespaceListerShim) List(selector labels.Selector) (ret []runtime.Object, err error) { +func (ns *dynamicNamespaceListerShim) List(selector labels.Selector) (ret []runtime.Object, err error) { objs, err := ns.namespaceLister.List(selector) if err != nil { return nil, err @@ -82,6 +82,6 @@ func (ns *metadataNamespaceListerShim) List(selector labels.Selector) (ret []run } // Get will attempt to retrieve by namespace and name -func (ns *metadataNamespaceListerShim) Get(name string) (runtime.Object, error) { +func (ns *dynamicNamespaceListerShim) Get(name string) (runtime.Object, error) { return ns.namespaceLister.Get(name) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 49d0d4c..f623685 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -52,7 +52,7 @@ github.com/mxk/go-flowrate/flowrate github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.0 github.com/pmezard/go-difflib/difflib -# github.com/rancher/dynamiclistener v0.2.1-0.20200131054153-795bb90214d9 => ../dynamiclistener +# github.com/rancher/dynamiclistener v0.2.1-0.20200213165308-111c5b43e932 github.com/rancher/dynamiclistener github.com/rancher/dynamiclistener/cert github.com/rancher/dynamiclistener/factory @@ -60,9 +60,10 @@ github.com/rancher/dynamiclistener/server github.com/rancher/dynamiclistener/storage/file github.com/rancher/dynamiclistener/storage/kubernetes github.com/rancher/dynamiclistener/storage/memory -# github.com/rancher/wrangler v0.4.2-0.20200215064225-8abf292acf7b +# github.com/rancher/wrangler v0.5.1-0.20200312201919-371ff2551072 github.com/rancher/wrangler/pkg/apply github.com/rancher/wrangler/pkg/apply/injectors +github.com/rancher/wrangler/pkg/broadcast github.com/rancher/wrangler/pkg/condition github.com/rancher/wrangler/pkg/data github.com/rancher/wrangler/pkg/data/convert @@ -73,6 +74,7 @@ github.com/rancher/wrangler/pkg/kv github.com/rancher/wrangler/pkg/merr github.com/rancher/wrangler/pkg/name github.com/rancher/wrangler/pkg/objectset +github.com/rancher/wrangler/pkg/patch github.com/rancher/wrangler/pkg/ratelimit github.com/rancher/wrangler/pkg/schemas github.com/rancher/wrangler/pkg/schemas/definition @@ -264,6 +266,8 @@ k8s.io/apiserver/plugin/pkg/authenticator/token/webhook # k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible => k8s.io/client-go v0.17.2 k8s.io/client-go/discovery k8s.io/client-go/dynamic +k8s.io/client-go/dynamic/dynamicinformer +k8s.io/client-go/dynamic/dynamiclister k8s.io/client-go/informers k8s.io/client-go/informers/admissionregistration k8s.io/client-go/informers/admissionregistration/v1 @@ -400,8 +404,6 @@ k8s.io/client-go/listers/storage/v1 k8s.io/client-go/listers/storage/v1alpha1 k8s.io/client-go/listers/storage/v1beta1 k8s.io/client-go/metadata -k8s.io/client-go/metadata/metadatainformer -k8s.io/client-go/metadata/metadatalister k8s.io/client-go/pkg/apis/clientauthentication k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1 k8s.io/client-go/pkg/apis/clientauthentication/v1beta1