Running Juju on Ubuntu is a 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.
Ensure the following software components are installed on your development machine:
See Configuring for Vagrant 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 Trusty will be used.
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
Let's write a charm for GenghisApp - a single file MongoDB administration application.
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
Begin by editing the metadata.yaml file 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 # Prior to ubuntu 14.04, rubygems-integration should be replaced by rubygems on the following line apt-get install -y ruby1.9.3 rubygems-integration build-essential 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=80 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/charms local:trusty/genghisapp
Progress can be tracked with the GUI.
When the Genghis badge turns green, it is time to tunnel (VPN) 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
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 set up and our charm deployed, we can 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 issues with the Vagrant images, please file a bug report.