// listCollection will list the items in the specified namespace // it returns the following: // the list of items in the collection (if found) // a boolean if the operation is supported // an error if the operation is supported but could not be completed. func listCollection( dynamicClient *dynamic.Client, opCache operationNotSupportedCache, gvr unversioned.GroupVersionResource, namespace string, ) (*runtime.UnstructuredList, bool, error) { glog.V(5).Infof("namespace controller - listCollection - namespace: %s, gvr: %v", namespace, gvr) key := operationKey{op: operationList, gvr: gvr} if !opCache.isSupported(key) { glog.V(5).Infof("namespace controller - listCollection ignored since not supported - namespace: %s, gvr: %v", namespace, gvr) return nil, false, nil } apiResource := unversioned.APIResource{Name: gvr.Resource, Namespaced: true} unstructuredList, err := dynamicClient.Resource(&apiResource, namespace).List(v1.ListOptions{}) if err == nil { return unstructuredList, true, nil } // this is strange, but we need to special case for both MethodNotSupported and NotFound errors // TODO: https://github.com/kubernetes/kubernetes/issues/22413 // we have a resource returned in the discovery API that supports no top-level verbs: // /apis/extensions/v1beta1/namespaces/default/replicationcontrollers // 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) opCache[key] = true return nil, false, nil } return nil, true, err }
// deleteCollection is a helper function that will delete the collection of resources // 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 deleteCollection( dynamicClient *dynamic.Client, opCache operationNotSupportedCache, gvr unversioned.GroupVersionResource, namespace string, ) (bool, error) { glog.V(5).Infof("namespace controller - deleteCollection - namespace: %s, gvr: %v", namespace, gvr) key := operationKey{op: operationDeleteCollection, gvr: gvr} if !opCache.isSupported(key) { glog.V(5).Infof("namespace controller - deleteCollection ignored since not supported - namespace: %s, gvr: %v", namespace, gvr) return false, nil } apiResource := unversioned.APIResource{Name: gvr.Resource, Namespaced: true} // namespace controller does not want the garbage collector to insert the orphan finalizer since it calls // resource deletions generically. it will ensure all resources in the namespace are purged prior to releasing // namespace itself. orphanDependents := false err := dynamicClient.Resource(&apiResource, namespace).DeleteCollection(&v1.DeleteOptions{OrphanDependents: &orphanDependents}, &v1.ListOptions{}) if err == nil { return true, nil } // this is strange, but we need to special case for both MethodNotSupported and NotFound errors // TODO: https://github.com/kubernetes/kubernetes/issues/22413 // we have a resource returned in the discovery API that supports no top-level verbs: // /apis/extensions/v1beta1/namespaces/default/replicationcontrollers // 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) opCache[key] = true return false, nil } glog.V(5).Infof("namespace controller - deleteCollection unexpected error - namespace: %s, gvr: %v, error: %v", namespace, gvr, err) return true, err }
// deleteEachItem is a helper function that will list the collection of resources and delete each item 1 by 1. func deleteEachItem( dynamicClient *dynamic.Client, opCache operationNotSupportedCache, gvr unversioned.GroupVersionResource, namespace string, ) error { glog.V(5).Infof("namespace controller - deleteEachItem - namespace: %s, gvr: %v", namespace, gvr) unstructuredList, listSupported, err := listCollection(dynamicClient, opCache, gvr, namespace) if err != nil { return err } if !listSupported { return nil } apiResource := unversioned.APIResource{Name: gvr.Resource, Namespaced: true} for _, item := range unstructuredList.Items { if err = dynamicClient.Resource(&apiResource, namespace).Delete(item.Name, nil); err != nil && !errors.IsNotFound(err) && !errors.IsMethodNotSupported(err) { return err } } return nil }