Skip to content

Commit

Permalink
Specification for Preservation of ARM API Versioning (#1538)
Browse files Browse the repository at this point in the history
* First spec version

* Update specification

* Add task to regenerate diagrams
  • Loading branch information
theunrepentantgeek authored Jun 22, 2021
1 parent 0e4cd9c commit b6fed6a
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ tasks:
SHORT_VERSION:
sh: git rev-parse --short HEAD

generator:diagrams:
desc: Regenerate all GraphViz diagrams
dir: "./docs/design/images"
sources: ["*/*.dot"]
cmds:
- "for f in **/*.dot; do dot -Tpng -o${f%.dot}.png $f; done"

############### Controller targets ###############
controller:quick-checks:
deps: [header-check, controller:format-code, controller:test]
Expand Down
39 changes: 39 additions & 0 deletions docs/design/api-versions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# API Versions

Specification for how we will ensure the ARM API version we use for interaction with ARM matches the version originally requested by a user when they created the resource in their Kubernetes cluster.

## Why do we need this?

Sometimes, in addition to structural changes, there are behaviour changes between ARM API versions. It's therefore important that we use the requested API version when interacting with ARM to ensure that we get the behaviour requested.

### Example

Revisting the CRM example from the [Versioning](versioning.md) specification, consider what happens if we have two available versions of the resource `Person`, lets call them **v1** and **v2**. In **v2** the new properties `PostalAddress` and `ResidentialAddress` are mandatory, requiring that everyone have a both a mailing address and a home.

![example](images/api-versions/example.png)

If we have a valid **v1** `Person`, trying to submit that through the **v2** ARM API will fail because it's missing these addresses.

## Proposed Solution

We need to preserve the original API Version of each resource, and use that to create an appropriate resource for ARM.

### API Preservation

When generating storage variants, we'll inject a new `OriginalVersion` property of type **string** into the Spec of each resource, providing a place to capture the API version that was originally used to create the resource.

To populate the `OriginalVersion` property on each storage spec, we'll inject an `OriginalVersion()` method (returning **string**) into the API variant of each spec.

![preservation](images/api-versions/preservation.png)

API version shown on the left, corresponding Storage version shown on the right.

For each API spec, generated `AssignPropertiesTo*()` method will read the value of `OriginalVersion()` and write it to the `OriginalVersion` property on the storage variant. The `AssignPropertiesFrom*()` method will ignore `OriginalVersion`.

For each Storage spec, the generated `AssignPropertiesTo*()` and `AssignPropertiesFrom*()` methods will copy the `OriginalVersion` property between versions, preserving the original value.

### API Recovery

Into each storage resource variant, we'll inject a function `OriginalGVK(): GroupVersionKind` which will use `OriginalVersion` to create the GVK required.

SequenceDiagram TBC.
47 changes: 47 additions & 0 deletions docs/design/images/api-versions/example.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
digraph G {
nodesep="1"


subgraph cluster_api_v1 {
color=none

node [shape=plain, group=api, margin=0];
person_rsrc_api_v1 [label=<
<table border="0" cellborder="1" cellspacing="0">
<tr><td width="320px"><i>«api v1»</i><br/>Person</td></tr>
</table>
>];

person_spec_api_v1 [label=<
<table border="0" cellborder="1" cellspacing="0">
<tr><td width="320px"><i>«api v1»</i><br/>Person_Spec</td></tr>
<tr><td>FullName string<br/>KnownAs string<br/>FamilyName string</td></tr>
</table>
>];

person_rsrc_api_v1 -> person_spec_api_v1 [label="Spec"]

}

subgraph cluster_api_v2 {
color=none

node [shape=plain, group=api, margin=0];
person_rsrc_api_v2 [label=<
<table border="0" cellborder="1" cellspacing="0">
<tr><td width="320px"><i>«api v2»</i><br/>Person</td></tr>
</table>
>];

person_spec_api_v2 [label=<
<table border="0" cellborder="1" cellspacing="0">
<tr><td width="320px"><i>«api v2»</i><br/>Person_Spec</td></tr>
<tr><td>FullName string<br/>KnownAs string<br/>FamilyName string<br/>PostalAddress Address<br/>Residential Address</td></tr>
</table>
>];

person_rsrc_api_v2 -> person_spec_api_v2 [label="Spec"]

}

}
Binary file added docs/design/images/api-versions/example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 47 additions & 0 deletions docs/design/images/api-versions/preservation.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
digraph G {
nodesep="1"


subgraph cluster_api_v1 {
color=none

node [shape=plain, group=api, margin=0];
person_rsrc_api_v1 [label=<
<table border="0" cellborder="1" cellspacing="0">
<tr><td width="320px"><i>«api v1»</i><br/>Person</td></tr>
</table>
>];

person_spec_api_v1 [label=<
<table border="0" cellborder="1" cellspacing="0">
<tr><td width="320px"><i>«api v1»</i><br/>Person_Spec</td></tr>
<tr><td>FullName string<br/>KnownAs string<br/>FamilyName string</td></tr>
<tr><td>OriginalVersion() string</td></tr>
</table>
>];

person_rsrc_api_v1 -> person_spec_api_v1 [label="Spec"]

}

subgraph cluster_storage_v1 {
color=none

node [shape=plain, group=storage, margin=0];
person_rsrc_storage_v1 [label=<
<table border="0" cellborder="1" cellspacing="0">
<tr><td width="320px"><i>«storage v1»</i><br/>Person</td></tr>
</table>
>];

person_spec_storage_v1 [label=<
<table border="0" cellborder="1" cellspacing="0">
<tr><td width="320px"><i>«storage v1»</i><br/>Person_Spec</td></tr>
<tr><td>FullName string<br/>KnownAs string<br/>FamilyName string<br/>OriginalVersion string</td></tr>
</table>
>];

person_rsrc_storage_v1 -> person_spec_storage_v1 [label="Spec"]

}
}
Binary file added docs/design/images/api-versions/preservation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b6fed6a

Please sign in to comment.