A beginner's adventure in Charm authoring

Nate Finch nate.finch at canonical.com
Wed Sep 3 20:19:36 UTC 2014


I am working on writing a Juju charm to deploy the Discourse discussion
forum software using their new docker image install process.  This was my
first charm, and I'm writing it in Go, because I like Go.  This means I
can't use the python charm helpers, but since I don't actually know what
they do, that doesn't bother me much :)  Also, it's a good test to see how
hard it is to write the charm without the helpers.

Now that I know all the quirks, I think my second charm would be a lot
easier to write than my first.  There's just a lot to ingest for that first
charm.  However, even this first charm was not that bad.  Now, I have been
working on Juju-core for a year, so I know how a lot of stuff works that
outsiders would not.  There were still some hurdles to cross, which I
detail below, but most were just annoyances, not show stoppers.

Sorry for the length and the randomness, this is based on notes taken as I
was working on the charm in small chunks of time over several days.


I started by looking at the Charm Walkthrough... this was actually a
mistake, because that skips over some parts above it in the docs (namely
metadata.yaml, /hooks, and config.yaml)... and I thought I was starting
from the beginning and didn't see anything about those things, and so
didn't think they were documented.  This is partially my fault for not
looking through the docs more carefully, but... maybe the walkthrough
should talk about those things first? :)

Have I mentioned how much I hate YAML?  Is it possible to write the config
in JSON or something instead?  JSON's no picnic either, but at least it
doesn't care about white space.  I'd recommend TOML, but I doubt the
conservative dev-ops people would go for it.  Ideally we'd support all
three (and other formats if people wanted).

The docs on hook tools
<https://juju.ubuntu.com/docs/authors-hook-environment.html#hook-tools> is
missing one very important piece of information:  "hook tools are
executables that exist in the $PATH on the machine where the unit is
deployed" ... it took me a while to understand that these were actual
executables I could run from my hook's code and not like functions or
something from somewhere (where?).

We should document where the charm files are actually deployed on disk.  I
ended up figuring this out from one of the screenshots of charm debugging
which had the path shown, but there were times when I just wanted to ssh
into the machine and make sure the charm was deploying the stuff I thought
it was deploying.

Deploying a local charm is needlessly complex. Why do I need to create a
special directory structure, move my code under there, set --repository and
write local:<foo> and even then it has to go scanning through the
directory, looking for a charm with the right name in the metadata.yaml.
 Why can't I just say "deploy the charm in <this> directory"? e.g.   juju
deploy --local=<path>  Bam, done.

The docs says the environment variables
<https://juju.ubuntu.com/docs/authors-hook-environment.html#environment-variables>
are
"always available" except... they're not.  They're not when I SSH into the
machine.  They're not set when I do juju debug-hooks either (at least
before a hook fires).  The reason this confused me is that most of these
environment variables seem like they should be static, and could easily
just be set all the time, so I sort of assumed they were.  Now that I think
about it, they really can't be set all the time, in the case of
hulk-smashed charms, etc... but newbie charm authors won't be thinking of
that. We should make it more clear that these environment variables are
only available to the code running the hook when the hook is actively
running.

Why does the config file for juju-deploy --config need to have servicename:
 at the beginning of the file?  Of course it's for that servicename, that's
why I gave it to this deploy command.  If there's no top-level value, just
assume the whole thing is for this service.  This took me a while to figure
out... I sort of assumed the config file was just an easy shorthand so I
didn't have to type a bunch of stuff out on the command line.

It's really annoying to have to type the unit name for debug-hooks, rather
than just the service.  I don't care what unit, they're all the same,
right?  And if there's just one (which is most of the time when you're
debugging), me telling you which unit is spurious anyway... just go to the
only one that exists.  Also, juju debug-hooks says you're supposed to give
it the hook name, but it doesn't seem like that actually does anything.  I
can leave it off and it seems to have the exact same behavior.

Juju debug-hooks is really confusing:

When my install hook was broken, and I did juju debug-hooks <unit> install
....it brings me into a remote terminal prompt with zero information, no
files in the local directory, and nothing else to tell me what to do.   I
went back to look at the docs and it said I had to run juju resolved
--retry <hook>.  So I exited out of the prompt back to my local machine,
ran juju resolved --retry install and then ran juju debug-hooks <unit>
install again and... same stupid thing.  What the docs didn't make clear is
that I had to leave the debug session open, and then in a different
terminal on my local machine run juju resolved --retry install, and then...
boom, hey, look, useful information in my debug-hooks session.  It would
have been nice if something useful had been printed out there in the first
place.

Ideally, if there's only one broken hook on one broken service, all I
should need to do is type "juju debug-hooks" and have it do the right thing
(which would be the equivalent of the current juju debug-hooks <unit-name>
<hook> and then in another terminal juju resolved <hook> --retry).

The text that gets printed out when a hook starts debugging is confusing:

"You need to execute hooks manually if you want them to run for trapped
events."
What does execute them manually mean?  (I presume it means "run the
script/executable from the command prompt".... but that could be worded
better.
What the heck is a trapped event?  I presume it means "a hook that was told
to fire, but is instead triggering your debugging session".  Why call them
events here and "hook firing" everywhere else?

Juju resolved is a bad name for a command... Resolved is an adjective,
commands should be verbs that tell the computer what to do.  How about juju
resolve install or at least juju set-resolved install.  Yes, I know some
DVCS's use resolved as a command too - that doesn't make it a good idea.

....All that and I still haven't even gotten into relations at all.  Maybe
that'll come in a later revision of the charm, and another long email ;)

-Nate
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ubuntu.com/archives/juju-dev/attachments/20140903/2534e8d1/attachment.html>


More information about the Juju-dev mailing list