Restore the ability to kubectl apply --prune without -n flag

Before https://github.com/kubernetes/kubernetes/pull/83084, `kubectl
apply --prune` can prune resources in all namespaces specified in
config files.  After that PR got merged, only a single namespace is
considered for pruning.  It is OK if namespace is explicitly specified
by --namespace option, but what the PR does is use the default
namespace (or from kubeconfig) if not overridden by command line flag.
That breaks the existing usage of `kubectl apply --prune` without
--namespace option.  If --namespace is not used, there is no error,
and no one notices this issue unless they actually check that pruning
happens.  This issue also prevents resources in multiple namespaces in
config file from being pruned.

kubectl 1.16 does not have this bug.  Let's see the difference between
kubectl 1.16 and kubectl 1.17.  Suppose the following config file:

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: foo
  namespace: a
  labels:
    pl: foo
data:
  foo: bar
---
apiVersion: v1
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: bar
  namespace: a
  labels:
    pl: foo
data:
  foo: bar
```

Apply it with `kubectl apply -f file`.  Then comment out ConfigMap foo
in this file.  kubectl 1.16 prunes ConfigMap foo with the following
command:

$ kubectl-1.16 apply -f file -l pl=foo --prune
configmap/bar configured
configmap/foo pruned

But kubectl 1.17 does not prune ConfigMap foo with the same command:

$ kubectl-1.17 apply -f file -l pl=foo --prune
configmap/bar configured

With this patch, kubectl once again can prune the resource as before.
This commit is contained in:
Tatsuhiro Tsujikawa 2020-03-27 01:11:36 +00:00
parent 4bdb72ed11
commit 7af3b01f24
2 changed files with 24 additions and 3 deletions

View File

@ -77,9 +77,6 @@ func (p *pruner) pruneAll(o *ApplyOptions) error {
}
for n := range p.visitedNamespaces {
if len(o.Namespace) != 0 && n != o.Namespace {
continue
}
for _, m := range namespacedRESTMappings {
if err := p.prune(n, m); err != nil {
return fmt.Errorf("error pruning namespaced object %v: %v", m.GroupVersionKind, err)

View File

@ -223,6 +223,30 @@ __EOF__
# cleanup
kubectl delete svc prune-svc 2>&1 "${kube_flags[@]:?}"
## kubectl apply --prune can prune resources not in the defaulted namespace
# Pre-Condition: namespace nsb exists; no POD exists
kubectl create ns nsb
kube::test::get_object_assert pods "{{range.items}}{{${id_field:?}}}:{{end}}" ''
# apply a into namespace nsb
kubectl apply --namespace nsb -f hack/testdata/prune/a.yaml "${kube_flags[@]:?}"
kube::test::get_object_assert 'pods a -n nsb' "{{${id_field:?}}}" 'a'
# apply b with namespace
kubectl apply --namespace nsb -f hack/testdata/prune/b.yaml "${kube_flags[@]:?}"
kube::test::get_object_assert 'pods b -n nsb' "{{${id_field:?}}}" 'b'
# apply --prune must prune a
kubectl apply --prune --all -f hack/testdata/prune/b.yaml
# check wrong pod doesn't exist
output_message=$(! kubectl get pods a -n nsb 2>&1 "${kube_flags[@]:?}")
kube::test::if_has_string "${output_message}" 'pods "a" not found'
# check right pod exists
kube::test::get_object_assert 'pods b -n nsb' "{{${id_field:?}}}" 'b'
# cleanup
kubectl delete ns nsb
## kubectl apply -n must fail if input file contains namespace other than the one given in -n
output_message=$(! kubectl apply -n foo -f hack/testdata/prune/b.yaml 2>&1 "${kube_flags[@]:?}")
kube::test::if_has_string "${output_message}" 'the namespace from the provided object "nsb" does not match the namespace "foo".'
## kubectl apply -f some.yml --force
# Pre-condition: no service exists