Here are some notes that I’ve been collecting as my experience has grown since joining the Juju core team 2 months ago.
The first thing that I did when starting was play around with Juju as a user:
snap install --classic juju
This gave me some exposure to Juju’s terminology and concepts. It’s also been useful also in case I need to check to something works with a “known good” version while I write code and break things.
Creating a Development Environment
My personal setup (Canonical employees work remotely from home) is fairly straightforward:
- laptop (Dell XPS 15)
- VS Code
- Go 1.11
- GNU make 4.2
I found the Juju README quite helpful to get started. Luckily, Juju builds very easily via:
$ go get -d -v github.com/juju/juju/... $ make dep $ go install -v github.com/juju/juju/...
As it happens, this can be simplified further by simply running:
$ make install
You should now have a working Juju binary at
My general pattern for fixing bugs:
- Branch from the
developbranch of the Juju git repository
- Make changes to the code
- Run a few tests locally:
go test ./path/to/folder/...
- Run all unit and integration tests via Canonical’s build infrastructure for Juju. This is activated by pushing to my local branch to Github, then creating a pull request.
When developing a new feature, I often need to experiment by live testing on a LXD cluster locally:
- Bootstrap locally with LXD:
juju bootstrap localhost testing
- Deploy a minimal workload:
juju deploy wiki-simple
- Make changes to the code (often including copious logging messages!)
- Follow the unit testing steps above
- Run the following commands:
- Create a new Juju binary:
- Upload the new binary and upgrade the current system on the fly:
juju upgrade-model --build-agent
- Create a new Juju binary:
- Lower Juju’s logging levels:
juju model-config logging-config="juju.apiserver=TRACE;juju.api=TRACE;<root>=DEBUG"
- Evaluate the system by running
jujucommands with the
--show-log --logging-config="<root>=TRACE"arguments, e.g.
juju --show-log --logging-config="<root>=TRACE" status
Developing behind feature flags involves defining the flag, using it within the code base, then enabling it within the running
Speeding up local development
juju bootstrap command supports several configuration parameters, many of which are tailored for production environments. For local development, modifying the defaults can speed things up.
Turn off automatic package upgrades
By default Juju will run apt-get upgrade on machines it creates. While this is useful in production scenarios, it isn’t usually necessary for test deployments. Turning it off can greatly speed up deployments.
The relevant Juju configuration for this is:
Note that there is also a
enable-os-refresh-updateoption which you might be tempted to disable but I’ve found this normally causes more problems than it’s worth (charms fail to install).
To make use of these configuration options, add them to
juju bootstrap and
juju add-model commands as command-line arguments:
juju bootstrap --config enable-os-upgrade=false
The whole invocation can become quite convoluted with the addition of feature flags:
JUJU_DEV_FEATURE_FLAGS=mongodb-snap juju --debug bootstrap --config enable-os-upgrade=false localhost c-snap
To mitigate some of this verbosity, it’s possible to add these configuration settings to your own cloud definition. Again, from the wiki page “Faster LXD”:
Suggested Juju config for LXD deployments
Here’s a complete suggested configuration for test LXD deployments that takes into account the ideas discussed in this article (as well as turning on DEBUG logging):
logging-config: "<root>=DEBUG" enable-os-refresh-update: true enable-os-upgrade: false default-series: xenial
You can keep this in a file and pass it as the --config option to juju bootstrap and juju add-model but a more > convenient approach is to create a custom LXD cloud with these options set. A section like this in
~/.local/share/juju/clouds.yamlwill define a LXD cloud called “dev”:
clouds: dev: type: lxd config: default-series: xenial enable-os-refresh-update: true enable-os-upgrade: false logging-config: <root>=DEBUG
This can then be used like this:
juju bootstrap foo dev