Writing a JUJU Charm
How to Write a Charm for Juju
In the previous article we knew what juju and a charm is and how to use juju for charm deployments. Let us discuss how we write a custom charm to deploy on juju.
A charm is a collection of YAML files and hook files. The yaml files contain the configurations, configurable variables, and the meta data about your charm. And the hooks files contain the scripts which actually perform the action behind the scene. These hook files can be written in any programming language which can be run through the terminal like pear, python, bash etc. There are some additional files such as README, copyright and icon files to further support your charm.
Directory Structure for charm
You need to maintain a proper directory structure for writing a charm.
sudo apt-get install charm-tools cd ~ mkdir -p charms/precise cd charms/precise
Now the charm tools plugin comes in handy and creates a dummy charm for you with all the requisite files (with dummy content)
you can see the file structure by using the
tree command. The output generated is
-- example |-- config.yaml |-- hooks | |-- config-changed | |-- install | |-- relation-name-relation-broken | |-- relation-name-relation-changed | |-- relation-name-relation-departed | |-- relation-name-relation-joined | |-- start | |-- stop | `-- upgrade-charm |-- icon.svg |-- metadata.yaml |-- README.ex
Lets have a look at each of these files separately.
This file contains the information about your charm. It will be pretty clear from the content of the file itself.
name: example summary: <Fill in summary here> maintainer: root <root@saurabh-oVirt-Node> description: | <Multi-line description here> categories: - misc subordinate: false provides: provides-relation: interface: interface-name requires: requires-relation: interface: interface-name peers: peer-relation: interface: interface-name
You can remove the parameters which are not required for your purpose.
You need to define any one category with correspondence to what your charm does/provides. These are categories considered by juju:
- databases – MySQL, PostgreSQL, CouchDB, etc.
- file-servers – storage apps such as Ceph
- applications -applications like MediaWiki, WordPress
- cache-proxy – services such as HAProxy and Varnish.
- app-servers – infrastructure services like Apache Tomcat and Jboss
- miscellaneous – anything which doesn’t neatly fit anywhere above.
This file contains the configurable variables. The author can set the default values. But once the charm is deployed the user has the capability to override the defaults which are configured in this file.
Generally User-names, Passwords, ports are defined in this file. You can define as many variables as you want to be configurable by the user.
sample content of this file:
options: string-option: type: string default: "Default Value" description: "A short description of the configuration option" boolean-option: type: boolean default: False description: "A short description of the configuration option" int-option: type: int default: 9001 description: "A short description of the configuration option"
Hook files explained
Each and every hook file must have the execute permission. when ever you create a hook file add the execute permission to that hook.
chmod +x hook_name
Each and every hook should be idempotent to each other. In a simpler word every file should be independent from each other so that executing one file should not corrupt the configuration done by any other hook files.
3. install hook
When a charm is deployed the install hook is the first file that is executed by juju. This file contains the script which are run with a privilege of root user. The aim of this script file is to download and configure the application that your juju is intended to deliver. It is highly recommended that you install the applications using the “apt”. If the application is not available in apt repository. You can modify your install hook to download the application from internet but you need to cryptographically verify that the file is not damaged or tampered.
4. config-changed hook
This is the second hook file that is executed by juju There are various instances when this file is run
- Right after the install hook. When install hook is run the state of your charm changes hence this file is run.
- when the variables in config.yaml are set by user
- when any config change happens such as upgrade or when any relation is broken.
5. start hook
This is a very simple file, it is run third in the sequence by juju when any charm is deployed. This hook contains the script to start the installed application.
sample content would be like
#!/bin/bash set -e /etc/init.d/service-daemon start
6. relation-joined hook
This hook is run when some other charm service has joined your charm service. The relation to be joined must be defined in the metadata.yaml file.
7. relation-changed hook
It is always run once, after -joined, and will subsequently be run whenever that remote unit changes its settings for the relation. It should be the only hook that relies upon remote relation settings from relation-get, and it should not error if the settings are incomplete: you can guarantee that when the remote unit changes its settings, the hook will be run again. This hook is run after the relation is joined and when the relation is destroyed. So the configuration done in this file must be idempotent and should not affect the application apart from the relation change.
8. relation-departed hook
It is run once only, when the remote unit is known to be leaving the relation; it will only run once at least one -changed has been run, and after -departed has run, no further -changes will be run. This should be used to remove all references to the remote unit, because there’s no guarantee that it’s still part of the system; it’s perfectly probable (although not guaranteed) that the system running that unit has already shut down.
9. relation-broken hook
indicates that the current relation is no longer valid, and that the charm’s software must be configured as though the relation had never existed. It will only be called after every necessary -departed hook has been run; if it’s being executed, you can be sure that no remote units are currently known locally.
10. stop hook
This hook runs when a unit is destroyed or stopped. This file contains the script to stop the service which is deployed by the charm.
We hope this post was able to explain Juju to an understandable extent, still if we left something or you want us to cover something extra please post your suggestions in the comment and we will surely take them in our consideration.