Running juju on Ubuntu is an extremely straightforward process thanks to the addition of the local provider. OS X does not support virtualization at the operating system level, however. The next best solution is to use a virtualization wrapper like Vagrant.
To start you will want to ensure you've got the following tools installed on your development machine:
Head over to the Juju Vagrant provider documentation for instructions on downloading and preparing your new virtual machine.
We will need to create a directory structure that reflects the current standard for juju charm repositories.
mkdir -p ~/vagrant/charms/trusty
Feel free to add any other LTS based target directory, for example if you were to target Precise Pangolin as a release for your charm, the command would be:
mkdir -p ~/vagrant/charms/precise
For the remainder of this tutorial, I will assume we are targeting Trusty, as it's the current LTS target of choice.
Now is a good time to fetch Charm Tools. But what are charm tools you ask?
Charm Tools offer a means for users and charm authors to create, search, fetch, update, and manage charms.
These can be installed via homebrew.
brew install charm-tools
Lets charm up GenghisApp - a single file MongoDB administration app.
cd charms/trusty charm create genghisapp -t bash
This will create a skeleton structure of a charm ready for you to edit and populate with your services deployment and orchestration logic.
├── README.ex ├── 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 └── revision
We'll start by editing the metadata.yaml to populate the information about our charm.
name: genghisapp summary: Genghisapp the single file MongoDB administration tool maintainer: Charles Butler <firstname.lastname@example.org> description: | deploys the genghisapp gem, defaults to running on port 80. No additional relations are required to speak to the MongoDB Service. All data relating to the connection is stored in the browser Local Storage engine. categories: - app subordinate: false provides: website: interface: http
Now that juju knows something about our service we're ready to start writing the hooks.
#!/bin/bash set -ex apt-get install -y ruby1.9.3 rubygems update-alternatives --set ruby /usr/bin/ruby1.9.1 update-alternatives --set gem /usr/bin/gem1.9.1 HOME=/root gem install genghisapp bson_ext --no-ri --no-rdoc
#!/bin/bash set -ex hooks/stop sleep 2 hooks/start
#!/bin/bash set -ex PORT=`config-get port` if [ ! -f /root/.vegas/genghisapp/genghisapp.pid ] ; then HOME=/root genghisapp -L -p $PORT fi open-port $PORT
#!/bin/bash set -ex HOME=/root genghisapp -K
Since vagrant is going to be our working environment, we'll want to make sure its aware of all our charms; not just the current charm we are working on.
cd ~/vagrant vagrant init JujuBox vagrant up
You now have a Juju installation ready to be used for testing your charm on OSX, and an instance of Juju-Gui to interface with your services. Validate that the GUI is accessible from http://localhost:6080
Note: The password is output in your console feedback from the juju bootstrap.
Note: All your charms in $HOME/charms are available in the /vagrant directory of our JujuBox
You'll need to enter the juju environment we just bootstrapped in $HOME/charms
vagrant ssh juju deploy mongodb juju deploy --repository=/vagrant local:trusty/genghisapp
We are now free to watch progress through the GUI
When the Genghis badge turns green, we are ready to vpn our traffic through the vagrant image and interface with the Genghis server
Note: If your local network is using 10.0.3.x you will need to alter the Juju networking in the vagrant box, and substitute the network provided in the command above
It is possible to natively route traffic from your local machine to the lxc containers running within the Vagrant virtual machine.
sudo route add -net 10.0.3.0/24 172.16.250.15
This will only work until your next reboot. Instead, there is a way to create the route when you
up your vagrant image and tear it down when you
Install the vagrant-triggers plugin:
vagrant plugin install vagrant-triggers
Add the config.trigger rules in your Vagrantfile:
config.trigger.after [:provision, :up, :reload] do system('sudo route add -net 10.0.3.0/24 172.16.250.15 >/dev/null') end config.trigger.after [:halt, :destroy] do system('sudo route delete -net 10.0.3.0/24 172.16.250.15 >/dev/null') end
Now, when you
halt your Vagrant box, the route will be handled for you.
sshuttle creates a transparent proxy server on your local machine that allows you to connect directly to the lxc containers running within the Vagrant virtual machine. This process disassembles the TCP stream locally, multiplexes it statefully over the ssh session, and reassembles the packets on the other end of the tunnel.
Ensure that you have sshuttle installed
brew install sshuttle sshuttle -r vagrant@localhost:2222 10.0.3.0/24
Note: You can skip the brew install line if you already have sshuttle installed
Note: sshuttle does not work under OS X 10.10 (Yosemite) due to the deprecation of ipfw in favor of pf.
When prompted for the password enter
Now we are free to connect to genghis. Open up the Genghis running unit list and click on the Genghis host, then click on the port 80 link in the service detail.
With vagrant fully setup, our charm deployed. We can now iterate over our charm and update/test via normal means.
- Make edits on your HOST in your favorite editor, such as TextMate, Atom, or Brackets.
- run commands inside the JujuBox vagrant environment.
juju upgrade-charm genghisapp
- view results in your HOST browser of choice.
Installing juju, for deploying to non-local environments
If you encounter any bugs with the vagrant images, please file a bug report.