|
|
|
@@ -22,7 +22,7 @@ import (
|
|
|
|
|
"sync"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/golang/glog"
|
|
|
|
|
"k8s.io/klog"
|
|
|
|
|
|
|
|
|
|
"k8s.io/api/core/v1"
|
|
|
|
|
"k8s.io/apimachinery/pkg/api/errors"
|
|
|
|
@@ -110,7 +110,7 @@ func (d *namespacedResourcesDeleter) Delete(nsName string) error {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glog.V(5).Infof("namespace controller - syncNamespace - namespace: %s, finalizerToken: %s", namespace.Name, d.finalizerToken)
|
|
|
|
|
klog.V(5).Infof("namespace controller - syncNamespace - namespace: %s, finalizerToken: %s", namespace.Name, d.finalizerToken)
|
|
|
|
|
|
|
|
|
|
// ensure that the status is up to date on the namespace
|
|
|
|
|
// if we get a not found error, we assume the namespace is truly gone
|
|
|
|
@@ -169,13 +169,13 @@ func (d *namespacedResourcesDeleter) initOpCache() {
|
|
|
|
|
utilruntime.HandleError(fmt.Errorf("unable to get all supported resources from server: %v", err))
|
|
|
|
|
}
|
|
|
|
|
if len(resources) == 0 {
|
|
|
|
|
glog.Fatalf("Unable to get any supported resources from server: %v", err)
|
|
|
|
|
klog.Fatalf("Unable to get any supported resources from server: %v", err)
|
|
|
|
|
}
|
|
|
|
|
deletableGroupVersionResources := []schema.GroupVersionResource{}
|
|
|
|
|
for _, rl := range resources {
|
|
|
|
|
gv, err := schema.ParseGroupVersion(rl.GroupVersion)
|
|
|
|
|
if err != nil {
|
|
|
|
|
glog.Errorf("Failed to parse GroupVersion %q, skipping: %v", rl.GroupVersion, err)
|
|
|
|
|
klog.Errorf("Failed to parse GroupVersion %q, skipping: %v", rl.GroupVersion, err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -184,7 +184,7 @@ func (d *namespacedResourcesDeleter) initOpCache() {
|
|
|
|
|
verbs := sets.NewString([]string(r.Verbs)...)
|
|
|
|
|
|
|
|
|
|
if !verbs.Has("delete") {
|
|
|
|
|
glog.V(6).Infof("Skipping resource %v because it cannot be deleted.", gvr)
|
|
|
|
|
klog.V(6).Infof("Skipping resource %v because it cannot be deleted.", gvr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, op := range []operation{operationList, operationDeleteCollection} {
|
|
|
|
@@ -329,11 +329,11 @@ func (d *namespacedResourcesDeleter) finalizeNamespace(namespace *v1.Namespace)
|
|
|
|
|
// it returns true if the operation was supported on the server.
|
|
|
|
|
// it returns an error if the operation was supported on the server but was unable to complete.
|
|
|
|
|
func (d *namespacedResourcesDeleter) deleteCollection(gvr schema.GroupVersionResource, namespace string) (bool, error) {
|
|
|
|
|
glog.V(5).Infof("namespace controller - deleteCollection - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
klog.V(5).Infof("namespace controller - deleteCollection - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
|
|
|
|
|
key := operationKey{operation: operationDeleteCollection, gvr: gvr}
|
|
|
|
|
if !d.opCache.isSupported(key) {
|
|
|
|
|
glog.V(5).Infof("namespace controller - deleteCollection ignored since not supported - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
klog.V(5).Infof("namespace controller - deleteCollection ignored since not supported - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
return false, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -355,12 +355,12 @@ func (d *namespacedResourcesDeleter) deleteCollection(gvr schema.GroupVersionRes
|
|
|
|
|
// when working with this resource type, we will get a literal not found error rather than expected method not supported
|
|
|
|
|
// remember next time that this resource does not support delete collection...
|
|
|
|
|
if errors.IsMethodNotSupported(err) || errors.IsNotFound(err) {
|
|
|
|
|
glog.V(5).Infof("namespace controller - deleteCollection not supported - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
klog.V(5).Infof("namespace controller - deleteCollection not supported - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
d.opCache.setNotSupported(key)
|
|
|
|
|
return false, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glog.V(5).Infof("namespace controller - deleteCollection unexpected error - namespace: %s, gvr: %v, error: %v", namespace, gvr, err)
|
|
|
|
|
klog.V(5).Infof("namespace controller - deleteCollection unexpected error - namespace: %s, gvr: %v, error: %v", namespace, gvr, err)
|
|
|
|
|
return true, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -370,11 +370,11 @@ func (d *namespacedResourcesDeleter) deleteCollection(gvr schema.GroupVersionRes
|
|
|
|
|
// a boolean if the operation is supported
|
|
|
|
|
// an error if the operation is supported but could not be completed.
|
|
|
|
|
func (d *namespacedResourcesDeleter) listCollection(gvr schema.GroupVersionResource, namespace string) (*unstructured.UnstructuredList, bool, error) {
|
|
|
|
|
glog.V(5).Infof("namespace controller - listCollection - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
klog.V(5).Infof("namespace controller - listCollection - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
|
|
|
|
|
key := operationKey{operation: operationList, gvr: gvr}
|
|
|
|
|
if !d.opCache.isSupported(key) {
|
|
|
|
|
glog.V(5).Infof("namespace controller - listCollection ignored since not supported - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
klog.V(5).Infof("namespace controller - listCollection ignored since not supported - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
return nil, false, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -390,7 +390,7 @@ func (d *namespacedResourcesDeleter) listCollection(gvr schema.GroupVersionResou
|
|
|
|
|
// when working with this resource type, we will get a literal not found error rather than expected method not supported
|
|
|
|
|
// remember next time that this resource does not support delete collection...
|
|
|
|
|
if errors.IsMethodNotSupported(err) || errors.IsNotFound(err) {
|
|
|
|
|
glog.V(5).Infof("namespace controller - listCollection not supported - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
klog.V(5).Infof("namespace controller - listCollection not supported - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
d.opCache.setNotSupported(key)
|
|
|
|
|
return nil, false, nil
|
|
|
|
|
}
|
|
|
|
@@ -400,7 +400,7 @@ func (d *namespacedResourcesDeleter) listCollection(gvr schema.GroupVersionResou
|
|
|
|
|
|
|
|
|
|
// deleteEachItem is a helper function that will list the collection of resources and delete each item 1 by 1.
|
|
|
|
|
func (d *namespacedResourcesDeleter) deleteEachItem(gvr schema.GroupVersionResource, namespace string) error {
|
|
|
|
|
glog.V(5).Infof("namespace controller - deleteEachItem - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
klog.V(5).Infof("namespace controller - deleteEachItem - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
|
|
|
|
|
unstructuredList, listSupported, err := d.listCollection(gvr, namespace)
|
|
|
|
|
if err != nil {
|
|
|
|
@@ -425,15 +425,15 @@ func (d *namespacedResourcesDeleter) deleteEachItem(gvr schema.GroupVersionResou
|
|
|
|
|
func (d *namespacedResourcesDeleter) deleteAllContentForGroupVersionResource(
|
|
|
|
|
gvr schema.GroupVersionResource, namespace string,
|
|
|
|
|
namespaceDeletedAt metav1.Time) (int64, error) {
|
|
|
|
|
glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
|
|
|
|
|
// estimate how long it will take for the resource to be deleted (needed for objects that support graceful delete)
|
|
|
|
|
estimate, err := d.estimateGracefulTermination(gvr, namespace, namespaceDeletedAt)
|
|
|
|
|
if err != nil {
|
|
|
|
|
glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - unable to estimate - namespace: %s, gvr: %v, err: %v", namespace, gvr, err)
|
|
|
|
|
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - unable to estimate - namespace: %s, gvr: %v, err: %v", namespace, gvr, err)
|
|
|
|
|
return estimate, err
|
|
|
|
|
}
|
|
|
|
|
glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - estimate - namespace: %s, gvr: %v, estimate: %v", namespace, gvr, estimate)
|
|
|
|
|
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - estimate - namespace: %s, gvr: %v, estimate: %v", namespace, gvr, estimate)
|
|
|
|
|
|
|
|
|
|
// first try to delete the entire collection
|
|
|
|
|
deleteCollectionSupported, err := d.deleteCollection(gvr, namespace)
|
|
|
|
@@ -451,21 +451,21 @@ func (d *namespacedResourcesDeleter) deleteAllContentForGroupVersionResource(
|
|
|
|
|
|
|
|
|
|
// verify there are no more remaining items
|
|
|
|
|
// it is not an error condition for there to be remaining items if local estimate is non-zero
|
|
|
|
|
glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - checking for no more items in namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - checking for no more items in namespace: %s, gvr: %v", namespace, gvr)
|
|
|
|
|
unstructuredList, listSupported, err := d.listCollection(gvr, namespace)
|
|
|
|
|
if err != nil {
|
|
|
|
|
glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - error verifying no items in namespace: %s, gvr: %v, err: %v", namespace, gvr, err)
|
|
|
|
|
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - error verifying no items in namespace: %s, gvr: %v, err: %v", namespace, gvr, err)
|
|
|
|
|
return estimate, err
|
|
|
|
|
}
|
|
|
|
|
if !listSupported {
|
|
|
|
|
return estimate, nil
|
|
|
|
|
}
|
|
|
|
|
glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - items remaining - namespace: %s, gvr: %v, items: %v", namespace, gvr, len(unstructuredList.Items))
|
|
|
|
|
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - items remaining - namespace: %s, gvr: %v, items: %v", namespace, gvr, len(unstructuredList.Items))
|
|
|
|
|
if len(unstructuredList.Items) != 0 && estimate == int64(0) {
|
|
|
|
|
// if any item has a finalizer, we treat that as a normal condition, and use a default estimation to allow for GC to complete.
|
|
|
|
|
for _, item := range unstructuredList.Items {
|
|
|
|
|
if len(item.GetFinalizers()) > 0 {
|
|
|
|
|
glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - items remaining with finalizers - namespace: %s, gvr: %v, finalizers: %v", namespace, gvr, item.GetFinalizers())
|
|
|
|
|
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - items remaining with finalizers - namespace: %s, gvr: %v, finalizers: %v", namespace, gvr, item.GetFinalizers())
|
|
|
|
|
return finalizerEstimateSeconds, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -480,7 +480,7 @@ func (d *namespacedResourcesDeleter) deleteAllContentForGroupVersionResource(
|
|
|
|
|
// If estimate > 0, not all resources are guaranteed to be gone.
|
|
|
|
|
func (d *namespacedResourcesDeleter) deleteAllContent(namespace string, namespaceDeletedAt metav1.Time) (int64, error) {
|
|
|
|
|
estimate := int64(0)
|
|
|
|
|
glog.V(4).Infof("namespace controller - deleteAllContent - namespace: %s", namespace)
|
|
|
|
|
klog.V(4).Infof("namespace controller - deleteAllContent - namespace: %s", namespace)
|
|
|
|
|
resources, err := d.discoverResourcesFn()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return estimate, err
|
|
|
|
@@ -506,14 +506,14 @@ func (d *namespacedResourcesDeleter) deleteAllContent(namespace string, namespac
|
|
|
|
|
if len(errs) > 0 {
|
|
|
|
|
return estimate, utilerrors.NewAggregate(errs)
|
|
|
|
|
}
|
|
|
|
|
glog.V(4).Infof("namespace controller - deleteAllContent - namespace: %s, estimate: %v", namespace, estimate)
|
|
|
|
|
klog.V(4).Infof("namespace controller - deleteAllContent - namespace: %s, estimate: %v", namespace, estimate)
|
|
|
|
|
return estimate, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// estimateGrracefulTermination will estimate the graceful termination required for the specific entity in the namespace
|
|
|
|
|
func (d *namespacedResourcesDeleter) estimateGracefulTermination(gvr schema.GroupVersionResource, ns string, namespaceDeletedAt metav1.Time) (int64, error) {
|
|
|
|
|
groupResource := gvr.GroupResource()
|
|
|
|
|
glog.V(5).Infof("namespace controller - estimateGracefulTermination - group %s, resource: %s", groupResource.Group, groupResource.Resource)
|
|
|
|
|
klog.V(5).Infof("namespace controller - estimateGracefulTermination - group %s, resource: %s", groupResource.Group, groupResource.Resource)
|
|
|
|
|
estimate := int64(0)
|
|
|
|
|
var err error
|
|
|
|
|
switch groupResource {
|
|
|
|
@@ -534,7 +534,7 @@ func (d *namespacedResourcesDeleter) estimateGracefulTermination(gvr schema.Grou
|
|
|
|
|
|
|
|
|
|
// estimateGracefulTerminationForPods determines the graceful termination period for pods in the namespace
|
|
|
|
|
func (d *namespacedResourcesDeleter) estimateGracefulTerminationForPods(ns string) (int64, error) {
|
|
|
|
|
glog.V(5).Infof("namespace controller - estimateGracefulTerminationForPods - namespace %s", ns)
|
|
|
|
|
klog.V(5).Infof("namespace controller - estimateGracefulTerminationForPods - namespace %s", ns)
|
|
|
|
|
estimate := int64(0)
|
|
|
|
|
podsGetter := d.podsGetter
|
|
|
|
|
if podsGetter == nil || reflect.ValueOf(podsGetter).IsNil() {
|
|
|
|
|