Backporting_Capabilities#

Overview#

This document specifies how backwards-incompatible changes may be backported to maintenance branches of FreeIPA.

Use Cases#

The use case is fixing issues like RH bug 1117300, in which the fix to ticket 2886 could not be backported to IPA 3.0. Unfortunately, it is too late to backport this particular fix.

The process described here, and related the changes in IPA, will make such backports possible in the future.

== Design= =

IPA handles backwards-incompatible API changes by “capabilities”, which mark that a feature was introduced in a certain API version. This was implemented for V3/Messages.

when a client implements a capability, it unconitionally uses some new API semantics in the request to the server. Servers use the client’s API version to determine whether to use new or old semantics. A client that implements a capability cannot successfully connect to a server that does not implement the capability.

The above rules work with FreeIPA’s current API versioning scheme. This design defines a way to enable backporting backwards-incompatible features to maintenance branches, while respecting these rules.

FreeIPA master branch#

The master branch uses a two-element API versioning scheme, 2.x, where ‘x’ is a number that increases with each API change.

API versions are compared using LooseVersion rules of Python distutils.

Backwards-incompatible changes are recorded as *capabilities*.

For example, the capability ‘optional_uid_params’ was added in API version ‘2.54’. Every client of version ‘2.54’ or greater uses the new API. Every server of version ‘2.54’ or greater uses the client’s API version, which is sent in each RPC call, to determine the API to use.

Clients of version ‘2.54’ or greater cannot connect to servers older than ‘2.54’.

Client < ‘2.54’

Client >= ‘2.54

Server < ‘2.54’

Old API*

Cannot connect

Server >= ‘2.54’

Old API

New API*

  • A client may not connect to a server of lower version.

Maintenance API branches#

Currently, the API of a maintenance branch must remain fully backwards compatible with the version it was branched from. (Alternatively it may implement the exact same API changes as the master branch, in the same sequence, and update the API version accordingly.)

This design allows a single capability at a time to be backported. When this hapens, a ‘+’ and the name of the capability is appended to the API version. Once branched this way, versioning of the branch is strictly linear: additional capabilities may only be appended.

Only versions that already implement the ‘extra_capabilities’ capability may be forked in this way. ‘extra_capabilities’ will be added when support for the mechanism described here is added to FreeIPA.

Example#

Let’s say the master branch is at API version ‘2.500’, and a maintenance branch at ‘2.200’. The maintenance branch needs to backport the capability ‘b’ which was added in version ‘2.400’. After implementing the capability, the API version of the maintenance branch becomes ‘2.200+b’.

After a while the capability ‘a’, introduced in master with API version ‘2.300’, needs to be backported. When this is done, the API version becomes ‘2.200+b+a’.

All further versions of the ‘2.200’ branch must start with ‘2.200+b+a’; the version ‘2.200+a’ may never appear. .

A summary:

sema ntics under stood by s erver ↓

C lient <= ‘2 .200’

C lient = ‘2.2 00+b’

C lient >= ‘2 .200+ b+a’, < ‘2 .201’

C lient >= ‘2. 201’, < 2.300

C lient >= ‘2. 300’, < 2.400

C lient >= 2.400

re quest sema ntics →

old

‘b’

‘a’, ‘b’

old

‘a’

‘a’, ‘b’

S erver <= ‘2 .200’

old

Old API*

C annot co nnect

C annot co nnect

C annot co nnect

C annot co nnect

C annot co nnect

S erver = ‘2.2 00+b’

‘b’

Old API

‘b’ *

C annot co nnect

C annot co nnect

C annot co nnect

C annot co nnect

S erver >= ‘2 .200+ b+a’, < ‘2 .201’

‘a’, ‘b’

Old API

‘b’

‘a’, ‘b’ *

C annot co nnect

C annot co nnect

C annot co nnect

S erver >= ‘2. 201’, < 2.300

old

Old API

C annot co nnect †

C annot co nnect †

Old API *

C annot co nnect

C annot co nnect

S erver >= ‘2. 400’, < 2.400

‘a’

Old API

C annot co nnect †

C annot co nnect †

Old API

‘a’ *

C annot co nnect

S erver >= 2.400

‘a’, ‘b’

Old API

‘b’

‘a’, ‘b’

Old API

‘a’

‘a’, ‘b’ *

  • A client may still not connect to a server of lower version.

A version is lower than the same version with extra capability suffix attached (e.g. ‘2.10+xy’ < ‘2.10+xy+zzy’).

† See the “Optional suffix” section

Optional suffix#

To provide greater compatibility, the client may omit a suffix from the API version it sends, if the semantics with and without that capability are equivalent for that particular request. Only

For example, bug 1117300 only affects a few commands, and only when the numeric user or group ID option is set to a particular value. If a fix backported to version ‘2.30’, the client could send API version ‘2.30+optional_uid_params’ only in the case above, and otherwise keep sending ‘2.30’.

However, if the client version was ‘2.30+optional_uid_params+major_overhaul’, and the ‘major_overhaul’ capability changes the semantics of the call, ‘optional_uid_params’ may not be dropped.

The exact mechanics are not specified here or in the implementation that will accompany this design, since they depend on the particular feature being backported.

Limitations#

This scheme only allows “official” branches, over which the core FreeIPA team has full control. Third-party extensions are encouraged to adopt a private versioning scheme, and use it in parallel to the IPA core API version.

Implementation#

No additional requirements or changes were discovered during the implementation phase.

Feature Management#

No user-visible features to manage

Major configuration options and enablement#

No configuration options, no way to disable the feature.

Replication#

No impact on replication.

Updates and Upgrades#

No impact on updates and upgrades.

Dependencies#

No new package and library dependencies.

External Impact#

No impact on other development teams and components.

Backup and Restore#

No impact on B&R.

Test Plan#

Will be tested by FreeIPA’s testsuite, until a concrete use case arises. The test will check all cases in the table in the “Example” section.