on
Writing a Snappy application
So, having ingested all the information about Ubuntu Snappy Core, we can start developing our first application.
The platform
Ubuntu Snappy Core can currently be run on several platforms:
Fortunately, I have a Raspberry Pi 2 in a nice orange enclosure that I can use for my purposes.
Prerequisites
Before starting our favorite editor, we need to install some tools to develop a snappy application.
$ sudo add-apt-repository ppa:snappy-dev/tools
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install snappy-tools bzr
The code
I’ve put the code of this Snappy application on github, so ideally it should be easy to follow along.
The structure of a snappy application is rather simple.
├── Makefile
├── meta
│ ├── package.yaml
│ └── readme.md
├── README.md
└── src
└── main.go
If we ignore the Makefile
, and README.md
, it’s just three files.
The code itself is simple - it’s a golang application, using an excellent go package to turn on and off lights on a piglow device over i2c.
The meta
folder contains information describing the application: readme.md
(it’s required) for humans and package.yaml
for snappy.
name: blink
version: 1.0.0
vendor: Domas Monkus <domas.monkus@canonical.com>
services:
- name: blinker
description: blinker
start: bin/blink
name
, version
and vendor
are pretty much self-explanatory. services
is a bit more interesting. A snappy application
can either start a service or expose a binary (for other applications to use). Since I don’t want to have to ssh into my raspberry-pi to turn the
blinking lights on, I’m going to expose a service that will automatically be started. There’s a lot more metadata that can be provided for a service
(this is the absolute minimum) - please check out the documentation for more information.
Building and deploying
There’s two steps needed to create a snappy package in this case:
- Build the application binary.
- Create the snappy package.
To build the binary, we’re going to use go 1.5 cross-compilation capabilities (because raspberry pi2 is ARM):
$ env GOOS=linux GOARCH=arm go build -o bin/blink src/main.go
To build the snappy package, we’ll just run:
snappy build .
in the package directory.
After this is done, you should see a file blink_1.0.0_all.snap
in the directory.
To deploy it, we’re going to run a command:
snappy-remote --url=ssh://[IP-ADDRESS-of-RPi2]:22 install blink_1.0.0_all.snap
Oh-oh
We built the executable, the package, sent it over to the raspberry pi, but the lights are not blinking!
Well, that is because the application does not have access permissions to the i2c device. Fortunately, that’s easy to fix, we’ll just have to ssh into our orange matchbox:
$ ssh ubuntu@orangebox
...
$ sudo snappy hw-assign blink.sideload /dev/i2c-1
This will create a udev rule that adds access permissions to the cgroup specific to our application. The only downside is that the aplication has to be restarted for this to take effect. Yuck.
Let’s just do it:
$ ls /etc/systemd/system
blink_blinker_IDLRVAUReHSd.service [...]
$ sudo systemctl restart blink_blinker_IDLRVAUReHSd.service
Yay!
Update
My repository now contains a modified version of the snappy blinker, that changes the color based on the status of the juju master branch. Not completely useful yet, but not useless either.