2015-03-20 16:49:03 +00:00
|
|
|
/*
|
2015-05-01 16:19:44 +00:00
|
|
|
Copyright 2015 The Kubernetes Authors All rights reserved.
|
2015-03-20 16:49:03 +00:00
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2015-07-31 11:38:04 +00:00
|
|
|
package namespacecontroller
|
2015-03-20 16:49:03 +00:00
|
|
|
|
|
|
|
import (
|
2015-06-04 18:40:56 +00:00
|
|
|
"fmt"
|
2015-03-20 16:49:03 +00:00
|
|
|
"time"
|
|
|
|
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/api"
|
|
|
|
"k8s.io/kubernetes/pkg/api/errors"
|
2015-09-17 22:21:55 +00:00
|
|
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
2015-09-03 21:40:58 +00:00
|
|
|
"k8s.io/kubernetes/pkg/client/cache"
|
2015-09-03 21:43:19 +00:00
|
|
|
client "k8s.io/kubernetes/pkg/client/unversioned"
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/controller/framework"
|
|
|
|
"k8s.io/kubernetes/pkg/fields"
|
|
|
|
"k8s.io/kubernetes/pkg/labels"
|
|
|
|
"k8s.io/kubernetes/pkg/runtime"
|
|
|
|
"k8s.io/kubernetes/pkg/util"
|
2015-09-09 17:45:01 +00:00
|
|
|
"k8s.io/kubernetes/pkg/util/sets"
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/watch"
|
2015-06-04 02:59:07 +00:00
|
|
|
|
|
|
|
"github.com/golang/glog"
|
2015-03-20 16:49:03 +00:00
|
|
|
)
|
|
|
|
|
2015-07-31 11:38:04 +00:00
|
|
|
// NamespaceController is responsible for performing actions dependent upon a namespace phase
|
|
|
|
type NamespaceController struct {
|
2015-04-13 17:15:27 +00:00
|
|
|
controller *framework.Controller
|
|
|
|
StopEverything chan struct{}
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
|
|
|
|
2015-07-31 11:38:04 +00:00
|
|
|
// NewNamespaceController creates a new NamespaceController
|
2015-09-03 14:50:53 +00:00
|
|
|
func NewNamespaceController(kubeClient client.Interface, experimentalMode bool, resyncPeriod time.Duration) *NamespaceController {
|
2015-06-04 18:40:56 +00:00
|
|
|
var controller *framework.Controller
|
|
|
|
_, controller = framework.NewInformer(
|
2015-03-20 16:49:03 +00:00
|
|
|
&cache.ListWatch{
|
|
|
|
ListFunc: func() (runtime.Object, error) {
|
|
|
|
return kubeClient.Namespaces().List(labels.Everything(), fields.Everything())
|
|
|
|
},
|
|
|
|
WatchFunc: func(resourceVersion string) (watch.Interface, error) {
|
|
|
|
return kubeClient.Namespaces().Watch(labels.Everything(), fields.Everything(), resourceVersion)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&api.Namespace{},
|
2015-10-06 09:12:00 +00:00
|
|
|
// TODO: Can we have much longer period here?
|
2015-04-13 17:15:27 +00:00
|
|
|
resyncPeriod,
|
|
|
|
framework.ResourceEventHandlerFuncs{
|
|
|
|
AddFunc: func(obj interface{}) {
|
|
|
|
namespace := obj.(*api.Namespace)
|
2015-09-21 20:06:25 +00:00
|
|
|
if err := syncNamespace(kubeClient, experimentalMode, namespace); err != nil {
|
2015-06-04 18:40:56 +00:00
|
|
|
if estimate, ok := err.(*contentRemainingError); ok {
|
|
|
|
go func() {
|
|
|
|
// Estimate is the aggregate total of TerminationGracePeriodSeconds, which defaults to 30s
|
|
|
|
// for pods. However, most processes will terminate faster - within a few seconds, probably
|
|
|
|
// with a peak within 5-10s. So this division is a heuristic that avoids waiting the full
|
|
|
|
// duration when in many cases things complete more quickly. The extra second added is to
|
|
|
|
// ensure we never wait 0 seconds.
|
|
|
|
t := estimate.Estimate/2 + 1
|
|
|
|
glog.V(4).Infof("Content remaining in namespace %s, waiting %d seconds", namespace.Name, t)
|
|
|
|
time.Sleep(time.Duration(t) * time.Second)
|
|
|
|
if err := controller.Requeue(namespace); err != nil {
|
|
|
|
util.HandleError(err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
util.HandleError(err)
|
2015-06-04 02:59:07 +00:00
|
|
|
}
|
2015-04-13 17:15:27 +00:00
|
|
|
},
|
|
|
|
UpdateFunc: func(oldObj, newObj interface{}) {
|
|
|
|
namespace := newObj.(*api.Namespace)
|
2015-09-21 20:06:25 +00:00
|
|
|
if err := syncNamespace(kubeClient, experimentalMode, namespace); err != nil {
|
2015-06-04 18:40:56 +00:00
|
|
|
if estimate, ok := err.(*contentRemainingError); ok {
|
|
|
|
go func() {
|
|
|
|
t := estimate.Estimate/2 + 1
|
|
|
|
glog.V(4).Infof("Content remaining in namespace %s, waiting %d seconds", namespace.Name, t)
|
|
|
|
time.Sleep(time.Duration(t) * time.Second)
|
|
|
|
if err := controller.Requeue(namespace); err != nil {
|
|
|
|
util.HandleError(err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
util.HandleError(err)
|
2015-06-04 02:59:07 +00:00
|
|
|
}
|
2015-04-13 17:15:27 +00:00
|
|
|
},
|
|
|
|
},
|
2015-03-20 16:49:03 +00:00
|
|
|
)
|
|
|
|
|
2015-07-31 11:38:04 +00:00
|
|
|
return &NamespaceController{
|
2015-04-18 14:30:00 +00:00
|
|
|
controller: controller,
|
2015-04-13 17:15:27 +00:00
|
|
|
}
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
|
|
|
|
2015-04-13 17:15:27 +00:00
|
|
|
// Run begins observing the system. It starts a goroutine and returns immediately.
|
2015-07-31 11:38:04 +00:00
|
|
|
func (nm *NamespaceController) Run() {
|
2015-04-18 14:30:00 +00:00
|
|
|
if nm.StopEverything == nil {
|
|
|
|
nm.StopEverything = make(chan struct{})
|
|
|
|
go nm.controller.Run(nm.StopEverything)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stop gracefully shutsdown this controller
|
2015-07-31 11:38:04 +00:00
|
|
|
func (nm *NamespaceController) Stop() {
|
2015-04-18 14:30:00 +00:00
|
|
|
if nm.StopEverything != nil {
|
|
|
|
close(nm.StopEverything)
|
|
|
|
nm.StopEverything = nil
|
|
|
|
}
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// finalized returns true if the spec.finalizers is empty list
|
2015-09-21 20:06:25 +00:00
|
|
|
func finalized(namespace *api.Namespace) bool {
|
2015-03-20 16:49:03 +00:00
|
|
|
return len(namespace.Spec.Finalizers) == 0
|
|
|
|
}
|
|
|
|
|
|
|
|
// finalize will finalize the namespace for kubernetes
|
2015-09-21 20:06:25 +00:00
|
|
|
func finalizeNamespaceFunc(kubeClient client.Interface, namespace *api.Namespace) (*api.Namespace, error) {
|
2015-03-31 21:00:04 +00:00
|
|
|
namespaceFinalize := api.Namespace{}
|
|
|
|
namespaceFinalize.ObjectMeta = namespace.ObjectMeta
|
|
|
|
namespaceFinalize.Spec = namespace.Spec
|
2015-09-09 17:45:01 +00:00
|
|
|
finalizerSet := sets.NewString()
|
2015-03-20 16:49:03 +00:00
|
|
|
for i := range namespace.Spec.Finalizers {
|
|
|
|
if namespace.Spec.Finalizers[i] != api.FinalizerKubernetes {
|
|
|
|
finalizerSet.Insert(string(namespace.Spec.Finalizers[i]))
|
|
|
|
}
|
|
|
|
}
|
2015-03-31 21:00:04 +00:00
|
|
|
namespaceFinalize.Spec.Finalizers = make([]api.FinalizerName, 0, len(finalizerSet))
|
2015-03-20 16:49:03 +00:00
|
|
|
for _, value := range finalizerSet.List() {
|
|
|
|
namespaceFinalize.Spec.Finalizers = append(namespaceFinalize.Spec.Finalizers, api.FinalizerName(value))
|
|
|
|
}
|
|
|
|
return kubeClient.Namespaces().Finalize(&namespaceFinalize)
|
|
|
|
}
|
|
|
|
|
2015-06-04 18:40:56 +00:00
|
|
|
type contentRemainingError struct {
|
|
|
|
Estimate int64
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *contentRemainingError) Error() string {
|
|
|
|
return fmt.Sprintf("some content remains in the namespace, estimate %d seconds before it is removed", e.Estimate)
|
|
|
|
}
|
|
|
|
|
|
|
|
// deleteAllContent will delete all content known to the system in a namespace. It returns an estimate
|
|
|
|
// of the time remaining before the remaining resources are deleted. If estimate > 0 not all resources
|
|
|
|
// are guaranteed to be gone.
|
2015-09-17 22:21:55 +00:00
|
|
|
func deleteAllContent(kubeClient client.Interface, experimentalMode bool, namespace string, before unversioned.Time) (estimate int64, err error) {
|
2015-04-21 03:25:56 +00:00
|
|
|
err = deleteServiceAccounts(kubeClient, namespace)
|
|
|
|
if err != nil {
|
2015-06-04 18:40:56 +00:00
|
|
|
return estimate, err
|
2015-04-21 03:25:56 +00:00
|
|
|
}
|
2015-03-20 16:49:03 +00:00
|
|
|
err = deleteServices(kubeClient, namespace)
|
|
|
|
if err != nil {
|
2015-06-04 18:40:56 +00:00
|
|
|
return estimate, err
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
|
|
|
err = deleteReplicationControllers(kubeClient, namespace)
|
|
|
|
if err != nil {
|
2015-06-04 18:40:56 +00:00
|
|
|
return estimate, err
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
2015-06-04 18:40:56 +00:00
|
|
|
estimate, err = deletePods(kubeClient, namespace, before)
|
2015-03-20 16:49:03 +00:00
|
|
|
if err != nil {
|
2015-06-04 18:40:56 +00:00
|
|
|
return estimate, err
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
|
|
|
err = deleteSecrets(kubeClient, namespace)
|
|
|
|
if err != nil {
|
2015-06-04 18:40:56 +00:00
|
|
|
return estimate, err
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
2015-03-26 19:50:36 +00:00
|
|
|
err = deletePersistentVolumeClaims(kubeClient, namespace)
|
|
|
|
if err != nil {
|
2015-06-04 18:40:56 +00:00
|
|
|
return estimate, err
|
2015-03-26 19:50:36 +00:00
|
|
|
}
|
2015-03-20 16:49:03 +00:00
|
|
|
err = deleteLimitRanges(kubeClient, namespace)
|
|
|
|
if err != nil {
|
2015-06-04 18:40:56 +00:00
|
|
|
return estimate, err
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
|
|
|
err = deleteResourceQuotas(kubeClient, namespace)
|
|
|
|
if err != nil {
|
2015-06-04 18:40:56 +00:00
|
|
|
return estimate, err
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
|
|
|
err = deleteEvents(kubeClient, namespace)
|
|
|
|
if err != nil {
|
2015-06-04 18:40:56 +00:00
|
|
|
return estimate, err
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
2015-09-03 14:50:53 +00:00
|
|
|
// If experimental mode, delete all experimental resources for the namespace.
|
|
|
|
if experimentalMode {
|
|
|
|
err = deleteHorizontalPodAutoscalers(kubeClient.Experimental(), namespace)
|
|
|
|
if err != nil {
|
|
|
|
return estimate, err
|
|
|
|
}
|
2015-09-15 18:43:15 +00:00
|
|
|
err = deleteDaemonSets(kubeClient.Experimental(), namespace)
|
2015-09-03 14:50:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return estimate, err
|
|
|
|
}
|
2015-09-28 18:04:17 +00:00
|
|
|
err = deleteJobs(kubeClient.Experimental(), namespace)
|
|
|
|
if err != nil {
|
|
|
|
return estimate, err
|
|
|
|
}
|
2015-09-03 14:50:53 +00:00
|
|
|
err = deleteDeployments(kubeClient.Experimental(), namespace)
|
|
|
|
if err != nil {
|
|
|
|
return estimate, err
|
|
|
|
}
|
2015-09-28 23:41:36 +00:00
|
|
|
err = deleteIngress(kubeClient.Experimental(), namespace)
|
|
|
|
if err != nil {
|
|
|
|
return estimate, err
|
|
|
|
}
|
2015-09-03 14:50:53 +00:00
|
|
|
}
|
2015-06-04 18:40:56 +00:00
|
|
|
return estimate, nil
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
|
|
|
|
2015-09-21 20:06:25 +00:00
|
|
|
// updateNamespaceFunc is a function that makes an update to a namespace
|
|
|
|
type updateNamespaceFunc func(kubeClient client.Interface, namespace *api.Namespace) (*api.Namespace, error)
|
|
|
|
|
|
|
|
// retryOnConflictError retries the specified fn if there was a conflict error
|
|
|
|
// TODO RetryOnConflict should be a generic concept in client code
|
|
|
|
func retryOnConflictError(kubeClient client.Interface, namespace *api.Namespace, fn updateNamespaceFunc) (result *api.Namespace, err error) {
|
|
|
|
latestNamespace := namespace
|
|
|
|
for {
|
|
|
|
result, err = fn(kubeClient, latestNamespace)
|
|
|
|
if err == nil {
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
if !errors.IsConflict(err) {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
latestNamespace, err = kubeClient.Namespaces().Get(latestNamespace.Name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// updateNamespaceStatusFunc will verify that the status of the namespace is correct
|
|
|
|
func updateNamespaceStatusFunc(kubeClient client.Interface, namespace *api.Namespace) (*api.Namespace, error) {
|
|
|
|
if namespace.DeletionTimestamp.IsZero() || namespace.Status.Phase == api.NamespaceTerminating {
|
|
|
|
return namespace, nil
|
|
|
|
}
|
|
|
|
newNamespace := api.Namespace{}
|
|
|
|
newNamespace.ObjectMeta = namespace.ObjectMeta
|
|
|
|
newNamespace.Status = namespace.Status
|
|
|
|
newNamespace.Status.Phase = api.NamespaceTerminating
|
|
|
|
return kubeClient.Namespaces().Status(&newNamespace)
|
|
|
|
}
|
|
|
|
|
|
|
|
// syncNamespace orchestrates deletion of a Namespace and its associated content.
|
|
|
|
func syncNamespace(kubeClient client.Interface, experimentalMode bool, namespace *api.Namespace) (err error) {
|
2015-03-20 16:49:03 +00:00
|
|
|
if namespace.DeletionTimestamp == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2015-06-04 18:40:56 +00:00
|
|
|
glog.V(4).Infof("Syncing namespace %s", namespace.Name)
|
2015-03-20 16:49:03 +00:00
|
|
|
|
2015-09-21 20:06:25 +00:00
|
|
|
// 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
|
|
|
|
namespace, err = retryOnConflictError(kubeClient, namespace, updateNamespaceStatusFunc)
|
|
|
|
if err != nil {
|
|
|
|
if errors.IsNotFound(err) {
|
|
|
|
return nil
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
2015-09-21 20:06:25 +00:00
|
|
|
return err
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// if the namespace is already finalized, delete it
|
|
|
|
if finalized(namespace) {
|
2015-04-13 17:15:27 +00:00
|
|
|
err = kubeClient.Namespaces().Delete(namespace.Name)
|
2015-06-04 02:59:07 +00:00
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// there may still be content for us to remove
|
2015-09-03 14:50:53 +00:00
|
|
|
estimate, err := deleteAllContent(kubeClient, experimentalMode, namespace.Name, *namespace.DeletionTimestamp)
|
2015-03-20 16:49:03 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-06-04 18:40:56 +00:00
|
|
|
if estimate > 0 {
|
|
|
|
return &contentRemainingError{estimate}
|
|
|
|
}
|
2015-03-20 16:49:03 +00:00
|
|
|
|
|
|
|
// we have removed content, so mark it finalized by us
|
2015-09-21 20:06:25 +00:00
|
|
|
result, err := retryOnConflictError(kubeClient, namespace, finalizeNamespaceFunc)
|
2015-03-20 16:49:03 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// now check if all finalizers have reported that we delete now
|
2015-09-21 20:06:25 +00:00
|
|
|
if finalized(result) {
|
2015-04-13 17:15:27 +00:00
|
|
|
err = kubeClient.Namespaces().Delete(namespace.Name)
|
2015-06-04 02:59:07 +00:00
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
|
|
|
return err
|
|
|
|
}
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func deleteLimitRanges(kubeClient client.Interface, ns string) error {
|
|
|
|
items, err := kubeClient.LimitRanges(ns).List(labels.Everything())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := range items.Items {
|
|
|
|
err := kubeClient.LimitRanges(ns).Delete(items.Items[i].Name)
|
2015-06-04 02:59:07 +00:00
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
2015-03-20 16:49:03 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func deleteResourceQuotas(kubeClient client.Interface, ns string) error {
|
|
|
|
resourceQuotas, err := kubeClient.ResourceQuotas(ns).List(labels.Everything())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := range resourceQuotas.Items {
|
|
|
|
err := kubeClient.ResourceQuotas(ns).Delete(resourceQuotas.Items[i].Name)
|
2015-06-04 02:59:07 +00:00
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
2015-03-20 16:49:03 +00:00
|
|
|
return err
|
2015-04-21 03:25:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func deleteServiceAccounts(kubeClient client.Interface, ns string) error {
|
|
|
|
items, err := kubeClient.ServiceAccounts(ns).List(labels.Everything(), fields.Everything())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := range items.Items {
|
|
|
|
err := kubeClient.ServiceAccounts(ns).Delete(items.Items[i].Name)
|
2015-06-04 02:59:07 +00:00
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
2015-04-21 03:25:56 +00:00
|
|
|
return err
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func deleteServices(kubeClient client.Interface, ns string) error {
|
|
|
|
items, err := kubeClient.Services(ns).List(labels.Everything())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := range items.Items {
|
|
|
|
err := kubeClient.Services(ns).Delete(items.Items[i].Name)
|
2015-06-04 02:59:07 +00:00
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
2015-03-20 16:49:03 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func deleteReplicationControllers(kubeClient client.Interface, ns string) error {
|
|
|
|
items, err := kubeClient.ReplicationControllers(ns).List(labels.Everything())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := range items.Items {
|
|
|
|
err := kubeClient.ReplicationControllers(ns).Delete(items.Items[i].Name)
|
2015-06-04 02:59:07 +00:00
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
2015-03-20 16:49:03 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-09-17 22:21:55 +00:00
|
|
|
func deletePods(kubeClient client.Interface, ns string, before unversioned.Time) (int64, error) {
|
2015-04-20 18:53:06 +00:00
|
|
|
items, err := kubeClient.Pods(ns).List(labels.Everything(), fields.Everything())
|
2015-03-20 16:49:03 +00:00
|
|
|
if err != nil {
|
2015-06-04 18:40:56 +00:00
|
|
|
return 0, err
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
2015-09-17 22:21:55 +00:00
|
|
|
expired := unversioned.Now().After(before.Time)
|
2015-06-04 18:40:56 +00:00
|
|
|
var deleteOptions *api.DeleteOptions
|
|
|
|
if expired {
|
|
|
|
deleteOptions = api.NewDeleteOptions(0)
|
|
|
|
}
|
|
|
|
estimate := int64(0)
|
2015-03-20 16:49:03 +00:00
|
|
|
for i := range items.Items {
|
2015-06-04 18:40:56 +00:00
|
|
|
if items.Items[i].Spec.TerminationGracePeriodSeconds != nil {
|
|
|
|
grace := *items.Items[i].Spec.TerminationGracePeriodSeconds
|
|
|
|
if grace > estimate {
|
|
|
|
estimate = grace
|
|
|
|
}
|
|
|
|
}
|
|
|
|
err := kubeClient.Pods(ns).Delete(items.Items[i].Name, deleteOptions)
|
2015-06-04 02:59:07 +00:00
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
2015-06-04 18:40:56 +00:00
|
|
|
return 0, err
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-04 18:40:56 +00:00
|
|
|
if expired {
|
|
|
|
estimate = 0
|
|
|
|
}
|
|
|
|
return estimate, nil
|
2015-03-20 16:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func deleteEvents(kubeClient client.Interface, ns string) error {
|
|
|
|
items, err := kubeClient.Events(ns).List(labels.Everything(), fields.Everything())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := range items.Items {
|
|
|
|
err := kubeClient.Events(ns).Delete(items.Items[i].Name)
|
2015-06-04 02:59:07 +00:00
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
2015-03-20 16:49:03 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func deleteSecrets(kubeClient client.Interface, ns string) error {
|
|
|
|
items, err := kubeClient.Secrets(ns).List(labels.Everything(), fields.Everything())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := range items.Items {
|
|
|
|
err := kubeClient.Secrets(ns).Delete(items.Items[i].Name)
|
2015-06-04 02:59:07 +00:00
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
2015-03-20 16:49:03 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2015-03-26 19:50:36 +00:00
|
|
|
|
|
|
|
func deletePersistentVolumeClaims(kubeClient client.Interface, ns string) error {
|
|
|
|
items, err := kubeClient.PersistentVolumeClaims(ns).List(labels.Everything(), fields.Everything())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := range items.Items {
|
|
|
|
err := kubeClient.PersistentVolumeClaims(ns).Delete(items.Items[i].Name)
|
2015-06-04 02:59:07 +00:00
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
2015-03-26 19:50:36 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2015-09-03 14:50:53 +00:00
|
|
|
|
|
|
|
func deleteHorizontalPodAutoscalers(expClient client.ExperimentalInterface, ns string) error {
|
|
|
|
items, err := expClient.HorizontalPodAutoscalers(ns).List(labels.Everything(), fields.Everything())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := range items.Items {
|
|
|
|
err := expClient.HorizontalPodAutoscalers(ns).Delete(items.Items[i].Name, nil)
|
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-09-15 18:43:15 +00:00
|
|
|
func deleteDaemonSets(expClient client.ExperimentalInterface, ns string) error {
|
2015-09-08 23:58:25 +00:00
|
|
|
items, err := expClient.DaemonSets(ns).List(labels.Everything())
|
2015-09-03 14:50:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := range items.Items {
|
2015-09-08 23:58:25 +00:00
|
|
|
err := expClient.DaemonSets(ns).Delete(items.Items[i].Name)
|
2015-09-03 14:50:53 +00:00
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-09-28 18:04:17 +00:00
|
|
|
func deleteJobs(expClient client.ExperimentalInterface, ns string) error {
|
|
|
|
items, err := expClient.Jobs(ns).List(labels.Everything(), fields.Everything())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := range items.Items {
|
|
|
|
err := expClient.Jobs(ns).Delete(items.Items[i].Name, nil)
|
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-09-03 14:50:53 +00:00
|
|
|
func deleteDeployments(expClient client.ExperimentalInterface, ns string) error {
|
|
|
|
items, err := expClient.Deployments(ns).List(labels.Everything(), fields.Everything())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := range items.Items {
|
|
|
|
err := expClient.Deployments(ns).Delete(items.Items[i].Name, nil)
|
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2015-09-28 23:41:36 +00:00
|
|
|
|
|
|
|
func deleteIngress(expClient client.ExperimentalInterface, ns string) error {
|
|
|
|
items, err := expClient.Ingress(ns).List(labels.Everything(), fields.Everything())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for i := range items.Items {
|
|
|
|
err := expClient.Ingress(ns).Delete(items.Items[i].Name, nil)
|
|
|
|
if err != nil && !errors.IsNotFound(err) {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|