Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
Signed-off-by: razzle <harry@razzle.cloud>
  • Loading branch information
Noxsios committed Nov 16, 2023
1 parent c372739 commit 1ee083b
Showing 1 changed file with 74 additions and 1 deletion.
75 changes: 74 additions & 1 deletion content/2023-10-18.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,77 @@ meta = [
<!-- more -->

## Composition?
## History 101

Zarf has supported importing components from other `zarf.yaml`'s for quite a while:

```yaml
# taken from: https://docs.zarf.dev/examples/composable-packages/
components:
- name: local-games-path
required: true
description: "Example of a local composed package with a unique description for this component"
import:
# The local relative path to the folder containing this component's package definition
path: ../dos-games
# Example optional custom name to point to in the imported package (default is to use this component's name)
name: baseline
manifests:
- name: multi-games
files:
- quake-service.yaml
```
Back in May the team added [Composability via OCI](https://github.com/defenseunicorns/zarf/pull/1469) and introduced the idea of "skeleton" packages for this purpose.
Simply put: skeleton packages provide the ability to import components stored in an OCI repository instead of needing to re-define locally or with `git submodule`s.

To accomplish this, I clobbered together some pretty ugly glue code to allow for this new behavior to exist within component composition, but that introduced some new and nasty bugs while also exasterbating many others.

So Wayne ~~ordered~~, directed me to kindly remedy these issues, as well as formulate a better strategy for composition as a whole.

## The Old Way

At a high level component composition comprised of a recursive function (`getChildComponent`) that followed the [composite pattern](https://en.wikipedia.org/wiki/Composite_pattern).

This function would:

1. Keep track of "global" import history w/ a `pathAncestry` variable
2. Validate a import definition exists and is valid in the given _parent_ component
3. Fetch the remote / local component and read its `zarf.yaml`
4. Merge that package's `ZarfVariable`s and `ZarfConstant`s into the main package
5. Verify the imported component's architecture (set w/ `only.cluster.architecture`) matched the main package's architecture
6. Fix all of the component's filepaths to be relative to the main package (including actions!)
7. Merge its values into the main package's component, following this [strategy](https://docs.zarf.dev/examples/composable-packages/)
8. Recursively call itself until no more imports remained
9. Perform migrations on the final composed component

One of the largest detractors from the old pattern was consistency and readability.

The parent <-> child relationship was confusing to visualize, and the recursive immediate composition made debugging annoying.

## The New Hotness

- linked list (import chain)
- separation of concerns
- debugging / visualizing
- OCI caching + fetch `zarf.yaml` before fetching the component tarball
- ease adding flavor
- preventing circular + self imports
- migrate each node in the chain

```text
component "k3s" imports "k3s" in packages/distros/k3s, which imports "k3s" in common
component "zarf-injector" imports "zarf-injector" in packages/zarf-registry
component "zarf-seed-registry" imports "zarf-seed-registry" in packages/zarf-registry
component "zarf-registry" imports "zarf-registry" in packages/zarf-registry
component "zarf-agent" imports "zarf-agent" in packages/zarf-agent
component "logging" imports "logging" in packages/logging-pgl
component "git-server" imports "git-server" in packages/gitea
```

0 comments on commit 1ee083b

Please sign in to comment.