Skip to content

Instantly share code, notes, and snippets.

@facundobatista
Last active June 9, 2020 12:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save facundobatista/d3b7de7a624915227de051cba079e3d6 to your computer and use it in GitHub Desktop.
Save facundobatista/d3b7de7a624915227de051cba079e3d6 to your computer and use it in GitHub Desktop.

How to build a charm using modern tools

This tutorial aims to show you the steps needed to prepare a charm, starting from just the bare needed Python code and ending in the proper Juju deploy, using both Operator Framework and Charmcraft projects.

The only thing we need to start is our charm code and the metadata file. For the purposes of this tutorial, we'll go with a very simple Python code that doesn't do anything special, just log that it was installed properly, so we can see that the whole process is done.

Let's see it, will explain the code below...

#!/usr/bin/env python3

import logging

from ops.charm import CharmBase
from ops.main import main

logger = logging.getLogger(__name__)


class MyCharm(CharmBase):
    def __init__(self, *args):
        super().__init__(*args)
        self.framework.observe(self.on.install, self.on_install)

    def on_install(self, event):
        logger.info("Congratulations, the charm was properly installed!")


if __name__ == "__main__":
    main(MyCharm)

The overall structure is very simple: we have a couple imports (logging is from Python's stdlib, and ops is the Operator Framework, we'll see later how to make it available), then the logger at module level, our charm's class, and the init at the end. Note that the class inherits from CharmBase and then at the end we pass it to the framework's main: this is all we need to start using the Operator Framework.

In the charm class, after calling parent's __init__ (very important for the charm initialization), all we do is tell the framework to call our on_install method when the install event is triggered. The hooked method only logs that all succeeded.

Of course Juju also needs a metadata.yaml file with some information about our project:

name: tutocharm
summary: A charm for the tutorial.
description: A simple and basic charm to show the Operator Framework and Charmcraft in a tutorial.

So, I put that content in the respective files (and made the charm.py file executable):

$ tree .
.
├── metadata.yaml
├── requirements.txt
└── src
    └── charm.py

1 directory, 3 files

You may have spotted the requirements.txt file in that tree. It's where we can put all the Python dependencies we need. For this tutorial, we just included the Operator Framework, so the content of our requirements file is:

ops

We're ready to build our charm. For this we need the Charmcraft tool. Soon it will be ready as a snap, but for now we can use it from a virtual environment:

$ virtualenv --python=python3 env
...
$ source env/bin/activate
(env) $ pip install charmcraft
...
Successfully installed charmcraft-0.0.1

Ready to use charmcraft, then. Let's build our charm:

(env) $ charmcraft build
Done, charm left in 'tutocharm.charm'

That's all we need. The final step is deploy it, but before, in a different terminal, execute the following to see the logging we specified in the charm:

juju debug-log

Back to the original terminal, let's deploy our charm:

juju deploy ./tutocharm.charm

Wait some moments to let Juju do its magic, and at some point, in the juju debug-log terminal, a line very similar to the following one will appear:

unit-tutocharm-1: 13:26:10 INFO unit.tutocharm/1.juju-log Congratulations, the charm was properly installed!

That's all!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment