Skip to content

A survey for developers about application configuration

Hello

Markus Raab, the author of Elektra project, has created a survey to get FLOSS developer’s point of view on the configuration of application.

If you are a developer, please fill this survey to help Markus’ work on improving application configuration management. Feeling this survey should take about 15 mns.

Note that the survey will close on July 18th.

The fact that this blog comes 1 month after the beginning of the survey is entirely my fault. Sorry about that…

All the best

An improved Perl API for cme and Config::Model

Hello

While hacking on a script to update build dependencies on a Debian package, it occured to me that using Config::Model in a Perl program should be no more complicated than using cme from a shell script. That was an itch that I scratched immediately.

Fast forward a few days, Config::Model now features new cme() and modify() functions that have a behavior similar to cme modify command.

For instance, the following program is enough to update popcon’s configuration file:

use strict; # let's not forget best practices ;-)
use warnings;
use Config::Model qw(cme); # cme function must be imported
cme('popcon')->modify("PARTICIPATE=yes");

The object returned by cme() is a Config;:Model::Instance. All its methods are available for a finer control. For instance:

my $instance = cme('popcon');
$instance->load("PARTICIPATE=yes");
$instance->apply_fixes;
$instance->say_changes; 
$instance->save;

When run as root, the script above shows:

Changes applied to popcon configuration:
- PARTICIPATE: 'no' -> 'yes'

If need be, you can also retrieve the root node of the configuration tree to use Config;:Model::Node methods:

my $root_node = cme('popcon')->config_root;
say "is popcon active ? ",$root_node->fetch_element_value('PARTICIPATE');

In summary, using cme in a Perl program is now as easy as using cme from a shell script.

To provide feedback, comments, ideas, patches or to report problems, please follow the instructions from CONTRIBUTING page on github.

All the best

Automount usb devices with systemd

Hello

Ever since udisk-glue was obsoleted with udisk (the first generation), I’ve been struggling to find a solution to automatically mount a usb drive when such a device is connected to a kodi based home cinema PC. I wanted to avoid writing dedicated scripts or udev rules. Systemd is quite powerful and I thought that a simple solution should be possible using systemd configuration.

Actually, auto-mount notion covers 2 scenario :

  1. A device is mounted after being plugged in
  2. An already available device is mounted when a process accesses its mount point

The first case is the one that is needed with Kodi. The second may be useful so is  also documented in this post.

For the first case, add a line like the following in /etc/fstab:

/dev/sr0 /mnt/br auto defaults,noatime,auto,nofail 0 2

and reload systemd configuration:

sudo systemctl daemon-reload

The important parameters are “auto” and “nofail”: with “auto”, systemd mounts the filesystem as soon as the device is available. This behavior is different from sysvinit where “auto” is taken into account only when “mount -a” is run by init scripts. “nofail” ensures that boot does not fail when the device is not available.

The second case is handled by a line like the following one (even if the line is split here to improve readability):

/dev/sr0 /mnt/br auto defaults,x-systemd.automount,\
   x-systemd.device-timeout=5,noatime,noauto 0 2

With the line above in /etc/fstab, the file system is mounted when user does (for instance) “ls /mnt/br” (actually, the first “ls” fails and triggers the mount. A second “ls” gives the expected result. There’s probably a way to improve this behavior, but I’ve not found it… this is now fixed).

While testing automount, I realized that the unit may not be started after the daemon-reload command. To check the status of the created unit, run:

sudo systemctl status mnt-br.automount
● mnt-thumb.automount
   Loaded: loaded (/etc/fstab; generated)
   Active: inactive (dead)
    Where: /mnt/br
     Docs: man:fstab(5)
           man:systemd-fstab-generator(8)

In the example above, the unit was not started. Instead of rebooting, you can start the unit:

sudo systemctl start mnt-br.automount
● mnt-thumb.automount
   Loaded: loaded (/etc/fstab; generated)
   Active: active (waiting) since Sat 2018-03-31 12:09:53 CEST; 2s ago
    Where: /mnt/br
     Docs: man:fstab(5)
           man:systemd-fstab-generator(8)

“x-systemd.*” parameters are documented in systemd.mount(5).

Last but not least, using a plain device file (like /dev/sr0) works fine to automount optical devices. But it is difficult to predict the name of a device file created for a usb drive, so a LABEL or a UUID should be used in /etc/fstab instead of a plain device file. I.e. something like:

LABEL=my_usb_drive /mnt/my-drive auto defaults,auto,nofail 0 2

All the best

 

Perl6 is now up to date on Debian sid

Hello

Thanks to the help of Daniel Dehennin and Paul Cochrane, The rakudo implementation of Perl 6  is now up to date on Debian/sid.

Unlike previous version, Perl 6 on Debian uses moarvm backend. No other backend is provided.

Please use the following command to install Perl6 on Debian:

sudo apt-get install rakudo

All the best

Using custom cache object with AngularJS $http

Hello

At work, I’ve been bitten by the way AngularJS handles cache by default when using $https service. This post will show a simple way to improve cache handling with $http service.

The service I’m working on must perform the followings tasks:

  • retrieve data from a remote server.
  • save data to the same server.
  • retrieve the saved data and some extra information generated by the server to update a UI

At first, I’ve naively used $http.get cache parameter to enable or disable caching using a sequence like:

  1. $http.get(url, {cache: true} )
  2. $http.post(url)
  3. $http.get(url, {cache: false})
  4. $http.get(url, {cache: true})

Let’s say the calls above use the following data:

  1. $http.get(url, {cache: true}) returns “foo”
  2. $http.post(url) stores “bar”
  3. $http.get(url, {cache: false}) returns “bar”

I expected the next call $http.get(url, {cache: false}) to return “bar”. But no, I got “foo”, i.e. the obsolete data.

Turns out that cache object is completely left alone when {cache: false} is passed to $http.get.

ok. Fair enough. But this means that the value of the cache parameter should not change for a given URL. The default cache provided by $https cannot be cleared. (Well, actually, you can clear the cache under AngularJS’s hood, but that will probably not improve the readability of your code).

The naive approach does not work. Let’s try another solution by using a custom cache object as suggested by AngularJS doc. This cache object should be created by $cacheFactory service.

This cache object can then be passed to $http.get to be used as cache. When needed, the cache can be cleared. In the example above, the cache must be cleared after saving some data to the remote service.

There’s 2 possibilities to clear a cache:

  • Completely flush the cache using removeAll() function.
  • Clear the cache for the specific URL using remove(key) function. The only hitch is that the “key” used by $http is not documented.

So, we have to use the first solution and create a cache object for each API entry point:

angular.module('app').factory('myService', function ($http, $cacheFactory) {
  var myFooUrl = '/foo-rest-service';
  
  // create cache object. The cache id must be unique
  var fooCache = $cacheFactory('myService.foo'); 
  function getFooData () {
    return $http.get( myFooUrl, { cache: fooCache });
  };
 
  function saveFooData(data) {
    return $http.post( myFooUrl, { cache: fooCache }).then(function() {
      myCache.removeAll() ;
    });
  }
});

The code above ensures that:

  • cached data for foo service is always consistent
  • http get requests are not sent more than necessary

This simple approach has the following limitations:

  • cache is not refreshed if the data on the server are updated by another client
  • cache is flushed when only the browser page is reloaded

If you need more a more advance cache mechanism, you may want to check jmdobry’s angular cache project

All the best

How to automount optical media on Debian Linux for Kodi

Hello

This problem has been bugging me for a while: how to setup my Kodi based home cinema to automatically mount an optical media ?

Turns out the solution is quite simple, now that Debian has switched for systemd. Just add the following line to /etc/fstab:

/dev/sr0 /media/bluray auto defaults,nofail,x-systemd.automount 0 2

Where:

  • /dev/sr0 is the device file. You can also use one of the symbolic links setup by udev in /dev/disk/by-id
  • /media/bluray is the mount point. You can choose another mount point
  • nofail is required to avoid failure report when booting without a disc in the optical drive
  • x-systemd.automount is the option to configure systemd to automatically mount the inserted disc

Do not specify noauto: this would prevent systemd to automatically mount a disc, which defeats the purpose.

To test you setup:

  • Run the command journalctl -x -f in a terminal to check what is going on with systemd
  • Reload systemd configuration with sudo systemctl daemon-reload.
  • load a disc in your optical drive

Then, journalctl should show something like:

Sept. 27 16:07:01 frodo systemd[1]: Mounted /media/bluray.

And that’s it. No need to have obsolete packages like udisk-glue or autofs.

Last but not least: this blog is moderated, please do not waste your time (and mine) posting rants about systemd.

Edited: I’ve later realised that the instruction contained in this post works only if the mount point is opened, e.g. a program opens the mount point directory to check its content. Unfortunately, it’s not enough for kodi: once a media is plugged, systemd makes sure that the plugged device is ready to be mounted, but kodi does not know this. See this Automount usb devices with systemd for a solution.

All the best.

Major bug fix for cme update copyright command

Hello

Previous version of libconfig-model-dpkg-perl had 2 bugs related to copyright update command :

  • Too many directory paragraphs (like src/foo/*) were removed during update.
  • Some file paragraph were not merged, leading to needless paragraphs in debian/copyright file. This bug is less severe as no information is lost

Version 2.067 of libconfig-model-dpkg-perl fixes both issues. This version is available in unstable.

To use cme update dpkg-copyright command, the following packages are required:

All the best

Improving update of existing debian/copyright file

Hello

One of my last blog introduced the new cme update dpkg-copyright command and explained how to use this command to create a debian/copyright file from scratch.

We will see in this blog how cme update dpkg-copyright command can also be used if a debian/copyright file already exists.

During the lifetime of a package, creating a new debian/copyright copyright file should only happen once. When updating a package to a new upstream version, the content of the copyright file should be modified to reflect upstream changes by:

  • adding or removing file entries
  • updating © years or owners
  • updating licenses

cme update dpkg-copyright can be run with an existing debian/copyright file: the information extracted by licensecheck are merged in debian/copyright. Unfortunately, this merge may bring back the errors coming from licensecheck that you’ve cleaned up manually last time.

This last part is not optimal as the manual clean up must be repeated after cme update dpkg-copyright is run.

Here’s a way to avoid the last problem: cme update dpkg-copyright supports a way to modify the content of debian/copyright after the merge: the optional file debian/fix.scanned.copyright contains instructions to tweak the content of debian/copyright. (See Config::Model::Dpkg::Copyright man page for more details)

You may remember that Config::Model handles all configuration information as a tree. The information contained in the copyright file is also stored in a tree structure. debian/fix.scanned.copyright contains instructions to navigate this tree and modify the content of the tree.

Imagine that there’s a robot (or a monkey) in that configuration tree. Each instruction tells the robot either to move in the tree or to perform an operation.

The most useful instructions for debian/fix.scanned.copyright are:

  • ! to move to the root of the tree
  • = to assign a value , e.g: short_name=MIT or Copyright="2014, FooBar" (use double quotes when the value white space or other fancy characters).
  • .= to append to a value, e.g Copyright.=" Appended info."
  • =~ to apply a substitution with a Perl regexp, e.g. Copyright=~"/©\s*//g"
  • : to move a Files element, e.g. Files:"foo/baz.c"
  • :~ to remove a Files element, e.g. Files:~"bogus.c"

Otherwise:

  • Comments with # or // must begin at the beginning of the line
  • Instructions are separated by space(s) or new lines

Let’s see a commented example:

# go to the root of the tree (with '!')
# and remove a bogus Files entry (with ":~")
! Files:~"foo/bogus.c"

// go to a Files entry and append (operator '.=') some info to © owner
! Files:"foo/bar.h"
  Copyright.=" Appended info."

# go back to tree root and assign © info
! Files:"foo/baz.c" Copyright="2014, FooBar"

# add a global license and a file entry missed by licensecheck
# global license must be set before using it in Files entry
# note: MIT text license is provided by cme
! License=MIT
! Files:"3rdparty/missed.c" Copyright="2005 FooBar" License short_name=MIT

Other possible instructions for this file are described in Config::Model::Loader doc.

The number of instructions depends on the accuracy of licencecheck command. Hopefully, this number can be reduced by improving licensecheck.

Last but not least, the following packages are required:

You may want to install also libconfig-model-tkui-perl to update the copyright file with cme GUI.

In summary, the command cme updated dpkg-copyright associated with instructions stored in debian/fix.scanned.copyright enable Debian packagers to update with less effort debian/copyright file when updating a package.

All the best

The #newinjessie game: automatic configuration upgrade and other stuff in Debian/Jessie

Here are my contribution for the #newinjessie game, i.e. what new stuff I’ve contributed to the Jessie release of Debian.

See you in 2 years for Stretch release

All the best

Improving creation of debian copyright file

Hello

In my opinion, creating and maintaining Debian copyright file is the most boring task required to create a Debian package. Unfortunately, this file is also one of the most important of a package: it specifies some legal aspect regarding the use of the software.

Debian copyright file is scrutinized by ftp masters gatekeepers when accepting a new package in Debian project: this file must accurately describe the copyright and licenses of all files of a source package, preferably using a specific syntax. (Kudos to the ftp-masters team: reading copyright files must be even more boring than writing them).

The content of the copyright file must reflect accurately the license of all files. This license is often specified in the comments of a source files. The licensecheck command is able to scan sources files and reports the copyright and licenses declared in there. But it does not summarize this information: a copyright line is generated for each file of a package.

licensecheck2dep5 (provided by cdbs package as /usr/lib/cdbs/licensecheck2dep5) does better: the output of licensecheck is consolidated and translated in Debian copyright format. The result is better, but must be heavily edited to be reviewable by ftp-masters team.

The new update subcommand of cme (available with libconfig-model-dpkg-perl 2.061 currently in experimental) goes further than licensecheck2deb:

  • copyright are coalesced when possible (i.e. 2001,2002,2003-2005 is changed to 2001-2005)
  • file entries same copyright owner and license are grouped, group of files may be represented with a wild card (‘*’)
  • license text is filled with actual text for the most popular licenses

For instance, here’s the (slightly edited) output of cme run for pan package starting without debian/copyright file:

$ cme update dpkg-copyright
Adding dummy license text for license public-domain 
for path pan/general/sorted-vector.h
Adding dummy license text for license BSD-2-clause 
for path pan/usenet-utils/MersenneTwister.h
$ cat debian/copyright
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/

Files: *
Copyright: 1994-2001, Frank Pilhofer. The author may
License: GPL-2+

Files: pan/*
Copyright: 2002-2007, Charles Kerr 
License: GPL-2

Files: pan/data/cert-store.cc
  pan/data/cert-store.h
Copyright: 2011, Heinrich Müller 
  2002-2006, Charles Kerr 
License: GPL-2

Files: pan/general/e-util.cc
  pan/general/e-util.h
Copyright: 2000, 2001, Ximian, Inc
License: LGPL-2

Files: pan/general/locking.h
  pan/general/worker-pool.cc
  pan/general/worker-pool.h
Copyright: 2007, Calin Culianu 
  2002-2007, Charles Kerr 
License: LGPL-2+

Files: pan/general/sorted-vector.h
Copyright: 2002, Martin Holzherr (holzherr@infobrain.com).
License: public-domain
 Please fill license public-domain from header
 of pan/general/sorted-vector.h

[ about 100 more lines including license text for Zlib and several 
  GPL licenses ]

This is a good start, but some modifications must be applied to get a correct license file:

  • add missing upstream information (Upstream-Name, Upstream-Contact and Source items)
  • remove irrelevant text from some copyright owner (e.g. remove “The author may” from Files: * entry).
  • add some missing license text (e.g. include text from sorted-vector.h comments to specify upstream author’s version of public-domain)

These modifications can be done:

  • directly after update by running cme update dpkg-copyright --edit
  • after update by running cme edit dpkg-copyright
  • with your favorite editor

This post has mentioned creation of Debian copyright file, but does not address the problem of updating an existing copyright file when packaging a new version of a software. This will be the subject of a next post.

I hope this new feature of cme will save hours of work for Debian packagers. As usual comments and suggestions are welcome.

See also Updating debian copyright file with cme wiki page on github

Last but not least, the following packages are required:

You may want to install also libconfig-model-tkui-perl to update the copyright file with cme GUI.

All the best

 

[edited]:

  • Removed -quiet option from cme example. This option is not recommended to learn cme update.
  • Added link to github wiki page