// reorganizeTaints returns the updated set of taints, taking into account old taints that were not updated, // old taints that were updated, old taints that were deleted, and new taints. func reorganizeTaints(accessor meta.Object, overwrite bool, taintsToAdd []api.Taint, taintsToRemove []api.Taint) ([]api.Taint, error) { newTaints := append([]api.Taint{}, taintsToAdd...) var oldTaints []api.Taint var err error annotations := accessor.GetAnnotations() if annotations != nil { if oldTaints, err = api.GetTaintsFromNodeAnnotations(annotations); err != nil { return nil, err } } // add taints that already existing but not updated to newTaints for _, oldTaint := range oldTaints { existsInNew := false for _, taint := range newTaints { if taint.MatchTaint(oldTaint) { existsInNew = true break } } if !existsInNew { newTaints = append(newTaints, oldTaint) } } allErrs := []error{} for _, taintToRemove := range taintsToRemove { newTaints, err = deleteTaint(newTaints, taintToRemove) if err != nil { allErrs = append(allErrs, err) } } return newTaints, utilerrors.NewAggregate(allErrs) }
func validateNoOverwrites(accessor meta.Object, labels map[string]string) error { allErrs := []error{} for key := range labels { if value, found := accessor.GetLabels()[key]; found { allErrs = append(allErrs, fmt.Errorf("'%s' already has a value (%s), and --overwrite is false", key, value)) } } return utilerrors.NewAggregate(allErrs) }
// patchObj patches calculates a patch between the given new object and the existing marshaled object func patchObj(obj runtime.Object, metadata meta.Object, oldData []byte, mapping *meta.RESTMapping, f *clientcmd.Factory) (runtime.Object, error) { newData, err := json.Marshal(obj) if err != nil { return nil, err } patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj) if err != nil { return nil, err } client, err := f.ClientForMapping(mapping) if err != nil { return nil, err } helper := resource.NewHelper(client, mapping) return helper.Patch(metadata.GetNamespace(), metadata.GetName(), kapi.StrategicMergePatchType, patchBytes) }
// validateNoAnnotationOverwrites validates that when overwrite is false, to-be-updated annotations don't exist in the object annotation map (yet) func validateNoAnnotationOverwrites(accessor meta.Object, annotations map[string]string) error { var buf bytes.Buffer for key := range annotations { // change-cause annotation can always be overwritten if key == kubectl.ChangeCauseAnnotation { continue } if value, found := accessor.GetAnnotations()[key]; found { if buf.Len() > 0 { buf.WriteString("; ") } buf.WriteString(fmt.Sprintf("'%s' already has a value (%s)", key, value)) } } if buf.Len() > 0 { return fmt.Errorf("--overwrite is false but found the following declared annotation(s): %s", buf.String()) } return nil }
func shouldOrphanDependents(e event, accessor meta.Object) bool { // The delta_fifo may combine the creation and update of the object into one // event, so we need to check AddEvent as well. if e.oldObj == nil { if accessor.GetDeletionTimestamp() == nil { return false } } else { oldAccessor, err := meta.Accessor(e.oldObj) if err != nil { utilruntime.HandleError(fmt.Errorf("cannot access oldObj: %v", err)) return false } // ignore the event if it's not updating DeletionTimestamp from non-nil to nil. if accessor.GetDeletionTimestamp() == nil || oldAccessor.GetDeletionTimestamp() != nil { return false } } finalizers := accessor.GetFinalizers() for _, finalizer := range finalizers { if finalizer == api.FinalizerOrphan { return true } } return false }
// shouldUpdateFinalizers returns if we need to update the finalizers of the // object, and the desired list of finalizers. // When deciding whether to add the OrphanDependent finalizer, factors in the // order of highest to lowest priority are: options.OrphanDependents, existing // finalizers of the object, e.DeleteStrategy.DefaultGarbageCollectionPolicy. func shouldUpdateFinalizers(e *Store, accessor meta.Object, options *api.DeleteOptions) (shouldUpdate bool, newFinalizers []string) { shouldOrphan := false // Get default orphan policy from this REST object type if gcStrategy, ok := e.DeleteStrategy.(rest.GarbageCollectionDeleteStrategy); ok { if gcStrategy.DefaultGarbageCollectionPolicy() == rest.OrphanDependents { shouldOrphan = true } } // If a finalizer is set in the object, it overrides the default hasOrphanFinalizer := false finalizers := accessor.GetFinalizers() for _, f := range finalizers { if f == api.FinalizerOrphan { shouldOrphan = true hasOrphanFinalizer = true break } // TODO: update this when we add a finalizer indicating a preference for the other behavior } // If an explicit policy was set at deletion time, that overrides both if options != nil && options.OrphanDependents != nil { shouldOrphan = *options.OrphanDependents } if shouldOrphan && !hasOrphanFinalizer { finalizers = append(finalizers, api.FinalizerOrphan) return true, finalizers } if !shouldOrphan && hasOrphanFinalizer { var newFinalizers []string for _, f := range finalizers { if f == api.FinalizerOrphan { continue } newFinalizers = append(newFinalizers, f) } return true, newFinalizers } return false, finalizers }
// return if we need to update the finalizers of the object, and the desired list of finalizers func shouldUpdateFinalizers(accessor meta.Object, options *api.DeleteOptions) (shouldUpdate bool, newFinalizers []string) { if options == nil || options.OrphanDependents == nil { return false, accessor.GetFinalizers() } shouldOrphan := *options.OrphanDependents alreadyOrphan := false finalizers := accessor.GetFinalizers() newFinalizers = make([]string, 0, len(finalizers)) for _, f := range finalizers { if f == api.FinalizerOrphan { alreadyOrphan = true if !shouldOrphan { continue } } newFinalizers = append(newFinalizers, f) } if shouldOrphan && !alreadyOrphan { newFinalizers = append(newFinalizers, api.FinalizerOrphan) } shouldUpdate = shouldOrphan != alreadyOrphan return shouldUpdate, newFinalizers }
// validateNoTaintOverwrites validates that when overwrite is false, to-be-updated taints don't exist in the node taint list (yet) func validateNoTaintOverwrites(accessor meta.Object, taints []api.Taint) error { annotations := accessor.GetAnnotations() if annotations == nil { return nil } allErrs := []error{} oldTaints, err := api.GetTaintsFromNodeAnnotations(annotations) if err != nil { allErrs = append(allErrs, err) return utilerrors.NewAggregate(allErrs) } for _, taint := range taints { for _, oldTaint := range oldTaints { if taint.Key == oldTaint.Key && taint.Effect == oldTaint.Effect { allErrs = append(allErrs, fmt.Errorf("Node '%s' already has a taint with key (%s) and effect (%v), and --overwrite is false", accessor.GetName(), taint.Key, taint.Effect)) break } } } return utilerrors.NewAggregate(allErrs) }
func exportObjectMeta(accessor meta.Object, exact bool) { accessor.SetUID("") if !exact { accessor.SetNamespace("") } accessor.SetCreationTimestamp(unversioned.Time{}) accessor.SetDeletionTimestamp(nil) accessor.SetResourceVersion("") accessor.SetSelfLink("") if len(accessor.GetGenerateName()) > 0 && !exact { accessor.SetName("") } }
func (f *FakeControllerSource) key(accessor meta.Object) nnu { return nnu{accessor.GetNamespace(), accessor.GetName(), accessor.GetUID()} }