First steps with the Operator Framework

While I’m more or less the primary maintainer of charm-tools, it is also co-maintained by the Kubernetes and OpenStack teams. However, in general I would say that it’s mostly in maintenance-only mode with the expectation that it will be phased out in favor of the charmcraft tool to be developed by the Charm Tech team for use with the operator framework.

New templates can be added, though, if there’s need, but I would recommend using the entry-point pattern used by the OpenStack charm templates, which can be added with a single line PR to charm-tools.

Additionally, if it’s primarily for personal use, the charm command is pluggable in the same way as juju; just name the command charm-<subcommand> instead of juju-<subcommand>. Though the plugin subcommand would need to be different from the existing subcommands, like charm create, of course.

I’m slightly hesitant about baking in a new template for k8s yet, as I don’t know if the patterns are sufficiently mature to codify yet.

Not being on the Charm Tech team, I’d defer to @jameinel but I would personally agree with this sentiment. I would even take that a bit further and say that the difference between a K8s and machine charm in the new framework would really just be down to what APIs you use and possibly what helpers you import, so having an entirely separate template (or charmcraft init option) shouldn’t really be necessary.

I think having a template as a starting point is a great thing. We’ll want to make sure we look closely at the standard templates as we discover best practices and keep the templates up to date.
I do think K8s charms tends to feel a bit different than machine charms. We’re still exploring the space, but the fact that your main point of interaction is pod.set_spec rather than the myriad of ways that you might configure a machine tend to focus the charms in a different direction. (Far more is dependent on being the leader, etc). Also as the above template points out, a common pattern is identifying the OCI resource for your pod and using it in your pod spec.

My particular concern for the exact template above is things like "you can pass something called --config to render config.yaml, but the actual syntax of what that looks like is not well clarified, and it seems to affect how other templates are rendered (each template that is rendered is passed the config map.)
There are also some minor things like “it uses os.system() for everything rather than subprocess.run()”.

I appreciate the idea of flexibility, but I’d rather have someone learn how to generate a charm layout rather than learning how to generate the config for a template to generate a charm layout. (eg, for config.yaml it seems to just include the raw content of value.juju_config, which means they need to both learn how to write everything in config.yaml and how to put that into the structure that mkc.py wants it so that it can put it into the file.)

Hi,

The gap make-k8s-charm aimed to fill was to avoid having to duplicate ~100 lines for each charm creation (which charm now mainly avoids).
All the examples I’d found previously were more advanced than what you need to just get started.
Also, when you have to manually import too much code, you end up forgetting to remove things like “YourClassNameGoesHere”.

I have a pretty simple charm to create in mind, will have a go at creating it starting with charm create, will file bug if I have suggestions !

Thanks @timClicks for the operator framework getting started…

one thing as I get started with charming via this list of instructions … is it expected that the .git/ folder is brought in with this command

charm create -t operator-python <charm>

I did this command inside an empty .git folder and then realized this was nesting a .git project within my own… my guess here is to perform the command outside of my empty project, then move the contents sans .git/ yes?

EDIT: Is there other material with this that talks about how to add say some bash related commands I want to run… do I just run them via python in the appropriate method name (ie on_install)

I first mistakenly tried adding commands to the install directly… until I noticed it seemed to not work…

#!/bin/bash

apt install libxrender1 libxtst6 libxi6

juju-log -l 'INFO' 'Dependencies installed'

curl my_setup_bundle.sh --output my_setup_bundle.sh
chmod +x my_setup_bundle.sh

juju-log -l 'INFO' 'downloaded'

# Install dependency
yes n | my_setup_bundle.sh

../src/charm.py

The template script is rather naive and doesn’t expect that you’re already within a git repository. One option is available is to delete the inner .git directory.

1 Like

As for creating a “hooks/install” and having it not called. We recently landed a patch to address this.

https://github.com/canonical/operator/pull/221
and
https://github.com/canonical/operator/pull/283

it is a little bit tricky, because ‘hooks/install’ might be a symlink to ‘src/charm.py’ or it might be a shim python script that invokes ‘src/charm.py’, etc. We believe we’ve caught all the edge cases.

With the current operator framework you need to trigger main.main() on all the hooks. You can do this with a symlink from ‘hooks/install’ (which is what I think the template does, and works with Juju 2.7 and 2.8). Or you can create a ‘dispatch’ file in your charm’s root directory and point it at src/charm.py. (Which will work with 2.8 and means we don’t need a big symlink farm.) The operator framework can handle you doing both, so if you want to get the new stuff in 2.8+ you can have both.

The current plan for evolution is to leverage dispatch as the way to make sure stuff that the charm needs are installed (similar to how the reactive framework created minimal wrappers for each hook (eg https://api.jujucharms.com/charmstore/v5/postgresql-207/archive/hooks/install)

However, if you want to have some of your charm in python, but test something in bash, you can very much create ‘dispatch’ and point it at src/charm.py, and then drop in a shell script as ‘hooks/install’. And the operator framework will exec ‘hooks/install’ and then trigger ‘on_install’ events.

I would have expected this to work, even before we landed support for it. Are you sure that ‘src/charm.py’ was marked executable?
It might be that the code that says “if invoked via ‘install’, create all the symlinks for all the other hooks” doesn’t work if you wrap it in a bash script. (it used the target of the install hook to determine what target to create for the other hooks.)

You could create them yourself, or use ‘dispatch’ instead for Juju 2.8. :slight_smile:

1 Like

Suggested edit: I believe “–classic” is required when installing charm via snap

1 Like

Is there any reason why charm config is accessed as model.config ?
juju has model and mode-config, which are totally different from charm config.

2 Likes

Totally. I have the same question. It spontaneous makes me think I’m accessing the model config.

1 Like

Is there any reason why charm config is accessed as model.config ?
juju has model and mode-config, which are totally different from charm config.

IIRC, the thinking around that is that the model object represents everything in the Juju model from the charm’s current perspective. Charms can’t directly see model-level config, only their own charm-level config, and the hook tool used to get the charm’s config is config-get, hence model.config was chosen to reflect “the config that the charm can see in the model”.

That said, I totally agree that it’s confusing. Even though a charm author might know that they can’t directly access the model-level config, they will surely be aware that it exists. And there has also been some discussion about potentially allowing the charm access to at least some subset of the model-level config. Additionally, we also have shortcuts on the CharmBase class for the charm’s app, unit, meta, and charm dir, so it seems like it would be much more natural to include a config shortcut there so that it is accessed with self.config. That would then allow for deprecating the model.config name and moving / renaming it to make it less ambiguous (model.charm_config or maybe model.app.config come to mind).

2 Likes

That makes me feel hopeful. Makes alot more sense to me and probably appeals to less experienced developers which increases adoption.

All good there.

Submitted https://github.com/canonical/operator/pull/419 if you feel like reviewing or chiming in.

1 Like

thank you! +1’ed :slight_smile:

1 Like

Thanks for the great explaination. +1 to self.config !

1 Like

The same happened to me:

$ sudo snap install charm

I get (My system is in spanish, sorry):

$ sudo snap install charm
error: Esta revisión del snap "charm" se publicó usando el confinamiento clásico por lo cual podría
       realizar cambios arbitrarios del sistema fuera de la caja de seguridad en el que los snaps
       suelen estar confinados, lo cual podría suponer un riesgo para su sistema.

       Si lo entiende y desea continuar repita la orden incluyendo --classic.

If I use the --classic option everything seems to be fine:

$ sudo snap install charm --classic
Se ha instalado charm 2.7.8 por Canonical✓

The charm snap is no longer the recommended way to get started with operator framework charms. I updated the post to describe using charmcraft instead, and worked through updating a few of the examples to be in line with the latest version of the framework, though I’ve run out of time for today to updating all of them. I hope the getting started and first few examples are enough to get you going for now, though!

(I should note that the self.config alias is available in the master branch of the framework but hasn’t been released as of 0.10.0, so you may have to change that to self.model.config for now.)

1 Like

Thank you very much @cory_fu !

Is this post the place for getting started with the operator framework now? @jameinel @cory_fu ?

@chipaca or @jldev are also good people to ask, since they are driving the Operator framework.

My understanding is that they have been working on more official docs for the framework over the last month or so, but I don’t think those have been published yet.

1 Like

@jameinel I’m about to start learning operator now, so I’m kind of curious if I should wait before there is more polished docs?

I like very much the format that timClicks started here with very clear and hands on examples for the tasks that normally are part of the development process for a charm.

Looking forward to the (more) polished docs.

1 Like