snippet management for puppet

I’ve had some success using the emacs yasnippets package for Puppet snippet management.

Yasnippet has conditional expansion support so I able to set up a number of snippets that expanded differently based on which puppet the cursor whenever I hit “<backtic>-<backtic>-<tab>”, which is pretty easy to bang out on my keyboard.

The secret sauce was to use the elisp function ‘looking-back’ to to search backwards from cursor point for something that looks like ‘puppet-type {‘.

Here’s an example for cron:

# name : cron-quote
# key : ``
# condition : (looking-back "cron\s+\{[^\}]*")
# --
"${1:name}":
    command => "${2:command}",
    user => "${3:root}",
    hour => ${4:hour},
    minute => ${5:minute},
    $0;

I’ve posted the rest of my puppet-mode snipprts on github.
Enjoy.

improbable-bug-number-in-closes : your bug count is less than 100

Wondering how to get around the ‘improbable-bug-number-in-closes’  warning from Lintian, and can’t find the tag description ?

It is happening because your bug count is too low.

Solution:  Open at least 100 tickets.  Get cracking.

Using autoconf with Haskell FFI libraries

(This is a long post that’s not going to make much sense unless you’re interested in FFI (foreign function interface) libraries for Haskell.    If you don’t care about Haskell FFI libraries, then go check out Banjo Cat.)

I maintain a small Haskell library which provides Haskell bindings to the Augeas API.    Occasionally I put out a new version of the library when the Augueas API changes.   Of course, it usually takes a couple months for the API changes to surface in the Ubuntu augeas package, so I need build the Augeas libraries from source in order to update my library.  As a result, my Haskell library contains references to symbols that will be unresolved unless my users also build their Augeas library from source.

But, I want my users to be able to use the Haskell bindings with whatever version they may have available, so I like  I’d like it better if I didn’t have to force my users to also build Augeas from source.  Instead,  it would be better if somehow my build to somehow poll the user’s system to see what API methods were available, and then only compiled in support for the available methods.

The GNU autoconf tools can do this sort of library method polling, and there’s an autoconfUserHooks function that can be used in Setup.hs.  Here’s how I tied the two of these together for my project.

I’m going to assume you have the autoconf tools available in your development environment.  If you don’t have them installed, it shouldn’t be too hard to find them for your distribution of choice, or you could get the latest code from the folks at GNU..

Step 1: Write a configure.ac file:

The configure.ac file will be used by autoreconf to create your configure script.   Go through the template below and replace anything with ‘your-*’ with the values from your project.

## Replace yout-autoconf-vesion with your current autoconf version (autoconf --version)
## It should be an unquoted decimal value, like 2.65
AC_PREREQ(your-autoconf-version)
 
## Replace your-library with the name of your library
## Replace your-version with the Version value from your cabal file
AC_INIT([your-library],[your-version])
 
## Replace this with a file which should exist in your base source directory if you don't have a Setup.hs
## Your cabal file might be a good choice.
AC_CONFIG_SRCDIR(Setup.hs)
 
## This is the name of an include file that the ./configure script will create.
## I'll describe it more below
AC_CONFIG_HEADERS([Config.h])
 
## autoconfUserHooks requires this
AC_ARG_WITH([compiler],[])
 
## Check if your foreign library is available at all.
## Replace your-sanity-check-function with a function name from the foreign library which should be available from the very first release of the library.
## Replace your-foreign-library-name with the name of your foreign library
## Replace you-foreign-include-filename with the name of an include file which should be installed on the system if the development version of the library is installed.
## This block is first going to check if your base library is installed by checking if some 'should always exist' function can be found.
## Then its going to check if it can find the include file associated with the library .
## If it fails these tests, configure will return a non-zero value, and the build will fail.
 
sanity_check=no
dev_check=no
AC_SEARCH_LIBS([your-sanity-check-function],[your-foreign-library-name],[sanity-check=yes])
if test "x${sanity_check}" = "xyes" ; then
AC_CHECK_HEADERS([your-foreign-include-file-name],[dev_check=yes],[dev_check=no])
else
AC_MSG_ERROR([Unable to find your-sanity-check-function in your-foreign-library-name library.])
fi
if test "x${dev_check}" = "xno"; then
AC_MSG_ERROR([Unable to find your-foreign-include-filename])
fi
 
## Checking for available symbols.
## Go through your source and collect all the symbols you expect to be available in your foreign library.
## Then for each of the foreign functions you expect to be available, call the HAS_EXTERNAL_FUNC macro with
## the function name as the first argument, and the name for a unique macro definition you want written to your Config.h file
##
## Notes
## (Yes, If I mad more m4-fu, I could probably write this as a single argument macro.  I leave this as an exercise for the reader.)
 
AC_DEFUN([HAS_EXTERNAL_FUNC],
[
has_$1=no
AC_SEARCH_LIBS([$1],[your-foreign-library],[has_$1=yes])
if test "x${has_$1}" = "xyes"; then
     AC_DEFINE([$2],[],[your-foreign-library has the $1 function.])
fi
])
 
HAS_EXTERNAL_FUNC(your-foreign-function-name,HAS_YOUR_FOREIGN_FUNCTION_NAME)
HAS_EXTERNAL_FUNC(your-foreign-function-name2,HAS_YOUR_FOREIGN_FUNCTION_NAME2)
## ...
HAS_EXTERNAL_FUNC(your-foreign-function-namez,HAS_YOUR_FOREIGN_FUNCTION_NAMEZ)
 
## Builds an config.status file after ./configure is run
AC_OUTPUT

Step 2:  Build the configure script from the configure.ac file.

&gt; autoreconf
&gt; ./configure

The configure script should create a Config.h file.  For each found symbol, Config.h should contain something like

/* your-foreign-library has the your-foreign-function function. */
#define HAS_YOUR_FOREIGN_FUNCTION /**/

For each missing symbol, Configu.h should include something like

/* your-foregn-library library has the missing function. */
/* #undef HAS_MISSING */

Step 3: Uglify your Haskell source with conditional compilation.

Include the CPP  pragma in your source.  You most likely already using ForeignFunctionInterface, so your pragma line should look something like below.  Also include the Config.h file that ./configure created

{-# LANGUAGE CPP, ForeignFunctionInterface #-}
 
#ifndef _config_h
#include "../Config.h"
#define _config_h
#endif

Then for portion of the source where a foreign function is used, wrap it in a “#ifdef HAS_FUNCTION” wrapper. Below is an example from the haskell-augeas source for the small aug_error function.
Note if HAS_AUGEAS_ERROR isn’t defined, then the code compiles, but will report an error if called. There may be a better way to report the error, but this worked for my purposes.

-- ---------
-- aug_error
-- ---------
#ifdef HAS_AUGEAS_ERROR
foreign import ccall safe "augeas.h aug_error"
c_aug_error :: Ptr Augeas               -- aug
                -&gt; IO (AugErrCode)       -- error code
#endif
 
{-|
Return a human-readable message for the error code */
-}
aug_error :: Ptr Augeas  -- ^ Augeas pointer
               -&gt; IO (AugErrCode) -- ^ return value
aug_error aug_ptr =
#ifndef HAS_AUGEAS_ERROR
   Prelude.error "aug_error requires at least augeas version 0.6.0"
#else
   do
    ret &lt;- c_aug_error aug_ptr
    return(ret)
#endif

Also remember to add the wrappers around any test code that’s using foreign function calls.

Step 4:  Update your Setup.hs to call configure

If you’re using defaultUserHooks or simpleUserHooks in your Setup.hs,  switch to autoconfUserHooks.   This way running runghc Setup.hs build will call the ./configure script before compiling the source, so the Config.h include file will already exist.  This was just a simple swap in my case.

Step 5: Update your cabal file

In order for the Setup.hs sdist target to create a package which can be compiled from source, add the new configure.ac and configure scripts to the Extra-Sources-Files list in your cabal file.  Technically the configure script shouldn’t be included in the sdist package since it’s derived from the configure.ac file, but I think users expect there to already be a working configure script available out of the box.

Also add CPP to the Extentions list in the library block, otherwise  ‘runghc Setup.hs haddock’ will give an ‘error ../Config.h: No such file or dictionary’ error.

Name: your-package
...
Extra-Source-Files: Makefile, configure.ac, configure, Config.h.in

library
        ...
        Extensions: CPP

Step 6:  Add configure.ac to the VCS

The configure.ac file is a new source file, so don’t forgot to do your ‘darcs add’ equivilent for whatever VCS you’re using.

Step 7:  Maintenance

A new method may  be added to the foreign library.  At  that point you’ll have to add support the new method in your library.  To update your configure script, add a new HAS_EXTERNAL_FUNCTION line to your configure.ac file, and run ‘autoreconf’ to rebuild the configure script again.

And that’s all there is to it. Hopefully you’ve found this helpful.  If you find any errors, or if you have a better way of handling potentially missing symbols, please let me know about it.

(editted Dec 6th, 2010:  Updated step #5 to add Extensions:CPP for haddock support)

How many bailouts are too many for a three year old ?

Playing ‘pretend store’ with my three-year-old nephew “R” last night.

R:  What do you want ?

J:  Some fresh figs please.

R:  Here are some fig.

J:  How much do I owe you ?

R:  $10,000,000 !!!!

J:  What ?  I don’t need that much.  I need a bailout.

R:  What’s that ?

J:  A wheelbarrow full of money.

R:  OK.  Here it is.  Tens of hundreds of million dollars !! What do you want next ?

J:  Another bailout.

R:  OK.  Here it is.  Hundred of million dollars !  What do you want now ?

J:  I ran out of money again.  Another bailout, please..

R:  What ! No ! Stop that !

J:  OK, then I want a bonus.

R:  How much ?

J:  $10,000,000

R:  Too much ! What’s that for ?

J:  I’m too big to fail.

R:  Mooooooom !  Uncle Jude’s being silly again !

PXE-E61: Media test failure, check cable

I was getting the message above on my laptop when I turned it on.

Surprisingly, whacking the bottom 4 times fixed it.   Go figure.

-exclude-source-files with build_rpm

In setuptools, the bdist_egg command has an -exclude-source-files option that is missing in the bdist_rpm command.

So what’s the selfish sod to do if he wants to keep from distributing his source in an RPM ?

Including the install script below worked for me.

python setup.py bdist_rpm --install-script=install.sh

where install.sh is

python setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES
 
#goodbye py source
find $RPM_BUILD_ROOT -name \*.py -exec rm {} \;
sed -i '/\.py$/d' INSTALLED_FILES

warning: ‘sqlstm’ defined but not used

At my current job, I had the misfortune of having to deal with some Oracle Pro*C code. Since I’m a -Werror weenie, I was annoyed that this code was spitting out a ‘warning: ‘sqlstm’ defined but not used’ warning in all the proc generated source. Here’s how I inhibited the warning.

I added a new pc_common.h file

// If you know a better way to avoid the 'sqlstm' defined but not used warning, I tip my hat to you.
#define AVOID_THE_UNUSED_SQLSTM_WARNING(X) void avoid_the_sqlstm_defined_but_unused_warning_for_ ## X () { sqlstm = sqlstm; }

Then in some sample.pc that’s generating the warning:

#ifndef ORA_PROC
	#include "pc_common.h"
AVOID_THE_UNUSED_SQLSTM_WARNING(sample)
#endif

The problem is that the generated proc code includes a static struct named ‘sqlstm’, but then the generated code never references this struct. Instead it uses a local sqlstm variable whenever it’s used elsewhere in the generateed code.

The workaround adds a hopefully-unused function to the source that uses the static sqlstm struct. This is enough for the compiler to mark it as being used, even though the function itself is never used.

However, I did have to introduce the argument to the macro to force a unique name for these functions, since the linker will complain about there being multiple functions with the same signature in in different files.

Haskell FFI bindings for Augeas

I’ve published my first Haskell project on hackage.  Augeas, is a FFI binding for the Augeas API. I wrote it mainly to learn about Haskell’s FFI, and to keep busy while I was between jobs.  Also the API was small enough that it was a managable project.

Chapter 17 of Real World Haskell was very helpful during the project, however it didn’t cover file pointers, which were needed for the aug_print method.

The Bzlib2 Binding article in issue 2 of the Monad Reader, showed me how to do the Handle to CFile conversions, but I ran into some problems with their handleToCFile method during testing.

In my aug_print test, I was confused why I could no longer write to the Handle after calling aug_print. Eventually I found out that handleToFD closes the Handle passed to it.

I got around this by calling hDuplicate on the handle, and then calling handleToFD on the duplicate instead.

handleToCFile :: Handle -> String -> IO (Ptr CFile)
handleToCFile h m =
 do iomode <- newCString m
 
    -- Duplicate the handle, so the original stays open
    -- after the handleToFd call closes the duplicate
    dup_h <- hDuplicate h
    fd <- handleToFd dup_h
    fdopen fd iomode

Also, I made sure to close the Fd as well, which the Bzlib2 Bindings article did not show:

aug_print :: Ptr Augeas  -- ^ Augeas pointer
          -> Handle      -- ^ Already opened file handle
          -> ByteString  -- ^ PATH
          -> IO (AugRet) -- ^ return value
aug_print aug_ptr fptr_out bs_path =
    do
      useAsCString bs_path $ \path -> do
        out <- handleToCFile fptr_out "w"
        ret <- c_aug_print aug_ptr out path
        fflush out
        fclose out
        return(ret)

python-module-for-puppet

I’ve been using the python-module-for-puppet to make sure my build environment machines have the python modules they need.

The modules been working as advertised, but unfortunately some of machines need to be running older versions of a couple packages, so I forked the project and added support for an optional $version argument so the easy_install command could use “name==version” style commands.

It’s the first time I’ve submitted changes via github, so I hope it did it right.

So your wonky Indiana time zone is not mentioned in tzsetup-udeb ?

A bunch of  wonky Indiana time zones, were added to pkg-glibc/tzdata over 19 months ago, (along with a number of other time zone changes) but they still haven’t surfaced in the tzsetup-udeb package, as of 1/7/2009.

As a result, if you’re in one of these odd Indiana counties, the tzsetup portion of the installation won’t display your time zone, but you can set it to the correct time zone after the install finishes.

I filled bug 511153 after asking about it on the debian-boot IRC channel on irc.debian.org