# Versioning

Running `kustomize` means one is running a
particular version of a program, reading a
particular version of a [kustomization] file.

## Program Versioning

The command `kustomize version` prints a three
field version tag (e.g. `1.0.11`) that aspires to
[semantic versioning].

When enough changes have accumulated to
warrant a new release, a [release process]
is followed, and the fields in the version
number are bumped per semver.

## Kustomization File Versioning

At the time of writing (circa release of v2.0.0):

- A [kustomization] file is just a YAML file that
  can be successfully parsed into a particular Go
  struct defined in the `kustomize` binary.

- This struct does not have a version number,
  which is the same as saying that its version
  number matches the program's version number,
  since it's compiled in.

### Field Change Policy

- A field's meaning cannot be changed.

- A field may be deprecated, then removed.

- Deprecation means triggering a _minor_ (semver)
  version bump in the program, and
  defining a migration path in a non-fatal
  error message.

- Removal means triggering a _major_ (semver)
  version bump, and fatal error if field encountered
  (as with any unknown field).

### The `edit fix` Command

This `kustomize` command reads a Kustomization
file, converts deprecated fields to new
fields, and writes it out again in the latest
format.

This is a type version upgrade mechanism that
works within _major_ program revisions.  There is
no downgrade capability, as there's no use case
for it (see discussion below).

### Examples

At the time of writing, in v1.0.x, there were 12
minor releases, with backward compatible
deprecations fixable via `edit fix`.

With the 2.0.0 release, there were three field
removals:

- `imageTag` was deprecated when `images` was
   introduced, because the latter offers more
   general features for image data manipulation.
   `imageTag` was removed in v2.0.0.

- `patches` was deprecated and replaced by
   `patchesStrategicMerge` when `patchesJson6902`
   was introduced, to make a clearer
   distinction between patch specification formats.
   `patches` was removed in v2.0.0.

- `secretGenerator/commands` was removed
   due to security concerns in v2.0.0
   with no deprecation period.

The `edit fix` command in a v2.0.x binary
will no longer recognize these fields.

## Relationship to the k8s API

### Review of k8s API versioning

The k8s API has specific [conventions] and a
process for making [changes].

The presence of an `apiVersion` field in a k8s
native type signals:

- its reliability level (alpha vs beta vs
  generally available),

- the existence of code to provide default values
  to fields not present in a serialization,
  
- the existence of code to provide both forward
  and backward conversion between different
  versions of types.

The k8s API promises a lossless _conversion_
between versions over a specific range.  This
means that a recent client can write an object
bearing the newest possible value for its version,
the server will accept it and store it in
"versionless" JSON form in storage, and can
convert it to a range of older versions should
an older client request data.

For native k8s types, this all requires writing Go
code in the kubernetes core repo, to provide
defaulting and conversions.

For CRDs, there's a [proposal] on how to manage
versioning (e.g. a remote service can offer type
defaulting and conversions).

### Kustomization file versioning

The critical difference between k8s API versioning
and kustomization file versioning is

- A k8s API server is able to go _forward_ and
  _backward_ in versioning, to work with older
  clients, over [some range].

- The `kustomize edit fix` command only moves
  _forward_ within a _major_ program
  version.

At the time of writing, the YAML in a
kustomization file does not represent a [k8s API]
object, and the kustomize command and associated
library is neither a server of, nor a client to,
the k8s API.

### Additional Kustomization file rules

In addition to the [field change policy] described
above, kustomization files conform to
the following rules.

#### Eschew classic k8s fields

Field names with dedicated meaning in k8s
(`metadata`, `spec`, `status`, etc.)  aren't used.

This is enforced via code review.

#### Optional use of k8s `kind` and `apiVersion`

At the time of writing two [special] k8s
resource fields are allowed, but not required, in
a kustomization file: [`kind`] and [`apiVersion`].

If either field is present, they both must be, and
they must have the following values:

``` yaml
kind: Kustomization
apiVersion: kustomize.config.k8s.io/v1beta1
```

They are allowed to exist and have specific values
in a kustomization file only as a sort of
domain-squatting behavior for some future API.  A
kustomize user gains nothing from adding these
fields to a kustomization file.

### Why not require `kind` and `apiVersion`

#### Ease of use and setting proper expectations

Use cases for a kustomization file don't include a
server storing muliple k8s kinds and offering
version downgrades.

The kustomization file is more akin to a
`Makefile`.  A kustomize command can either read a
kustomization file, or it cannot, and in the later
case will complain as specifically as possible
about why (e.g. `unknown field Foo`).

So requiring a `kind` and `apiVersion` would just
be boilerplate in a user's files, and in all the
examples and tests.

Nevertheless, _a user still benefits from a
versioning policy_ and has a `fix` command to
upgrade files as needed.

#### We can change our minds

When/if the kustomization struct graduates to some
kind of API status, with an expectation of
"versionless" storage and downgrade capability,
whatever it looks like at that moment can be
locked into `/v1beta1` or `/v1` and the `kind`
and `apiVersion` fields can be required from that
moment forward.

[field change policy]: #field-change-policy
[some range]: https://kubernetes.io/docs/reference/using-api/deprecation-policy
[proposal]: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/customresources-versioning.md
[beta-level rules]: https://github.com/kubernetes/community/blob/master/contributors/devel/api_changes.md#alpha-beta-and-stable-versions
[changes]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md
[adapt]: https://github.com/kubernetes-sigs/kustomize/blob/master/pkg/types/kustomization.go#L166
[special]: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#resources
[k8s API]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md
[conventions]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md
[release process]: ../build/README.md
[kustomization]: glossary.md#kustomization
[`kind`]: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#types-kinds
[`apiVersion`]: https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-versioning
[semantic versioning]: https://semver.org
