Likely useful prep work before writing charm code

It may be tempting to kickstart operator code with e.g. charmcraft init kubernetes, but we could probably move faster at first by starting slower.

The following sections describe optional steps you may choose to take.

Learn about the workload

  • Inspect official docs, compare againts existing docker-compose or helm charts.
  • Skim through the issues people are currently having (most active github issues, forum posts).
  • Find the release roadmap and see what implications the release cadence may have on LTS considerations.
  • Check if there are ready-made alert rules or dashboards for your workload. This could tell you a lot about what operators are interested in.
  • Try to deploy the vanialla workload yourself, locally, in a VM. Inspect the logs generated.
  • Pay careful attention to multiplicity - charms are all about scaling.

Come up with some design docs

Design docs are a useful reference point when considering charm behavior or new charm features in the future.

  • Document a few common deployment scenarios. This could be captured by a deployment diagram.
  • Document the lifecycle of the workload in a digestable form. This could be captured by a state diagram. Pay careful attention to what happens between state transitions.

This design information may already be available in the upstream docs, or you could contribute it upstream yourself.

Write standalone, charm-independent helper code

Sometimes, unintentionally, we end up with general purpose business logic that is tightly coupled with charm code unnecessarily. Probably the best example for this is config building.

Ideally, when we write general purpose code for charms, it should be fully decoupled from charm code and usable as an independent PyPI package, as if the upstream maintainers themselves wrote it.

Such helper code may already be available, or you could contribute it upstream yourself.

Pack a snap (VM charm) or a rock (K8s charm)

Before we can charm anything, we need to have the workload available as a snap (for VM charms; if your workload is already available as a deb from the ubuntu archive, then a snap may not be necessary) or a rock (for K8s charms; if an oci image is already available, then a rock may not be necessary).

When you write a *craft.yaml, you suddenly become more aware of operational considerations.

  • Would the snap/rock need to run on multiple platforms?
  • What should be the default config files?
  • (snap) What snap configs and plugs would we need?
  • (rock) What pebble service(s) would we need? Can you think of any general purpose pebble checks to be added at this point?
  • To reduce the scope of integration tests you would need in the charm, consider writing some integration tests at this stage. snapcraft test/rockcraft test could be used for that.

See also

5 Likes

FYI, Charm-Tech is going to try to promote this approach more from this cycle onwards (we’ve seen in in charms and agree that it’s a good approach). Our suggestion is (probably going to be) to start off with splitting off this code so that charm.py is where the Juju-specific code lives, and pretty much nothing else.

For example, if I’m charming Dovecot, then I’d have a src/dovecot.py that doesn’t import ops and has a class/functions that are purely for managing Dovecot, and a src/charm.py that imports dovecot.py and has the observing, handles connecting up various integrations, and so on.

Assuming I wrote src/dovecot.py well, and there was a need for it, then I could indeed split this off and offer it to the upstream as a management API, or put it on PyPI as one, for others to use regardless of whether they’re using Juju or not. However, I think this can definitely be a “plan that you might do this one day” rather than something to aim for initially.

What’s your opinion on Rock versus other container images for K8s charms? For example, would you say that part of being a great charm is that it uses a Rock rather than a different type of image?

I’m also curious that it seems like you’re saying that for machines a deb is equally as good as a Snap, which seems the opposite position to Rock vs non-Rock. Wouldn’t we say that great machines charms use Snaps and great K8s charms use Rocks, and debs and non-Rock images are there to be used when just starting out?

1 Like
  • Deb vs snap depends on charm author I think. Debs are slow to update, but snaps need some extra maintenance.
  • Non-rock could be ok, because currently we replace any pre-existing pebble layer so it doesn’t really matter if we use a rock or non-rock. Rocks have their own compliance and base benefits: auto cve fixes also encourage using rocks.
1 Like