From 26d5fbb15a91c6439bd83c8e99fd23b5c0173566 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Wed, 23 Oct 2013 17:17:41 +0000 Subject: Add fstab.configure This will allow the user to append text to /etc/fstab during a deployment, without having to write custom configuration extensions. --- morphlib/exts/fstab.configure | 40 ++++++++++++++++++++++ yarns/fstab-configure.yarn | 62 ++++++++++++++++++++++++++++++++++ yarns/implementations.yarn | 77 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100755 morphlib/exts/fstab.configure create mode 100644 yarns/fstab-configure.yarn diff --git a/morphlib/exts/fstab.configure b/morphlib/exts/fstab.configure new file mode 100755 index 00000000..0100dacb --- /dev/null +++ b/morphlib/exts/fstab.configure @@ -0,0 +1,40 @@ +#!/usr/bin/python +# Copyright (C) 2013 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# =*= License: GPL-2 =*= + + +import os +import sys + + +def asciibetical(strings): + + def key(s): + return [ord(c) for c in s] + + return sorted(strings, key=key) + + +fstab_filename = os.path.join(sys.argv[1], 'etc', 'fstab') + +fstab_vars = sorted(x for x in os.environ if x.startswith('FSTAB_')) +with open(fstab_filename, 'a') as f: + for var in fstab_vars: + f.write('%s\n' % os.environ[var]) + +os.chown(fstab_filename, 0, 0) +os.chmod(fstab_filename, 0644) diff --git a/yarns/fstab-configure.yarn b/yarns/fstab-configure.yarn new file mode 100644 index 00000000..cd7e7438 --- /dev/null +++ b/yarns/fstab-configure.yarn @@ -0,0 +1,62 @@ +`fstab.configure` +================= + +The `fstab.configure` extension appends text to the `/etc/fstab` from +environment variables beginning with `FSTAB_`. It also sets the +ownership and permissions of the file. + +The first thing to test is that the extension doesn't write anything +if not requested to do so, but does create the file if it doesn't +exist. + + SCENARIO fstab.configure does nothing by default + GIVEN a directory called tree/etc + WHEN fstab.configure is run against tree + THEN file tree/etc/fstab exists + AND file tree/etc/fstab has permissions -rw-r--r-- + AND file tree/etc/fstab is owned by uid 0 + AND file tree/etc/fstab is owned by gid 0 + AND file tree/etc/fstab is empty + +Append a something to the file, and verify the contents are exactly +correct. + + SCENARIO fstab.configure appends requested lines + GIVEN a directory called tree/etc + AND an environment variable FSTAB_FOO containing "foo" + WHEN fstab.configure is run against tree + THEN file tree/etc/fstab exists + AND file tree/etc/fstab has permissions -rw-r--r-- + AND file tree/etc/fstab is owned by uid 0 + AND file tree/etc/fstab is owned by gid 0 + AND file tree/etc/fstab contains "foo\n" + +Append something to an existing file, with wrong ownership and +permission. + + SCENARIO fstab.configure appends to existing file + GIVEN a directory called tree/etc + AND a file called tree/etc/fstab containing "# comment\n" + AND tree/etc/fstab is owned by uid 1 + AND tree/etc/fstab is owned by gid 1 + AND tree/etc/fstab has permissions 0600 + AND an environment variable FSTAB_FOO containing "foo" + WHEN fstab.configure is run against tree + THEN file tree/etc/fstab exists + AND file tree/etc/fstab has permissions -rw-r--r-- + AND file tree/etc/fstab is owned by uid 0 + AND file tree/etc/fstab is owned by gid 0 + AND file tree/etc/fstab contains "# comment\nfoo\n" + +Implement running `fstab.configure` +----------------------------------- + +When we actually run `fstab.configure`, we source `$DATADIR/env` to +get the desired environment variables. + + IMPLEMENTS WHEN fstab.configure is run against (\S+) + if [ -e "$DATADIR/env" ] + then + . "$DATADIR/env" + fi + "$SRCDIR/morphlib/exts/fstab.configure" "$DATADIR/$MATCH_1" diff --git a/yarns/implementations.yarn b/yarns/implementations.yarn index 6e1fae18..3d403f30 100644 --- a/yarns/implementations.yarn +++ b/yarns/implementations.yarn @@ -419,3 +419,80 @@ Generating a manifest. if ! grep -q hello_world "$DATADIR/manifest"; then die "Output isn't what we expect" fi + +IMPLEMENTS for test file and directory handling +=============================================== + +The IMPLEMENTS sections in this chapter create files and directories +for use as test data, and set and test their contents and permissions +and ownerships. + +Create a directory +------------------ + + IMPLEMENTS GIVEN a directory called (\S+) + mkdir -p "$DATADIR/$MATCH_1" + +Create a file +------------- + +The file contents is used as a `printf`(1) format string. + + IMPLEMENTS GIVEN a file called (\S+) containing "(.*)" + printf "$MATCH_2" > "$DATADIR/$MATCH_1" + +Set attributes on a file or directory +------------------------------------- + + IMPLEMENTS GIVEN (\S+) is owned by uid (\S+) + chown "$MATCH_2" "$DATADIR/$MATCH_1" + + IMPLEMENTS GIVEN (\S+) is owned by gid (\S+) + chgrp "$MATCH_2" "$DATADIR/$MATCH_1" + + IMPLEMENTS GIVEN (\S+) has permissions (\S+) + chmod "$MATCH_2" "$DATADIR/$MATCH_1" + +Check attributes of a file on the filesystem +-------------------------------------------- + + IMPLEMENTS THEN file (\S+) exists + test -e "$DATADIR/$MATCH_1" + + IMPLEMENTS THEN file (\S+) has permissions (\S+) + stat -c %A "$DATADIR/$MATCH_1" | grep -Fx -e "$MATCH_2" + + IMPLEMENTS THEN file (\S+) is owned by uid (\d+) + stat -c %u "$DATADIR/$MATCH_1" | grep -Fx -e "$MATCH_2" + + IMPLEMENTS THEN file (\S+) is owned by gid (\d+) + stat -c %g "$DATADIR/$MATCH_1" | grep -Fx -e "$MATCH_2" + + IMPLEMENTS THEN file (\S+) is empty + stat -c %s "$DATADIR/$MATCH_1" | grep -Fx 0 + +Check contents of a file +------------------------ + +We treat the contents of the file in the step as a `printf`(1) format +string, to allow newlines and other such stuff to be expressed. + + IMPLEMENTS THEN file (\S+) contains "(.*)" + printf "$MATCH_2" | diff - "$DATADIR/$MATCH_1" + + +IMPLEMENTS for running programs +=============================== + +This chapter contains IMPLEMENTS sections for running programs. It is +currently a bit of a placeholder. + +Remember environment variables to set when running +-------------------------------------------------- + +We need to manage the environment. We store the extra environment +variables in `$DATADIR/env`. We treat the value as a format string for +`printf`(1) so that newlines etc can be used. + + IMPLEMENTS GIVEN an environment variable (\S+) containing "(.*)" + printf "export $MATCH_1=$MATCH_2" >> "$DATADIR/env" -- cgit v1.2.1