Skip to content

Commit

Permalink
Share k8s worker and control-plane charms (#11)
Browse files Browse the repository at this point in the history
* Share k8s worker and control-plane charms

* linting issues

* adjust path to working charm directory

* Adjust integration tests to new directory structure

* Apply linting fix

* If the charm is reconciled, and an update status hook runs, we should catch ReconcilerErrors

* Add tag-prefix argument to publish-to-edge job

* prepare for workers joining the cluster

* Use tokens interface to share clustering credentials to workers

* charm names are in charmcraft.yaml, not metadata.yaml

* Review comment

* Update peers relation definition in charmcraft.yaml

* worker charm needs git package to build

* Successfully ran integration tests locally

* LXD profile for kubernetes-workers

* Unit base charm tests with is_worker flag parameterized

* Rename interface used to cluster workers

* Wait for microcluster before joining nodes

* Adjust k8s override-prime for rebuild-ability

* Flip the heirarchy so that k8s is the inner charm
  • Loading branch information
addyess authored Feb 5, 2024
1 parent fdc58b6 commit 9a4556f
Show file tree
Hide file tree
Showing 39 changed files with 378 additions and 370 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/auto-update-libs-k8s-worker.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Auto-update K8s-worker charm libraries
name: Auto-update K8s charm libraries

on:
schedule:
Expand All @@ -9,4 +9,4 @@ jobs:
uses: canonical/operator-workflows/.github/workflows/auto_update_charm_libs.yaml@main
secrets: inherit
with:
working-directory: ./charms/k8s-worker/
working-directory: ./charms/worker/k8s
12 changes: 0 additions & 12 deletions .github/workflows/auto-update-libs-k8s.yaml

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/build-charm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- uses: canonical/setup-lxd@v0.1.1
- name: Extract charm name
working-directory: ${{ inputs.working-directory }}
run: echo "CHARM_NAME=$([ -f metadata.yaml ] && yq '.name' metadata.yaml || echo UNKNOWN)" >> $GITHUB_ENV
run: echo "CHARM_NAME=$([ -f charmcraft.yaml ] && yq '.name' charmcraft.yaml || echo UNKNOWN)" >> $GITHUB_ENV
- name: Pack charm
if: ${{ env.CHARM_NAME != 'UNKNOWN' && !cancelled() }}
working-directory: ${{ inputs.working-directory }}/${{ matrix.path }}
Expand All @@ -34,7 +34,7 @@ jobs:
echo "CHARM_FILE=$(ls ${{env.CHARM_NAME}}_*.charm)" >> $GITHUB_ENV
- name: Upload charm artifact
if: ${{ env.CHARM_FILE != '' && !cancelled() }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ env.CHARM_NAME }}-charm
path: ${{ inputs.working-directory }}/${{ env.CHARM_FILE }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/integration_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ jobs:
strategy:
matrix:
path:
- "./charms/k8s/"
- "./charms/k8s-worker/"
- "./charms/worker/k8s/"
- "./charms/worker/"
uses: ./.github/workflows/build-charm.yaml
with:
working-directory: ${{ matrix.path }}
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/publish-k8s-worker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ jobs:
secrets: inherit
with:
channel: latest/edge
working-directory: ./charms/k8s-worker/
working-directory: ./charms/worker/k8s/
tag-prefix: k8s-worker
3 changes: 2 additions & 1 deletion .github/workflows/publish-k8s.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ jobs:
secrets: inherit
with:
channel: latest/edge
working-directory: ./charms/k8s/
working-directory: ./charms/k8s/
tag-prefix: k8s
12 changes: 0 additions & 12 deletions .github/workflows/tests-k8s-worker.yaml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/tests-k8s.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ jobs:
secrets: inherit
with:
self-hosted-runner: false
working-directory: ./charms/k8s/
working-directory: ./charms/worker/k8s/
69 changes: 69 additions & 0 deletions charms/CONTRIBUTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Contributing

## Structure of the charms

The `k8s` and `k8s-worker` charms are noticeably tucked into one-another.

```
└── worker
├── charmcraft.yaml
├── requirements.txt
└── k8s
├── charmcraft.yaml
├── lib
│ └── charms/...
├── requirements.txt
└── src
└── charm.py
```

While unfamiliar to some charm developers, this lets both charms share the exact same `src` folder. This is accomplished by using the `parts.charm.charm-entrypoint` value in the `worker` directory set to `k8s/src/charm.py`.

### What's unique

The unique parts of the charm are what are in each charm's top-level directory:

```
charmcraft.yaml
config.yaml
actions.yaml
metadata.yaml
requirements.yaml
```

In order to exclude the `k8s` exclusive components from the `k8s-worker` charm, charmcraft will read the `worker/.jujuignore` file to determine what to leave out of the final charm.

### What's not

The shared portions of each charm are within `worker/k8s` (except for the above mentioned exclusions). This includes shared libraries from `worker/k8s/lib`, shared source from `worker/k8s/src`, shared python dependencies from `worker/k8s/requirements.txt`

### How to distinguish which charm code should engage

The charm can distinguish whether it's a `control-plane` or `worker` unit by using `self.is_worker` or `self.is_control_plane` by querying its metadata.

### Why two charms?

Much of the charm's behavior will be identical. They will employ many of the same relations, many of the same resources, configure the same snap, and use many of the same configuration options. One might therefore assume the two should be 1 charm. History with Charmed Kubernetes has proven that having 2 charms split between control-plane and worker has advantages when a relation is split across `requires` and `provides`.

### Why not use a charm library?

Sharing code between a charm library is a really reasonable idea, there are limitations that a charm library presents:
* limited to a single file
* PRs where the library changes doesn't reflect in the secondary charm
* updating a second charm isn't immediate
- must upload to charmhub, then download into the secondary charms

### How to use two charms in the same code base:

In cases where the charms should diverge the behavior, use a runtime switch to make the decision

```python
if self.is_control_plane:
# do control-plane only thing
...
# do more common things
...
if self.is_worker:
# do worker only thing
...
```
13 changes: 0 additions & 13 deletions charms/k8s-worker/charmcraft.yaml

This file was deleted.

27 changes: 0 additions & 27 deletions charms/k8s-worker/metadata.yaml

This file was deleted.

1 change: 0 additions & 1 deletion charms/k8s-worker/requirements.txt

This file was deleted.

49 changes: 0 additions & 49 deletions charms/k8s-worker/src/charm.py

This file was deleted.

33 changes: 0 additions & 33 deletions charms/k8s-worker/tests/unit/test_base.py

This file was deleted.

Loading

0 comments on commit 9a4556f

Please sign in to comment.