Overrides

During an image life cycle there can be a need to do a slightly tweaked builds – using different base images, injecting newer libraries etc. We want to support such scenarios without a need of duplicating whole image sources.

To achieve this CEKit supports overrides mechanism for its descriptors. You can override anything from the descriptor. The overrides are based on overrides descriptor – a YAML object containing overrides for the image descriptor.

To use an override descriptor you need to pass --overrides-file argument to CEKit. This may be a path based object or a URL scheme (HTTP/HTTPS/file). You can also pass JSON/YAML object representing changes directly via --overrides command line argument.

Example

Use overrides.yaml file located in current working directory

$ cekit build --overrides-file overrides.yaml podman
Example

Use overrides.yaml file located on a remote server

$ cekit build --overrides-file https://example.com/overrides.yaml podman
Example

Override a label via command line

$ cekit build --overrides '{"labels": [{"name": "foo", "value": "overridden"}]}' podman

Note

It is possible to specify YAML as well as JSON on the CLI e.g.

$  cekit -v build --overrides 'labels:
 - name: foo
   value: overridden' --dry-run podman

Overrides chaining

You can even specify multiple overrides. Overrides are resolved that last specified is the most important one. This means that values from last override specified overrides all values from former ones.

Example

If you run following command, label foo will be set to baz.

$ cekit build --overrides "{'labels': [{'name': 'foo', 'value': 'bar'}]} --overrides "{'labels': [{'name': 'foo', 'value': 'baz'}]}" podman

How overrides works

CEKit is using YAML format for its descriptors. Overrides in CEKit works on YAML node level.

Scalar nodes

Scalar nodes are easy to override, if CEKit finds any scalar node in an overrides descriptor it updates its value in image descriptor with the overridden one.

Example

Overriding scalar node

# Image descriptor

schema_version: 1
name: "dummy/example"
version: "0.1"
from: "busybox:latest"
# Override descriptor

schema_version: 1
from: "fedora:latest"
# Resulting image descriptor

schema_version: 1
name: "dummy/example"
version: "0.1"
from: "fedora:latest"

Sequence nodes

Sequence nodes are a little bit tricky, if they’re representing plain arrays, we cannot easily override any value so CEKit is just replacing the whole sequence.

Example

Overriding plain array node.

# Image descriptor

schema_version: 1
name: "dummy/example"
version: "0.1"
from: "busybox:latest"
run:
    cmd:
        - "echo"
        - "foo"
# Override descriptor

schema_version: 1
run:
    cmd:
        - "bar"
# Resulting image descriptor

schema_version: 1
name: "dummy/example"
version: "0.1"
from: "busybox:latest"
run:
    cmd:
        - "bar"

Mapping nodes

Mappings are merged via name key. If CEKit is overriding a mapping or array of mappings it tries to find a name key in mapping and use and identification of mapping. If two name keys matches, all keys of the mapping are updated.

Example

Updating mapping node.

# Image descriptor

schema_version: 1
name: "dummy/example"
version: "0.1"
from: "busybox:latest"
envs:
    - name: "FOO"
      value: "BAR"
# Override descriptor

schema_version: 1
envs:
    - name: "FOO"
      value: "new value"
# Resulting image descriptor

schema_version: 1
name: "dummy/example"
version: "0.1"
from: "busybox:latest"
envs:
    - name: "FOO"
      value: "new value"

Removing keys

Overriding can result into need of removing a key from a descriptor. You can achieve this by overriding a key with a YAML null value.

You can use either the null word or the tilde character: ~ to remove particular key.

Example

Remove value from a defined variable.

If you have a variable defined in a following way:

envs:
    - name: foo
      value: bar

you can remove value key via following override:

envs:
    - name: foo
      value: ~

It will result into following variable definition:

envs:
    - name: foo

Warning

In some cases it will not be possible to remove the element and an error saying that schema cannot be validated will be shown. If you run it again with verbose output enabled (--verbose) you will see required.novalue messages.

Improvement to this behavior is tracked here: https://github.com/cekit/cekit/issues/460

Artifact Overrides

While artifact overrides function in general as per scalar nodes there is some special case handling for merging for the common keys of target and dest and description.

If the original definition contains a non-default destination e.g. /destination and the override does not specify a destination then the original value will be maintained rather than overwriting it with the default value of /tmp/artifacts.

If the original contains a target or description definition and the override does not specify a target/description then the original value will be maintained.

Examples

  1. Maintain destination with plain override with new target

    Original (URL artifact)
     name: 'bar.jar'
     dest: '/tmp/destination/'
     url: 'https://foo/original-bar.jar'
     target: 'original-bar.jar'
    
    Overrides (Plain artifact)
     name: 'bar.jar'
     md5: 234234234234
     target: 'bar2222.jar'
    
    Result
     name: 'bar.jar'
     dest: '/tmp/destination/'
     md5: 234234234234
     target: 'bar2222.jar'
    
  2. Maintain destination and target with plain override:

    Original (URL artifact)
     name: 'bar.jar'
     dest: '/tmp/destination/'
     url: 'https://foo/original-bar.jar'
     target: 'original-bar.jar'
    
    Overrides (Plain artifact)
     name: 'bar.jar'
     md5: 234234234234
    
    Result
     name: 'bar.jar'
     dest: '/tmp/destination/'
     md5: 234234234234
     target: 'original-bar.jar'