123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576 |
- package controller
- import (
- "encoding/json"
- "fmt"
- "sync"
- apps "k8s.io/api/apps/v1"
- v1 "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/api/errors"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/apimachinery/pkg/labels"
- "k8s.io/apimachinery/pkg/runtime/schema"
- "k8s.io/apimachinery/pkg/types"
- utilerrors "k8s.io/apimachinery/pkg/util/errors"
- "k8s.io/klog"
- )
- type BaseControllerRefManager struct {
- Controller metav1.Object
- Selector labels.Selector
- canAdoptErr error
- canAdoptOnce sync.Once
- CanAdoptFunc func() error
- }
- func (m *BaseControllerRefManager) CanAdopt() error {
- m.canAdoptOnce.Do(func() {
- if m.CanAdoptFunc != nil {
- m.canAdoptErr = m.CanAdoptFunc()
- }
- })
- return m.canAdoptErr
- }
- func (m *BaseControllerRefManager) ClaimObject(obj metav1.Object, match func(metav1.Object) bool, adopt, release func(metav1.Object) error) (bool, error) {
- controllerRef := metav1.GetControllerOfNoCopy(obj)
- if controllerRef != nil {
- if controllerRef.UID != m.Controller.GetUID() {
-
- return false, nil
- }
- if match(obj) {
-
-
-
-
- return true, nil
- }
-
-
- if m.Controller.GetDeletionTimestamp() != nil {
- return false, nil
- }
- if err := release(obj); err != nil {
-
- if errors.IsNotFound(err) {
- return false, nil
- }
-
-
- return false, err
- }
-
- return false, nil
- }
-
- if m.Controller.GetDeletionTimestamp() != nil || !match(obj) {
-
- return false, nil
- }
- if obj.GetDeletionTimestamp() != nil {
-
- return false, nil
- }
-
- if err := adopt(obj); err != nil {
-
- if errors.IsNotFound(err) {
- return false, nil
- }
-
-
- return false, err
- }
-
- return true, nil
- }
- type PodControllerRefManager struct {
- BaseControllerRefManager
- controllerKind schema.GroupVersionKind
- podControl PodControlInterface
- }
- func NewPodControllerRefManager(
- podControl PodControlInterface,
- controller metav1.Object,
- selector labels.Selector,
- controllerKind schema.GroupVersionKind,
- canAdopt func() error,
- ) *PodControllerRefManager {
- return &PodControllerRefManager{
- BaseControllerRefManager: BaseControllerRefManager{
- Controller: controller,
- Selector: selector,
- CanAdoptFunc: canAdopt,
- },
- controllerKind: controllerKind,
- podControl: podControl,
- }
- }
- func (m *PodControllerRefManager) ClaimPods(pods []*v1.Pod, filters ...func(*v1.Pod) bool) ([]*v1.Pod, error) {
- var claimed []*v1.Pod
- var errlist []error
- match := func(obj metav1.Object) bool {
- pod := obj.(*v1.Pod)
-
- if !m.Selector.Matches(labels.Set(pod.Labels)) {
- return false
- }
- for _, filter := range filters {
- if !filter(pod) {
- return false
- }
- }
- return true
- }
- adopt := func(obj metav1.Object) error {
- return m.AdoptPod(obj.(*v1.Pod))
- }
- release := func(obj metav1.Object) error {
- return m.ReleasePod(obj.(*v1.Pod))
- }
- for _, pod := range pods {
- ok, err := m.ClaimObject(pod, match, adopt, release)
- if err != nil {
- errlist = append(errlist, err)
- continue
- }
- if ok {
- claimed = append(claimed, pod)
- }
- }
- return claimed, utilerrors.NewAggregate(errlist)
- }
- func (m *PodControllerRefManager) AdoptPod(pod *v1.Pod) error {
- if err := m.CanAdopt(); err != nil {
- return fmt.Errorf("can't adopt Pod %v/%v (%v): %v", pod.Namespace, pod.Name, pod.UID, err)
- }
-
-
- patchBytes, err := ownerRefControllerPatch(m.Controller, m.controllerKind, pod.UID)
- if err != nil {
- return err
- }
- return m.podControl.PatchPod(pod.Namespace, pod.Name, patchBytes)
- }
- func (m *PodControllerRefManager) ReleasePod(pod *v1.Pod) error {
- klog.V(2).Infof("patching pod %s_%s to remove its controllerRef to %s/%s:%s",
- pod.Namespace, pod.Name, m.controllerKind.GroupVersion(), m.controllerKind.Kind, m.Controller.GetName())
- patchBytes, err := deleteOwnerRefStrategicMergePatch(pod.UID, m.Controller.GetUID())
- if err != nil {
- return err
- }
- err = m.podControl.PatchPod(pod.Namespace, pod.Name, patchBytes)
- if err != nil {
- if errors.IsNotFound(err) {
-
- return nil
- }
- if errors.IsInvalid(err) {
-
-
-
-
-
-
-
- return nil
- }
- }
- return err
- }
- type ReplicaSetControllerRefManager struct {
- BaseControllerRefManager
- controllerKind schema.GroupVersionKind
- rsControl RSControlInterface
- }
- func NewReplicaSetControllerRefManager(
- rsControl RSControlInterface,
- controller metav1.Object,
- selector labels.Selector,
- controllerKind schema.GroupVersionKind,
- canAdopt func() error,
- ) *ReplicaSetControllerRefManager {
- return &ReplicaSetControllerRefManager{
- BaseControllerRefManager: BaseControllerRefManager{
- Controller: controller,
- Selector: selector,
- CanAdoptFunc: canAdopt,
- },
- controllerKind: controllerKind,
- rsControl: rsControl,
- }
- }
- func (m *ReplicaSetControllerRefManager) ClaimReplicaSets(sets []*apps.ReplicaSet) ([]*apps.ReplicaSet, error) {
- var claimed []*apps.ReplicaSet
- var errlist []error
- match := func(obj metav1.Object) bool {
- return m.Selector.Matches(labels.Set(obj.GetLabels()))
- }
- adopt := func(obj metav1.Object) error {
- return m.AdoptReplicaSet(obj.(*apps.ReplicaSet))
- }
- release := func(obj metav1.Object) error {
- return m.ReleaseReplicaSet(obj.(*apps.ReplicaSet))
- }
- for _, rs := range sets {
- ok, err := m.ClaimObject(rs, match, adopt, release)
- if err != nil {
- errlist = append(errlist, err)
- continue
- }
- if ok {
- claimed = append(claimed, rs)
- }
- }
- return claimed, utilerrors.NewAggregate(errlist)
- }
- func (m *ReplicaSetControllerRefManager) AdoptReplicaSet(rs *apps.ReplicaSet) error {
- if err := m.CanAdopt(); err != nil {
- return fmt.Errorf("can't adopt ReplicaSet %v/%v (%v): %v", rs.Namespace, rs.Name, rs.UID, err)
- }
-
-
- patchBytes, err := ownerRefControllerPatch(m.Controller, m.controllerKind, rs.UID)
- if err != nil {
- return err
- }
- return m.rsControl.PatchReplicaSet(rs.Namespace, rs.Name, patchBytes)
- }
- func (m *ReplicaSetControllerRefManager) ReleaseReplicaSet(replicaSet *apps.ReplicaSet) error {
- klog.V(2).Infof("patching ReplicaSet %s_%s to remove its controllerRef to %s/%s:%s",
- replicaSet.Namespace, replicaSet.Name, m.controllerKind.GroupVersion(), m.controllerKind.Kind, m.Controller.GetName())
- patchBytes, err := deleteOwnerRefStrategicMergePatch(replicaSet.UID, m.Controller.GetUID())
- if err != nil {
- return err
- }
- err = m.rsControl.PatchReplicaSet(replicaSet.Namespace, replicaSet.Name, patchBytes)
- if err != nil {
- if errors.IsNotFound(err) {
-
- return nil
- }
- if errors.IsInvalid(err) {
-
-
-
-
- return nil
- }
- }
- return err
- }
- func RecheckDeletionTimestamp(getObject func() (metav1.Object, error)) func() error {
- return func() error {
- obj, err := getObject()
- if err != nil {
- return fmt.Errorf("can't recheck DeletionTimestamp: %v", err)
- }
- if obj.GetDeletionTimestamp() != nil {
- return fmt.Errorf("%v/%v has just been deleted at %v", obj.GetNamespace(), obj.GetName(), obj.GetDeletionTimestamp())
- }
- return nil
- }
- }
- type ControllerRevisionControllerRefManager struct {
- BaseControllerRefManager
- controllerKind schema.GroupVersionKind
- crControl ControllerRevisionControlInterface
- }
- func NewControllerRevisionControllerRefManager(
- crControl ControllerRevisionControlInterface,
- controller metav1.Object,
- selector labels.Selector,
- controllerKind schema.GroupVersionKind,
- canAdopt func() error,
- ) *ControllerRevisionControllerRefManager {
- return &ControllerRevisionControllerRefManager{
- BaseControllerRefManager: BaseControllerRefManager{
- Controller: controller,
- Selector: selector,
- CanAdoptFunc: canAdopt,
- },
- controllerKind: controllerKind,
- crControl: crControl,
- }
- }
- func (m *ControllerRevisionControllerRefManager) ClaimControllerRevisions(histories []*apps.ControllerRevision) ([]*apps.ControllerRevision, error) {
- var claimed []*apps.ControllerRevision
- var errlist []error
- match := func(obj metav1.Object) bool {
- return m.Selector.Matches(labels.Set(obj.GetLabels()))
- }
- adopt := func(obj metav1.Object) error {
- return m.AdoptControllerRevision(obj.(*apps.ControllerRevision))
- }
- release := func(obj metav1.Object) error {
- return m.ReleaseControllerRevision(obj.(*apps.ControllerRevision))
- }
- for _, h := range histories {
- ok, err := m.ClaimObject(h, match, adopt, release)
- if err != nil {
- errlist = append(errlist, err)
- continue
- }
- if ok {
- claimed = append(claimed, h)
- }
- }
- return claimed, utilerrors.NewAggregate(errlist)
- }
- func (m *ControllerRevisionControllerRefManager) AdoptControllerRevision(history *apps.ControllerRevision) error {
- if err := m.CanAdopt(); err != nil {
- return fmt.Errorf("can't adopt ControllerRevision %v/%v (%v): %v", history.Namespace, history.Name, history.UID, err)
- }
-
-
- patchBytes, err := ownerRefControllerPatch(m.Controller, m.controllerKind, history.UID)
- if err != nil {
- return err
- }
- return m.crControl.PatchControllerRevision(history.Namespace, history.Name, patchBytes)
- }
- func (m *ControllerRevisionControllerRefManager) ReleaseControllerRevision(history *apps.ControllerRevision) error {
- klog.V(2).Infof("patching ControllerRevision %s_%s to remove its controllerRef to %s/%s:%s",
- history.Namespace, history.Name, m.controllerKind.GroupVersion(), m.controllerKind.Kind, m.Controller.GetName())
- patchBytes, err := deleteOwnerRefStrategicMergePatch(history.UID, m.Controller.GetUID())
- if err != nil {
- return err
- }
- err = m.crControl.PatchControllerRevision(history.Namespace, history.Name, patchBytes)
- if err != nil {
- if errors.IsNotFound(err) {
-
- return nil
- }
- if errors.IsInvalid(err) {
-
-
-
-
- return nil
- }
- }
- return err
- }
- type objectForDeleteOwnerRefStrategicMergePatch struct {
- Metadata objectMetaForMergePatch `json:"metadata"`
- }
- type objectMetaForMergePatch struct {
- UID types.UID `json:"uid"`
- OwnerReferences []map[string]string `json:"ownerReferences"`
- }
- func deleteOwnerRefStrategicMergePatch(dependentUID types.UID, ownerUIDs ...types.UID) ([]byte, error) {
- var pieces []map[string]string
- for _, ownerUID := range ownerUIDs {
- pieces = append(pieces, map[string]string{"$patch": "delete", "uid": string(ownerUID)})
- }
- patch := objectForDeleteOwnerRefStrategicMergePatch{
- Metadata: objectMetaForMergePatch{
- UID: dependentUID,
- OwnerReferences: pieces,
- },
- }
- patchBytes, err := json.Marshal(&patch)
- if err != nil {
- return nil, err
- }
- return patchBytes, nil
- }
- type objectForAddOwnerRefPatch struct {
- Metadata objectMetaForPatch `json:"metadata"`
- }
- type objectMetaForPatch struct {
- OwnerReferences []metav1.OwnerReference `json:"ownerReferences"`
- UID types.UID `json:"uid"`
- }
- func ownerRefControllerPatch(controller metav1.Object, controllerKind schema.GroupVersionKind, uid types.UID) ([]byte, error) {
- blockOwnerDeletion := true
- isController := true
- addControllerPatch := objectForAddOwnerRefPatch{
- Metadata: objectMetaForPatch{
- UID: uid,
- OwnerReferences: []metav1.OwnerReference{
- {
- APIVersion: controllerKind.GroupVersion().String(),
- Kind: controllerKind.Kind,
- Name: controller.GetName(),
- UID: controller.GetUID(),
- Controller: &isController,
- BlockOwnerDeletion: &blockOwnerDeletion,
- },
- },
- },
- }
- patchBytes, err := json.Marshal(&addControllerPatch)
- if err != nil {
- return nil, err
- }
- return patchBytes, nil
- }
|