Add missing attributes to /system/function/{functionName}
Expected Behaviour
Attributes used to create a function with the POST endpoint should be mirrored when retrieving the function meta data using the GET endpoint
Current Behaviour
The attributes are currently as follows:
| Name | POST | GET |
|---|---|---|
| service |
|
|
| network |
|
|
| image |
|
|
| envProcess |
|
|
| envVars |
|
|
| constraints |
|
|
| labels |
|
|
| annotations |
|
|
| secrets |
|
|
| registryAuth |
|
|
| limits |
|
|
| requests |
|
|
| readOnlyRootFilesystem |
|
|
Possible Solution
-
swagger.ymladd missing attributes toFunctionListEntry -
gateway/requests/requests.goadd missing attributes toFunctiontype -
faas-swarm/handlers/reader.goadd missing attributes inreadServicesfunc -
faas-netesadd missing attributes -
faas-operatoradd missing attributes -
faas-clidescribeverb when merged may need updating
Context
I'm writing a terraform provider for openfaas, to work well with terraform, it's best if the underlying infrastructure apis have mirrored POST/GET endpoints. This is also a very common practice in REST apis
Thanks for adding the context for this.
The service list / endpoint is used for auto-scaling, event connectors and checking readiness. What kind of latency or size increase would we expect for this?
@openfaas/core please take a look. I'd like your input.
@ewilde this may also need adding to /system/functions
@martindekov was writing a script to add new labels to existing deployments but could not do so because if any functions had env-vars or secrets then they would be removed by the update.
I can help out with testing this out later since I am familiar with the problem.
I think that it's a good idea to mirror them, it'll improve coherence of API
@alexellis if we are worried about the latency/size impact, we could
- move this to subpaths,
/system/functions/specand/system/functions/{name}/spec. So that/system/functionswould just be a summary. - Or add a nullable
specfield and only include it if a GET parameter is sent. - Or add a nullable
specfield and a GET parameterhide_specto explicitly hide it in those cases where you don't want it
I think option 1 is easier to document and maintain
I like that option 1 is a non-breaking change that achieves what we need for Ed's terraform use-case and for anyone else who wants to make an update to an existing deployment who may not have all the original source data. With OpenFaaS Cloud for example we have all the data i.e. lists of secrets/envs so there it hasn't been an issue yet.
For Ed and for @martindekov who was writing a script over the last few days to migrate labels this would be ideal.
Happy to go with option 1. However; looks like it would be a breaking change though, if I've understood the proposal correctly
To create a new function resource you would POST to /system/functions/spec and read the resource GET from /system/functions/{name}/spec. Presumably older versions of the cli would still POST to /system/functions and other components would read from /system/functions/{name}?
If we are to go with option 1, I would prefer to GET from /system/functions/spec/{name}, instead of /system/functions/{name}/spec/. Think that more closely aligns with a restful API. You are creating a function spec resource and reading the spec resource with the identifier {name}
I like this
GET from
/system/functions/spec/{name}, instead of/system/functions/{name}/spec/.
What if we extend the main existing API to return all available data and then add a summary APi if needed for internal components later?
It is a larger potentially breaking change if we do it that way. But it might be worth it for API consistency
Hi all, I would love to help pick this back up as I am trying to use the openfaas terraform provider but I cannot get some things in the provider to work without the information described in this issue. See below for my thoughts on how to solve. I am happy to create the PRs but will definitely need some guidance on the right approach.
Goal: Update the gateway to return all the information about a function in order to support terraform and pulumi providers.
Suggested Steps
- faas: Update swagger.yml and
Functionin requests.go - faas-swarm: Update reader.go
- faas-netes: Update reader.go
- openfaas-operator: Update replicas.go and list.go
- terraform-provider-openfaas: Update structure.go
- pulumi-openfaas: Update client.go
Searching for where Function is used It doesn't seem like we would need to update faas-cli. Let me know if you think I am missing any other references.
Resources
- Original PR: https://github.com/openfaas/faas/pull/849
Also related https://github.com/pulumi/pulumi-openfaas (specifically https://github.com/pulumi/pulumi-openfaas/blob/master/pkg/client/client.go#L89)
@ameier38 the steps you layout look good and if we just extend the current model with the missing fields per https://github.com/openfaas/faas/issues/848#issuecomment-423802184 then it should be straightforward and compatible with the current implementations.
We will be discussing this issue in our next members call. Will let you know where we get.
Related work: https://github.com/openfaas/faas/issues/784
^ this may allow for "exporting" of functions.
Part of the challenge with this issue is that we encode the "missing" data in the container spec, so limits/requests are parsed and then implemented on the spec.
It's possible that we could do a non-lossy conversion back, but it's more likely that to achieve this what we really need to do is to store the JSON that was used to create / update the function.
i.e.
{
"service": "nodeinfo",
"image": "functions/nodeinfo:burner",
"envProcess": "node main.js",
"labels": {
"com.openfaas.scale.min": "2",
"com.openfaas.scale.max": "15"
},
"environment": {
"output": "verbose",
"debug": "true"
}
}
The above would be put into an annotation called spec, so that the REST API could return this when requested.
We also need to separate out desired state vs status. I.e. readyReplicas cannot be set by the deployment request, but it is going to be returned on the function endpoint.
How do we want to address that? ^
@ameier38 we discussed this issue at our members meeting this evening on zoom. @alexellis suggested again the approach in the above comment.
Openfaas-operator is already serialising the full function specification in an annotation see: deployment.go#L183
We could adapt this approach to other providers: faas-netes and faas-swarm. Maybe start with a openfaas-operator?
We also need to separate out desired state vs status. I.e. readyReplicas cannot be set by the deployment request, but it is going to be returned on the function endpoint.
Thoughts on this?
@alexellis Could faas.requests.Function be refactored into something like:
type FunctionResponse struct {
Name string `json:"name"`
Image string `json:"image"`
Replicas uint64 `json:"replicas"`
EnvProcess string `json:"envProcess"`
Secrets []string `json:"secrets"`
Labels *map[string]string `json:"labels"`
Annotations *map[string]string `json:"annotations"`
Limits *FunctionResources `json:"limits"`
Requests *FunctionResources `json:"requests"`
AvailableReplicas uint64 `json:"availableReplicas"`
InvocationCount uint64 `json:"invocationCount"` // not sure this is needed
}
Already started in the corresponding PR
As you mentioned we could create an annotation by serializing CreateFunctionRequest. This could then be used to populate FunctionResponse when requesting a function (similar to this) along with AvailableReplicas and InvocationCount
I think this is also related: https://github.com/openfaas/faas/issues/565
Do you think all of the data inputted can be retrieved from Kubernetes and Swarm objects, or is using an annotation the only way to make this work reliably?
I think everything in https://github.com/openfaas/faas/issues/848#issuecomment-503369088 except InvocationCount could come from the k8s/swarm objects
@LucasRoesler I checked the k8s Deployment type and I think you are right. I also like the idea of just pulling the info from the pod.
Given that, I don't think we would need to update faas.request.Function but rather create a new type in faas-netes/faas-swarm, say FunctionSpec, with Function embeded plus the additional fields. We could then use FunctionSpec here and here instead of Function. After Function is moved to faas-provider we could then re-sync.
Let me know what you think.
@ameier38 i am not sure about using an embedding, but passing around FunctionSpec sounds like a good idea to me
I would like to see this approached iteratively - we can start with fixing envProcess whilst we figure out the game-plan for the bigger picture (not trivial by the looks of it)
@ameier38 agreed to put up a PR to fix faas-netes reading the envProcess. Let us know when that's ready for review.
https://github.com/openfaas/faas/issues/848#issuecomment-508377961
@LucasRoesler is the above done now? I think I merged a PR from you for it?
That part of the issue appears to have been addressed in: https://github.com/openfaas/faas-netes/pull/549
@martindekov I heard you had an interest in this issue, do you want to go about making some changes and PRs? What's your availability like?
@ameier38 please look at the new types that were spun out into the faas-provider project. https://github.com/openfaas/faas-provider/tree/master/types