Tag : snap

post image

How to create a snap for timg with snapcraft on Ubuntu

In this post we are going to see how to create a snap for a utility called timg. If this is the very first time you heard about snap installation packages, see How to create your first snap.

Today we learn the following items about creating snaps with snapcraft,

  • the source of timg comes with a handmade Makefile, and requires to tinker a bit the make plugin parameters.
  • the program is written in C and requires a couple of external libraries. We make sure their relevant code has been added to the snap.
  • should we select strict confinement or classic confinement? We discuss how to choose between these two.

So, what does this timg do?

Background

The Linux terminal emulators have become quite cool and they have colors!

Apart from the standard colors, most terminal emulators (like the GNOME Terminal depicted above) support true color (16 million colors!).

Yes! True color in the terminal emulators! Get the AWK code from the page True Colour (16 million colours) support in various terminal applications and terminals
and test it yourself. You may notice in the code that it uses some escape sequences to specify the RGB value (256*256*256 ~= 16 million colors).

What is timg?

Alright, back to the point of the post. What does timg do? Well, it takes an image as input and resizes it down to the character dimensions of your terminal window (for example, 80×25). And shows the image in color, just by using characters in color, in whatever resolution the terminal window is in!

This one is the Ubuntu logo, a PNG image file, shown as colored block characters.

And here is a flower, by @Doug8888.

timg would be especially helpful if you are connecting remotely to your server, minding your own business, and want to see what an image file looks like. Bam!

Apart from static images, timg can also display animated gifs! Let’s start snapping!

Getting familiar with the timg source

The source of timg can be found at https://github.com/hzeller/timg Let’s try to compile it manually in order to get an idea what requirements it may have.

The Makefile is in the src/ subdirectory and not in the root directory of the project. At the github page they say to install these two development packages (GraphicsMagic++, WebP) and then make would simply work and generate the executable. In the screenshot I show for brevity that I have them already installed (after I read the Readme.md file about this).

Therefore, four mental notes when authoring the snapcraft.yaml file:

  1. The Makefile is in a subdirectory, src/, and not in the root directory of the project.
  2. The program requires two development libraries in order to compile.
  3. In order for timg to run as a snap, we need to somehow bundle these two libraries inside the snap (or link them statically).
  4. timg is written in C++ and requires g++. Let’s instruct the snapcraft.yaml file to check that the build-essential metapackage is installed before compiling.

Starting off with snapcraft

Let’s create a directory timg-snap/, and run snapcraft init in there in order to create a skeleton snapcraft.yaml to work on.

ubuntu@snaps:~$ mkdir timg-snap
ubuntu@snaps:~$ cd timg-snap/
ubuntu@snaps:~/timg-snap$ snapcraft init
Created snap/snapcraft.yaml.
Edit the file to your liking or run `snapcraft` to get started
ubuntu@snaps:~/timg-snap$ cat snap/snapcraft.yaml 
name: my-snap-name # you probably want to 'snapcraft register <name>'
version: '0.1' # just for humans, typically '1.2+git' or '1.3.2'
summary: Single-line elevator pitch for your amazing snap # 79 char long summary
description: |
  This is my-snap's description. You have a paragraph or two to tell the
  most important story about your snap. Keep it under 100 words though,
  we live in tweetspace and your description wants to look good in the snap
  store.

grade: devel # must be 'stable' to release into candidate/stable channels
confinement: devmode # use 'strict' once you have the right plugs and slots

parts:
  my-part:
    # See 'snapcraft plugins'
    plugin: nil

Filling in the metadata

The upper part of a snapcraft.yaml configuration file is the metadata. We fill them in in one go, and they are the easy part. The metadata consist of the following fields

  1. name, the name of the snap as it will be known publicly at the Ubuntu Store.
  2. version, the version of the snap. Can be an appropriate branch or tag in the source code repository, or the current date if no branch or tag exist.
  3. summary, a short description under 80 characters.
  4. description, a bit longer description, under 100 words.
  5. grade, either stable or devel. We want to release the snap in the stable channel of the Ubuntu Store. We make sure the snap works, and write stable here.
  6. confinement, initially we put devmode so as not to restrict the snap in any way. Once it works as devmode, we later consider whether to select strict or classic confinement.

For the name, we are going to use timg,

ubuntu@snaps:~/timg-snap$ snapcraft register timg
Registering timg.
You already own the name 'timg'.

Yeah, I registered the name the other day :-).

Next, which version of timg?

When we look for a branch or a tag in the repository, we find that there is a v0.9.5 tag, with the latest commit in 27th Jun 2016.

However, in the main branch (master) there are two commits that look significant. Therefore, instead of using tag v0.9.5, we are snapping the master branch. We are using today’s date as the version, 20170226.

We glean the summary and description from the repository. Therefore, the summary is A terminal image viewer, and the description is A viewer that uses 24-Bit color capabilities and unicode character blocks to display images in the terminal.

Finally, the grade will be stable and the confinement will be devmode (initially, until the snap actually works).

Here is the updated snapcraft.yaml with the completed metadata section:

ubuntu@snaps:~/timg-snap$ cat snap/snapcraft.yaml 
name: timg
version: '20170226'
summary: A terminal image viewer
description: |
  A viewer that uses 24-Bit color capabilities and unicode character blocks 
  to display images in the terminal.
 
grade: stable 
confinement: devmode

parts:
  my-part:
    # See 'snapcraft plugins'
    plugin: nil

Figuring out the “parts:”

This is the moment where we want to replace the stub parts: section shown above with a real parts:.

We know the URL to the git repository and we have seen that there is an existing Makefile. The existing Makefile commands for the make Snapcraft plugin. As the documentation says, This plugin always runs ‘make’ followed by ‘make install’. In order to identify the make plugin, we went through the list of available Snapcraft plugins.

Therefore, we initially change from the stub

parts:
  my-part:
    # See 'snapcraft plugins'
    plugin: nil

to

parts:
  timg:
    source: https://github.com/hzeller/timg.git
    plugin: make

Here is the current snapcraft.yaml,

name: timg
version: '20170226'
summary: A terminal image viewer
description: |
  A viewer that uses 24-Bit color capabilities and unicode character blocks 
  to display images in the terminal.
 
grade: stable 
confinement: devmode

parts:
  timg:
    source: https://github.com/hzeller/timg.git
    plugin: make

Let’s run the snapcraft prime command and see what happens!

ubuntu@snaps:~/timg-snap$ snapcraft prime
Preparing to pull timg 
Pulling timg 
Cloning into '/home/ubuntu/timg-snap/parts/timg/src'...
remote: Counting objects: 144, done.
remote: Total 144 (delta 0), reused 0 (delta 0), pack-reused 144
Receiving objects: 100% (144/144), 116.00 KiB | 0 bytes/s, done.
Resolving deltas: 100% (89/89), done.
Checking connectivity... done.
Preparing to build timg 
Building timg 
make -j4
make: *** No targets specified and no makefile found.  Stop.
Command '['/bin/sh', '/tmp/tmpem97fh9d', 'make', '-j4']' returned non-zero exit status 2
ubuntu@snaps:~/timg-snap$

snapcraft could not find a Makefile in the source and as we hinted earlier, the Makefile is only located inside the src/ subdirectory. Can we instruct snapcraft to look into src/ of the source for the Makefile?

Each snapcraft plugin has its own options, and there are general shared options that relate to all plugins. In this case, we want to look into the snapcraft options relating to the source code. Here we go,

 

  • source-subdir: pathSnapcraft will checkout the repository or unpack the archive referred to by the source keyword into parts/<part-name>/src/ but it will only copy the specified subdirectory into parts/<part-name>/build/

We have the appropriate option, let’s update the parts:

parts:
  timg:
    source: https://github.com/hzeller/timg.git
    source-subdir: src
    plugin: make

And run snapcraft again!

ubuntu@snaps:~/timg-snap$ snapcraft prime 
The 'pull' step of 'timg' is out of date:

The 'source-subdir' part property appears to have changed.

Please clean that part's 'pull' step in order to continue
ubuntu@snaps:~/timg-snap$ snapcraft clean
Cleaning up priming area
Cleaning up staging area
Cleaning up parts directory
ubuntu@snaps:~/timg-snap$ snapcraft prime 
Skipping pull timg (already ran)
Preparing to build timg 
Building timg 
make -j4
g++ `GraphicsMagick++-config --cppflags --cxxflags` -Wall -O3 -fPIC -c -o timg.o timg.cc
g++ -Wall -O3 -fPIC   -c -o terminal-canvas.o terminal-canvas.cc
/bin/sh: 1: GraphicsMagick++-config: not found
timg.cc:33:22: fatal error: Magick++.h: No such file or directory
compilation terminated.
Makefile:10: recipe for target 'timg.o' failed
make: *** [timg.o] Error 1
make: *** Waiting for unfinished jobs....
Command '['/bin/sh', '/tmp/tmpeeyxj5kw', 'make', '-j4']' returned non-zero exit status 2
ubuntu@snaps:~/timg-snap$

Here it tells us that it cannot find the development library GraphicsMagick++. According to the Snapcraft common keywords, we need to specify this development library so that Snapcraft can install it:

 

  • build-packages: [deb, deb, deb…]A list of Ubuntu packages to install on the build host before building the part. The files from these packages typically will not go into the final snap unless they contain libraries that are direct dependencies of binaries within the snap (in which case they’ll be discovered via ldd), or they are explicitly described in stage-packages.

Therefore, let’s find the name of the development package,

ubuntu@snaps:~/timg-snap$ apt-cache search graphicsmagick++ | grep dev
graphicsmagick-libmagick-dev-compat/xenial 1.3.23-1build1 all
libgraphicsmagick++1-dev/xenial 1.3.23-1build1 amd64
  format-independent image processing - C++ development files
libgraphicsmagick1-dev/xenial 1.3.23-1build1 amd64
  format-independent image processing - C development files
ubuntu@snaps:~/timg-snap$

The package name is a lib + graphicsmagick++ and ends with -dev. We got it! Here is the updated parts:

parts:
  timg:
    source: https://github.com/hzeller/timg.git
    source-subdir: src
    plugin: make
    build-packages: 
      - libgraphicsmagick++1-dev

Let’s run snapcraft prime again!

ubuntu@snaps:~/timg-snap$ snapcraft 
Installing build dependencies: libgraphicsmagick++1-dev
[...]
The following NEW packages will be installed:
  libgraphicsmagick++-q16-12 libgraphicsmagick++1-dev libgraphicsmagick-q16-3
  libgraphicsmagick1-dev libwebp5
[...]
Building timg 
make -j4
g++ `GraphicsMagick++-config --cppflags --cxxflags` -Wall -O3 -fPIC -c -o timg.o timg.cc
g++ -Wall -O3 -fPIC   -c -o terminal-canvas.o terminal-canvas.cc
g++ -o timg timg.o terminal-canvas.o `GraphicsMagick++-config --ldflags --libs`
/usr/bin/ld: cannot find -lwebp
collect2: error: ld returned 1 exit status
Makefile:7: recipe for target 'timg' failed
make: *** [timg] Error 1
Command '['/bin/sh', '/tmp/tmptma45jzl', 'make', '-j4']' returned non-zero exit status 2
ubuntu@snaps:~/timg-snap$

Simply by specifying the development library libgraphicsmagick++1-dev, Ubuntu also installs the code libraries, including libgraphicsmagick++-q16-12, along with the (dynamic) code library libwebp.

We still got an error, and the error is related to the webp library. The development version of the webp library (a static library) is missing. Let’s find it!

ubuntu@snaps:~/timg-snap$ apt-cache search libwebp | grep dev
libwebp-dev - Lossy compression of digital photographic images.
ubuntu@snaps:~/timg-snap$

Bingo! The libwebp5 package that was installed further up, provides only a dynamic (.so) library. By requiring the libwebp-dev package, we get the static (.a) library as well. Let’s update the parts: section!

parts:
  timg:
    source: https://github.com/hzeller/timg.git
    source-subdir: src
    plugin: make
    build-packages:
      - libgraphicsmagick++1-dev
      - libwebp-dev

Here is the updated snapcraft.yaml file,

name: timg
version: '20170226'
summary: A terminal image viewer
description: |
  A viewer that uses 24-Bit color capabilities and unicode character blocks 
  to display images in the terminal.
 
grade: stable 
confinement: devmode

parts:
  timg:
    source: https://github.com/hzeller/timg.git
    source-subdir: src
    plugin: make
    build-packages: 
      - libgraphicsmagick++1-dev
      - libwebp-dev

Let’s run snapcraft!

ubuntu@snaps:~/timg-snap$ snapcraft prime
Skipping pull timg (already ran)
Preparing to build timg 
Building timg 
make -j4
g++ `GraphicsMagick++-config --cppflags --cxxflags` -Wall -O3 -fPIC -c -o timg.o timg.cc
g++ -Wall -O3 -fPIC   -c -o terminal-canvas.o terminal-canvas.cc
g++ -o timg timg.o terminal-canvas.o `GraphicsMagick++-config --ldflags --libs`
make install DESTDIR=/home/ubuntu/timg-snap/parts/timg/install
install timg /usr/local/bin
install: cannot create regular file '/usr/local/bin/timg': Permission denied
Makefile:13: recipe for target 'install' failed
make: *** [install] Error 1
Command '['/bin/sh', '/tmp/tmptq_s1itc', 'make', 'install', 'DESTDIR=/home/ubuntu/timg-snap/parts/timg/install']' returned non-zero exit status 2
ubuntu@snaps:~/timg-snap$

We have a new problem. The Makefile was hand-crafted and does not obey the parameters of the Snapcraft make plugin to install into the prime/ directory. The Makefile tries to install in /usr/local/bin/ !

We need to instruct the Snapcraft make plugin not to run make install but instead pick the generated executable timg and place it into the prime/ directory. According to the documentation,

- artifacts:
 (list)
 Link/copy the given files from the make output to the snap
 installation directory. If specified, the 'make install'
 step will be skipped.

So, we need to put something in artifacts:. But what?

ubuntu@snaps:~/timg-snap/parts/timg$ ls build/src/
Makefile            terminal-canvas.h  timg*     timg.o
terminal-canvas.cc  terminal-canvas.o  timg.cc
ubuntu@snaps:~/timg-snap/parts/timg$

In the build/ subdirectory we can find the make output. Since we specified source-subdir: src, our base directory for artifacts: is build/src/. And in there we can find the executable timg, which will be the parameter for artifacts:. With artifacts: we specify the files from the make output that will be copied to the snap installation directory (in prime/).

Here is the updated parts: of snapcraft.yaml,

parts:
  timg:
    source: https://github.com/hzeller/timg.git
    source-subdir: src
    plugin: make
    build-packages: 
      - libgraphicsmagick++1-dev
      - libwebp-dev
    artifacts: [timg]

Let’s run snapcraft prime!

ubuntu@snaps:~/timg-snap$ snapcraft prime
Preparing to pull timg 
Pulling timg 
Cloning into '/home/ubuntu/timg-snap/parts/timg/src'...
remote: Counting objects: 144, done.
remote: Total 144 (delta 0), reused 0 (delta 0), pack-reused 144
Receiving objects: 100% (144/144), 116.00 KiB | 207.00 KiB/s, done.
Resolving deltas: 100% (89/89), done.
Checking connectivity... done.
Preparing to build timg 
Building timg 
make -j4
g++ `GraphicsMagick++-config --cppflags --cxxflags` -Wall -O3 -fPIC -c -o timg.o timg.cc
g++ -Wall -O3 -fPIC   -c -o terminal-canvas.o terminal-canvas.cc
g++ -o timg timg.o terminal-canvas.o `GraphicsMagick++-config --ldflags --libs`
Staging timg 
Priming timg 
ubuntu@snaps:~/timg-snap$

We are rolling!

Exposing the command

Up to now, snapcraft generated the executable but did not expose a command for the users to run. We need to expose a command and this is done in the apps: section.

First of all, where is the command located in the prime/ subdirectory?

ubuntu@snaps:~/timg-snap$ ls prime/
meta/  snap/  timg*  usr/
ubuntu@snaps:~/timg-snap$

It is in the root of the prime/ subdirectory. We are ready to add the apps: section in snapcraft.yaml,

ubuntu@snaps:~/timg-snap$ cat snap/snapcraft.yaml 
name: timg
version: '20170226'
summary: A terminal image viewer
description: |
  A viewer that uses 24-Bit color capabilities and unicode character blocks 
  to display images in the terminal.
 
grade: stable 
confinement: devmode

apps:
  timg: 
    command: timg

parts:
  timg:
    source: https://github.com/hzeller/timg.git
    source-subdir: src
    plugin: make
    build-packages: 
      - libgraphicsmagick++1-dev
      - libwebp-dev
    artifacts: [timg]

Let’s run snapcraft prime again and then try the snap!

ubuntu@snaps:~/timg-snap$ snapcraft prime 
Skipping pull timg (already ran)
Skipping build timg (already ran)
Skipping stage timg (already ran)
Skipping prime timg (already ran)
ubuntu@snaps:~/timg-snap$ snap try --devmode prime/
timg 20170226 mounted from /home/ubuntu/timg-snap/prime
ubuntu@snaps:~/timg-snap$

Image source: https://www.flickr.com/photos/mustangjoe/6091603784/

We used snap try –devmode prime/ as a way to enable the snap and try the command. It is an efficient way for testing and avoids the alternative of generating .snap files, installing them, then uninstalling them. With snap try prime/, it uses directly the directory (in this case, prime/) which has the snap content.

Restricting the snap

Up to now, the snap has been running in devmode (developer mode), which is unrestricted. Let’s see how it runs in a confinement,

ubuntu@snaps:~/timg-snap$ snap list
Name           Version   Rev   Developer  Notes
core           16-2      1337  canonical  -
timg           20170226  x1               devmode,try
ubuntu@snaps:~/timg-snap$ snap try --jailmode prime
timg 20170226 mounted from /home/ubuntu/timg-snap/prime
ubuntu@snaps:~/timg-snap$ snap list
Name           Version   Rev   Developer  Notes
core           16-2      1337  canonical  -
timg           20170226  x2               jailmode,try
ubuntu@snaps:~/timg-snap$ timg pexels-photo-149813.jpeg 
Trouble loading pexels-photo-149813.jpeg (Magick: Unable to open file (pexels-photo-149813.jpeg) reported by magick/blob.c:2828 (OpenBlob))
ubuntu@snaps:~/timg-snap$

Here we quickly switch from devmode to jailmode (confinement: strict) without having to touch the snapcraft.yaml file. As expected, timg could not read the image because we did not permit any access to the filesystem.

At this stage we need to make a decision. With jailmode, we can easily specify that a command has access to the files of the user’s $HOME directory, and only there. If an image file is located elsewhere, we can always copy of the $HOME directory and run timg on the copy in $HOME. If we are happy with this, we can set up snapcraft.yaml as follows:

name: timg
version: '20170226'
summary: A terminal image viewer
description: |
  A viewer that uses 24-Bit color capabilities and unicode character blocks 
  to display images in the terminal.
 
grade: stable 
confinement: strict

apps:
  timg: 
    command: timg
    plugs: [home]

parts:
  timg:
    source: https://github.com/hzeller/timg.git
    source-subdir: src
    plugin: make
    build-packages: 
      - libgraphicsmagick++1-dev
      - libwebp-dev
    artifacts: [timg]

On the other hand, if we want the timg snap to have read-access to all the filesystem, we can use confinement: classic and be done with it. Here is how snapcraft.yaml would look in that case,

name: timg
version: '20170226'
summary: A terminal image viewer
description: |
  A viewer that uses 24-Bit color capabilities and unicode character blocks 
  to display images in the terminal.
 
grade: stable 
confinement: classic

apps:
  timg: 
    command: timg

parts:
  timg:
    source: https://github.com/hzeller/timg.git
    source-subdir: src
    plugin: make
    build-packages: 
      - libgraphicsmagick++1-dev
      - libwebp-dev
    artifacts: [timg]

In the following we are selecting the option of the strict confinement. Therefore, images should be in the $HOME only.

Packaging and testing

Let’s package the snap, that is, create the .snap file and try it out on a brand-new installation of Ubuntu!

ubuntu@snaps:~/timg-snap$ snapcraft 
Skipping pull timg (already ran)
Skipping build timg (already ran)
Skipping stage timg (already ran)
Skipping prime timg (already ran)
Snapping 'timg' \                                                 
Snapped timg_20170226_amd64.snap
ubuntu@snaps:~/timg-snap$

How do we get a brand new installation of Ubuntu in seconds so that we can test the snap?

See Trying out LXD containers on our Ubuntu and set up LXD on your system. Then, come back here and try the following commands,

$ lxc launch ubuntu:x snaptesting
Creating snaptesting
Starting snaptesting
$ lxc file push timg_20170226_amd64.snap snaptesting/home/ubuntu/
$ lxc exec snaptesting -- sudo su - ubuntu
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

ubuntu@snaptesting:~$ ls
timg_20170226_amd64.snap
ubuntu@snaptesting:~$ snap install timg_20170226_amd64.snap 
error: access denied (try with sudo)
ubuntu@snaptesting:~$ sudo snap install timg_20170226_amd64.snap
error: cannot find signatures with metadata for snap "timg_20170226_amd64.snap"
ubuntu@snaptesting:~$ sudo snap install timg_20170226_amd64.snap --dangerous
error: cannot perform the following tasks:
- Mount snap "core" (1337) ([start snap-core-1337.mount] failed with exit status 1: Job for snap-core-1337.mount failed. See "systemctl status snap-core-1337.mount" and "journalctl -xe" for details.
)
ubuntu@snaptesting:~$ sudo apt install squashfuse
[...]
Setting up squashfuse (0.1.100-0ubuntu1~ubuntu16.04.1) ...
ubuntu@snaptesting:~$ sudo snap install timg_20170226_amd64.snap --dangerous
timg 20170226 installed
ubuntu@snaptesting:~$ wget https://farm7.staticflickr.com/6187/6091603784_d6960c8be2_z_d.jpg
[...]
2017-02-26 22:12:18 (636 KB/s) - ‘6091603784_d6960c8be2_z_d.jpg’ saved [240886/240886]
ubuntu@snaptesting:~$ timg 6091603784_d6960c8be2_z_d.jpg 
[it worked!]
ubuntu@snaptesting:~$

So, we launched an LXD container called snaptesting, then copied in there the .snap file. Then, we connected to the container as a normal user and tried to install the snap. Initially, the installation failed because we need sudo when we install snaps in unprivileged LXD containers. It again failed because the .snap was unsigned (we need the –dangerous parameter). Then, it further failed because we need to install the squashfuse package (not preinstalled in the Ubuntu 16.04 images). Eventually, the snap was installed and we managed to view the image.

It is important to test a snap in a brand new installation of Linux in order to make sure whether we need to stage any code library inside the snap. In this case, static libraries were used and all went well!

Publishing to the Ubuntu Store

Here are the instructions to publish a snap to the Ubuntu Store. We have already published a few snaps in the previous tutorials. For timg, we got confinement: strict, and grade: stable. We are therefore publishing in the stable channel.

$ snapcraft push timg_20170226_amd64.snap 
Pushing 'timg_20170226_amd64.snap' to the store.
Uploading timg_20170226_amd64.snap [                                       ]   0%
Uploading timg_20170226_amd64.snap [=======================================] 100%
Ready to release!|                                                               
Revision 6 of 'timg' created.
$ snapcraft release timg 6 stable
Track    Arch    Series    Channel    Version    Revision
latest   amd64   16        stable     20170226   6
                           candidate  ^          ^
                           beta       0.9.5      5
                           edge       0.9.5      5
The 'stable' channel is now open.

We pushed the .snap file to the Ubuntu Store and we got a revision number 6. Then, we released the timg revision 6 to the stable channel of the Ubuntu Store.

There was no released snap in the candidate channel, therefore, it inherits the package from the stable channel. Hence, the ^ characters.

In previous tests I uploaded some older versions of the snap to the beta and edge channels. These older versions refer to the old tag 0.9.5 of the timg source code.

Let’s knock down the old 0.9.5 by releasing the stable version to the beta and edge channels as well.

$ snapcraft release timg 6 beta
Track    Arch    Series    Channel    Version    Revision
latest   amd64   16        stable     20170226   6
                           candidate  ^          ^
                           beta       20170226   6
                           edge       0.9.5      5
$ snapcraft release timg 6 edge
Track    Arch    Series    Channel    Version    Revision
latest   amd64   16        stable     20170226   6
                           candidate  ^          ^
                           beta       20170226   6
                           edge       20170226   6

Playing with timg

Let’s run timg without parameters,

ubuntu@snaptesting:~$ timg
Expected image filename.
usage: /snap/timg/x1/timg [options] <image> [<image>...]
Options:
    -g<w>x<h>  : Output pixel geometry. Default from terminal 80x48
    -s[<ms>]   : Scroll horizontally (optionally: delay ms (60)).
    -d<dx:dy>  : delta x and delta y when scrolling (default: 1:0).
    -w<seconds>: If multiple images given: Wait time between (default: 0.0).
    -t<seconds>: Only animation or scrolling: stop after this time.
    -c<num>    : Only Animation or scrolling: number of runs through a full cycle.
    -C         : Clear screen before showing image.
    -F         : Print filename before showing picture.
    -v         : Print version and exit.
If both -c and -t are given, whatever comes first stops.
If both -w and -t are given for some animation/scroll, -t takes precedence
ubuntu@snaptesting:~$

Here it says that for the current zoom level of our terminal emulator, our resolution is a mere 80×48.

Let’s zoom out a bit and maximize the GNOME Terminal window.

    -g<w>x<h>  : Output pixel geometry. Default from terminal 635x428

It is a better resolution but I can hardly see the characters because they are too small. Let’s invoke the old command to show this car again.

What you are seeing is the resized image (from 1080p). Looks great, even if it is made of colored text characters!

What next? timg can play animated gifs as well!

$ wget https://m.popkey.co/9b7141/QbAV_f-maxage-0.gif -O JonahHillAmazed.gif$ timg JonahHillAmazed.gif

Try to install the timg snap yourself in order to experience the animated gif! Failing that, watch the asciinema recording (if the video looks choppy, run it a second time), https://asciinema.org/a/dezbe2gpye84e0pjndp8t0pvh

Thanks for reading!

 

 

 

 

 

post image

How to make a snap package for lolcat with snapcraft on Ubuntu

In this post we are going to see how to make snap installation packages for a program called lolcat.

What you need for this tutorial? This tutorial is similar to Snap a python application. If you first follow that tutorial, then this one will reinforce what you have learned and expand to dealing with more programming languages than just Python.

What will you learn?

  1. How to deal with different source code repositories and get into the process of snapping them in a snap (pun intended).
  2. How to use the Snapcraft plugins for Python, golang, Rust and C/C++.
  3. How to deal with confinement decisions and when to select strict confinement or classic confinement.
  4. How to test the quality of an app before releasing to the Ubuntu Store
  5. What is this truecolor terminal emulator thing, what is lolcat and why it is cool (at least to a select few).

True-color terminal emulators

Terminal emulators like GNOME Terminal support the facility to display text in different colors.

You know this already because by default in Ubuntu you can see filenames in different colors, depending on whether they are executable (green), a directory (blue), a symbolic link (cyan) and so on. If you go 20+ years in the past, even the Linux console supported since then 256 colors.

What changed recently in terms of colors in the terminal emulators, is that newer terminal emulators support 16 million colors; what is described as true-color.

Here is an AWK script (of all scripting languages!) that shows a smooth gradient, from red to green to blue. In old terminal emulators and the Linux console, they were escape sequences to specify the colors, and you had to specify them by name. With the recent improvement among terminal emulators, it is now possible to specify the color by RGB value, thus 256*256*256 ~= 16 million different colors. You can read more about this in the article True Colour (16 million colours) support in various terminal applications and terminals. I found that AWK script there in this article. Try it one your Ubuntu as well!

Now, there is this Unix command called cat, which is used to print the contents of a text file in the terminal. cat /etc/passwd would show the contents of /etc/passwd. So, some people wrote an improved cat, called lolcat, that shows the content of files in a rainbow of colors.

In the screenshot above, the utility lolcat (a version we made and call lolcat-go) is used as a filter to a command (snapcraft –help), and colorizes the text that it receives with a nice rainbow of colors.

In practice, the lolcat utility merely sets the color for each character being printed. It starts with a random color and circles around the rainbow, heading diagonally towards the bottom-right. In the screenshot above, you can see the text snapcraft and Usage: in strong blue, and then diagonally (heading to bottom-right), the colors shift to green and then to orange.

Select which repositories to snap

The first implementation of the lolcat rainbow utility was probably by busyloop, written in Ruby. Since then, several others re-implemented lolcat into more programming languages. In this post we are going to snap:

  1. The Python lolcat by tehmaze.
  2. The golang lolcat by cezarsa.
  3. The Rust lolcat by ur0 (a version that uses Rust’s concurrency feature!)
  4. The C lolcat by jaseg (a version optimized for speed!)

Here we can see a) the URL of the source code, the available b) branches and c) tags. This is useful in the next section when we instruct Snapcraft which version of the source code to use.

In terms of versions among the four implementations, the Python lolcat has a recent tag 0.44, therefore we are using this tag and specify a version 0.44. For the rest, we are using the latest (master) checkout of their repositories, so we use the current date as a version number, in the form YYYYMMDD (for example, 20170226).

Completing the snapcraft.yaml metadata

When creating a snap, we need to write up a nice snap summary (less than 80 characters) and a description (less than 100 words). The summary will look like lolcat-python utility written in Python, and the description lolcat is a utility similar to the Unix “cat” command. lolcat adds rainbow colors to the text output.

In addition, we need suitable names for the four snaps. We are going to use lolcat-python, lolcat-go, lolcat-rust, and lolcat-c for each one of the four snaps.

All in all, here is the information we collected so far:

  1. Python: name is “lolcat-python“, version is “0.44“, summary: lolcat-python utility written in Python, description: lolcat-python is a utility similar to the Unix “cat” command. lolcat-python adds rainbow colors to the text output.
  2. Go: name is “lolcat-go“, version is “20170226“, summary: lolcat-go utility written in Go, description: lolcat-go is a utility similar to the Unix “cat” command. lolcat-go adds rainbow colors to the text output.
  3. Rush: name is “lolcat-rust“, version is “20170226“, summary: lolcat-rust utility written in Rust, description: lolcat-rust is a utility similar to the Unix “cat” command. lolcat-rust adds rainbow colors to the text output.
  4. C: name is “lolcat-c“, version is “20170226“, summary: lolcat-c utility written in C, description: lolcat-c is a utility similar to the Unix “cat” command. lolcat-c adds rainbow colors to the text output.

The final part in the metadata is the grade (whether it is devel or stable) and the confinement (whether it is devmode, classic or strict).

We select stable as the grade because we aim to add these snaps to the Ubuntu Store. If the grade is specified as devel, then the corresponding snap cannot be added to the stable channel (publicly available to all) of the Ubuntu Store. There is a section below on testing the four lolcat implementations and we will set accordingly the grade to either stable or devel, depending on the outcome of these tests.

We select initially devmode (DEVeloper MODE) as the confinement in order not to confine initially out snap. If our snap fails to run, we want to be sure it is some issue with our settings and not a byproduct of the choice of a stricter confinement. Once the snap can be built and run successfully, we change the confinement to either strict or classic and deal at that point with any issues that appear from there on.

Here is how the metadata look in the snapcraft.yaml configuration file for the Python variant of the snap.

Up to this point, all four snapcraft.yaml files, with metadata filled in, can be found at https://github.com/simos/lolcat-snap/tree/v1.0

Working on the “parts” section in snapcraft.yaml

We completed the easy metadata section, now it is time to work on the parts: section of snapcraft.yaml. (After the parts: section work, we just need the apps: section, where we expose the generated executable to the users of the snap).

Initially, snapcraft init will generate a stock snapcraft.yaml file, which has a stub parts: section. Here it how it looks,

parts:
  my-part:
    # See 'snapcraft plugins'
    plugin: nil

It defines the start of the parts: section. Then, a name, my-part: (we choose this name) is defined. Finally, the contents of my-part: are listed, here in two lines. The first line of my-part: is a comment (starts with #) and the second specifies the plugin, which is nil (it is reserved, and does nothing).

Note how these lines are aligned vertically. First is parts: at the start of the line, then two columns further, is my-part:. Then, two more columns further, we get the comment and the plugin: directive, both on the same column. We use spaces and not tabs. If you get any errors later on, check that you follow properly the formatting. You can have the levels separated by more than two columns, if you wish. But make sure that the same level lines are aligned on the same column.

Let’s figure out the initial versions of the parts:. Let’s do Python first!

parts:
  lolcat-python:
    source: https://github.com/tehmaze/lolcat.git
    source-tag: '0.44'
    plugin: python

We used the name lolcat-python: (our choice) for the name of this parts:. In there, we specify the source: for the source code repository, and any branches or tags that may be relevant. As we saw above, we work on the 0.44 tag. Finally, the source is written in Python, and we select the python plugin. (We will figure out later if we need to specify which of Python 2 or Python 3, if we get a relevant error).

Here is the Go,

parts:
  lolcat-go:
    source: https://github.com/cezarsa/glolcat.git
    plugin: go

Fairly expected. We do not specify a version, therefore it will use the latest snapshot of the source at the time of running snapcraft. We chose the name locat-go, and the golang plugin is called go.

Time for Rust,

parts:
  lolcat-rust:
    source: https://github.com/ur0/lolcat.git
    plugin: rust

Again, very similar to the above. We do not specify a specific source code version (there isn’t any tag or stable branch in the repository). We chose the name lolcat-rust, and the Rust plugin in snapcraft is called rust.

Finally, the version written in C,

parts:
  lolcat-c:
    source: https://github.com/jaseg/lolcat.git
    plugin: make

Again, we chose a name for this part, and it’s lolcat-c. Then, specified the URL for the source code. As for the plugin, we wrote make, although the source is written in C. Actually, the plugin: directive specifies how to build the source code. The make plugin does the make; make install sequence for us, and it’s our first choice when we see an existing Makefile file in a repository.

At this stage, we have four initial versions of configuration files. We are ready to try them out and deal with any errors that may appear.

Working on the Python version

Here is the configuration (snapcraft.yaml) for the Python variant up to this point,

name: lolcat-python
version: '0.44'
summary: lolcat utility written in Python
description: |
  lolcat-python is a utility similar to the Unix "cat" command. 
  lolcat-python adds rainbow colors to the text output.
  The source code is available at https://github.com/tehmaze/lolcat

grade: stable
confinement: devmode

parts:
  lolcat-python:
    source: https://github.com/tehmaze/lolcat.git
    source-tag: '0.44'
    plugin: python

Let’s run snapcraft prime. The prime parameter will perform the necessary compilation and will put the result in the prime/ subdirectory. Since snapcraft prime does only the initial compilation steps, it is more convenient to use for repeated tests. Once it works with snapcraft prime, we would be ready in a single extra step to produce the final .snap file (by running snapcraft, no parameters).

$ snapcraft prime
Preparing to pull lolcat-python 
[...]
Pulling lolcat-python 
[...]
Installing collected packages: pip, six, pyparsing, packaging, appdirs, setuptools, wheel
[...]
Successfully downloaded lolcat
Preparing to build lolcat-python 
Building lolcat-python 
[...]
Successfully built lolcat
[...]
Successfully installed lolcat-0.44
Staging lolcat-python 
Priming lolcat-python 
$ _

It worked beautifully! Any result is in the prime/ subdirectory, and we can identify even the executable.

$ ls prime/
bin/  etc/  lib/  meta/  snap/  usr/
$ ls prime/bin
lolcat*
$ _

We are now ready to create the apps: section of the snapcraft.yaml configuration file, in order to expose the executable to the users,

apps:
  lolcat-python:
    command: lolcat

The name: of this snap is lolcat-python, and the name we chose in the apps: section is the same, lolcat-python. Since they are the same, once we install the snap, the newly available command will be called lolcat-python. If there was a difference between the two (for example, name: lolcat-python and apps: lolcat: […], then the command for the users would end up being something like lolcat-python.lolcat, which may not be desirable.

Working on the Go version

Here is the configuration (snapcraft.yaml) for the Go variant up to this point,

name: lolcat-go
version: '20170226'
summary: lolcat utility written in golang
description: |
  lolcat-go is a utility similar to the Unix "cat" command.
  lolcat-go adds rainbow colors to the text output.
  The source code is available at https://github.com/cezarsa/glolcat

grade: devel
confinement: devmode

parts:
  lolcat-go:
    source: https://github.com/cezarsa/glolcat.git
    plugin: go

Let’s run snapcraft prime and see how it goes.

$ snapcraft prime
Preparing to pull lolcat-go 
[...]
Building lolcat-go 
[...]Staging lolcat-go 
Priming lolcat-go 
$ ls prime/bin/
glolcat.git
$ _

Lovely! The go plugin managed to make sense of the repository and compile the Go version of lolcat. The generated executable is called glolcat.git. Therefore, the apps: section looks like

apps:
  lolcat-go:
    command: glolcat.git

In this way, once we install the Go snap of lolcat, there will be an executable lolcat-go exposed to the users. This executable will be the glolcat.git that was generated by the Snapcraft go plugin in prime/bin/. Snapcraft tries to find the final executable in either prime/ or prime/bin/, therefore we do not need to specify specifically bin/glolcat.git.

Working on the Rust version

Here is the configuration (snapcraft.yaml) for the Rust variant up to this point,

name: lolcat-rust
version: '20170226'
summary: lolcat utility written in Rust
description: |
  lolcat-rust is a utility similar to the Unix "cat" command.
  lolcat-rust adds rainbow colors to the text output.
  The source code is available at https://github.com/ur0/lolcat

grade: stable
confinement: devmode

parts:
  lolcat-rust:
    source: https://github.com/ur0/lolcat.git
    plugin: rust

Let’s run snapcraft prime and see how it goes.

$ snapcraft prime
Preparing to pull lolcat-rust 
[...]
Downloading 'rustup.sh'[================] 100%
[...]
Preparing to build lolcat-rust 
Building lolcat-rust 
[...]
Staging lolcat-rust 
Priming lolcat-rust 
$ ls prime/bin/
lolcat
$ _

Without a hitch! The rust plugin noticed that we do not have the Rust compiler, and downloaded it for us! Then, it completed the compilation and the final executable is called lolcat. Therefore, the apps: section looks like

apps:
  lolcat-rust:
    command: lolcat

The apps: section will expose the generated lolcat executable by the name lolcat-rust. Since the name: field is also lolcat-rust, the resulting executable once we install the snap will be lolcat-rust as well. Again, Snapcraft looks by default into both prime/ and prime/bin/ for the command:, therefore it is not required to write specifically command: bin/lolcat.

Working on the C (make) version

Here is the configuration (snapcraft.yaml) for the C (using Makefile) variant up to this point,

name: lolcat-c
version: '20170226'
summary: lolcat utility written in C
description: |
  lolcat-c is a utility similar to the Unix "cat" command.
  lolcat-c adds rainbow colors to the text output.
  The source code is available at https://github.com/jaseg/lolcat

grade: stable
confinement: devmode

parts:
  lolcat-c:
    source: https://github.com/jaseg/lolcat.git
    plugin: make

Let’s run snapcraft prime and see how it goes.

$ snapcraft prime
Preparing to pull lolcat-c 
Pulling lolcat-c 
[...]
Submodule 'memorymapping' (https://github.com/NimbusKit/memorymapping) registered for path 'memorymapping'
Submodule 'musl' (git://git.musl-libc.org/musl) registered for path 'musl'
Cloning into 'memorymapping'...
[...]
Cloning into 'musl'...
[...]
Building lolcat-c 
make -j4
"Using musl at musl"
cd musl; ./configure
[...]sh tools/musl-gcc.specs.sh "/usr/local/musl/include" "/usr/local/musl/lib" "/lib/ld-musl-x86_64.so.1" > lib/musl-gcc.specs
printf '#!/bin/sh\nexec "${REALGCC:-gcc}" "$@" -specs "%s/musl-gcc.specs"\n' "/usr/local/musl/lib" > tools/musl-gcc
chmod +x tools/musl-gcc
make[1]: Leaving directory '/home/myusername/SNAPCRAFT/lolcat-snap/c/parts/lolcat-c/build/musl'
Command '['/bin/sh', '/tmp/tmpetv6irll', 'make', '-j4']' returned non-zero exit status 2
Exit 1
$ _

Well, well. Finally an error!

So, the C version of lolcat was written using the musl libc library. This library was referenced as a git submodule, and snapcraft followed the instructions of the Makefile to pull and compile musl!

Then, for some reason, snapcraft fails to compile lolcat using a musl-gcc wrapper for this newly compiled musl libc. As if we need to specify that the make ; make install sequence should instead be make lolcat; make install. Indeed, looking at the instructions at https://github.com/jaseg/lolcat, this appears to be the case.

Therefore, how do we tell snapcraft that for the make plugin, it should run make lolcat instead of the standard make?

By reading the documentation of the Snapcraft make plugin, we find that

- make-parameters:
 (list of strings)
 Pass the given parameters to the make command.

Therefore, the parts: should look like

parts:
  lolcat-c:
    source: https://github.com/jaseg/lolcat.git
    plugin: make
    make-parameters: [lolcat]

We enclose lolcat in brackets ([lolcat]) because make-parameters accepts a list of strings. If it accepted just a string, we would not need those brackets.

Let’s snap prime again!

$ snapcraft prime
Preparing to pull lolcat-c 
[...]
Building lolcat-c 
make lolcat -j4
"Using musl at musl"
[...]
chmod +x tools/musl-gcc
[...]
gcc -c -std=c11 -Wall -g -Imusl/include -o lolcat.o lolcat.c
[...]
Staging lolcat-c 
Priming lolcat-c 
$ ls prime/bin
ls: cannot access 'prime/bin': No such file or directory
Exit 2
$ ls prime/
censor*  command-lolcat-c.wrapper*  lolcat*  meta/  snap/
$ _

Success! The lolcat executable has been generated, and in fact it is located in prime/ (not in prime/bin/ as in all three previous cases). Also, it took 1 minute and 40 seconds to produce the executable on my computer!

Hmm, there is also a censor executable. I wonder, what does it do?

$ ls -l | ./censor 
█▄█▄█ ██
█▄▄▄▄█▄▄█▄ █ ▄▄▄▄ ▄▄▄▄ █████ ███  ██ ██:██ ▄▄▄▄▄▄
█▄▄▄▄█▄▄█▄ █ ▄▄▄▄ ▄▄▄▄   ███ ███  ██ ██:██ ▄▄▄▄▄▄███▄█▄▄██▄.▄▄▄▄▄▄▄
█▄▄▄▄█▄▄█▄ █ ▄▄▄▄ ▄▄▄▄ █████ ███  ██ ██:██ █▄█▄▄█
█▄▄▄▄▄▄▄█▄ █ ▄▄▄▄ ▄▄▄▄  ████ ███  ██ ██:██ ▄▄█▄
█▄▄▄▄▄▄▄█▄ █ ▄▄▄▄ ▄▄▄▄  ████ ███  ██ ██:██ ▄▄▄▄
$ _

This censor executable is a filter, just like lolcat, and what it does is that it replaces any input letters with block characters. Like censoring the text. Let’s expose both lolcat and censor in this snap! Here is the apps: section,

apps:
  lolcat-c:
    command: lolcat
  censor:
    command: censor

For lolcat, since both the name: and the apps: command are named lolcat-c, the final executable will be lolcat-c. For censor, the executable will be named lolcat-c.censor (composed from the name: and the name we put in apps:).

Which confinement, strict or classic?

When we are about to publish a snap to the Ubuntu Store, we need to decide which confinement to apply, strict or classic.

The strict confinement will by default fully restrict the snap and it is up to us to specify what is allowed. For example, there will be no network connectivity, and we would need to explicitly specify it if we want to provide network connectivity.

The strict confinement can be tricky if the snap needs to read files in general. If the snap were to read file only from the user’s home directory, then that’s easy because we can specify plugs: [home] and be done with it.

In our case, lolcat can be used in two ways,

Note the different colors; the lolcat implementations start every time with a random initial rainbow color

In the first command, lolcat-go requires read access for the file /etc/lsb-release. This would be tricky to specify with the strict confinement, and we would need to use the classic confinement instead.

In the second command, lolcat-go is merely used as a filter. The executable is self-contained and does not read any files whatsoever. Because the cat command does the reading for lolcat.

Therefore, we can select here the strict confinement as long as we promise to use lolcat as a filter only. That is, lolcat would run fully confined! And it will fail if we ask it to read a file like in the first command.

Final configuration files

Here are the four final configuration files! I highlight below what really changes between them (bold+italics).

$ cat python/snap/snapcraft.yaml 
name: lolcat-python
version: '0.44'
summary: lolcat utility written in Python
description: |
  lolcat-python is a utility similar to the Unix "cat" command. 
  lolcat-python adds rainbow colors to the text output.
  The source code is available at https://github.com/tehmaze/lolcat

grade: stable
confinement: strict

apps:
  lolcat-python:
    command: lolcat

parts:
  lolcat-python:
    source: https://github.com/tehmaze/lolcat.git
    source-tag: '0.44'
    plugin: python

$ cat go/snap/snapcraft.yaml 
name: lolcat-go
version: '20170226'
summary: lolcat utility written in golang
description: |
  lolcat-go is a utility similar to the Unix "cat" command.
  lolcat-go adds rainbow colors to the text output.
  The source code is available at https://github.com/cezarsa/glolcat

grade: devel
confinement: strict

apps:
  lolcat-go:
    command: glolcat.git

parts:
  lolcat-go:
    source: https://github.com/cezarsa/glolcat.git
    plugin: go

$ cat rust/snap/snapcraft.yaml 
name: lolcat-rust
version: '20170226'
summary: lolcat utility written in Rust
description: |
  lolcat-rust is a utility similar to the Unix "cat" command.
  lolcat-rust adds rainbow colors to the text output.
  The source code is available at https://github.com/ur0/lolcat

grade: stable
confinement: strict

apps:
  lolcat-rust:
    command: lolcat

parts:
  lolcat-rust:
    source: https://github.com/ur0/lolcat.git
    plugin: rust

$ cat c/snap/snapcraft.yaml 
name: lolcat-c
version: '20170226'
summary: lolcat utility written in C
description: |
  lolcat-c is a utility similar to the Unix "cat" command.
  lolcat-c adds rainbow colors to the text output.
  The source code is available at https://github.com/jaseg/lolcat

grade: stable
confinement: strict

apps:
  lolcat-c:
    command: lolcat
  censor:
    command: censor

parts:
  lolcat-c:
    source: https://github.com/jaseg/lolcat.git
    plugin: make
    make-parameters: [lolcat]
$ _

Quality testing

We have four lolcat snaps available to upload to the Ubuntu Store. Let’s test them first to see which ones are actually good enough to make it today to the Ubuntu Store!

A potential problem with filters like lolcat, is that they may not know how to deal with some UTF-8-encoded strings. In the UTF-8 encoding, text in English like what you read now, is encoded just like ASCII. Problems may occur when you have text in other scripts, where each Unicode character would occupy more than one byte. For example, each character in “Γεια σου κόσμε” is encoded as two bytes in the UTF-8 encoding. Furthermore, there are characters that are stored in Plane 1 of Unicode (Emojis!) which require the maximum of four bytes to encode in UTF-8. Here is an example of emoji characters, “🐧🐨🐩🐷🐸🐹🐺🐼🏴👏” (if they appear as empty boxes, you do not have the proper fonts installed.

What we are seeing here, is that the current implementations of lolcat for Python and Go do not work with non-ASCII encodings. At the moment, they can only colorize text in English.

On the other hand, the Rust and C implementations work fine on all Unicode characters!

There is another issue to watch for. Specifically,

The Unix ls command takes care to understand when you are redirecting the output, and if you do so, by default it does not colorize the output. This is a very useful default for ls because in most cases you want clean text files with no escape sequences for the color. To further our testing, let’s see how well the remaining two lolcat implementations deal with content that happen to already have escape sequences (for example, for color),

We generated a text file (cat-color.txt) with color escape sequences. The Rust implementation choked on them, while the C implementation worked fine!

We have a winner! The C implementation of lolcat will be published in the Ubuntu Store, in the stable channel (available to all). The Rust implementation will be published in the candidate channel (pending a fix when dealing with text that already has escape sequences), while the Python and Go implementations will be published in the edge channels. (Note: if the authors of these lolcat implementations are reading this, my aim here is to demonstrate the different channels. I plan to write a follow-up post on how to fix these issues in the source code and how to re-release all snaps to the stable channel.)

Let’s publish to the Ubuntu Store

The documentation page Publish your snap from snapcraft.io explains the details on publishing a snap on the Ubuntu Store.

In summary, when releasing a snap to the Ubuntu Store, you specify in which channel(s) you want it to be in:

  1. stable channel, for publicly available snaps. These can be searched when running snap find, and will be installed when you run snap install.
  2. candidate channel, for snaps that are very soon to be released to the stable channel. For this and the following channels, you need to specify explicitly the channel when you try to install. Otherwise, you will get the error that the snap is not found.
  3. beta channel, for beta versions of snaps.
  4. edge channel, for testing versions of snaps. This is the furthest away from stable.

If you release a snap in the stable channel, it implies that it will be shown in those below. Or, if you release a snap in the beta channel, it will appear as well in the channel below (edge).

Furthermore, when we were filling in the metadata of the snapcraft.yaml configuration files, there was a field called grade, with options for either stable or devel. If the grade has been specified as devel, then the snap can only be installed in either the beta or edge channels.

So, this is what we are going to do:

  1. The C implementation, lolcat-c, will have grade: stable, and get published in the stable channel of the Ubuntu Store.
  2. The Rust implementation, lolcat-rust, will have grade: devel, and get published in the beta channel of the Ubuntu Store.
  3. The Go and Python implementations, lolcat-go and lolcat-python, will have the grade: devel and get published in the edge channel of the Ubuntu Store.

We have already ran snapcraft login, and logged in with our Ubuntu Single SignOn (SSO) account.

We successfully registered the names on the Ubuntu Store, and then we pushed the snap files. We note down the revision, which is Revision 1 for each one of them.

The snapcraft release command looks like

  snapcraft [options] release <snap-name> <revision> <channel>

The snapcraft release command instructs the Ubuntu Store to release the recently pushed .snap file into the specified channels.

How to install them

Here we install lolcat-c.

First we perform a search for lolcat. The snap lolcat-c is found. There is a feature in the snap find command, that if we were to search for lolcat-c, it would show results for both lolcat and c (shows irrelevant results).

We then run the snap info command to show the Ubuntu Store info for the snap lolcat-c.

Then, we install lolcat-c, by running snap install lolcat-c.

Finally, we run snap info again, and we can see more information since the snap has just been installed. In particular, we can see that there is the additional command lolcat-c.censor. Oh, and then snap is just 24kB in size.

Let’s install the Rust implementation!

The Rust implementation of lolcat can be found in the beta and edge channels. In order to install it, we need to specify the correct channel (here, either beta or edge). And that’s it!

The Go implementation of lolcat is in the edge channel. We install and test it successfully.

Finally, the Python implementation of lolcat, installed from the edge channel.

Hope you enjoyed the post!

post image

How to create a snap with snapcraft for howdoi (CLI utilility for stackoverflow)

In the tutorial How to create a snap for how2 (stackoverflow from the terminal) in Ubuntu 16.04 we saw how to create a snap with snapcraft for the CLI utility called how2. That was a software based on nodejs.

In this post we will repeat the process for another CLI utility called howdoi by Benjamin Gleitzman, which does a similar task with how2 but is implemented in Python and has a few usability differences as well. howdoi does not have yet a package in the repositories of Ubuntu, either.

Since we covered already the details in How to create a snap for how2 (stackoverflow from the terminal) in Ubuntu 16.04, this post would be more focused, and shorter. 🙂

Planning

Reading through https://github.com/gleitz/howdoi we see that howdoi

  1. is software based on Python (therefore: plugin: python)
  2. requires networking (therefore: plugs: [network])
  3. and has no need to save files (therefore it does not need access to the filesystem)

Crafting with snapcraft

Let’s start with snapcraft.

$ mkdir howdoi
$ cd howdoi/
$ snapcraft init
Created snap/snapcraft.yaml.
Edit the file to your liking or run `snapcraft` to get started

Now we edit snap/snapcraft.yaml and here are our changes (in bold) from the initial generated file.

$ cat snap/snapcraft.yaml 
name: howdoi # you probably want to 'snapcraft register <name>'
version: '20170207' # just for humans, typically '1.2+git' or '1.3.2'
summary: instant coding answers via the command line # 79 char long summary
description: |
  Are you a hack programmer? Do you find yourself constantly Googling 
  for how to do basic programing tasks?
  Suppose you want to know how to format a date in bash. Why open your browser 
  and read through blogs (risking major distraction) when you can simply 
  stay in the console and ask howdoi.

grade: stable # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots

apps:
  howdoi:
    command: howdoi
    plugs: [network]

parts:
  howdoi:
    plugin: python
    source: https://github.com/gleitz/howdoi.git

First, we selected to use the name howdoi because again, it’s not a reserved name :-). Also, we registered it with snapcraft,

$ snapcraft register howdoi
Registering howdoi.
Congratulations! You're now the publisher for 'howdoi'.

Second, we did not notice a particular branch or tag for howdoi, therefore we put the date of the snap creation.

Third, the summary and the description are just pasted from the Readme.md of the howdoi repository.

Fourth, we select the grade stable and enforce the strict confinement.

The apps: howdoi: command: howdoi is the standard sequence to specify the command that will be exposed to the user. The user will be typing howdoi and the command howdoi inside the snap will be invoked.

The parts: howdoi: plugin: python source: … is the standard sequence to specify that the howdoi that was referenced just earlier, is software written in Python and the source comes from this github repository.

Let’s craft the snap.

$ snapcraft 
Preparing to pull howdoi 
...                                                                     
Pulling howdoi 
...
Preparing to build howdoi 
Building howdoi 
...
Successfully built howdoi
...
Installing collected packages: howdoi, cssselect, Pygments, requests, lxml, pyquery, requests-cache
Successfully installed Pygments-2.2.0 cssselect-1.0.1 howdoi-1.1.9 lxml-3.7.2 pyquery-1.2.17 requests-2.13.0 requests-cache-0.4.13
Staging howdoi 
Priming howdoi 
Snapping 'howdoi' |                                                                       
Snapped howdoi_20170207_amd64.snap
$ snap install howdoi_20170207_amd64.snap --dangerous
howdoi 20170207 installed
$ howdoi format date bash
DATE=`date +%Y-%m-%d`
$ _

Beautiful! It worked!

Publish to the Ubuntu Store

Let’s publish the snap to the Ubuntu Store. We are going to push the file howdoi_20170207_amd64.snap and then check that it has passed the automatic checking. Once it has done so, we release to the stable channel.

$ snapcraft push howdoi_20170207_amd64.snap 
Pushing 'howdoi_20170207_amd64.snap' to the store.
Uploading howdoi_20170207_amd64.snap [=============================================================] 100%
Ready to release!|                                                                                       
Revision 1 of 'howdoi' created.

Just a reminder: We can release the snap to the stable channel simply by running snapcraft release howdoi 1 stable. The alternative to this command, is to do all the following through the Web.

We log in into https://myapps.developer.ubuntu.com/ to check whether snap is ready to publish. In the following screenshots, you would click where the arrows are showing. See the captions for explanations.

Here is the uploaded snap in our account page in the Ubuntu Store. The snap was uploaded using snapcraft, although it is also possible to uploaded from the account page as well.

 

The package (the snap) is ready to publish, because it passed the automated tests and was not flagged for manual review.

By default, the package has not been released to a channel. We click on Release in order to select which channels to release it to.

For this specific package, we select the stable channel. It is not necessary to select the other channels, because by default a higher channel implies those below. Then, click on the Release button.

The package got released, and it shown it got released in stable, candidate, beta and edge (we selected stable, but the rest are implied because “stable” beats the rest.) Note that the Package status has changed to “Published”, and we have the option to Unpublish or even Make private. Ignore the arrow, it was pasted by mistake.

post image

How to create a snap for how2 (stackoverflow from the terminal) in Ubuntu 16.04

Stackoverflow is an invaluable resource for questions related to programming and other subjects.

Normally, the workflow for searching http://stackoverflow.com/, is to search Google using a Web browser. Most probably, the result will be a question from stackoverflow.

A more convenient way to query StackOverflow, is to use the how2 command-line utility.

Here is how it looks:

In this HowTo, we will see:

  1. How to set up snapcraft in order to make the snap
  2. How to write the initial snapcraft.yaml configure
  3. Build the snap with trial and error
  4. Create the final snap
  5. Make the snap available to the Ubuntu Store

Set up snapcraft

snapcraft is a utility that helps us create snaps. Let’s install snapcraft.

$ sudo apt update
...
Reading state information... Done
All packages are up to date.
$ sudo apt install snapcraft
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  snapcraft
...
Preparing to unpack .../snapcraft_2.26_all.deb ...
Unpacking snapcraft (2.26) ...
Setting up snapcraft (2.26) ...
$_

In Ubuntu 16.04, snapcraft was updated in early February and has a few differences from the previous version. Make sure you have snapcraft 2.26 or newer.

Let’s create a new directory for the development of the httpstat snap and initialize it with snapcraft so that create the necessary initial files.

$ mkdir how2
$ cd how2/
$ snapcraft init
Created snap/snapcraft.yaml.
Edit the file to your liking or run `snapcraft` to get started
$ ls -l
total 4
drwxrwxr-x 2 myusername myusername 4096 Feb   6 14:09 snap
$ ls -l snap/
total 4
-rw-rw-r-- 1 myusername myusername 676 Feb   6 14:09 snapcraft.yaml
$ _

We are in this how2/ directory and from here we run snapcraft in order to create the snap. snapcraft will take the instructions from snap/snapcraft.yaml and do its best to create the snap.

These are the initial contents of snap/snapcraft.yaml:

name: my-snap-name # you probably want to 'snapcraft register <name>'
version: '0.1' # just for humans, typically '1.2+git' or '1.3.2'
summary: Single-line elevator pitch for your amazing snap # 79 char long summary
description: |
  This is my-snap's description. You have a paragraph or two to tell the
  most important story about your snap. Keep it under 100 words though,
  we live in tweetspace and your description wants to look good in the snap
  store.

grade: devel # must be 'stable' to release into candidate/stable channels
confinement: devmode # use 'strict' once you have the right plugs and slots

parts:
  my-part:
    # See 'snapcraft plugins'
    plugin: nil

I have formatted as italics the first chunk of configuration lines of snapcraft.yaml, because this chunk is what rarely changes when you develop the snap. The other chunk is the one that the actual actions take place. It is good to distinguish those two chunks.

This snap/snapcraft.yaml configuration file is actually usable and can create an (empty) snap. Let’s create this empty snap, install it, uninstall it and then clean up to the initial pristine state.

$ snapcraft 
Preparing to pull my-part 
Pulling my-part 
Preparing to build my-part 
Building my-part 
Staging my-part 
Priming my-part 
Snapping 'my-snap-name' |                                                                 
Snapped my-snap-name_0.1_amd64.snap
$ snap install my-snap-name_0.1_amd64.snap 
error: cannot find signatures with metadata for snap "my-snap-name_0.1_amd64.snap"
$ snap install my-snap-name_0.1_amd64.snap --dangerous
error: cannot perform the following tasks:
- Mount snap "my-snap-name" (unset) (snap "my-snap-name" requires devmode or confinement override)
Exit 1
$ snap install my-snap-name_0.1_amd64.snap --dangerous --devmode
my-snap-name 0.1 installed
$ snap remove my-snap-name
my-snap-name removed
$ snapcraft clean
Cleaning up priming area
Cleaning up staging area
Cleaning up parts directory
$ ls
my-snap-name_0.1_amd64.snap  snap/
$ rm my-snap-name_0.1_amd64.snap 
rm: remove regular file 'my-snap-name_0.1_amd64.snap'? y
removed 'my-snap-name_0.1_amd64.snap'
$ _

While developing the snap, we will be going through this cycle of creating the snap, testing it and then removing it. There are ways to optimize a bit this process, learn soon we will.

In order to install the snap from a .snap file, we had to use –dangerous because the snap has not been digitally signed. We also had to use –devmode because snapcraft.yaml specifies the developer mode, which is a relaxed (in terms of permissions) development mode.

Writing the snapcraft.yaml for how2

Here is the first chunk of snapcraft.yaml, the chunk that does not change while developing the snap.

name: how2 # you probably want to 'snapcraft register <name>'
version: '20170206' # just for humans, typically '1.2+git' or '1.3.2'
summary: how2, stackoverflow from the terminal
description: |
  how2 finds the simplest way to do something in a unix shell. 
  It is like the man command, but you can query it in natural language.

grade: stable # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots

We specify the name and version of the snap. The name is not registered already and it is not reserved, because

$ snapcraft register how2
Registering how2.
Congratulations! You're now the publisher for 'how2'.

We add a suitable summary and description that was copied conveniently from the development page of how2.

We set the grade to stable so that the snap can make it to the stable channel and be available to anyone.

We set the confinement to strict, which means that by default the snap will have no special access (no filesystem access, no network access, etc) unless we carefully allow what is really needed.

Here goes the other chunk.

apps:
  how2:
    command: how2

parts:
  how2:
    plugin: nodejs
    source: https://github.com/santinic/how2.git

How did we write this other chunk?

The apps: how2 : command: how2 is generic. That is, we specify an app that we name as how2, and it is invoked as a command with the name how2. The command could also be bin/how2 or node how2. We will figure out later whether we need to change it because snapcraft will show an error message.

The parts: how2: plugin: nodejs is also generic. We know that how2 is build on nodejs and we figured that one out from the github page of how2. Then, we looked into the list of plugins for snapcraft, and found the nodejs plugin page. At the end of the nodejs plugin page there is a link to examples for the user of nodejs in snapcraft.yaml. This link is actually a search in github with search terms filename:snapcraft.yaml “plugin: nodejs”(in all files that are named snapcraft.yaml, search for “plugin: nodejs”). For this search to work, you need to be logged in to Github first. For the specific case of nodejs, we can try without additional parameters as most examples do not show a use of special parameters.

Work on the snapcraft.yaml with trial and error

We come up with the following snapcraft.yaml by piecing together the chunks from the previous section:

$ cat snap/snapcraft.yamlname: how2 # you probably want to 'snapcraft register <name>'
version: '20170206' # just for humans, typically '1.2+git' or '1.3.2'
summary: how2, stackoverflow from the terminal
description: |
  how2 finds the simplest way to do something in a unix shell. 
  It is like the man command, but you can query it in natural language.

grade: devel # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots

apps:
  how2:
    command: how2
    plugs:
      - network

parts:
  how2:
    plugin: nodejs
    source: https://github.com/santinic/how2.git

Let’s run snapcraft in order to build the snap.

$ snapcraft clean
Cleaning up priming area
Cleaning up staging area
Cleaning up parts directory
$ snapcraft 
Preparing to pull how2 
Pulling how2 
...
Downloading 'node-v4.4.4-linux-x64.tar.gz'[===============================] 100%
npm --cache-min=Infinity install
...
npm-latest@1.0.2 node_modules/npm-latest
├── vcsurl@0.1.1
├── colors@0.6.2
└── registry-url@3.1.0 (rc@1.1.6)
...
Preparing to build how2 
Building how2 
...
Staging how2 
Priming how2 
Snapping 'how2' |                                                                              
Snapped how2_20170206_amd64.snap
$ _

Wow, it created successfully the snap on the first try! Let’s install it and then test it.

$ sudo snap install how2_20170206_amd64.snap --dangerous
how2 20170206 installed
$ how2 read file while changing
/Cannot connect to Google.
Error: Error on response:Error: getaddrinfo EAI_AGAIN www.google.com:443 : undefined
$ _

It works again, and the only problem is the confinement. We need to allow the snap to access the Internet, and only the Internet.

Add the ability to access the Internet

To be able to access the network, we need to relax the confinement of the snap and allow access to the network interface.

There is an identifier called plugs, and accepts an array of names of interfaces, from the list of available interfaces.

In snapcraft.yaml, you can specify such an array in either of the following formats:

plugs: [ network]
         or
plugs: 
   - network

Here is the final version of snapcraft.yaml for how2:

name: how2 # you probably want to 'snapcraft register <name>'
version: '20170206' # just for humans, typically '1.2+git' or '1.3.2'
summary: how2, stackoverflow from the terminal
description: |
  how2 finds the simplest way to do something in a unix shell. 
  It is like the man command, but you can query it in natural language.

grade: devel # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots

apps:
  how2:
    command: how2
    plugs: [ network ]

parts:
  how2:
    plugin: nodejs
    source: https://github.com/santinic/how2.git

Let’s create the snap, install and run the test query.

$ snapcraft 
Skipping pull how2 (already ran)
Skipping build how2 (already ran)
Skipping stage how2 (already ran)
Skipping prime how2 (already ran)
Snapping 'how2' |                                                                              
Snapped how2_20170206_amd64.snap
$ sudo snap install how2_20170206_amd64.snap --dangerous
how2 20170206 installed
$ how2 read file while changing
terminal - Output file contents while they change

You can use tail command with -f  :


   tail -f /var/log/syslog 

It's good solution for real time  show.


Press SPACE for more choices, any other key to quit.

That’s it! It works fine!

Make the snap available in the Ubuntu Store

The command snapcraft push will upload the .snap file to the Ubuntu Store. Then, we use the snapcraft release command to release the snap into the beta channel of the Ubuntu Store. Because we specified the grade as devel, we cannot release to the stable channel. When we release a snap to the beta channel, it is considered as released to the edge channel as well (because beta is higher than edge).

$ snapcraft push how2_20170206_amd64.snap 
Pushing 'how2_20170206_amd64.snap' to the store.
Uploading how2_20170206_amd64.snap [====================================================================] 100%
Ready to release!|                                                                                            
Revision 1 of 'how2' created.
$ snapcraft release how2 1 stable
Revision 1 (strict) cannot target a stable channel (stable, grade: devel)
$ snapcraft release how2 1 beta
The 'beta' channel is now open.

Channel    Version    Revision
stable     -          -
candidate  -          -
beta       20170206   1
edge       ^          ^
$ _

Everything looks fine now. Let’s remove the manually-installed snap and install it from the Ubuntu Store.

$ snap remove how2
how2 removed
$ snap info how2
name:      how2
summary:   "how2, stackoverflow from the terminal"
publisher: simosx
description: |
  how2 finds the simplest way to do something in a unix shell. 
  It is like the man command, but you can query it in natural language.
  
channels:              
  beta:   20170206 (1) 11MB -
  edge:   20170206 (1) 11MB -

$ snap install how2
error: cannot install "how2": snap not found
$ snap install how2 --channel=beta
how2 (beta) 20170206 from 'simosx' installed
$ how2 how to edit an XML file
How to change values in XML file

Using XMLStarlet (http://xmlstar.sourceforge.net/):
...omitted... 

post image

How to create a snap for a Python app with networking using snapcraft in Ubuntu 16.04

Update #1: 6 Feb 2017  httpstat needs curl. Originally, this HowTo would freshly compile curl from the github source. Now, this HowTo shows how to reuse the existing curl package from the Ubuntu repositories.

In this post we see how to create a snap package (or, just snap) of some software in Ubuntu 16.04. A snap is a confined package, that can only do as much as we allow it. Once we create it, we can install the same snap in different Linux distributions!

Each software has different needs. This one 1) requires access to the Internet and 2) requires an additional binary to be added to the snap. And nothing else.

Here is what we will be doing today.

  1. Get to know this cool software that we are going to snap, httpstat.
  2. Setup snapcraft that helps us create the snap.
  3. Start building the snap incrementally, trial and error.
  4. Complete the httpstat snap
  5. Register the name on the Ubuntu Store
  6. Upload and release the snap to the Ubuntu Store so anyone can install it!
  7. Install and run the new snap!

About httpstat

httpstat can be found at https://github.com/reorx/httpstat and it is a network utility that shows how fast is the access to a website.

$ apt search httpstat
Sorting... Done
Full Text Search... Done

It is not available yet as an apt package, so all the better to create a snap.

Let’s get the source of httpstat and run it manually. This will give us a good idea what dependencies it may have.

$ git clone https://github.com/reorx/httpstat
Cloning into 'httpstat'...
remote: Counting objects: 251, done.
remote: Total 251 (delta 0), reused 0 (delta 0), pack-reused 251
Receiving objects: 100% (251/251), 330.04 KiB | 336.00 KiB/s, done.
Resolving deltas: 100% (138/138), done.
Checking connectivity... done.
$ cd httpstat/
$ ls
httpstat.py  httpstat_test.sh  LICENSE  Makefile  README.md  screenshot.png  setup.py
$ python httpstat.py 
Usage: httpstat URL [CURL_OPTIONS]
       httpstat -h | --help
       httpstat --version

Arguments:
  URL     url to request, could be with or without `http(s)://` prefix

Options:
  CURL_OPTIONS  any curl supported options, except for -w -D -o -S -s,
                which are already used internally.
  -h --help     show this screen.
  --version     show version.

Environments:
  HTTPSTAT_SHOW_BODY    Set to `true` to show response body in the output,
                        note that body length is limited to 1023 bytes, will be
                        truncated if exceeds. Default is `false`.
  HTTPSTAT_SHOW_IP      By default httpstat shows remote and local IP/port address.
                        Set to `false` to disable this feature. Default is `true`.
  HTTPSTAT_SHOW_SPEED   Set to `true` to show download and upload speed.
                        Default is `false`.
  HTTPSTAT_SAVE_BODY    By default httpstat stores body in a tmp file,
                        set to `false` to disable this feature. Default is `true`
  HTTPSTAT_CURL_BIN     Indicate the curl bin path to use. Default is `curl`
                        from current shell $PATH.
  HTTPSTAT_DEBUG        Set to `true` to see debugging logs. Default is `false`

$ python httpstat.py www.google.com
Connected to 216.58.206.4:80 from 192.168.1.106:37920

HTTP/1.1 302 Found
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: http://www.google.gr/?gfe_rd=cr&ei=4bWUWJAnqML68Ae3gKqYBQ
Content-Length: 258
Date: Fri, 03 Feb 2017 14:54:57 GMT

Body stored in: /tmp/tmpRGDhKE

  DNS Lookup   TCP Connection   Server Processing   Content Transfer
[    12ms    |      51ms      |       52ms        |        1ms       ]
             |                |                   |                  |
    namelookup:12ms           |                   |                  |
                        connect:63ms              |                  |
                                      starttransfer:115ms            |
                                                                 total:116ms  

We cloned the repository, then noticed that there is a httpstat.py file in there, and we ran the file. The Python script accepts as a parameter a URL and that’s it. No need for compilation, aye!

We show the httpstat output for google.com. httpstat shows how much time it took for each individual stage of the transfer, in this case (no SSL/TLS, just the redirected page) is

  1. DNS Lookup
  2. TCP Connection
  3. Server Processing
  4. Content Transfer

A system administrator would need to reduce those times. For example, they could switch to a different server, get a faster server or optimize the server software so that it delivers the content much faster.

Set up Snapcraft

snapcraft is a utility that helps us create snaps. Let’s install snapcraft.

$ sudo apt update
...
Reading state information... Done
All packages are up to date.
$ sudo apt install snapcraft
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  snapcraft
...
Preparing to unpack .../snapcraft_2.26_all.deb ...
Unpacking snapcraft (2.26) ...
Setting up snapcraft (2.26) ...
$_

In Ubuntu 16.04, snapcraft was updated today (early Feb) and has a few differences from the previous version. Make sure you have snapcraft 2.26 or newer.

Let’s create a new directory for the development of the httpstat snap and initialize it with snapcraft so that create the necessary initial files.

$ mkdir httpstat
$ cd httpstat/
$ snapcraft init
Created snap/snapcraft.yaml.
Edit the file to your liking or run `snapcraft` to get started
$ ls -l
total 4
drwxrwxr-x 2 myusername myusername 4096 Feb   3 17:09 snap
$ ls -l snap/
total 4
-rw-rw-r-- 1 myusername myusername 676 Feb   3 17:09 snapcraft.yaml
$ _

We are in this httpstat/ directory and from here we run snapcraft in order to create the snap. snapcraft will take the instructions from snap/snapcraft.yaml and do its best to create the snap.

These are the contents of snap/snapcraft.yaml:

$ cat snap/snapcraft.yaml 
name: my-snap-name # you probably want to 'snapcraft register <name>'
version: '0.1' # just for humans, typically '1.2+git' or '1.3.2'
summary: Single-line elevator pitch for your amazing snap # 79 char long summary
description: |
  This is my-snap's description. You have a paragraph or two to tell the
  most important story about your snap. Keep it under 100 words though,
  we live in tweetspace and your description wants to look good in the snap
  store.

grade: devel # must be 'stable' to release into candidate/stable channels
confinement: devmode # use 'strict' once you have the right plugs and slots

parts:
  my-part:
    # See 'snapcraft plugins'
    plugin: nil
$ _

This snap/snapcraft.yaml configuration file is actually usable and can create an (empty) snap. Let’s create this empty snap, install it, uninstall it and then clean up to the initial pristine state.

$ snapcraft 
Preparing to pull my-part 
Pulling my-part 
Preparing to build my-part 
Building my-part 
Staging my-part 
Priming my-part 
Snapping 'my-snap-name' |                                                                 
Snapped my-snap-name_0.1_amd64.snap
$ snap install my-snap-name_0.1_amd64.snap 
error: cannot find signatures with metadata for snap "my-snap-name_0.1_amd64.snap"
$ snap install my-snap-name_0.1_amd64.snap --dangerous
error: cannot perform the following tasks:
- Mount snap "my-snap-name" (unset) (snap "my-snap-name" requires devmode or confinement override)
Exit 1
$ snap install my-snap-name_0.1_amd64.snap --dangerous --devmode
my-snap-name 0.1 installed
$ snap remove my-snap-name
my-snap-name removed
$ snapcraft clean
Cleaning up priming area
Cleaning up staging area
Cleaning up parts directory
$ ls
my-snap-name_0.1_amd64.snap  snap/
$ rm my-snap-name_0.1_amd64.snap 
rm: remove regular file 'my-snap-name_0.1_amd64.snap'? y
removed 'my-snap-name_0.1_amd64.snap'
$ _

While developing the snap, we will be going through this cycle of creating the snap, testing it and then removing it. There are ways to optimize a bit this process, learn soon we will.

In order to install the snap from a .snap file, we had to use –dangerous because the snap has not been digitally signed. We also had to use –devmode because snapcraft.yaml specifies the developer mode, which is a relaxed (in terms of permissions) development mode.

Creating the httpstat snapcraft.yaml, first part

Here is the first part of the httpstat snapcraft.yaml. The first part is about the description and we are not going to change anything from here later. The second part is the snap creation instructions and it is the interesting part for trial and error.

$ cat snap/snapcraft.yaml 
name: httpstat # you probably want to 'snapcraft register <name>'
version: '1.1.3' # just for humans, typically '1.2+git' or '1.3.2'
summary: Curl statistics made simple # 79 char long summary
description: |
    httpstat is a utility that analyses show fast is a website
    when you are trying to connect to it.
    This utility is particularly useful to Web administrators

grade: stable # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots

First, for the a name, we use httpstat. We are going to actually register it (snap register) further down in this HowTo, just before publishing the snap. If someone else is a maintainer of a package and it is a known major software package, we might need some extra steps to contact the maintainers or make our own httpstat-unofficial snap.

Second, we select a version. Instead of using the latest development version that might not work or may happen to be broken momentarily, you can pick and choose the stable branch or the latest tag.

The tag “v1.1.3” will do!

Third and fourth, we add a summary and a description from text we got from the httpstat Github page.

Fifth, we select a grade. That would be either devel or stable. This snap is going to be stable.

Sixth, we select the confinement of the snap. The best of the best is strict, which means that no much outside access is allowed outside. It is us who need to specify (afterwards) explicitly what actually is allowed. If you were to keep it at devmode, then there is no confinement at all and all is allowed just like with deb packages.

Creating the snapcraft.yaml, second part

Let’s start off with this initial version of the second part. This guide has helped us to figure out the initial stuff.

apps: 
  httpstat:
    command: bin/httpstat

parts:
  httpstat:
    plugin: python
    source: https://github.com/reorx/httpstat.git
    source-tag: v1.1.3

First, in apps section we specify that the users will be running an executable named httpstat, which can be found as bin/httpstat. Whether the real executable is bin/httpstat or something else, is determined by the parts section.

Second, in the parts section we provide instructions as to how to process this httpstat target.  We specify that we want to use the python plugin (snapcraft plugin reference), which is a plugin that performs python setup.py build and python setup.py install. Other plugins would ./configure; make; make install and so on. We specify the git URL for the source (note that it ends with .git) and the tag (snapcraft source reference).

Let’s join together the first part (it is the final version) and this second part (needs some more love),

$ cat snap/snapcraft.yaml 
name: httpstat # you probably want to 'snapcraft register <name>'
version: '1.1.3' # just for humans, typically '1.2+git' or '1.3.2'
summary: Curl statistics made simple # 79 char long summary
description: |
    httpstat is a utility that analyses show fast is a website
    when you are trying to connect to it.
    This utility is particularly useful to Web administrators

grade: stable # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots

apps: 
  httpstat:
    command: bin/httpstat

parts:
  httpstat:
    plugin: python
    source: https://github.com/reorx/httpstat.git
    source-tag: v1.1.3

Now we can run snapcraft, create the snap, install it and test it on a website. If we get an error, we fix it and try again.

$ snapcraft 
Preparing to pull httpstat 
...                                                       
Pulling httpstat 
...
Note: checking out '0f0e653309982178302ec1d5023bda2de047a72d'.
...
Successfully downloaded httpstat
Preparing to build httpstat 
Building httpstat 
...
Installing collected packages: httpstat
Successfully installed httpstat-1.1.3
Staging httpstat 
Priming httpstat 
Snapping 'httpstat' \                                                                     
Snapped httpstat_1.1.3_amd64.snap
$ snap install httpstat_1.1.3_amd64.snap --dangerous
httpstat 1.1.3 installed
$ httpstat www.google.com
Traceback (most recent call last):
  File "/snap/httpstat/x4/bin/httpstat", line 11, in <module>
    sys.exit(main())
  File "/snap/httpstat/x4/lib/python3.5/site-packages/httpstat.py", line 155, in main
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=cmd_env)
  File "/snap/httpstat/x4/usr/lib/python3.5/subprocess.py", line 947, in __init__
    restore_signals, start_new_session)
  File "/snap/httpstat/x4/usr/lib/python3.5/subprocess.py", line 1551, in _execute_child
    raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: 'curl'
Exit 1

We are almost there. Our confined httpstat snap needs to use a curl binary. Two ways to include this binary. The easy way is to stage the binary from the existing APT package of the Ubuntu repositories. The more involved way would be to freshly compile curl from source, with the opportunity to enable compilation flags to cut down the binary to the bare minimum.

If you prefer to try the more involved way, append these lines to the snapcraft.yaml file (therefore they go in the parts section) and you are set to go. These lines add a new parts subsection for curl, instructing to use autotools (./configure; make; make install) to compile the source of curl from github.

  curl:
    plugin: autotools
    source: https://github.com/curl/curl.git

In the following we are going to reuse the existing package for curl, found in the repositories. It is the same .deb file you get when you would run sudo apt install curl.

Here are the instructions to reuse an existing APT package that is found in the repositories. We use stage-packages and is put in the same level in the httpstat parts.

    stage-packages: 
        - curl

Here is the new version of snapcraft.yaml,

$ cat snap/snapcraft.yaml 
name: httpstat # you probably want to 'snapcraft register <name>'
version: '1.1.3' # just for humans, typically '1.2+git' or '1.3.2'
summary: Curl statistics made simple # 79 char long summary
description: |
    httpstat is a utility that analyses show fast is a website
    when you are trying to connect to it.
    This utility is particularly useful to Web administrators

grade: stable # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots

apps: 
  httpstat:
    command: bin/httpstat

parts:
  httpstat:
    plugin: python
    source: https://github.com/reorx/httpstat.git
    source-tag: v1.1.3
    stage-packages: 
        - curl

Let’s run snapcraft again and produce an updated snap.

$ snapcraft
Preparing to pull httpstat 
...
Get:42 http://gb.archive.ubuntu.com/ubuntu xenial-updates/main amd64 curl amd64 7.47.0-1ubuntu2.2 [139 kB]
...
Pulling httpstat 
...
Successfully downloaded httpstat
Preparing to build httpstat 
Building httpstat 
...
Collecting httpstat
Installing collected packages: httpstat
Successfully installed httpstat-1.1.3
Staging httpstat 
Priming httpstat 
Snapping 'httpstat' -                                                                     
Snapped httpstat_1.1.3_amd64.snap
$ _

We are ready to install the new snap and test it out.

$ snap install httpstat_1.1.3_amd64.snap --dangerous
 httpstat 1.1.3 installed
 $ httpstat google.com
 > curl -w <output-format> -D <tempfile> -o <tempfile> -s -S google.com
 curl error: curl: (6) Couldn't resolve host 'google.com'
 Exit 6

We are almost there! The snap does not have access to the Internet because of the strict confinement. We need to allow networking access while keep blocking everything else (for example, the httpstat would not have any access to our home directory).

To allow networking access to a snap, we need to specify the networking is OK for this snap. network is an interface in snaps and it is one of the many supported interfaces for snaps. There is the notion of plugs (provider of resource) and slots (consumer of resource). For most cases, like this one here, we need a plug, for network.

Here is how it is specified (and in general can have multiple items from the interface reference page for snaps),

    plugs:
      - network

Once we add these two lines, we reach the final version of snapcraft.yaml for httpstat.

name: httpstat # you probably want to 'snapcraft register <name>'
version: '1.1.3' # just for humans, typically '1.2+git' or '1.3.2'
summary: Curl statistics made simple # 79 char long summary
description: |
    httpstat is a utility that analyses show fast is a website
    when you are trying to connect to it.
    This utility is particularly useful to Web administrators

grade: stable # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots

apps: 
  httpstat:
    command: bin/httpstat
    plugs:
      - network

parts:
  httpstat:
    plugin: python
    source: https://github.com/reorx/httpstat.git
    source-tag: v1.1.3
    stage-packages: 
      - curl

Let’s get going, produce the snap, install it and test it!

$ snapcraft clean
Cleaning up priming area
Cleaning up staging area
Cleaning up parts directory
$ snapcraft 
Preparing to pull httpstat 
...
Get:42 http://gr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 curl amd64 7.47.0-1ubuntu2.2 [139 kB]
...
Pulling httpstat 
...
Successfully downloaded httpstat
Preparing to build httpstat 
Building httpstat 
...
Collecting httpstat
Installing collected packages: httpstat
Successfully installed httpstat-1.1.3
Staging httpstat 
Priming httpstat 
Snapping 'httpstat' /                                                                     
Snapped httpstat_1.1.3_amd64.snap
$ snap install httpstat_1.1.3_amd64.snap  --dangerous
httpstat 1.1.3 installed
$ httpstat https://www.google.com

HTTP/1.1 302 Found
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: https://www.google.gr/?gfe_rd=cr&ei=qCWWWPn3BLOT8QfItrHIDA
Content-Length: 259
Date: Sat, 04 Feb 2017 12:04:08 GMT
Alt-Svc: quic=":443"; ma=2592000; v="35,34"

Body stored in: /tmp/tmpwotxl1u0

  DNS Lookup   TCP Connection   SSL Handshake   Server Processing   Content Transfer
[     2ms    |       6ms      |     109ms     |       48ms        |        0ms       ]
             |                |               |                   |                  |
    namelookup:2ms            |               |                   |                  |
                        connect:8ms           |                   |                  |
                                    pretransfer:117ms             |                  |
                                                      starttransfer:165ms            |
                                                                                 total:165ms  
$ _

And that’s it! The snap, with strict confinement, works.

When we try the snap further, we might find enhancements and other ways to make it better. If someone wants to help, they simply need just this small snapcraft.yaml (gist) in order to try themselves to make the snap better. The first revision of the gist is the version that compiles curl from source.

Register the snap name

Before publishing publicly a snap, you first need to create an account for the Ubuntu Store (use your Launchpad.net account or Ubuntu Single Sign On (SSO) as it is now called, if you already have one). Then run snapcraft login to log in and then, snapcraft register to register the new package name. Here we go,

$ snapcraft login
Enter your Ubuntu One SSO credentials.
Email: me@example.com
Password: **********
We strongly recommend enabling multi-factor authentication: https://help.ubuntu.com/community/SSO/FAQs/2FA
Login successful.
$ snapcraft register httpstat
Registering httpstat.
Congratulations! You're now the publisher for 'httpstat'.

That’s it. Let’s see the snap in the list of our registered snaps,

$ snapcraft list-registered
Name         Since                 Visibility    Price    Notes
httpstat     2017-02-03T17:28:45Z  public        -        -

We are now ready to publish the snap.

Publish the snap

We publish the snap by first running snapcraft push. We push the *.snap file instead of the snapcraft.yaml. The process of creating an account to pushing and releasing the snap, is described at Publishing your snap.

$ snapcraft push httpstat_1.1.3_amd64.snap 
Pushing 'httpstat_1.1.3_amd64.snap' to the store.
Uploading httpstat_1.1.3_amd64.snap [                                                              ]   0%
Uploading httpstat_1.1.3_amd64.snap [==============================================================] 100%
Ready to release!|                                                                                       
Revision 1 of 'httpstat' created.

The snap has been uploaded, but not released yet to the public in one of the four channels, stable, candidate, beta or edge. Let’s see the snap online. Log in to https://myapps.developer.ubuntu.com/

When we click on the snap name, we get the detailed page for the snap. Here it is,

The important part is where it says Package status is Ready to publish. When that happens, and when it happens immediately, it means our snap managed to pass all the automated tests and it is ready to publish. For more complicated snaps, it requires a manual review process.

There are two ways to release a snap to the public, through the Web interface of the Ubuntu Store, and using snapcraft. We examine both options.

Release the snap using the Web interface of the Ubuntu Store

As shown in the screenshot of the snap details Web page, we click where it says the revision (#1) and the version (1.1.3). It looks like «#1       1.1.3» at the screenshot above. Here is the page of the Technical details for this revision and version.

A snap is released into channels. In the screenshot above, there is Channels, and a link called Release. Click on the link for Release.

Here we select the channels to release the snap in, and click on Release. We selected all channels. The most important is stable, which means the snap is public to everyone.

If you performed the release using Ubuntu Store, skip the following subsection about releasing the snap using snapcraft.

Release the snap using snapcraft

Let’s release the snap, with snapcraft release. There are four channels, stable, candidate, beta and edge. We release the snap to all four channels.

$ snapcraft release httpstat 1 edge
The 'edge' channel is now open.
$ snapcraft release httpstat 1 beta
The 'beta' channel is now open.
$ snapcraft release httpstat 1 candidate
The 'candidate' channel is now open.
$ snapcraft release httpstat 1 stable
The 'stable' channel is now open.
$ snapcraft status httpstat
Arch    Channel    Version    Revision
amd64   stable     1.1.3      1
        candidate  1.1.3      1
        beta       1.1.3      1
        edge       1.1.3      1

That’s it!

Install and run the new snap

We are going to uninstall the locally installed httpstat so that we can get it from the Ubuntu Store!

$ snap remove httpstat
httpstat removed
$ snap info httpstat
name:      httpstat
summary:   "Curl statistics made simple"
publisher: simosx
description: |
  httpstat is a utility that analyses show fast is a website
  when you are trying to connect to it.
  This utility is particularly useful to Web administrators
  
channels:              
  stable:    1.1.3 (1) 9MB -
  candidate: 1.1.3 (1) 9MB -
  beta:      1.1.3 (1) 9MB -
  edge:      1.1.3 (1) 9MB -

$ snap install httpstat
httpstat 1.1.3 from 'simosx' installed
$ snap info httpstat
name:      httpstat
summary:   "Curl statistics made simple"
publisher: simosx
description: |
  httpstat is a utility that analyses show fast is a website
  when you are trying to connect to it.
  This utility is particularly useful to Web administrators
  
commands:
  - httpstat
tracking:    stable
installed:   1.1.3 (1) 9MB -
refreshed:   2017-02-04 20:57:31 +0200 EET
channels:              
  stable:    1.1.3 (1) 9MB -
  candidate: 1.1.3 (1) 9MB -
  beta:      1.1.3 (1) 9MB -
  edge:      1.1.3 (1) 9MB -

As an alternative to installing by using the snap command, we can also install the snap in Ubuntu deskop using the Ubuntu Software. Here is how it looks!

Everything looks fine! Let’s finish the tutorial by httpstat-ing ubuntu.com 🙂

$ httpstat https://www.ubuntu.com
HTTP/1.1 200 OK
Date: Sat, 04 Feb 2017 20:23:50 GMT
Server: gunicorn/17.5
Strict-Transport-Security: max-age=15768000
Content-Type: text/html; charset=utf-8
Age: 17
Content-Length: 33671
X-Cache: HIT from privet.canonical.com
X-Cache-Lookup: HIT from privet.canonical.com:80
Via: 1.0 privet.canonical.com:80 (squid/2.7.STABLE7)
Vary: Accept-Encoding

Body stored in: /tmp/tmpybh9xabj

  DNS Lookup   TCP Connection   SSL Handshake   Server Processing   Content Transfer
[    10ms    |      61ms      |     135ms     |       63ms        |       123ms      ]
             |                |               |                   |                  |
    namelookup:10ms           |               |                   |                  |
                        connect:71ms          |                   |                  |
                                    pretransfer:206ms             |                  |
                                                      starttransfer:269ms            |
                                                                                 total:392ms  
post image

How to install Inkscape 0.92 (latest) as a snap in Ubuntu 16.04

Inkscape is professional open-source vector graphics editor. The latest version is 0.92. Here is a video demonstrating the new Inkscape 0.92 features. And detailed Inkscape 0.92 Release Notes.

Here is how to install as the Inkscape snap on Ubuntu 16.04 (and other GNU/Linux distributions that support snaps). The snap was created by Inkscape Board member Ted Gould.

Let’s see what is available as a snap for Inkscape.

$ snap info inkscape
name:      inkscape
summary:   "Vector Graphics Editor"
publisher: inkscape
description: |
  An Open Source vector graphics editor, with capabilities similar to
  Illustrator, CorelDraw, or Xara X, using the W3C standard Scalable Vector
  Graphics (SVG) file format.
  
  Inkscape supports many advanced SVG features (markers, clones, alpha blending,
  etc.) and great care is taken in designing a streamlined interface.
  It is very easy to edit nodes, perform complex path operations, trace
  bitmaps and much more.
  
  We also aim to maintain a thriving user and developer community by using
  open, community-oriented development.
  
channels:                      
  stable:    0.92.0     (1880) 148MB -
  candidate: 0.92.0     (2307) 149MB -
  beta:      0.92.0     (2307) 149MB -
  edge:      0.92+devel (2314) 149MB -

We can see that there is already a stable snap for 0.92. If we are comfortable with the stable snap (it’s 0.92!), we can install it from the Ubuntu Software as well.

The one with the nonfree tag is that snap. The other is the package from the repositories, an older version. For some reason, the snaps have the nonfree tag, which weirdly helps to distinguish from the repository packages.

Let’s install the stable Inkscape snap and let’s run it.

Ok, it has a retro look. What’s going on? Is retro in fashion again?

Let’s run the snapped Inkscape from the command line:

$ inkscape
Gtk-Message: Failed to load module "overlay-scrollbar"
Gtk-Message: Failed to load module "gail"
Gtk-Message: Failed to load module "atk-bridge"
Gtk-Message: Failed to load module "canberra-gtk-module"

So this is what is going on. There is a bug in the current stable version of the snap. These errors mean, among other things, that the theming is not working. You can read some feedback in a recent AskUbuntu answer about snap packaging by Sergio Schvezov. In addition, it was a bug that was mentioned on G+ a few days ago.

Let’s try out the package from the edge channel and see whether it has fixed the theming issue.

$ snap remove inkscape
inkscape removed
$ snap install inkscape --channel=edge
inkscape (edge) 0.92+devel from 'inkscape' installed

Instead of the option –channel=edge above, you can also use –edge. My preference is to show the verbose version when I type commands in tutorials so that it is easy to see that edge refers to the channel.

Let’s run the edge Inkscape from the command line.

$ inkscape
Gtk-Message: Failed to load module "canberra-gtk-module"
Gtk-Message: Failed to load module "canberra-gtk-module"

Only the canberra GTK module is missing now, which is a nice improvement. canberra refers to libcanberra and has to do with sound events.

Let’s try Inkscape, minus the sound events.

Here it is then, and it looks fine.

Most users do not know much about vector graphics. Inkscape makes it easy to learn because it has built-in tutorial.

Here is how to get it to load up.

You click on Help→Tutorials→Inkscape: Basic to start off with the first tutorial. You can see that there is a good set of tutorials.

Here is how the first tutorial looks like. It is an Inkscape document (*.svg), and you can freely edit the document while you are reading and learning more about Inkscape!

Make an effort to complete the full set of the Inkscape tutorials.

post image

How to try the new MUFFIN (“Ribbon”) toolbar of LibreOffice 5.3 in Ubuntu 16.04

LibreOffice 5.3 has several new features and one of them is the new MUFFIN toolbars.

Let’s try them out.

First, we installed LibreOffice 5.3 on Ubuntu using a snap and start the new version of LibreOffice Writer.

By default, the new MUFFIN toolbar is not available because it is currently an experimental feature. We need to enable the support for experimental features.

Click on the menu Tools→Options or press Alt+F12. You get the following,

In LibreOffice→Advanced, we enable the Enable experimental features (may be unstable) and click OK.

We are asked to restart LibreOffice and we click on Restart Now.

After the restart, there are a few new submenus in the View menu. Specifically, there is a Toolbar Layout submenu which a few options. The Notebookbar is the one that resembles the Ribbon in MSOffice. We select it.

The default Notebookbar is the one in the Tabbed style. There are two more styles as shown below.

The following is Contextual groups:

And this one is Contextual single:

post image

How to install LibreOffice 5.3 from snap on Ubuntu 16.04 (and others)

Update #1: 3 Feb 2017: The new LibreOffice 5.3 has been released to the stable snap channel, which means the process of installing is quite easier. See at the end of this post for the simplified instructions, to install from fresh or switch channel from edge to stable.

LibreOffice 5.3 was released a few days ago, and it has several new nice features.

LibreOffice 5.3, installed from a snap.

Caption 1  LibreOffice 5.3, installed from a snap.

The LibreOffice project provides a tarball for Ubuntu with the new version, that can be downloaded, extracted and then we can run it.

However, we can install a snap with LibreOffice 5.3, which makes it convenient for testing and not messing up our system.

The following apply to Ubuntu 16.04 or newer. It also applies to Ubuntu 14.04 once you follow this tutorial.

Let’s check what snaps are available for LibreOffice.

$ snap info libreoffice
name:      libreoffice
summary:   "LibreOffice is a powerful office suite including word processing and creation of spreadsheets, slideshows and databases"
publisher: canonical
description: |
  LibreOffice is a powerful office suite – its clean interface and
  feature-rich tools help you unleash your creativity and enhance your
  productivity. LibreOffice includes several applications that make it the most
  powerful Free and Open Source office suite on the market: Writer (word
  processing), Calc (spreadsheets), Impress (presentations), Draw (vector
  graphics and flowcharts), Base (databases), and Math (formula editing).
channels:                 
  stable:    5.2.3.2 (10) 364MB -
  candidate: 5.2.3.2 (10) 364MB -
  beta:      5.2.3.2 (10) 364MB -
  edge:      5.3.0.2 (14) 374MB -
$ _

We learn that there are several channels for snaps, and the new version of LibreOffice is currently in the edge channel. This channel is that channel that is less stable than all others. That is, if we go for edge, we are bleeding edge in terms of LibreOffice. And some things may not work due to packaging. By installing this snap, we help in testing the packaging of the LibreOffice snap.

Let’s install LibreOffice from the edge channel:

$ sudo snap install libreoffice --channel=edge
libreoffice (edge) 5.3.0.2 from 'canonical' installed
$ _

Let’s get some info again from the installed LibreOffice snap.

$ snap info libreoffice
name:      libreoffice
summary:   "LibreOffice is a powerful office suite including word processing and creation of spreadsheets, slideshows and databases"
publisher: canonical
description: |
  LibreOffice is a powerful office suite – its clean interface and
  feature-rich tools help you unleash your creativity and enhance your
  productivity. LibreOffice includes several applications that make it the most
  powerful Free and Open Source office suite on the market: Writer (word
  processing), Calc (spreadsheets), Impress (presentations), Draw (vector
  graphics and flowcharts), Base (databases), and Math (formula editing).
commands:
  - libreoffice.impress
  - libreoffice
  - libreoffice.math
  - libreoffice.writer
  - libreoffice.base
  - libreoffice.calc
  - libreoffice.draw
tracking:    edge
installed:   5.3.0.2 (14) 374MB -
refreshed:   2017-01-19 04:24:50 +0200 EET
channels:                 
  stable:    5.2.3.2 (10) 364MB -
  candidate: 5.2.3.2 (10) 364MB -
  beta:      5.2.3.2 (10) 364MB -
  edge:      5.3.0.2 (14) 374MB -

We verify that LibreOffice 5.3 was installed and now we know the new commands to run the new version.

Let’s figure out now how to run the new LibreOffice. Because we already have LibreOffice (the stock Ubuntu LibreOffice) installed.

$ whereis libreoffice
libreoffice: /usr/bin/libreoffice /usr/lib/libreoffice /etc/libreoffice 
/usr/share/libreoffice /snap/bin/libreoffice /snap/bin/libreoffice.calc 
/snap/bin/libreoffice.math /snap/bin/libreoffice.draw /snap/bin/libreoffice.writer 
/snap/bin/libreoffice.impress /snap/bin/libreoffice.base 
/usr/share/man/man1/libreoffice.1.gz
$ _

The stock LibreOffice is under the /usr tree. The freshly installed LibreOffice is under the /snap tree.

Caption 2  Trying to find “libreoffice” in Dash. It shows both the stock LibreOffice and the snapped LibreOffice.

The icons from both corresponding versions are the same. Empirically, the first for LibreOffice Writer would be the stock LibreOffice, while the second one is the snapped LibreOffice.

We can move the icons on the Launcher and then launch them. If we selected our preferred version, then we are fine. Otherwise, we try with the other same icon.

Here is how LibreOffice 5.3 Writer looks like.

Update #1 (3 Feb 2017)

Let’s try again to see whether there are new snaps for LibreOffice because we got a hint that the new LibreOffice 5.3 has hit the stable channel.

$ snap info libreoffice
name:      libreoffice
summary:   "LibreOffice is a powerful office suite including word processing and creation of spreadsheets, slideshows and databases"
publisher: canonical
description: |
  LibreOffice is a powerful office suite – its clean interface and
  feature-rich tools help you unleash your creativity and enhance your
  productivity. LibreOffice includes several applications that make it the most
  powerful Free and Open Source office suite on the market: Writer (word
  processing), Calc (spreadsheets), Impress (presentations), Draw (vector
  graphics and flowcharts), Base (databases), and Math (formula editing).
channels:                 
  stable:    5.3.0.3 (17) 374MB -
  candidate: 5.3.0.3 (17) 374MB -
  beta:      5.3.0.3 (17) 374MB -
  edge:      5.3.0.3 (17) 374MB -

Indeed, the testing snap that was initially in the edge channel, has been moved up to the rest of the channels and reached the stable channel.

If a snap is in the stable channel, this means we can install from Ubuntu Software. GUI time!

That is, open Ubuntu Software and perform a search for libreoffice. For some reason, the snaps in Ubuntu Software have the nonfree tag, so we have a hint that the first result is the snap.

Let’s click on the first result in order to get more info, before installing.

Yep, it is LibreOffice 5.3.0.3. I suppose that since it is a snap, it is assumed that it may contain non-free components. Considering that Ubuntu Software does not offer any other indication whether a package is traditional or a snap, it is important to have that hint.

We click to install. If we did not already sign in with a Launchpad.net account, it will ask us to input the email/password now (since this is a snap). If you do not have a Launchpad Single-SignOn account, create one at https://login.launchpad.net/ (it’s free).

Here is how it looks like in Ubuntu Software, having installed LibreOffice as a snap.

Let’s click on Launch to start LibreOffice. If you actually do that, you (with snapd version 2.21) actually launch LibreOffice Base. It’s a bug, https://bugs.launchpad.net/snappy/+bug/1661590

Until the bug gets fixed, launch the LibreOffice snap from Dash :-).

Update #2: 3 Feb 2017

Suppose you already installed LibreOffice from the edge channel and you want to switch to the stable channel. How do you do that?

Channel switching in snaps is supported since the summer, Snapd 2.0.10: new media interfaces, channel switching

Let’s try it out.

$ snap info libreoffice
name:      libreoffice
summary:   "LibreOffice is a powerful office suite including word processing and creation of spreadsheets, slideshows and databases"
publisher: canonical
description: |
  LibreOffice is a powerful office suite – its clean interface and
  feature-rich tools help you unleash your creativity and enhance your
  productivity. LibreOffice includes several applications that make it the most
  powerful Free and Open Source office suite on the market: Writer (word
  processing), Calc (spreadsheets), Impress (presentations), Draw (vector
  graphics and flowcharts), Base (databases), and Math (formula editing).
commands:
  - libreoffice.impress
  - libreoffice
  - libreoffice.math
  - libreoffice.writer
  - libreoffice.base
  - libreoffice.calc
  - libreoffice.draw
tracking:    edge
installed:   5.3.0.3 (17) 374MB -
refreshed:   2017-02-01 20:51:51 +0200 EET
channels:                 
  stable:    5.3.0.3 (17) 374MB -
  candidate: 5.3.0.3 (17) 374MB -
  beta:      5.3.0.3 (17) 374MB -
  edge:      5.3.0.3 (17) 374MB -

We are tracking the edge channel and want to switch to the stable channel. The snap is identical, so it should merely change the tracking parameter.

$ snap refresh libreoffice --channel=stable
snap "libreoffice" has no updates available

To switch channel, we need to refresh the installed snap, and indicate the new channel to switch to.

Unfortunately, both edge and stable have identical snaps and we probably have hit this bug (Channel switching (track new channel) does not work if the two channels happen to have identical snap packages). I tried with other snaps that had different versions between the channels and it worked just fine.

Therefore, for now, we can remove the snap and install again from the default channel.

$ snap remove libreoffice
libreoffice removed
$ snap install libreoffice
libreoffice 5.3.0.3 from 'canonical' installed

That’s it!