mirror of https://github.com/k3s-io/k3s
Merge pull request #64847 from janetkuo/ds-reaper-hack
Automatic merge from submit-queue (batch tested with PRs 63386, 64624, 62297, 64847). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Keep kubectl delete hack for DaemonSet until 1.12 **What this PR does / why we need it**: As pointed out here: https://github.com/kubernetes/kubernetes/pull/64797#issuecomment-395152965, the server side fix is in 1.11. We're keeping kubectl hack until 1.12 to support 1.11 kubectl + 1.10.0-4 server. **Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*: Fixes # **Special notes for your reviewer**: **Release note**: ```release-note NONE ```pull/8/head
commit
7a6320ef29
|
@ -105,6 +105,7 @@ go_library(
|
|||
"//vendor/github.com/renstrom/dedent:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
"//vendor/k8s.io/api/apps/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/autoscaling/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/policy/v1beta1:go_default_library",
|
||||
|
@ -126,6 +127,7 @@ go_library(
|
|||
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
|
||||
|
|
|
@ -24,9 +24,15 @@ import (
|
|||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/uuid"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
|
@ -285,6 +291,16 @@ func (o *DeleteOptions) DeleteResult(r *resource.Result) error {
|
|||
}
|
||||
|
||||
func (o *DeleteOptions) deleteResource(info *resource.Info, deleteOptions *metav1.DeleteOptions) error {
|
||||
// TODO: Remove this in or after 1.12 release.
|
||||
// Server version >= 1.11 no longer needs this hack.
|
||||
mapping := info.ResourceMapping()
|
||||
if mapping.Resource.GroupResource() == (schema.GroupResource{Group: "extensions", Resource: "daemonsets"}) ||
|
||||
mapping.Resource.GroupResource() == (schema.GroupResource{Group: "apps", Resource: "daemonsets"}) {
|
||||
if err := updateDaemonSet(info.Namespace, info.Name, o.DynamicClient); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := resource.NewHelper(info.Client, info.Mapping).DeleteWithOptions(info.Namespace, info.Name, deleteOptions); err != nil {
|
||||
return cmdutil.AddSourceToErr("deleting", info.Source, err)
|
||||
}
|
||||
|
@ -293,6 +309,55 @@ func (o *DeleteOptions) deleteResource(info *resource.Info, deleteOptions *metav
|
|||
return nil
|
||||
}
|
||||
|
||||
// TODO: Remove this in or after 1.12 release.
|
||||
// Server version >= 1.11 no longer needs this hack.
|
||||
func updateDaemonSet(namespace, name string, dynamicClient dynamic.Interface) error {
|
||||
dsClient := dynamicClient.Resource(schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "daemonsets"}).Namespace(namespace)
|
||||
obj, err := dsClient.Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ds := &appsv1.DaemonSet{}
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, ds); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We set the nodeSelector to a random label. This label is nearly guaranteed
|
||||
// to not be set on any node so the DameonSetController will start deleting
|
||||
// daemon pods. Once it's done deleting the daemon pods, it's safe to delete
|
||||
// the DaemonSet.
|
||||
ds.Spec.Template.Spec.NodeSelector = map[string]string{
|
||||
string(uuid.NewUUID()): string(uuid.NewUUID()),
|
||||
}
|
||||
// force update to avoid version conflict
|
||||
ds.ResourceVersion = ""
|
||||
|
||||
out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(ds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = dsClient.Update(&unstructured.Unstructured{Object: out}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Wait for the daemon set controller to kill all the daemon pods.
|
||||
if err := wait.Poll(1*time.Second, 5*time.Minute, func() (bool, error) {
|
||||
updatedObj, err := dsClient.Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
updatedDS := &appsv1.DaemonSet{}
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(updatedObj.Object, ds); err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return updatedDS.Status.CurrentNumberScheduled+updatedDS.Status.NumberMisscheduled == 0, nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// deletion printing is special because we do not have an object to print.
|
||||
// This mirrors name printer behavior
|
||||
func (o *DeleteOptions) PrintObj(info *resource.Info) {
|
||||
|
|
Loading…
Reference in New Issue