105.3.3
by Michael Terry
fixups and expanded tutorial |
1 |
# Snapcraft Tutorial
|
2 |
||
3 |
Let's make a snap from scratch using Snapcraft! We'll pick something a little |
|
4 |
interesting: a webcam server. |
|
5 |
||
6 |
## Preparation
|
|
7 |
||
8 |
You'll want a webcam and a Snappy device. We'll assume you have those, |
|
9 |
but if you need help setting up a Snappy install, there is help |
|
10 |
[online](https://developer.ubuntu.com/en/snappy/start/). |
|
11 |
||
12 |
(Even if you don't have either of those, you can still follow along. You just |
|
13 |
won't be able to use the final snap package you create. But you'll get to see |
|
105.3.6
by Michael Terry
Some wording changes |
14 |
how Snapcraft works, which is still super rewarding.) |
105.3.3
by Michael Terry
fixups and expanded tutorial |
15 |
|
105.3.6
by Michael Terry
Some wording changes |
16 |
You should also install Snapcraft: |
105.3.3
by Michael Terry
fixups and expanded tutorial |
17 |
|
18 |
$ sudo add-apt-repository ppa:snappy-dev/snapcraft-daily
|
|
19 |
$ sudo apt-get update
|
|
20 |
$ sudo apt-get install snapcraft
|
|
21 |
||
22 |
## Approach
|
|
23 |
||
24 |
This example is easy because we won't be doing much of the heavy lifting |
|
25 |
ourselves. We're going to integrate a couple pieces of code together to make |
|
26 |
an interesting app. |
|
27 |
||
28 |
Namely, we'll combine a web server with a webcam program and combine |
|
29 |
them to serve a new frame every ten seconds. |
|
30 |
||
31 |
### The Web Server
|
|
32 |
||
33 |
Go has a simple web server in its standard libraries. So let's just use that. |
|
34 |
||
35 |
It's trivial to write a complete (but basic) web server in a few lines: |
|
36 |
||
37 |
package main
|
|
38 |
import "net/http"
|
|
39 |
func main() {
|
|
40 |
panic(http.ListenAndServe(":8080", http.FileServer(http.Dir("."))))
|
|
41 |
}
|
|
42 |
||
120.2.5
by Daniel Holbach
indicate what's a file and directory name |
43 |
This will serve the current directory on port `:8080`. If there is an
|
44 |
`index.html` in the current directory, it will be served. Otherwise a
|
|
45 |
directory listing will be shown. |
|
105.3.3
by Michael Terry
fixups and expanded tutorial |
46 |
|
47 |
I've provided the above code in a simple GitHub |
|
48 |
[repository](https://github.com/mikix/golang-static-http). |
|
49 |
||
50 |
### The Webcam Program
|
|
51 |
||
52 |
There is a webcam program provided in the Ubuntu archives called `fswebcam`.
|
|
53 |
It has a lot of neat features. But all we'll be needing for now is its ability |
|
54 |
to take a webcam freeze frame and drop it to a file by calling it like so: |
|
55 |
||
56 |
$ fswebcam output.jpg
|
|
57 |
||
58 |
## Snapcraft Recipe
|
|
59 |
||
60 |
OK, let's create a Snapcraft recipe that combines the above programs into a |
|
61 |
useful snap. |
|
62 |
||
63 |
Snapcraft reads a single file, `snapcraft.yaml`, which tells it how to combine
|
|
64 |
code. It contains a list of `parts`, or pieces of code, and some metadata for
|
|
65 |
the final snap it will create. But let's not worry about the metadata yet. |
|
66 |
||
67 |
### Web Server Part
|
|
68 |
||
69 |
Let's start with the web server. |
|
70 |
||
71 |
parts:
|
|
72 |
golang-static-http:
|
|
73 |
plugin: go1.4-project
|
|
74 |
source: git://github.com/mikix/golang-static-http
|
|
75 |
||
76 |
You've got a `parts` list with one item, named `golang-static-http`, but we |
|
77 |
could call it anything. That part has a few options. A `plugin` option that
|
|
78 |
tells Snapcraft how to interpret the part. In this case, it's a Go project |
|
79 |
using Go 1.4. And finally, a `source` option telling Snapcraft where to
|
|
80 |
download the code. |
|
81 |
||
82 |
Go ahead and create `snapcraft.yaml` with the above contents in an empty
|
|
83 |
directory. |
|
84 |
||
85 |
Now we can build and "stage" this recipe. Staging just means putting the output |
|
86 |
of the parts in a common folder that has the same layout as the snap we'll |
|
87 |
eventually create. It lets you look at how the snap is constructed and make |
|
88 |
sure everything is in place. |
|
89 |
||
90 |
$ snapcraft stage
|
|
91 |
||
92 |
You'll see a bunch of output, including Snapcraft downloading the Go compiler. |
|
93 |
It will use this to compile the code found on GitHub. Eventually when it is |
|
120.2.5
by Daniel Holbach
indicate what's a file and directory name |
94 |
done, you'll be able to inspect the `./stage` folder and see the web server
|
95 |
executable sitting in `./stage/bin`:
|
|
105.3.3
by Michael Terry
fixups and expanded tutorial |
96 |
|
97 |
$ ls stage/bin
|
|
98 |
golang-static-http
|
|
99 |
||
100 |
### Webcam Part
|
|
101 |
||
102 |
Now let's add the webcam program `fswebcam` to our snap. Edit `snapcraft.yaml` |
|
103 |
to look like: |
|
104 |
||
105 |
parts:
|
|
106 |
golang-static-http:
|
|
107 |
plugin: go1.4-project
|
|
108 |
source: git://github.com/mikix/golang-static-http
|
|
109 |
fswebcam:
|
|
110 |
plugin: ubuntu
|
|
111 |
||
112 |
We've added a new part called `fswebcam` handled by the `ubuntu` plugin. That |
|
113 |
plugin will include an Ubuntu package and its dependencies into your snap. It |
|
114 |
will use the name of the part as the package name to include. |
|
115 |
||
116 |
Now let's stage our recipe again. |
|
117 |
||
118 |
$ snapcraft stage
|
|
119 |
||
120.2.5
by Daniel Holbach
indicate what's a file and directory name |
120 |
You'll note that Snapcraft skipped downloading and building |
121 |
`golang-static-htpp` again because it knew it had already done so.
|
|
105.3.3
by Michael Terry
fixups and expanded tutorial |
122 |
|
123 |
You'll also see Snapcraft downloading and unpacking all the Ubuntu packages |
|
120.2.5
by Daniel Holbach
indicate what's a file and directory name |
124 |
into your snap. If you look at `./stage`, you'll see a lot more files now:
|
105.3.3
by Michael Terry
fixups and expanded tutorial |
125 |
|
126 |
$ ls stage
|
|
127 |
bin etc lib usr var
|
|
128 |
||
129 |
### Gluing the Parts Together
|
|
130 |
||
131 |
OK, so we have the two programs in our staging area. But how do we make them |
|
132 |
work together? |
|
133 |
||
134 |
We'll write a tiny little script that runs the server and `fswebcam` together:
|
|
135 |
||
136 |
#!/bin/sh
|
|
137 |
set -e
|
|
138 |
||
139 |
cd "$SNAPP_APP_DATA_PATH" |
|
140 |
||
141 |
golang-static-http &
|
|
142 |
||
143 |
while :; do |
|
144 |
fswebcam shot.jpeg |
|
145 |
sleep 10 |
|
146 |
done |
|
147 |
||
148 |
Save the above as `webcam-webui` and make it executable:
|
|
149 |
||
150 |
$ chmod a+x webcam-webui
|
|
151 |
||
152 |
Alright, let's put this script in our snap too: |
|
153 |
||
154 |
parts:
|
|
155 |
golang-static-http:
|
|
156 |
plugin: go1.4-project
|
|
157 |
source: git://github.com/mikix/golang-static-http
|
|
158 |
fswebcam:
|
|
159 |
plugin: ubuntu
|
|
160 |
glue:
|
|
161 |
plugin: copy
|
|
162 |
files:
|
|
163 |
webcam-webui: bin/webcam-webui
|
|
164 |
||
165 |
The `copy` plugin takes a list of files to just directly copy without building
|
|
166 |
or downloading anything. In this case, we just want to put our glue script in |
|
120.2.5
by Daniel Holbach
indicate what's a file and directory name |
167 |
the `bin/` directory.
|
105.3.3
by Michael Terry
fixups and expanded tutorial |
168 |
|
169 |
If we run Snapcraft again, we won't be surprised: |
|
170 |
||
171 |
$ snapcraft stage
|
|
172 |
||
173 |
We should now see both the web server and our script in stage/bin (the webcam |
|
174 |
program is in stage/usr/bin since it came from Ubuntu): |
|
175 |
||
176 |
$ ls stage/bin
|
|
177 |
golang-static-http webcam-webui
|
|
178 |
||
179 |
### Package Metadata
|
|
180 |
||
181 |
"But how do we actually make a snap?", you may be wondering. To do that, we |
|
182 |
need some metadata files required by Snappy that describe how our code should |
|
183 |
be installed and run. |
|
184 |
||
185 |
You can read all about the [format of this metadata](https://developer.ubuntu.com/en/snappy/guides/packaging-format-apps/), |
|
186 |
but we'll assume here that you're already familiar. |
|
187 |
||
188 |
Let's make a new subdirectory called `meta` and put our Snappy package files
|
|
189 |
there. Here's the contents of `meta/package.yaml`:
|
|
190 |
||
191 |
name: webcam-webui
|
|
192 |
version: 1
|
|
193 |
vendor: You <you@example.com>
|
|
194 |
services:
|
|
195 |
- name: webcam-webui
|
|
196 |
start: bin/webcam-webui
|
|
197 |
||
198 |
And a very simple `meta/readme.md`:
|
|
199 |
||
200 |
# Webcam web UI
|
|
201 |
||
202 |
Exposes your webcam over a web UI |
|
203 |
||
204 |
Now that we have that sorted, we can tell Snapcraft where to find our metadata: |
|
205 |
||
206 |
parts:
|
|
207 |
golang-static-http:
|
|
208 |
plugin: go1.4-project
|
|
209 |
source: git://github.com/mikix/golang-static-http
|
|
210 |
fswebcam:
|
|
211 |
plugin: ubuntu
|
|
212 |
glue:
|
|
213 |
plugin: copy
|
|
214 |
files:
|
|
215 |
webcam-webui: bin/webcam-webui
|
|
216 |
snappy-metadata: meta
|
|
217 |
||
218 |
And tell Snapcraft to actually make the snap package: |
|
219 |
||
220 |
$ snapcraft assemble
|
|
221 |
||
222 |
You should now have a `webcam-webui_1_amd64.snap` file sitting in your
|
|
223 |
directory (assuming you are running on amd64). Congratulations! |
|
120.1.1
by Daniel Holbach
add some next steps |
224 |
|
225 |
||
226 |
## Next steps
|
|
227 |
||
228 |
Well done, your first snap using snapcraft is ready. If you want to check out |
|
229 |
a few examples for reference or to get inspired, have a look at the |
|
230 |
`examples` directory in the source directory of snapcraft:
|
|
231 |
||
232 |
bzr branch lp:snapcraft
|
|
233 |
cd snapcraft/examples
|
|
234 |
||
235 |
In `examples/` you can find a diverse set of examples which should help you
|
|
236 |
get started on your own projects. |
|
237 |
||
238 |
If you should have any more questions, ask us on |
|
239 |
||
240 |
* `#snappy` on `irc.freenode.net` or |
|
241 |
* the [snappy-app-devel](https://lists.ubuntu.com/mailman/listinfo/snappy-app-devel) |
|
242 |
mailing list |
|
243 |