Syntax for referring to item versions
Some work is already done to versioned actions, but it's not expose in CLI and other items like rules, triggers, feeds will need to be doc.
From @vinodmut : All items are versioned using semantic versioning. We need a way to refer to particular versions of items.
This is needed both in the CLI and API.
A proposal for the syntax that continues to use ':' delimiters:
Fully qualified name with version would look like:
namespace:name:version
So examples include:
[email protected]:myaction:0.1.0
[email protected]:myaction:0.1.*
[email protected]:myaction:>=1.2.3
[email protected]:myaction:~1.2.3
[email protected]:myaction // implies latest version
The versioning syntax is based on the semantic versioning as supported by npm: https://github.com/npm/node-semver
Since we allow arbitrarily nested namespaces, and both namespaces and versions are optional, we can avoid ambiguities by requiring that namespaces and item names start with [a-zA-Z]. Versions would start with [0-9~><=^].
I'm looking at the possibility of implementing versioning and have tons of questions since this spans almost the entire project. Wondering if anybody has put more thought into this; and also if someone could comment on my questions below:
How should the API behave with versioned entities?
PUT /api/v1/namespaces/guest/actions/helloWorld
- entity doesn't exist
- create entity with version 0.0.1
&& then PUT /api/v1/namespaces/guest/actions/helloWorld
- entity exists
- no version specified
- mutate the latest version of the entity, or require a version to be specified?
- what mutations should be allowed? e.g. allow annotation updates but not code updates
I'd be inclined to think changes should be disallowed to a versioned document without specification of the version
How should we name && refer to versioned entities?
/api/v1/namespaces/ns/entity/name/version
wsk action get /helloWorld/0.0.1
wsk action get /guest/helloWorld --> gets 0.0.2
I'm not amped to tackle package versioning at the moment, but wondering if versioning for it would work as so:
| Fully qualified name | Alias | Namespace | Package | Name | Version |
|---|---|---|---|---|---|
/whisk.system/cloudant/0.0.5/read |
/whisk.system |
cloudant |
read |
0.0.5 | |
/myOrg/video/0.0.1/transcode |
video/0.0.1/transcode/ |
/myOrg |
video |
transcode |
0.0.1 |
/myOrg/video/0.0.2/transcode |
video/transcode |
/myOrg |
video |
transcode |
0.0.2 |
How to store versioned entities
I'm not very far into the codebase yet (and have little experience with CouchDB), but wonder if there is a clear "best" approach
- keep the storage key as is and nest the versioned documents? guessing this is a bad approach.
If we add version to the storage key, how do we do quick lookups in the case of "latest" or no version specified, like in wsk action get /guest/helloWorld --> gets 0.0.2
-
can we just duplicate the document under both keys,
/guest/helloWorld/and/guest/helloWorld/0.0.2 -
or maybe there is some secondary indexing available in the data store API?
-
something else?
One of the many use-cases for OpenWhisk is for implementing API:s. However, for this to be a serious alternative compared to building microservices we need to have proper versioning. Otherwise it will be very hard to convince customers that they can only have 1 active version of their function in production at any given time, and they can't specify which version to invoke. Furthermore, when upgrading a function, there is no way to perform blue-green or canary deployments so upgrading becomes a very risky business.
I'm not convinced that semantic versioning is the ideal solution. First, I think it's more than is needed, and secondly, what about invoking an action and asking for version>0.0.1 and there's several versions that satisfy the condition. Which version should be chosen?
Working with API:s, many vendors provide the ability to assign any arbitrary tag as a version number, and that's all that is needed. The same could be applied here, which also would give one the option of using GitHub commit tags as version numbers, just as we do with image tags.
Another question that comes to mind is how to refer to versions in the API and CLI. Starting with the API, there is no de-facto standard for resource versioning. Some suggest using path parameters, others suggest request parameters or http headers such as Accept or If-Match with ETags, or even custom headers. A clear advantage of using a header would be that this will not break v1 of the API. For the CLI we would just add a --version flag for the appropriate commands. But how should we handle when the version is omitted? If we use the notion of a default version, which the user could indicate using a --default flag (default true) when creating or updating an entity, we could fall back to this default version. The difference between a default version and the latest version is that they are not necessarily the same.
Once we implement versioning, we can move on to routing. Being able to specify a version to invoke, we can implement green-blue and canary deployments. To be able to support canary deployments, we need a way to specify load-balancing between versions. If all actions where fired trough triggers, we could use rules for this, but I don't think they are. Invoking an action through the API doesn't involve any trigger or rule, so either we would have to implement some kind of default trigger/rule for this under the hood, or we need a new entity for load-balancing that the controller can use.