faas-netes: Improve secrets api errors

The Secrets API current returns all errors from the k8s cluster as 500 Server Error. This obfuscates validation errors and can be confusing.

For example @rgee0 shared this in Slack

$ echo 'burt' | faas secret create I_LOVE_UNDERSCORES
Creating secret: I_LOVE_UNDERSCORES
WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.
server returned unexpected status code: 500 - 

$ echo 'burt' | faas secret create i-prefer-lowercase
Creating secret: i-prefer-lowercase
WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.
Created: 202 Accepted

Expected Behaviour

If the error is a known error, for example a validation error about the secret name, then we should return the appropriate http status code

$ echo 'burt' | faas secret create I_LOVE_UNDERSCORES
Creating secret: I_LOVE_UNDERSCORES
ERROR 422: The Secret "I_LOVE_UNDERSCORES" is invalid: metadata.name: Invalid value: "I_LOVE_UNDERSCORES": a DNS-1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')

Current Behaviour

All errors are returned at 500

$ echo 'burt' | faas secret create I_LOVE_UNDERSCORES
Creating secret: I_LOVE_UNDERSCORES
WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.
server returned unexpected status code: 500 - 

Possible Solution

The is comes from this block of code https://github.com/openfaas/faas-netes/blob/422fa85178b3479f1214dea7c7718c26808d80a5/handlers/secrets.go#L87-L92

Instead of returning the plain error, we should use the ReasonForError helper in the k8s.io/apimachinery/pkg/api/errors package defined here https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/api/errors/errors.go#L575

to capture the reason and decide the appropriate API response. For example

 _, err = kube.Create(secret)
switch {
case k8serrors.ReasonForError(err) == metav1.StatusReasonNotAcceptable:
    w.WriteHeader(http.StatusUnprocessableEntity)
// and other cases ...
case err == nil:
// do nothing
default:
    w.WriteHeader(http.StatusInternalServerError)
    log.Printf("Secret create error: %v\n", err)
    return
}

This should be done for each endpoint, not just the creation endpoint because there are various errors that could arise due to cluster configuration.

Steps to Reproduce (for bugs)

  1. install the latest openfaas on k8s
  2. install the latest CLI
  3. execute echo 'burt' | faas secret create I_LOVE_UNDERSCORES

Context

Managing secrets via the openfaas CLI simplifies the cognitive overhead and improves the scriptability of OpenFaaS. The current error messages are not informative enough to fix the underlying issue

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 22 (22 by maintainers)

Most upvoted comments

Yes 1.9 would be the best choice since we want to support as many K8s version as possible. I think is a good idea to post in the readme that the minimum version supported by faas-netes is 1.9 after the upgrade.

/assign: acornies

Derek assign :me

I want to give this a shot this weekend. let me see if Derek listens to me.

Derek assign :me

https://httpstatuses.com/ is a good reference for the different standard http status codes and there meanings. We should be thoughtful to map to those where possible