kubernetes / kubectl

Issue tracker and mirror of kubectl code
Apache License 2.0
2.83k stars 913 forks source link

`kubectl get --ignore-not-found` behavior unclear #1596

Open jmazzitelli opened 5 months ago

jmazzitelli commented 5 months ago

What happened:

kubectl get exit code does not match what the --help description says will happen.

kubectl get -h
...
    --ignore-not-found=false:
    If the requested object does not exist the command will return exit code 0.
$ kubectl get pod --ignore-not-found=true ; echo "==>exit code=$?"
==>exit code=0

$ kubectl get pod --ignore-not-found=false ; echo "==>exit code=$?"
No resources found in default namespace.
==>exit code=0

$ kubectl get pod -l foo=bar --ignore-not-found=true ; echo "==>exit code=$?"
==>exit code=0

$ kubectl get pod -l foo=bar --ignore-not-found=false ; echo "==>exit code=$?"
No resources found in default namespace.
==>exit code=0

$ kubectl get pod foo --ignore-not-found=true ; echo "==>exit code=$?"
==>exit code=0

$ kubectl get pod foo --ignore-not-found=false ; echo "==>exit code=$?"
Error from server (NotFound): pods "foo" not found
==>exit code=1

What you expected to happen:

The requested object does not exist (there are no pods). And yet, --ignore-not-found=false still results in an exit code of 0. Although --ignore-not-found does change the stdout behavior (error messages are printed out or not), the exit code doesn't match expectations of the documentation regarding the exit code.

How to reproduce it (as minimally and precisely as possible):

See above. Just don't have any pods in the default namespace.

Environment:

kubectl version v1.29.1

k8s-ci-robot commented 5 months ago

This issue is currently awaiting triage.

SIG CLI takes a lead on issue triage for this repo, but any Kubernetes member can accept issues by applying the triage/accepted label.

The triage/accepted label can be added by org members by writing /triage accepted in a comment.

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md). If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
brianpursley commented 5 months ago

To clarify, you are saying these two cases have the wrong exit code?

$ kubectl get pod --ignore-not-found=false ; echo "==>exit code=$?"
No resources found in default namespace.
==>exit code=0
$ kubectl get pod -l foo=bar --ignore-not-found=false ; echo "==>exit code=$?"
No resources found in default namespace.
==>exit code=0

And that they should have exit code 1 like this one?

$ kubectl get pod foo --ignore-not-found=false ; echo "==>exit code=$?"
Error from server (NotFound): pods "foo" not found
==>exit code=1

I think what is happening, is in case 1 and 2, you are not requesting a specific pod, so there is no NotFound error that occurs.

You can see what I mean if you use -v7 to look at the logs. Here you can see the HTTP response is 200 OK:

$ kubectl get pod -v7
I0503 16:34:23.156766   50407 loader.go:395] Config loaded from file:  /home/brian/.kube/config
I0503 16:34:23.162638   50407 round_trippers.go:463] GET https://k8s-master:6443/api/v1/namespaces/default/pods?limit=500
I0503 16:34:23.162662   50407 round_trippers.go:469] Request Headers:
I0503 16:34:23.162678   50407 round_trippers.go:473]     User-Agent: kubectl/v1.28.0 (linux/amd64) kubernetes/10a1216
I0503 16:34:23.162690   50407 round_trippers.go:473]     Accept: application/json;as=Table;v=v1;g=meta.k8s.io,application/json;as=Table;v=v1beta1;g=meta.k8s.io,application/json
I0503 16:34:23.213080   50407 round_trippers.go:574] Response Status: 200 OK in 50 milliseconds
No resources found in default namespace.

vs requesting a specific pod, where you can see the HTTP response is 404 NotFound:

$ kubectl get pod foo -v7
I0503 16:35:05.554206   50521 loader.go:395] Config loaded from file:  /home/brian/.kube/config
I0503 16:35:05.558568   50521 round_trippers.go:463] GET https://k8s-master:6443/api/v1/namespaces/default/pods/foo
I0503 16:35:05.558588   50521 round_trippers.go:469] Request Headers:
I0503 16:35:05.558603   50521 round_trippers.go:473]     User-Agent: kubectl/v1.28.0 (linux/amd64) kubernetes/10a1216
I0503 16:35:05.558614   50521 round_trippers.go:473]     Accept: application/json;as=Table;v=v1;g=meta.k8s.io,application/json;as=Table;v=v1beta1;g=meta.k8s.io,application/json
I0503 16:35:05.607220   50521 round_trippers.go:574] Response Status: 404 Not Found in 48 milliseconds
I0503 16:35:05.607768   50521 helpers.go:246] server response object: [{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "pods \"foo\" not found",
  "reason": "NotFound",
  "details": {
    "name": "foo",
    "kind": "pods"
  },
  "code": 404
}]
Error from server (NotFound): pods "foo" not found

So in case 1 and 2, the command is successfully returning an empty result, and in example 3, the command is failing because it could not find the specific pod you have specified.

I think that explains the behavior you are seeing. Whether it is the correct behavior I suppose is open for discussion.

The help text from the flag does imply that it only applies when you request a specific object, but maybe it isn't clear enough.

   --ignore-not-found=false:
    If the requested object does not exist the command will return exit code 0.

I guess kubectl could print a warning if you use --ignore-not-found without requesting a specific object, saying that it has no effect.


Incidentally, I do think there is a related bug, when you use --ignore-not-found with --watch:

$ kubectl get pod foo --watch --ignore-not-found
Error from server (NotFound): pods "foo" not found
$ echo $?
1

In this case, I think the exit code should be 0.

jmazzitelli commented 5 months ago

Right. When reading that help text where it says "the requested object" - I assume "the requested object" means whatever I'm asking to get. And I am requesting an object when I use --selector or just a empty get (now, granted, I could be requesting multiple objects (plural) - but I really don't know what I have - that's why I'm getting them :)

The help text from the flag does imply that it only applies when you request a specific object, but maybe it isn't clear enough.

Yes. I think at minimum this is a problem that can easily be corrected - just make the help text more clear. It seems to me reading that help text that the exit code should be non-zero if the requested object (or objects, again I don't know how many there are) does not exist.

I guess kubectl could print a warning if you use --ignore-not-found without requesting a specific object, saying that it has no effect.

If that is the correct expected behavior, that would help also.

But, frankly, I think the behavior should change, too. If I ask to get resources, and I get nothing back, exit code should be 0 if --ignore-not-found=true and exit code should be 1 if --ignore-not-found=false. Saying "false" implies "do NOT ignore this if nothing is found - tell me with exit code 1".

ardaguclu commented 4 months ago

I think, this KEP https://github.com/kubernetes/enhancements/issues/2551 will propose a standartization with respect to exit code and will fix this.

k8s-triage-robot commented 1 month ago

The Kubernetes project currently lacks enough contributors to adequately respond to all issues.

This bot triages un-triaged issues according to the following rules:

You can:

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

sftim commented 1 month ago

/retitle kubectl get --ignore-not-found behavior unclear

/sig cli

sftim commented 1 month ago

I'm not sure there's a bug here.

Fetching a collection of Pods (ie, when not specifying a particular Pod name) returns a collection. The collection has no Pods in it, but the list has succeeded and a collection is returned.

As an enhancement, we might provide a way to get a failure exit when you fetch a collection and it's empty.

IMO this is actually either a support request or a feature. Maybe we could improve the built-in help to explain the current behavior better.

jmazzitelli commented 1 month ago

Maybe we could improve the built-in help to explain the current behavior better.

Yes, that was suggested earlier and what I thought is fine to do in order to help address the confusion.

> The help text from the flag does imply that it only applies when you request a specific object, but maybe it isn't clear enough.

Yes. I think at minimum this is a problem that can easily be corrected - just make the help text more clear. It seems to me
reading that help text that the exit code should be non-zero if the requested object (or objects, again I don't know how
many there are) does not exist.
k8s-triage-robot commented 3 weeks ago

The Kubernetes project currently lacks enough active contributors to adequately respond to all issues.

This bot triages un-triaged issues according to the following rules:

You can:

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle rotten