Versioning
This document describes Capact versioning strategy.
Overviewβ
The versioning for OCF and Hub are similar in concept to how Kubernetes implements versioning. Below is a table comparing Capact versioning to Kubernetes versioning.
Capact | Kubernetes |
---|---|
Hub Version | Kubernetes Version |
OCF Version | Resource apiVersion |
Manifests revision | resourceVersion |
TypeInstance resourceVersion | resourceVersion |
Engine | kube-controller-manager |
CLI | kubectl |
Go SDK | client-go |
Diagramβ
NOTE: The diagram visualizes future application version features, which are not yet implemented.
The following diagram shows the versioning concept:
OCF Versionβ
This is the version of the Open Capability Format itself. The version changes every time there is a change in any of OCF entity manifest, such as adding or removing properties in a manifest or introducing a brand-new entity.
Supporting multiple OCF versions in Hubβ
NOTE This section describes our long-term goal. Currently, the feature is not implemented.
Hub supports multiple versions of OCF. To achieve that, we reuse the API versioning concept from Kubernetes. A single OCF version is used to store resources in the database. However, Hub does the conversion between the stored resource and one of the supported OCF versions by Hub on-the-fly.
The cluster administrator migrates the storage version of the resource manually during Hub upgrade/downgrade. In the future, we will introduce automatic migration between storage versions or external tools that facilitates the process.
Example:
Hub 0.3.0 can support OCF versions 0.2.0 and 0.1.0. The RepoMetadata entity is defined as follows:
kind: RepoMetadata
# (...)
spec:
hubVersion: 0.1.0
ocfVersion:
default: 0.2.0
supported:
- 0.1.0
- 0.2.0
# (...)
The manifest version stored in Hub is 0.2.0. However, using a different API endpoint, the user can fetch manifests in version 0.1.0. Hub supports on-the-fly conversion between the default (stored) OCF manifests to the OCF manifests in supported versions.
Deprecation policy of OCF versionsβ
The deprecation policy is very similar to the Kubernetes deprecation policy. The only change is that we will use Semantic Versioning for versioning OCF. There are multiple reasons to use SemVer 2 for OCF versioning:
- Unification of versioning across all Project Capact components.
- Clear way to represent new features without breaking changes. You can easily see that there is a new OCF feature that you can use. In Kubernetes API versioning, a new non-breaking feature doesnβt change the version, e.g.
v1
. - Unification with other projects in the open source community, such as OAM, CNAB, CloudEvents, AsyncAPI.
Once we deprecate an OCF version, we will include deprecation notices in Hub release notes. We will warn users every time they access deprecated OCF:
- in CLI,
- through the GraphQL API (using Warning header).
A deprecated OCF version will have a transition period (see Kubernetes deprecation policy for details) where itβs still supported by Hub. After that period, we remove support for the deprecated OCF version from the Hub release.
Hub rejects any submission of OCF manifests in unsupported versions.
The OCF storage version in Hub is never the deprecated one. This way, there wonβt be a case when existing manifests are removed during Hub upgrade due to an unsupported version.
Manifests revisionβ
Unlike Kubernetes resourceVersion, we store all previous revisions of manifests such Type, Implementation, Interface and Attribute. Users can consume them anytime. Manifests can refer to older revisions of the other manifests.
Example: Implementation implements specific Interface revision. Revision of the Interface is increased once input or output Type changes. Content Creator updates the revision manually.
TypeInstance resourceVersionβ
This is the version of TypeInstance metadata and spec fields. Unlike Kubernetes, we store historical data for audits and rollback purposes.
Core manifestsβ
We version core manifests (manifests, which are located under core
subdirectory) in the same way as the OCF itself. Core entities are strictly tied into the Hub release, and they are read-only.
Application versionβ
NOTE: The following subsection describes future application version features, which are not yet implemented.
The Implementation manifest contains the appVersion field, which defines the supported version of the actual application. The appVersion field is independent from the revision.
The appVersion is a string in the following format:
appVersion: "1.0.x, 1.1.0 - 1.3.0" # String with allowed version ranges
It is inspired by the CNAB dependency version object. If the appVersion ranges are in SemVer 2 format, you can use ranges using dashes. If the appVersion ranges are not in SemVer 2, then you have to specify every supported appVersion in the string.
Default application versions in SemVer formatβ
During the submission of the Implementation manifest, if the appVersion field is defined in the SemVer format, Hub updates the following versions:
latest
β depending on the Hub configuration, it points to stable or edge versionstable
β points to the Implementation with highest semVer version in range without suffix starting from the hyphenFor example, if the range is defined as
1.0.x - 1.1.0-beta1
, the 1.0.9 is picked as an appVersion.edge
β points to the Implementation with highest semVer version in range, even if it contains suffix starting from the hyphenFor example, if the range is defined as
1.0.x - 1.1.0-beta1
, the 1.1.0-beta1 is picked as an appVersion.
You can use the versions in Implementation manifest to filter prerequisite Implementations based on the appVersion value. For example, if your Implementation depends on the latest stable PostgreSQL version, then you can use the stable
version as the application version of PostgreSQL.
Default application versions in different format than SemVerβ
If the application is not versioned using SemVer format, we assume that all possible appVersion values are sorted from oldest to newest. This way, the latest
version is always the newest appVersion value.
Example:
In the following example, the baz
version is picked as the latest one.
ocfVersion: 0.0.1
revision: 1.0.0
metadata:
prefix: cap.implementation.database.mysql
name: install
spec:
appVersion: "foo, bar, baz"
Conflict preventionβ
An application version can be defined as a range. During Implementation manifest submission, the Hub validates whether the application version range doesn't overlap with the same revision of the Implementation manifest. As noted earlier, the manifest revision property is independent from the appVersion.
Example:
- The following implementation manifest already exists in the Hub:
ocfVersion: 0.0.1
kind: Implementation
metadata:
prefix: cap.implementation.database.mysql
name: install
revision: 1.0.0
spec:
appVersion: "8.0.0-8.0.20"
- When you try to submit the following manifest to the Hub...
ocfVersion: 0.0.1
metadata:
prefix: cap.implementation.database.mysql
name: install
revision: 1.0.1
spec:
appVersion: "8.0.x"
- ...the operation fails as the appVersion property range overlaps with existing
cap.implementation.database.mysql.install
Implementation manifest.
Engine and CLI versionsβ
Engine and CLI versions need to be compatible with Hub, as they consume content from Hub. This is similar case as the kubectl
is compatible with the Kubernetes APIServer.