From 13968d16f6fc06c5ca958b6489b29c8b1ed18a19 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 19 Nov 2012 10:36:52 +0100
Subject: [PATCH 01/26] change __jail to boolean, fixes #128

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 cdist/conf/type/__jail/gencode-remote     | 23 ++++++-----------------
 cdist/conf/type/__jail/man.text           | 22 +++++++++++-----------
 cdist/conf/type/__jail/parameter/boolean  |  3 +++
 cdist/conf/type/__jail/parameter/optional |  3 ---
 4 files changed, 20 insertions(+), 31 deletions(-)
 create mode 100644 cdist/conf/type/__jail/parameter/boolean

diff --git a/cdist/conf/type/__jail/gencode-remote b/cdist/conf/type/__jail/gencode-remote
index 4aff6509..56a1b643 100755
--- a/cdist/conf/type/__jail/gencode-remote
+++ b/cdist/conf/type/__jail/gencode-remote
@@ -34,15 +34,8 @@ fi
 
 state="$(cat "$__object/parameter/state")"
 
-if [ -f "$__object/parameter/started" ]; then
-   started="$(cat "$__object/parameter/started")"
-else
-   if [ ! "$state" = "present" ]; then
-      started="false"
-   else
-      started="true"
-   fi
-fi
+started="false"
+[ -f "$__object/parameter/started" -a "$state" = "present" ] && started="true"
 
 if [ -f "$__object/parameter/ip" ]; then
    ip="$(cat "$__object/parameter/ip")"
@@ -66,8 +59,8 @@ if [ -f "$__object/parameter/interface" ]; then
    interface="$(cat "$__object/parameter/interface")"
 fi
 
-if [ -f "$__object/parameter/devfs-enable" ]; then
-   devfsenable="$(cat "$__object/parameter/devfs-enable")"
+if [ -f "$__object/parameter/devfs-disable" ]; then
+   devfsenable="false"
 else
    devfsenable="true"
 fi
@@ -82,12 +75,12 @@ fi
 #     is pointless. Treat this as an error.
 if [ -n "$devfsruleset" -a "$devfsenable" = "false" ]; then
    exec >&2
-   echo "Can't have --devfs-ruleset defined without --devfs-enable true."
+   echo "Can't have --devfs-ruleset defined without --devfs-disable"
    exit 1
 fi
 
 if [ -f "$__object/parameter/onboot" ]; then
-   onboot="$(cat "$__object/parameter/onboot")"
+   onboot="true"
 fi
 
 if [ -f "$__object/parameter/jaildir" ]; then
@@ -357,7 +350,3 @@ else   # The jail does not currently exist
       exit 0
    fi
 fi
-
-# Debug
-#set +x
-
diff --git a/cdist/conf/type/__jail/man.text b/cdist/conf/type/__jail/man.text
index 8682effe..62b6e02e 100644
--- a/cdist/conf/type/__jail/man.text
+++ b/cdist/conf/type/__jail/man.text
@@ -27,9 +27,6 @@ OPTIONAL PARAMETERS
 name::
    The name of the jail. Default is to use the object_id as the jail name.
 
-started::
-   Either "true" or "false." Defaults to true.
-
 ip::
    The ifconfig style IP/netmask combination to use for the jail guest. If
    the state parameter is "present," this parameter is required.
@@ -41,23 +38,26 @@ interface::
    The name of the physical interface on the jail server to bind the jail to.
    Defaults to the first interface found in the output of ifconfig -l.
 
-devfs-enable::
-   Whether to allow devfs mounting within the jail. Must be "true" or "false."
-   Defaults to true.
-
 devfs-ruleset::
    The name of the devfs ruleset to associate with the jail. Defaults to
    "jailrules." This ruleset must be copied to the server via another type.
    To use this option, devfs-enable must be "true."
 
-onboot::
-   Whether to add the jail to rc.conf's jail_list variable. Must be either
-   "true" or "false." Defaults to false.
-
 jaildir::
    The location on the remote server to use for hosting jail filesystems.
    Defaults to /usr/jail.
 
+BOOLEAN PARAMETERS
+------------------
+started::
+   Whether to start jail
+
+devfs-disable::
+   Whether to disallow devfs mounting within the jail
+
+onboot::
+   Whether to add the jail to rc.conf's jail_list variable. 
+
 
 CAVEATS
 -------
diff --git a/cdist/conf/type/__jail/parameter/boolean b/cdist/conf/type/__jail/parameter/boolean
new file mode 100644
index 00000000..1dd61f6b
--- /dev/null
+++ b/cdist/conf/type/__jail/parameter/boolean
@@ -0,0 +1,3 @@
+onboot
+started
+devfs-disable
diff --git a/cdist/conf/type/__jail/parameter/optional b/cdist/conf/type/__jail/parameter/optional
index 1b5f0810..08ecd469 100644
--- a/cdist/conf/type/__jail/parameter/optional
+++ b/cdist/conf/type/__jail/parameter/optional
@@ -1,10 +1,7 @@
 name
-started
 ip
 hostname
 interface
-devfs-enable
 devfs-ruleset
-onboot
 jaildir
 jailbase

From d419722a2429c9527ee02dd3d7db1e50e6cf3272 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 19 Nov 2012 13:43:45 +0100
Subject: [PATCH 02/26] adapt documentation to use boolean parameter as well

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 cdist/conf/type/__jail/man.text | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/cdist/conf/type/__jail/man.text b/cdist/conf/type/__jail/man.text
index 62b6e02e..f4b9e3a1 100644
--- a/cdist/conf/type/__jail/man.text
+++ b/cdist/conf/type/__jail/man.text
@@ -78,7 +78,7 @@ __jail www --state present --ip "192.168.1.2" --jailbase /my/jail/base.tgz
 __jail www --state absent --jailbase /my/jail/base.tgz
 
 # Ensure that the jail called www is started
-__jail www --state present --started true \
+__jail www --state present --started \
    --ip "192.168.1.2 netmask 255.255.255.0" \
    --jailbase /my/jail/base.tgz
 
@@ -88,10 +88,10 @@ __jail thisjail --state present --name www \
    --jailbase /my/jail/base.tgz
 
 # Go nuts
-__jail lotsofoptions --state present --name testjail --started true \
+__jail lotsofoptions --state present --name testjail --started \
    --ip "192.168.1.100 netmask 255.255.255.0" \
    --hostname "testjail.example.com" --interface "em0" \
-   --onboot yes --jailbase /my/jail/base.tgz --jaildir /jails
+   --onboot --jailbase /my/jail/base.tgz --jaildir /jails
 --------------------------------------------------------------------------------
 
 

From 2fe647a1f718979da09b8cde00f9e4c4a1ccca9f Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 19 Nov 2012 15:17:46 +0100
Subject: [PATCH 03/26] Revert "implement before/after to declare dependencies
 and deprecate require"

Comment from asteven:
    Some problems showed up while updating the docs and tests.
    You should revert the merge for now.

This reverts commit 84770b9ef2afbfa1232845ce6538b56df99cee3a.
---
 cdist/core/cdist_object.py    |  2 --
 cdist/emulator.py             | 25 ++++---------------------
 cdist/resolver.py             | 17 +++--------------
 cdist/test/object/__init__.py |  1 -
 4 files changed, 7 insertions(+), 38 deletions(-)

diff --git a/cdist/core/cdist_object.py b/cdist/core/cdist_object.py
index 7e587bf3..90a21e59 100644
--- a/cdist/core/cdist_object.py
+++ b/cdist/core/cdist_object.py
@@ -186,8 +186,6 @@ class CdistObject(object):
         return os.path.join(self.path, "explorer")
 
     requirements = fsproperty.FileListProperty(lambda obj: os.path.join(obj.absolute_path, 'require'))
-    before = fsproperty.FileListProperty(lambda obj: os.path.join(obj.absolute_path, 'before'))
-    after = fsproperty.FileListProperty(lambda obj: os.path.join(obj.absolute_path, 'after'))
     autorequire = fsproperty.FileListProperty(lambda obj: os.path.join(obj.absolute_path, 'autorequire'))
     parameters = fsproperty.DirectoryDictProperty(lambda obj: os.path.join(obj.base_path, obj.parameter_path))
     explorers = fsproperty.DirectoryDictProperty(lambda obj: os.path.join(obj.base_path, obj.explorer_path))
diff --git a/cdist/emulator.py b/cdist/emulator.py
index bd3661d3..a9c760cb 100644
--- a/cdist/emulator.py
+++ b/cdist/emulator.py
@@ -23,7 +23,6 @@
 import argparse
 import logging
 import os
-import warnings
 import sys
 
 import cdist
@@ -93,12 +92,8 @@ class Emulator(object):
 
     def commandline(self):
         """Parse command line"""
-        self.meta_parameters = dict.fromkeys(('after', 'before'))
-        meta_parser = argparse.ArgumentParser(add_help=False)
-        for meta_parameter in self.meta_parameters.keys():
-            meta_parser.add_argument('--%s' % meta_parameter, action='append', required=False)
 
-        parser = argparse.ArgumentParser(add_help=False, parents=[meta_parser], argument_default=argparse.SUPPRESS)
+        parser = argparse.ArgumentParser(add_help=False, argument_default=argparse.SUPPRESS)
 
         for parameter in self.cdist_type.required_parameters:
             argument = "--" + parameter
@@ -124,11 +119,6 @@ class Emulator(object):
         self.args = parser.parse_args(self.argv[1:])
         self.log.debug('Args: %s' % self.args)
 
-        # Handle meta parameters
-        for meta_parameter in self.meta_parameters.keys():
-            if meta_parameter in self.args:
-                self.meta_parameters[meta_parameter] = getattr(self.args, meta_parameter)
-                delattr(self.args, meta_parameter)
 
     def setup_object(self):
         # Setup object_id - FIXME: unset / do not setup anymore!
@@ -185,18 +175,10 @@ class Emulator(object):
 
     def record_requirements(self):
         """record requirements"""
-        for key in ('before', 'after'):
-            if key in self.meta_parameters and self.meta_parameters[key]:
-                for value in self.meta_parameters[key]:
-                    self.log.debug("Recording requirement: %s %s %s", self.cdist_object.name, key, value)
-                    dependency_list = getattr(self.cdist_object, key)
-                    # append to the object.after or object.before lists
-                    dependency_list.append(value)
 
         if "require" in self.env:
-            warnings.warn("The 'require' envrionment variable is deprecated. Use the --before and --after meta parameters to define dependencies.", category=PendingDeprecationWarning, stacklevel=2)
-
             requirements = self.env['require']
+            self.log.debug("reqs = " + requirements)
             for requirement in requirements.split(" "):
                 # Ignore empty fields - probably the only field anyway
                 if len(requirement) == 0: continue
@@ -205,10 +187,11 @@ class Emulator(object):
                 cdist_object = self.cdist_object.object_from_name(requirement)
 
                 self.log.debug("Recording requirement: " + requirement)
+
                 # Save the sanitised version, not the user supplied one
                 # (__file//bar => __file/bar)
                 # This ensures pattern matching is done against sanitised list
-                self.cdist_object.after.append(cdist_object.name)
+                self.cdist_object.requirements.append(cdist_object.name)
 
     def record_auto_requirements(self):
         """An object shall automatically depend on all objects that it defined in it's type manifest.
diff --git a/cdist/resolver.py b/cdist/resolver.py
index d181d066..7e3a1a68 100644
--- a/cdist/resolver.py
+++ b/cdist/resolver.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# 2011-2012 Steven Armstrong (steven-cdist at armstrong.cc)
+# 2011 Steven Armstrong (steven-cdist at armstrong.cc)
 #
 # This file is part of cdist.
 #
@@ -109,21 +109,10 @@ class DependencyResolver(object):
                     raise RequirementNotFoundError(pattern)
 
     def _preprocess_requirements(self):
-        """Find all before, after and autorequire dependencies and merge them
-        to be just requirements for further processing.
+        """Find all autorequire dependencies and merge them to be just requirements
+        for further processing.
         """
         for cdist_object in self.objects.values():
-            if cdist_object.after:
-                cdist_object.requirements.extend(cdist_object.after)
-                # As we changed the object on disc, we have to ensure it is not 
-                # preprocessed again if someone would call us multiple times.
-                cdist_object.after = []
-            if cdist_object.before:
-                for other_object in self.find_requirements_by_name(cdist_object.before):
-                    other_object.requirements.append(cdist_object.name)
-                # As we changed the object on disc, we have to ensure it is not 
-                # preprocessed again if someone would call us multiple times.
-                cdist_object.before = []
             if cdist_object.autorequire:
                 # The objects (children) that this cdist_object (parent) defined
                 # in it's type manifest shall inherit all explicit requirements 
diff --git a/cdist/test/object/__init__.py b/cdist/test/object/__init__.py
index 7bdc037e..3a91f709 100644
--- a/cdist/test/object/__init__.py
+++ b/cdist/test/object/__init__.py
@@ -87,7 +87,6 @@ class ObjectTestCase(test.CdistTestCase):
         self.cdist_object.code_local = ''
         self.cdist_object.code_remote = ''
         self.cdist_object.state = ''
-        self.cdist_object.requirements = []
 
     def test_name(self):
         self.assertEqual(self.cdist_object.name, '__third/moon')

From 785c9ad4aae5df68a5a074c37a0584f8e0346f12 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 19 Nov 2012 15:20:22 +0100
Subject: [PATCH 04/26] no after/before for now (--changes)

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 docs/changelog | 1 -
 1 file changed, 1 deletion(-)

diff --git a/docs/changelog b/docs/changelog
index 943d83e4..798a5b00 100644
--- a/docs/changelog
+++ b/docs/changelog
@@ -10,7 +10,6 @@ next:
 	* New Type: __user_groups (Steven Armstrong)
 	* Type __user: Remove --groups support (now provided by __user_groups)
 	* Type __apt_ppa: Bugfix: Installeded ppa detection (Steven Armstrong)
-	* Core: Support for --after and --before parameters
 
 2.1.0pre8: 2012-11-15
 	* Type cleanup: __apt_ppa, __apt_ppa_update_index, __file, 

From 3dfad32d4c35b62f60612889e515300479e599ed Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 19 Nov 2012 17:24:01 +0100
Subject: [PATCH 05/26] add new type: __localch_kvm_vm

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 cdist/conf/type/__localch_kvm_vm/README       | 10 +++
 cdist/conf/type/__localch_kvm_vm/manifest     | 72 +++++++++++++++++++
 .../type/__localch_kvm_vm/parameter/optional  |  4 ++
 .../type/__localch_kvm_vm/parameter/required  |  2 +
 4 files changed, 88 insertions(+)
 create mode 100644 cdist/conf/type/__localch_kvm_vm/README
 create mode 100644 cdist/conf/type/__localch_kvm_vm/manifest
 create mode 100644 cdist/conf/type/__localch_kvm_vm/parameter/optional
 create mode 100644 cdist/conf/type/__localch_kvm_vm/parameter/required

diff --git a/cdist/conf/type/__localch_kvm_vm/README b/cdist/conf/type/__localch_kvm_vm/README
new file mode 100644
index 00000000..9752aad2
--- /dev/null
+++ b/cdist/conf/type/__localch_kvm_vm/README
@@ -0,0 +1,10 @@
+To be executed on the Xen Host.
+Using "xe" tool from Citrix Xen.
+
+Todo:
+
+    - Setup DNS -> bind 
+        - via puppet
+        - move away from puppet to cdist (intrusive)
+    - Boot VM
+    - Kickstart
diff --git a/cdist/conf/type/__localch_kvm_vm/manifest b/cdist/conf/type/__localch_kvm_vm/manifest
new file mode 100644
index 00000000..3e5df044
--- /dev/null
+++ b/cdist/conf/type/__localch_kvm_vm/manifest
@@ -0,0 +1,72 @@
+################################################################################
+# Default VM parameters
+#
+cores=4
+memory=$((8*1024*1024*1024))
+system_disk_size=$((50*1024*1024*1024))
+
+[ -f "$__object/parameter/memory" ] && memory="$(cat "$__object/parameter/memory")"
+[ -f "$__object/parameter/cores" ] && cores="$(cat "$__object/parameter/cores")"
+[ -f "$__object/parameter/system-disk-size" ] && system_disk_size="$(cat "$__object/parameter/system-disk-size")"
+
+# Convert memory to MiB (kvm/qemu requirement)
+memory_mebibytes=$(($memory/(1024*1024)))
+
+################################################################################
+# Required VM parameters
+#
+nic_pz="$(cat "$__object/parameter/nic-pz")"
+nic_fz="$(cat "$__object/parameter/nic-fz")"
+vm=$__object_id
+
+basedir=/opt/local.ch/sys/kvm/vm/$vm
+system_disk=$basedir/system-disk
+start_on_boot=$basedir/start-on-boot
+vnc_socket=unix:$basedir/vnc
+pidfile=$basedir/pid
+monitor=$basedir/monitor
+
+mkdir -p "$__object/files"
+start_file_source=$__object/files/start
+start_file_destination=$basedir/start
+
+#Base VM directory
+__directory $basedir --parents yes \
+    --owner root --group root
+
+cat << eof > "$start_file_source"
+#!/bin/sh
+# Generated shell script - do not modify
+#
+
+/usr/libexec/qemu-kvm \\
+    -name $vm \\
+    -enable-kvm \\
+    -m $memory_mebibytes \\
+    -drive file=${system_disk},if=virtio \\
+    -vnc $vnc_socket \\
+    -cpu host \\
+    -boot order=nc \\
+    -pidfile "$pidfile" \\
+    -monitor "unix:$monitor,server,nowait" \\
+    -net nic,macaddr=$nic_pz,model=virtio,vlan=200 \\
+        -net tap,script=/opt/local.ch/sys/kvm/bin/ifup-pz,downscript=/opt/local.ch/sys/kvm/bin/ifdown,vlan=200 \\
+    -net nic,macaddr=$nic_fz,model=virtio,vlan=300 \\
+        -net tap,script=/opt/local.ch/sys/kvm/bin/ifup-fz,downscript=/opt/local.ch/sys/kvm/bin/ifdown,vlan=300 \\
+    -smp $cores
+eof
+
+require="__directory/$basedir" __file $start_file_destination \
+    --source $start_file_source --mode 0755 --owner root --group root
+
+require="__directory/$basedir" __qemu_img "$system_disk" \
+    --size "$system_disk_size"
+
+# Normally, create a flag to start a VM on boot (if not
+# explicitly told we should not)
+if [ ! -f "$__object/parameter/do-not-start-on-boot" ]; then
+    require="__directory/$basedir" __file "$start_on_boot" \
+        --mode 0600 --owner root --group root
+else
+    __file "$start_on_boot" --state absent
+fi
diff --git a/cdist/conf/type/__localch_kvm_vm/parameter/optional b/cdist/conf/type/__localch_kvm_vm/parameter/optional
new file mode 100644
index 00000000..1b05d9fb
--- /dev/null
+++ b/cdist/conf/type/__localch_kvm_vm/parameter/optional
@@ -0,0 +1,4 @@
+cores
+memory
+system-disk-size
+do-not-start-on-boot
diff --git a/cdist/conf/type/__localch_kvm_vm/parameter/required b/cdist/conf/type/__localch_kvm_vm/parameter/required
new file mode 100644
index 00000000..01161205
--- /dev/null
+++ b/cdist/conf/type/__localch_kvm_vm/parameter/required
@@ -0,0 +1,2 @@
+nic-pz
+nic-fz

From a6452cfabd1215decdfaa8dbe4e254fb272f189f Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 19 Nov 2012 17:24:38 +0100
Subject: [PATCH 06/26] rename type to reflect new environment

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 cdist/conf/type/{__localch_kvm_vm => __nico_kvm_vm}/README        | 0
 cdist/conf/type/{__localch_kvm_vm => __nico_kvm_vm}/manifest      | 0
 .../type/{__localch_kvm_vm => __nico_kvm_vm}/parameter/optional   | 0
 .../type/{__localch_kvm_vm => __nico_kvm_vm}/parameter/required   | 0
 4 files changed, 0 insertions(+), 0 deletions(-)
 rename cdist/conf/type/{__localch_kvm_vm => __nico_kvm_vm}/README (100%)
 rename cdist/conf/type/{__localch_kvm_vm => __nico_kvm_vm}/manifest (100%)
 rename cdist/conf/type/{__localch_kvm_vm => __nico_kvm_vm}/parameter/optional (100%)
 rename cdist/conf/type/{__localch_kvm_vm => __nico_kvm_vm}/parameter/required (100%)

diff --git a/cdist/conf/type/__localch_kvm_vm/README b/cdist/conf/type/__nico_kvm_vm/README
similarity index 100%
rename from cdist/conf/type/__localch_kvm_vm/README
rename to cdist/conf/type/__nico_kvm_vm/README
diff --git a/cdist/conf/type/__localch_kvm_vm/manifest b/cdist/conf/type/__nico_kvm_vm/manifest
similarity index 100%
rename from cdist/conf/type/__localch_kvm_vm/manifest
rename to cdist/conf/type/__nico_kvm_vm/manifest
diff --git a/cdist/conf/type/__localch_kvm_vm/parameter/optional b/cdist/conf/type/__nico_kvm_vm/parameter/optional
similarity index 100%
rename from cdist/conf/type/__localch_kvm_vm/parameter/optional
rename to cdist/conf/type/__nico_kvm_vm/parameter/optional
diff --git a/cdist/conf/type/__localch_kvm_vm/parameter/required b/cdist/conf/type/__nico_kvm_vm/parameter/required
similarity index 100%
rename from cdist/conf/type/__localch_kvm_vm/parameter/required
rename to cdist/conf/type/__nico_kvm_vm/parameter/required

From 8408f433e997ed7eccbafd5fe847da8bce2704b6 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 19 Nov 2012 17:27:35 +0100
Subject: [PATCH 07/26] remove type from here - goes into cdist-nico repo

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 cdist/conf/type/__nico_kvm_vm/README          | 10 ---
 cdist/conf/type/__nico_kvm_vm/manifest        | 72 -------------------
 .../type/__nico_kvm_vm/parameter/optional     |  4 --
 .../type/__nico_kvm_vm/parameter/required     |  2 -
 4 files changed, 88 deletions(-)
 delete mode 100644 cdist/conf/type/__nico_kvm_vm/README
 delete mode 100644 cdist/conf/type/__nico_kvm_vm/manifest
 delete mode 100644 cdist/conf/type/__nico_kvm_vm/parameter/optional
 delete mode 100644 cdist/conf/type/__nico_kvm_vm/parameter/required

diff --git a/cdist/conf/type/__nico_kvm_vm/README b/cdist/conf/type/__nico_kvm_vm/README
deleted file mode 100644
index 9752aad2..00000000
--- a/cdist/conf/type/__nico_kvm_vm/README
+++ /dev/null
@@ -1,10 +0,0 @@
-To be executed on the Xen Host.
-Using "xe" tool from Citrix Xen.
-
-Todo:
-
-    - Setup DNS -> bind 
-        - via puppet
-        - move away from puppet to cdist (intrusive)
-    - Boot VM
-    - Kickstart
diff --git a/cdist/conf/type/__nico_kvm_vm/manifest b/cdist/conf/type/__nico_kvm_vm/manifest
deleted file mode 100644
index 3e5df044..00000000
--- a/cdist/conf/type/__nico_kvm_vm/manifest
+++ /dev/null
@@ -1,72 +0,0 @@
-################################################################################
-# Default VM parameters
-#
-cores=4
-memory=$((8*1024*1024*1024))
-system_disk_size=$((50*1024*1024*1024))
-
-[ -f "$__object/parameter/memory" ] && memory="$(cat "$__object/parameter/memory")"
-[ -f "$__object/parameter/cores" ] && cores="$(cat "$__object/parameter/cores")"
-[ -f "$__object/parameter/system-disk-size" ] && system_disk_size="$(cat "$__object/parameter/system-disk-size")"
-
-# Convert memory to MiB (kvm/qemu requirement)
-memory_mebibytes=$(($memory/(1024*1024)))
-
-################################################################################
-# Required VM parameters
-#
-nic_pz="$(cat "$__object/parameter/nic-pz")"
-nic_fz="$(cat "$__object/parameter/nic-fz")"
-vm=$__object_id
-
-basedir=/opt/local.ch/sys/kvm/vm/$vm
-system_disk=$basedir/system-disk
-start_on_boot=$basedir/start-on-boot
-vnc_socket=unix:$basedir/vnc
-pidfile=$basedir/pid
-monitor=$basedir/monitor
-
-mkdir -p "$__object/files"
-start_file_source=$__object/files/start
-start_file_destination=$basedir/start
-
-#Base VM directory
-__directory $basedir --parents yes \
-    --owner root --group root
-
-cat << eof > "$start_file_source"
-#!/bin/sh
-# Generated shell script - do not modify
-#
-
-/usr/libexec/qemu-kvm \\
-    -name $vm \\
-    -enable-kvm \\
-    -m $memory_mebibytes \\
-    -drive file=${system_disk},if=virtio \\
-    -vnc $vnc_socket \\
-    -cpu host \\
-    -boot order=nc \\
-    -pidfile "$pidfile" \\
-    -monitor "unix:$monitor,server,nowait" \\
-    -net nic,macaddr=$nic_pz,model=virtio,vlan=200 \\
-        -net tap,script=/opt/local.ch/sys/kvm/bin/ifup-pz,downscript=/opt/local.ch/sys/kvm/bin/ifdown,vlan=200 \\
-    -net nic,macaddr=$nic_fz,model=virtio,vlan=300 \\
-        -net tap,script=/opt/local.ch/sys/kvm/bin/ifup-fz,downscript=/opt/local.ch/sys/kvm/bin/ifdown,vlan=300 \\
-    -smp $cores
-eof
-
-require="__directory/$basedir" __file $start_file_destination \
-    --source $start_file_source --mode 0755 --owner root --group root
-
-require="__directory/$basedir" __qemu_img "$system_disk" \
-    --size "$system_disk_size"
-
-# Normally, create a flag to start a VM on boot (if not
-# explicitly told we should not)
-if [ ! -f "$__object/parameter/do-not-start-on-boot" ]; then
-    require="__directory/$basedir" __file "$start_on_boot" \
-        --mode 0600 --owner root --group root
-else
-    __file "$start_on_boot" --state absent
-fi
diff --git a/cdist/conf/type/__nico_kvm_vm/parameter/optional b/cdist/conf/type/__nico_kvm_vm/parameter/optional
deleted file mode 100644
index 1b05d9fb..00000000
--- a/cdist/conf/type/__nico_kvm_vm/parameter/optional
+++ /dev/null
@@ -1,4 +0,0 @@
-cores
-memory
-system-disk-size
-do-not-start-on-boot
diff --git a/cdist/conf/type/__nico_kvm_vm/parameter/required b/cdist/conf/type/__nico_kvm_vm/parameter/required
deleted file mode 100644
index 01161205..00000000
--- a/cdist/conf/type/__nico_kvm_vm/parameter/required
+++ /dev/null
@@ -1,2 +0,0 @@
-nic-pz
-nic-fz

From b996dcbae187ed5ab635d884bff80553e588a88b Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 19 Nov 2012 17:42:39 +0100
Subject: [PATCH 08/26] bugfix __qemu_img

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 cdist/conf/type/__qemu_img/gencode-remote | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cdist/conf/type/__qemu_img/gencode-remote b/cdist/conf/type/__qemu_img/gencode-remote
index e5ff1b4f..2a76cf8f 100644
--- a/cdist/conf/type/__qemu_img/gencode-remote
+++ b/cdist/conf/type/__qemu_img/gencode-remote
@@ -3,7 +3,7 @@
 # not existing and state != absent
 #
 state="present"
-[ -f "$__object/parameter/state" ] state="$(cat "$__object/parameter/state")"
+[ -f "$__object/parameter/state" ] && state="$(cat "$__object/parameter/state")"
 [ "$state" = "absent" ] && exit 0
 
 exists="$(cat "$__object/explorer/exists")"

From 661e33ac4b20cab30cb1d18075ed335f42b28042 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Tue, 20 Nov 2012 18:09:57 +0100
Subject: [PATCH 09/26] document on how to speed up shell execution

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 docs/man/man7/cdist-best-practice.text | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/docs/man/man7/cdist-best-practice.text b/docs/man/man7/cdist-best-practice.text
index a8851f7f..818c423a 100644
--- a/docs/man/man7/cdist-best-practice.text
+++ b/docs/man/man7/cdist-best-practice.text
@@ -30,6 +30,15 @@ Host *
   ControlPersist 10
 --------------------------------------------------------------------------------
 
+SPEEDING UP SHELL EXECUTION
+----------------------------
+On the source host, ensure that /bin/sh is *not* bash: bash is quite slow for
+script execution. Instead, you could use dash after installing it:
+
+--------------------------------------------------------------------------------
+ln -sf /bin/dash /bin/sh
+--------------------------------------------------------------------------------
+
 
 MULTI MASTER OR ENVIRONMENT SETUPS
 ----------------------------------

From 8bf196fdc0b62ce807ac5b526455dd64aaf6975b Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Tue, 20 Nov 2012 22:41:38 +0100
Subject: [PATCH 10/26] add helpful log message when resolving dependencies

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 cdist/resolver.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/cdist/resolver.py b/cdist/resolver.py
index 7e3a1a68..c1b2c292 100644
--- a/cdist/resolver.py
+++ b/cdist/resolver.py
@@ -77,6 +77,7 @@ class DependencyResolver(object):
         lists of all dependencies including the key object itself.
         """
         if self._dependencies is None:
+            log.info("Resolving dependencies...")
             self._dependencies = d = {}
             self._preprocess_requirements()
             for name,cdist_object in self.objects.items():

From a1ed12b382a9efb872c28cf372746b14ae1011d5 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 21 Nov 2012 09:21:13 +0100
Subject: [PATCH 11/26] roadmap proposal

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 docs/dev/logs/2012-11-21.roadmap-proposal | 6 ++++++
 1 file changed, 6 insertions(+)
 create mode 100644 docs/dev/logs/2012-11-21.roadmap-proposal

diff --git a/docs/dev/logs/2012-11-21.roadmap-proposal b/docs/dev/logs/2012-11-21.roadmap-proposal
new file mode 100644
index 00000000..cd60ffe6
--- /dev/null
+++ b/docs/dev/logs/2012-11-21.roadmap-proposal
@@ -0,0 +1,6 @@
+Target version      proposed date       features
+2.1.                2012-12-01          initial support for before/after requirements
+2.2.                2013-03-01          initial notifications support,
+                                        replace require="" with before/after
+2.3.                2013-06-01          installation support: pre-os and install types
+2.4.                2013-09-01          performance speedup via parallelisation

From 9e9271fd4f91d859145280c732d3f5dde8fc67cc Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 21 Nov 2012 09:44:38 +0100
Subject: [PATCH 12/26] why should I use cdist?

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 docs/web/cdist.mdwn     |  1 +
 docs/web/cdist/why.mdwn | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)
 create mode 100644 docs/web/cdist/why.mdwn

diff --git a/docs/web/cdist.mdwn b/docs/web/cdist.mdwn
index ee24e910..74457fc8 100644
--- a/docs/web/cdist.mdwn
+++ b/docs/web/cdist.mdwn
@@ -11,6 +11,7 @@ cdist is an alternative to other configuration management systems like
 [cfengine](http://www.cfengine.org/)
 and [puppet](http://www.puppetlabs.com/).
 
+ * [[Why should I use cdist?|why]]
  * [[Documentation|documentation]]
  * [[Supported Operating Systems|os]]
  * [[Installation|install]]
diff --git a/docs/web/cdist/why.mdwn b/docs/web/cdist/why.mdwn
new file mode 100644
index 00000000..883d6338
--- /dev/null
+++ b/docs/web/cdist/why.mdwn
@@ -0,0 +1,37 @@
+[[!meta title="Why should I use cdist?"]]
+
+There are several motivations to use cdist, these
+are probably the most popular ones.
+
+## Known language
+
+Cdist is being configured in
+[shell script](https://en.wikipedia.org/wiki/Shell_script).
+Shell script is used by UNIX system engineers for decades.
+So when cdist is introduced, your staff does not need to learn a new
+[DSL](https://en.wikipedia.org/wiki/Domain-specific_language)
+or programming language.
+
+## Powerful language
+
+Not only is shell scripting widely known by system engineers,
+but it is also a very powerful language. Here are some features
+which make daily work easy:
+
+ * Configuration can react dynamicly on explored values
+ * High level string manipulation (using sed, awk, grep)
+ * Conditional support (**if, case**)
+ * Loop support (**for, while**)
+ * Support for dependencies between cdist types
+
+## More than shell scripting
+
+If you compare regular shell scripting with cdist, there is one major
+difference: When using cdist types,
+the results are 
+[idempotent](https://en.wikipedia.org/wiki/Idempotence). 
+In practise, that means it does not matter in which order you 
+call cdist types, the result is always the same.
+
+
+[[!tag cdist unix]]

From 2b32e1e9f434744eaed836298ebd3b4b2463373b Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 21 Nov 2012 11:26:52 +0100
Subject: [PATCH 13/26] more reasons to use cdist

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 docs/web/cdist/why.mdwn | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/docs/web/cdist/why.mdwn b/docs/web/cdist/why.mdwn
index 883d6338..6aa3516f 100644
--- a/docs/web/cdist/why.mdwn
+++ b/docs/web/cdist/why.mdwn
@@ -1,5 +1,7 @@
 [[!meta title="Why should I use cdist?"]]
 
+[[!toc]]
+
 There are several motivations to use cdist, these
 are probably the most popular ones.
 
@@ -30,8 +32,40 @@ If you compare regular shell scripting with cdist, there is one major
 difference: When using cdist types,
 the results are 
 [idempotent](https://en.wikipedia.org/wiki/Idempotence). 
-In practise, that means it does not matter in which order you 
+In practise that means it does not matter in which order you 
 call cdist types, the result is always the same.
 
+## Zero dependency configuration management
+
+Cdist requires very litte on a target system. Even better,
+in almost all cases all dependencies are usually fulfilled.
+Cdist does not require an agent or a high level programming
+languages on the target host: it will run on any host that
+has an **ssh server running** and a posix compatible shell
+(**/bin/sh**).
+
+## Push based distribution
+
+Cdist uses the push based model for configuration. In this
+scenario, one (or more) computers connect the target hosts
+and apply the configuration. That way the source host has
+very little requirements: Cdist can even run on a sysadmin
+notebook that is loosely connected to the network and has
+limited amount of resources.
+
+Furthermore, from a security point of view, only one machine 
+needs access to the target hosts. No target hosts will ever
+need to connect back to the source host, which contains the
+full configuration.
+
+## Highly scalable
+
+If at some point you manage more hosts than can be handled from
+a single source host, you can simply add more resources: Either
+add more cores to one host or add hosts.
+Cdist will utilise the given resources in parallel.
+
+## Integration into inventory management
+
 
 [[!tag cdist unix]]

From 4d63694e20b3d564d148e272b0afb0c6c8002649 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 21 Nov 2012 11:34:32 +0100
Subject: [PATCH 14/26] introduce new web-doc target to publish only the web
 documentation

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 build | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/build b/build
index fb01c565..6fe8960f 100755
--- a/build
+++ b/build
@@ -331,14 +331,17 @@ eof
         done
     ;;
         
-    web)
-        set -e
+    web-doc)
         rsync -av "${basedir}/docs/web/" "${WEBTOPDIR}"
 
         cd "${WEBDIR}" && git add "${WEBBASE}"
         cd "${WEBDIR}" && git commit -m "cdist update" "${WEBBASE}" "${WEBPAGE}"
         cd "${WEBDIR}" && make pub
+    ;;
 
+    web)
+        set -e
+        $0 web-doc
         # Fix ikiwiki, which does not like symlinks for pseudo security
         ssh tee.schottelius.org \
           "cd /home/services/www/nico/www.nico.schottelius.org/www/software/cdist/man &&

From 9c99346ddf77935a81d80d24472ffa232b506847 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 21 Nov 2012 16:09:00 +0100
Subject: [PATCH 15/26] remove emtpy heading

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 docs/web/cdist/why.mdwn | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/docs/web/cdist/why.mdwn b/docs/web/cdist/why.mdwn
index 6aa3516f..0fcdf5c5 100644
--- a/docs/web/cdist/why.mdwn
+++ b/docs/web/cdist/why.mdwn
@@ -65,7 +65,4 @@ a single source host, you can simply add more resources: Either
 add more cores to one host or add hosts.
 Cdist will utilise the given resources in parallel.
 
-## Integration into inventory management
-
-
 [[!tag cdist unix]]

From 0c15d0ff024db2cfa8f29a8fcec39c5bd8b1e5b3 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 21 Nov 2012 22:52:14 +0100
Subject: [PATCH 16/26] ++ideas

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 docs/dev/logs/2012-11-21.idea-shell-testing | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 docs/dev/logs/2012-11-21.idea-shell-testing

diff --git a/docs/dev/logs/2012-11-21.idea-shell-testing b/docs/dev/logs/2012-11-21.idea-shell-testing
new file mode 100644
index 00000000..2a657053
--- /dev/null
+++ b/docs/dev/logs/2012-11-21.idea-shell-testing
@@ -0,0 +1,3 @@
+Use roundup for testing included types?
+
+    http://bmizerany.github.com/roundup/

From 1bd27fffaefffeb040a353da629ddad2a68d73a8 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Tue, 27 Nov 2012 10:57:10 +0100
Subject: [PATCH 17/26] __jail: started -> stopped, correct help output

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 cdist/conf/type/__jail/gencode-remote    | 6 +++---
 cdist/conf/type/__jail/man.text          | 4 ++--
 cdist/conf/type/__jail/parameter/boolean | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/cdist/conf/type/__jail/gencode-remote b/cdist/conf/type/__jail/gencode-remote
index 56a1b643..1f326bf1 100755
--- a/cdist/conf/type/__jail/gencode-remote
+++ b/cdist/conf/type/__jail/gencode-remote
@@ -34,8 +34,8 @@ fi
 
 state="$(cat "$__object/parameter/state")"
 
-started="false"
-[ -f "$__object/parameter/started" -a "$state" = "present" ] && started="true"
+started="true"
+[ -f "$__object/parameter/stopped" ] && started="false"
 
 if [ -f "$__object/parameter/ip" ]; then
    ip="$(cat "$__object/parameter/ip")"
@@ -75,7 +75,7 @@ fi
 #     is pointless. Treat this as an error.
 if [ -n "$devfsruleset" -a "$devfsenable" = "false" ]; then
    exec >&2
-   echo "Can't have --devfs-ruleset defined without --devfs-disable"
+   echo "Can't have --devfs-ruleset defined with --devfs-disable"
    exit 1
 fi
 
diff --git a/cdist/conf/type/__jail/man.text b/cdist/conf/type/__jail/man.text
index f4b9e3a1..48794637 100644
--- a/cdist/conf/type/__jail/man.text
+++ b/cdist/conf/type/__jail/man.text
@@ -49,8 +49,8 @@ jaildir::
 
 BOOLEAN PARAMETERS
 ------------------
-started::
-   Whether to start jail
+stopped::
+   Do not start the jail
 
 devfs-disable::
    Whether to disallow devfs mounting within the jail
diff --git a/cdist/conf/type/__jail/parameter/boolean b/cdist/conf/type/__jail/parameter/boolean
index 1dd61f6b..39144f6f 100644
--- a/cdist/conf/type/__jail/parameter/boolean
+++ b/cdist/conf/type/__jail/parameter/boolean
@@ -1,3 +1,3 @@
 onboot
-started
+stopped
 devfs-disable

From 868421bf16ffbc06f65278948997c73ad959ee5d Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Fri, 30 Nov 2012 10:01:37 +0100
Subject: [PATCH 18/26] Update examples to match new parameters

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 cdist/conf/type/__jail/man.text | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/cdist/conf/type/__jail/man.text b/cdist/conf/type/__jail/man.text
index 48794637..b439e0f5 100644
--- a/cdist/conf/type/__jail/man.text
+++ b/cdist/conf/type/__jail/man.text
@@ -77,8 +77,8 @@ __jail www --state present --ip "192.168.1.2" --jailbase /my/jail/base.tgz
 # Remove the jail called www
 __jail www --state absent --jailbase /my/jail/base.tgz
 
-# Ensure that the jail called www is started
-__jail www --state present --started \
+# The jail www should not be started
+__jail www --state present --stopped \
    --ip "192.168.1.2 netmask 255.255.255.0" \
    --jailbase /my/jail/base.tgz
 
@@ -88,7 +88,7 @@ __jail thisjail --state present --name www \
    --jailbase /my/jail/base.tgz
 
 # Go nuts
-__jail lotsofoptions --state present --name testjail --started \
+__jail lotsofoptions --state present --name testjail \
    --ip "192.168.1.100 netmask 255.255.255.0" \
    --hostname "testjail.example.com" --interface "em0" \
    --onboot --jailbase /my/jail/base.tgz --jaildir /jails

From 8e6073bc6f2061dfb8138a1064b8ebfd4262dcb9 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Fri, 30 Nov 2012 10:21:12 +0100
Subject: [PATCH 19/26] ++changes

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 docs/changelog | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/docs/changelog b/docs/changelog
index 798a5b00..87971c08 100644
--- a/docs/changelog
+++ b/docs/changelog
@@ -4,12 +4,16 @@ Changelog
 	* Changes are always commented with their author in (braces)
 	* Exception: No braces means author == Nico Schottelius
 
-next:
-	* Core: Ensure global and type explorers are executable
+2.1.0:
+	* Core: Ensure global explorers are executable
+	* Core: Ensure type explorers are executable (Steven Armstrong)
 	* Type __rvm_gemset: Change parameter "default" to be boolean
 	* New Type: __user_groups (Steven Armstrong)
 	* Type __user: Remove --groups support (now provided by __user_groups)
 	* Type __apt_ppa: Bugfix: Installeded ppa detection (Steven Armstrong)
+	* Type __jail: Change optional parameter "started" to boolean "stopped" parameter,
+		change optional parameter "devfs-enable" to boolean "devfs-disable" parameter and
+		change optional parameter "onboot" to boolean.
 
 2.1.0pre8: 2012-11-15
 	* Type cleanup: __apt_ppa, __apt_ppa_update_index, __file, 

From 3a419ed58b58ae80bca2b731d582a85744e1e656 Mon Sep 17 00:00:00 2001
From: Steven Armstrong <steven@icarus.ethz.ch>
Date: Fri, 30 Nov 2012 10:29:20 +0100
Subject: [PATCH 20/26] make type explorers executable after transfering them

Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>
---
 cdist/core/explorer.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cdist/core/explorer.py b/cdist/core/explorer.py
index 86ce52ac..d926552a 100644
--- a/cdist/core/explorer.py
+++ b/cdist/core/explorer.py
@@ -153,7 +153,7 @@ class Explorer(object):
                 destination = os.path.join(self.remote.type_path, cdist_type.explorer_path)
                 self.remote.mkdir(destination)
                 self.remote.transfer(source, destination)
-                self.remote.run(["chmod", "0700", "%s" % (destination)])
+                self.remote.run(["chmod", "0700", "%s/*" % (destination)])
                 self._type_explorers_transferred.append(cdist_type.name)
 
     def transfer_object_parameters(self, cdist_object):

From 1ef5bcaa74cecefc85c0d53d484e2559bc3aba7d Mon Sep 17 00:00:00 2001
From: Steven Armstrong <steven@icarus.ethz.ch>
Date: Fri, 30 Nov 2012 11:59:38 +0100
Subject: [PATCH 21/26] new type: __ssh_authorized_keys - manage ssh
 authorized_keys files

Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>
---
 .../type/__ssh_authorized_keys/explorer/entry |  45 ++++++++
 .../__ssh_authorized_keys/explorer/passwd     |  23 ++++
 .../type/__ssh_authorized_keys/gencode-remote |  82 ++++++++++++++
 .../conf/type/__ssh_authorized_keys/man.text  | 101 ++++++++++++++++++
 .../conf/type/__ssh_authorized_keys/manifest  |  74 +++++++++++++
 .../__ssh_authorized_keys/parameter/boolean   |   2 +
 .../__ssh_authorized_keys/parameter/optional  |   4 +
 .../parameter/required_multiple               |   1 +
 8 files changed, 332 insertions(+)
 create mode 100755 cdist/conf/type/__ssh_authorized_keys/explorer/entry
 create mode 100755 cdist/conf/type/__ssh_authorized_keys/explorer/passwd
 create mode 100755 cdist/conf/type/__ssh_authorized_keys/gencode-remote
 create mode 100644 cdist/conf/type/__ssh_authorized_keys/man.text
 create mode 100755 cdist/conf/type/__ssh_authorized_keys/manifest
 create mode 100644 cdist/conf/type/__ssh_authorized_keys/parameter/boolean
 create mode 100644 cdist/conf/type/__ssh_authorized_keys/parameter/optional
 create mode 100644 cdist/conf/type/__ssh_authorized_keys/parameter/required_multiple

diff --git a/cdist/conf/type/__ssh_authorized_keys/explorer/entry b/cdist/conf/type/__ssh_authorized_keys/explorer/entry
new file mode 100755
index 00000000..9992d32d
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/explorer/entry
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# 2012 Steven Armstrong (steven-cdist at armstrong.cc)
+#
+# This file is part of cdist.
+#
+# cdist 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, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist 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 cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+
+owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")"
+if [ -f "$__object/parameter/file" ]; then
+   file="$(cat "$__object/parameter/file")"
+else
+   home="$("$__type_explorer/passwd" | cut -d':' -f 6)"
+   file="$home/.ssh/authorized_keys"
+fi
+
+# no authorized_keys file, nothing we could do
+[ -f "$file" ] || exit 0
+
+# NOTE: keep variables in sync in manifest/explorer/gencode-*
+prefix="#cdist:$__object_name"
+suffix="#/cdist:$__object_name"
+awk -v prefix="$prefix" -v suffix="$suffix" '{
+   if (index($0,prefix)) {
+      triggered=1
+   }
+   if (triggered) {
+      if (index($0,suffix)) {
+            triggered=0
+      }
+      print
+   }
+}' "$file"
diff --git a/cdist/conf/type/__ssh_authorized_keys/explorer/passwd b/cdist/conf/type/__ssh_authorized_keys/explorer/passwd
new file mode 100755
index 00000000..e6352ee0
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/explorer/passwd
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# 2012 Steven Armstrong (steven-cdist at armstrong.cc)
+#
+# This file is part of cdist.
+#
+# cdist 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, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist 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 cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+
+owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")"
+
+getent passwd "$owner" || true
diff --git a/cdist/conf/type/__ssh_authorized_keys/gencode-remote b/cdist/conf/type/__ssh_authorized_keys/gencode-remote
new file mode 100755
index 00000000..cc86cc19
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/gencode-remote
@@ -0,0 +1,82 @@
+#!/bin/sh
+#
+# 2012 Steven Armstrong (steven-cdist at armstrong.cc)
+#
+# This file is part of cdist.
+#
+# cdist 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, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist 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 cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+
+owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")"
+if [ -f "$__object/parameter/file" ]; then
+   file="$(cat "$__object/parameter/file")"
+else
+   home="$(cut -d':' -f 6 "$__object/explorer/passwd")"
+   file="$home/.ssh/authorized_keys"
+fi 
+
+entry="$__object/files/entry"
+if [ ! -s "$__object/explorer/entry" ]; then
+   state_is='absent'
+else
+   state_is=$(diff -q "$entry" "$__object/explorer/entry" >/dev/null \
+      && echo present \
+      || echo changed
+   )
+fi
+
+state_should="$(cat "$__object/parameter/state" 2>/dev/null || echo present)"
+if [ "$state_should" = "$state_is" ]; then
+   # Nothing to do, move along
+   exit 0
+fi
+
+remove_entry() {
+   # NOTE: keep variables in sync in manifest/explorer/gencode-*
+   prefix="#cdist:$__object_name"
+   suffix="#/cdist:$__object_name"
+   cat << DONE
+tmpfile=\$(mktemp)
+awk -v prefix="$prefix" -v suffix="$suffix" '
+{
+   if (index(\$0,prefix)) {
+      triggered=1
+   }
+   if (triggered) {
+      if (index(\$0,suffix)) {
+         triggered=0
+      }
+   } else {
+      print
+   }
+}' "$file" > "\$tmpfile"
+mv -f "\$tmpfile" "$file"
+DONE
+}
+
+case "$state_should" in
+   present)
+      if [ "$state_is" = "changed" ]; then
+         remove_entry
+      fi
+      cat << DONE
+cat >> "$file" << ${__type##*/}_DONE
+$(cat "$entry")
+${__type##*/}_DONE
+DONE
+   ;;
+   absent)
+      remove_entry
+   ;;
+esac
diff --git a/cdist/conf/type/__ssh_authorized_keys/man.text b/cdist/conf/type/__ssh_authorized_keys/man.text
new file mode 100644
index 00000000..7177f26e
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/man.text
@@ -0,0 +1,101 @@
+cdist-type__ssh_authorized_keys(7)
+==================================
+Steven Armstrong <steven-cdist--@--armstrong.cc>
+
+
+NAME
+----
+cdist-type__ssh_authorized_keys - manage ssh authorized_keys files
+
+
+DESCRIPTION
+-----------
+Adds or removes ssh keys from a authorized_keys file.
+
+This type also manages the directory containing the authorized_keys
+file and sets strict ownership and permissions. You can disable this feature
+with the --noparent boolean parameter.
+
+The existence, ownership and permissions of the authorized_keys file itself are
+also managed. This can be disabled with the --nofile boolean parameter. It is
+then left to the user to ensure that the file exists and that ownership and 
+permissions work with ssh.
+
+
+REQUIRED PARAMETERS
+-------------------
+key::
+   the ssh key which shall be added to this authorized_keys file.
+   Must be a string and can be specified multiple times.
+
+
+OPTIONAL PARAMETERS
+-------------------
+owner::
+   the user owning the authorized_keys file, defaults to object_id.
+
+state::
+   if the given keys should be 'present' or 'absent', defaults to 'present'.
+
+file::
+   an alternative destination file, defaults to ~$owner/.ssh/authorized_keys
+
+comment::
+   an optional comment
+
+
+BOOLEAN PARAMETERS
+------------------
+noparent::
+   don't create or change ownership and permissions of the directory containing
+   the authorized_keys file
+
+nofile::
+   don't manage existence, ownership and permissions of the the authorized_keys
+   file
+
+
+EXAMPLES
+--------
+
+--------------------------------------------------------------------------------
+# add your ssh key to remote root's authorized_keys file
+__ssh_authorized_keys root \
+   --key "$(cat ~/.ssh/id_rsa.pub)"
+
+# allow key to login as user-name
+__ssh_authorized_keys user-name \
+   --key "ssh-rsa AXYZAAB3NzaC1yc2..."
+
+# same as above, but with explicit owner, two keys and a comment
+__ssh_authorized_keys some-fancy-id \
+   --owner user-name \
+   --key "ssh-rsa AXYZAAB3NzaC1yc2..." \
+   --key "ssh-rsa AZXYAAB3NzaC1yc2..." \
+   --comment "allow the members of project foo to login"
+
+# same as above, but authorized_keys file in non standard location
+__ssh_authorized_keys some-fancy-id \
+   --file /etc/ssh/keys/user-name/authorized_keys \
+   --owner user-name \
+   --key "ssh-rsa AXYZAAB3NzaC1yc2..."
+
+# same as above, but directory and authorized_keys file is created elswhere
+__ssh_authorized_keys some-fancy-id \
+   --file /etc/ssh/keys/user-name/authorized_keys \
+   --owner user-name \
+   --noparent \
+   --nofile \
+   --key "ssh-rsa AXYZAAB3NzaC1yc2..."
+--------------------------------------------------------------------------------
+
+
+SEE ALSO
+--------
+- cdist-type(7)
+
+
+COPYING
+-------
+Copyright \(C) 2012 Steven Armstrong. Free use of this software is
+granted under the terms of the GNU General Public License version 3 (GPLv3).
diff --git a/cdist/conf/type/__ssh_authorized_keys/manifest b/cdist/conf/type/__ssh_authorized_keys/manifest
new file mode 100755
index 00000000..268b1fbe
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/manifest
@@ -0,0 +1,74 @@
+#!/bin/sh
+#
+# 2012 Steven Armstrong (steven-cdist at armstrong.cc)
+#
+# This file is part of cdist.
+#
+# cdist 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, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist 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 cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+
+owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")"
+state="$(cat "$__object/parameter/present" 2>/dev/null || echo "present")"
+if [ -f "$__object/parameter/file" ]; then
+   file="$(cat "$__object/parameter/file")"
+else
+   home="$(cut -d':' -f 6 "$__object/explorer/passwd")"
+   if [ -z "$home" ]; then
+      echo "Failed to get home directory from explorer." >&2
+      exit 1
+   fi
+   file="$home/.ssh/authorized_keys"
+fi
+
+if [ ! -f "$__object/parameter/noparent" -o ! -f "$__object/parameter/nofile" ]; then
+   group="$(cut -d':' -f 4 "$__object/explorer/passwd")"
+   if [ -z "$group" ]; then
+      echo "Failed to get owners group from explorer." >&2
+      exit 1
+   fi
+
+   if [ ! -f "$__object/parameter/noparent" ]; then
+      # Ensure that the directory in which the authorized_keys shall be exists and 
+      # has the right permissions.
+      ssh_directory="${file%/*}"
+      __directory "$ssh_directory" --state present --parents \
+         --owner "$owner" --group "$group" --mode 0700
+      export require="__directory/$ssh_directory"
+   fi
+   if [ ! -f "$__object/parameter/nofile" ]; then
+      # Ensure that authorized_keys file exists and has the right permissions.
+      __file "$file" \
+         --owner "$owner" \
+         --group "$group" \
+         --mode 0600 \
+         --state exists
+   fi
+fi
+
+# NOTE: keep variables in sync in manifest/explorer/gencode-*
+prefix="#cdist:$__object_name"
+suffix="#/cdist:$__object_name"
+
+mkdir "$__object/files"
+
+# Generate entry for inclusion in authorized_keys file
+entry="$__object/files/entry"
+echo "$prefix" > "$entry"
+if [ -f "$__object/parameter/comment" ]; then
+   echo "# $(cat "$__object/parameter/comment")" >> "$entry"
+fi
+cat "$__object/parameter/key" >> "$entry"
+# ensure we have a newline after keys
+echo >> "$entry"
+echo "$suffix" >> "$entry"
diff --git a/cdist/conf/type/__ssh_authorized_keys/parameter/boolean b/cdist/conf/type/__ssh_authorized_keys/parameter/boolean
new file mode 100644
index 00000000..4bb126fe
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/parameter/boolean
@@ -0,0 +1,2 @@
+noparent
+nofile
diff --git a/cdist/conf/type/__ssh_authorized_keys/parameter/optional b/cdist/conf/type/__ssh_authorized_keys/parameter/optional
new file mode 100644
index 00000000..bfbd72ab
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/parameter/optional
@@ -0,0 +1,4 @@
+owner
+state
+file
+comment
diff --git a/cdist/conf/type/__ssh_authorized_keys/parameter/required_multiple b/cdist/conf/type/__ssh_authorized_keys/parameter/required_multiple
new file mode 100644
index 00000000..06bfde49
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/parameter/required_multiple
@@ -0,0 +1 @@
+key

From f37f3d201ce2174626ab41e47b4c93000a933dc4 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Fri, 30 Nov 2012 14:41:47 +0100
Subject: [PATCH 22/26] __ssh_authorized_key has been superseeded by
 __ssh_authorized_keys

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 .../explorer/dstuser_group                    | 15 -----
 cdist/conf/type/__ssh_authorized_key/man.text | 46 -------------
 cdist/conf/type/__ssh_authorized_key/manifest | 66 -------------------
 .../__ssh_authorized_key/parameter/optional   |  2 -
 4 files changed, 129 deletions(-)
 delete mode 100644 cdist/conf/type/__ssh_authorized_key/explorer/dstuser_group
 delete mode 100644 cdist/conf/type/__ssh_authorized_key/man.text
 delete mode 100755 cdist/conf/type/__ssh_authorized_key/manifest
 delete mode 100644 cdist/conf/type/__ssh_authorized_key/parameter/optional

diff --git a/cdist/conf/type/__ssh_authorized_key/explorer/dstuser_group b/cdist/conf/type/__ssh_authorized_key/explorer/dstuser_group
deleted file mode 100644
index c79f8d9f..00000000
--- a/cdist/conf/type/__ssh_authorized_key/explorer/dstuser_group
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-
-# Get option dstuser if defined
-if [ -f "$__object/parameter/dstuser" ]; then
-   dstuser=`cat "$__object/parameter/dstuser"`
-else
-   dstuser="root"
-fi
-
-if id $dstuser >/dev/null 2>&1 ; then
-    id -ng $dstuser
-else
-   echo "$__object_id: Destination user $dstuser does not exist" >&2
-   exit 1
-fi
diff --git a/cdist/conf/type/__ssh_authorized_key/man.text b/cdist/conf/type/__ssh_authorized_key/man.text
deleted file mode 100644
index b372b354..00000000
--- a/cdist/conf/type/__ssh_authorized_key/man.text
+++ /dev/null
@@ -1,46 +0,0 @@
-cdist-type__ssh_authorized_key(7)
-=================================
-Aurélien Bondis <aurelien.bondis--@--gmail-DOT-com>
-
-
-NAME
-----
-cdist-type__ssh_authorized_key - Sends a user's public key to another user's authorized_keys
-
-
-DESCRIPTION
------------
-This type sends a rsa key. By default uses root's key and sends it to root's authorized_keys
-
-
-REQUIRED PARAMETERS
--------------------
-None.
-
-
-OPTIONAL PARAMETERS
--------------------
-srcuser:: the user to take the rsa public key from
-dstuser:: the user to give the rsa public key to
-
-
-EXAMPLES
---------
-
---------------------------------------------------------------------------------
-#deploy root's public key
-__ssh_authorized_key admin
-#deploy bob's public key to alice's authorized_keys
-__ssh_authorized_key --srcuser bob --dstuser alice
---------------------------------------------------------------------------------
-
-
-SEE ALSO
---------
-- cdist-type(7)
-
-
-COPYING
--------
-Free use of this software is
-granted under the terms of the GNU General Public License version 3 (GPLv3).
diff --git a/cdist/conf/type/__ssh_authorized_key/manifest b/cdist/conf/type/__ssh_authorized_key/manifest
deleted file mode 100755
index 86c58740..00000000
--- a/cdist/conf/type/__ssh_authorized_key/manifest
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/sh
-#
-# 2011 Aurélien Bondis  aurelien.bondis AT gmail DOT com
-#
-# This file is part of cdist.
-#
-# cdist 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, either version 3 of the License, or
-# (at your option) any later version.
-#
-# cdist 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 cdist. If not, see <http://www.gnu.org/licenses/>.
-#
-#
-# This type allows to send a public ssh key from a user to the
-# authorized_keys of another
-#
-#require="__package openssh-server --state present"
-# Get option srcuser if defined
-if [ -f "$__object/parameter/srcuser" ]; then
-   srcuser=`cat "$__object/parameter/srcuser"`
-fi
-# Get option dstuser if defined
-if [ -f "$__object/parameter/dstuser" ]; then
-   dstuser=`cat "$__object/parameter/dstuser"`
-else
-   dstuser="root"
-fi
-
-# retrieve destination group
-dstgroup=$(cat "$__object/explorer/dstuser_group")
-
-# if a source user is defined, use it's public key
-if [ "$srcuser" ]; then
-   srcrsa="/home/${srcuser}/.ssh/id_rsa.pub"
-# if no source user is defined we use root's public key
-else
-   srcrsa="/root/.ssh/id_rsa.pub"
-fi
-# if a destination user is defined, insert in it's authorized_keys
-if [ "$dstuser" ]; then
-   sshpath="/home/$dstuser/.ssh"
-# if no destination user is defined we use root's home
-else
-   sshpath="/root/.ssh"
-fi
-rsa=`cat $srcrsa`
-__directory $sshpath \
-    --owner $dstuser \
-    --group $dstgroup \
-    --mode 700
-# the file authorized_keys depends on the .ssh folder
-require="__directory${sshpath}" \
-    __file "$sshpath/authorized_keys" \
-    --mode 640 \
-    --owner $dstuser \
-    --group $dstgroup
-# the line added depends on authorized_keys existence
-require="__file${sshpath}/authorized_keys" __addifnosuchline sshkey --file \
- "$sshpath/authorized_keys" --line "$rsa"
diff --git a/cdist/conf/type/__ssh_authorized_key/parameter/optional b/cdist/conf/type/__ssh_authorized_key/parameter/optional
deleted file mode 100644
index 4903f5be..00000000
--- a/cdist/conf/type/__ssh_authorized_key/parameter/optional
+++ /dev/null
@@ -1,2 +0,0 @@
-srcuser
-dstuser

From de9b38a2015fbc16692ea3c4d3311fa435a570b7 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Fri, 30 Nov 2012 14:51:15 +0100
Subject: [PATCH 23/26] ++changes

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 docs/changelog             | 2 ++
 docs/web/cdist/update.mdwn | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/docs/changelog b/docs/changelog
index 87971c08..ba73785c 100644
--- a/docs/changelog
+++ b/docs/changelog
@@ -14,6 +14,8 @@ Changelog
 	* Type __jail: Change optional parameter "started" to boolean "stopped" parameter,
 		change optional parameter "devfs-enable" to boolean "devfs-disable" parameter and
 		change optional parameter "onboot" to boolean.
+	* New Type: __ssh_authorized_keys (Steven Armstrong)
+	* Remove Type __ssh_authorized_key: Superseeded by __ssh_authorized_keys
 
 2.1.0pre8: 2012-11-15
 	* Type cleanup: __apt_ppa, __apt_ppa_update_index, __file, 
diff --git a/docs/web/cdist/update.mdwn b/docs/web/cdist/update.mdwn
index 3331ec85..a50e7224 100644
--- a/docs/web/cdist/update.mdwn
+++ b/docs/web/cdist/update.mdwn
@@ -42,6 +42,8 @@ To upgrade to the lastet version do
  * The types **\_\_autofs**, **\_\_autofs_map** and **\_\_autofs_reload** have been removed
    (no maintainer, no users)
  * Type **\_\_user**: Parameter --groups removed (use the new \_\_user_groups type)
+ * Type **\_\_ssh_authorized_key** has been replaced by more flexible type 
+    **\_\_ssh_authorized_keys**
  * require="" is deprecated: Use --after and --before as parameters instead
 
 ### Updating from 1.7 to 2.0

From 56b6c95ed4811b64dc869da277c89febe9a1e029 Mon Sep 17 00:00:00 2001
From: Steven Armstrong <steven@icarus.ethz.ch>
Date: Fri, 30 Nov 2012 13:48:34 +0100
Subject: [PATCH 24/26] implement conf-dir from CDIST_PATH environment variable

Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>
---
 cdist/context.py         |  2 +-
 cdist/exec/local.py      |  9 ++++++++-
 cdist/test/exec/local.py | 19 +++++++++++++++++++
 docs/man/man1/cdist.text | 13 +++++++++----
 4 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/cdist/context.py b/cdist/context.py
index 767b17a8..e0391be8 100644
--- a/cdist/context.py
+++ b/cdist/context.py
@@ -38,7 +38,7 @@ class Context(object):
         remote_copy,
         remote_exec,
         initial_manifest=False,
-        add_conf_dirs=[],
+        add_conf_dirs=None,
         exec_path=sys.argv[0],
         debug=False):
 
diff --git a/cdist/exec/local.py b/cdist/exec/local.py
index 7ef11458..7f640411 100644
--- a/cdist/exec/local.py
+++ b/cdist/exec/local.py
@@ -23,6 +23,7 @@
 import io
 import os
 import sys
+import re
 import subprocess
 import shutil
 import logging
@@ -37,7 +38,7 @@ class Local(object):
     Directly accessing the local side from python code is a bug.
 
     """
-    def __init__(self, target_host, out_path, exec_path, add_conf_dirs=[], cache_dir=None):
+    def __init__(self, target_host, out_path, exec_path, add_conf_dirs=None, cache_dir=None):
 
         self.target_host = target_host
         self.out_path = out_path
@@ -92,6 +93,12 @@ class Local(object):
         if self.home_dir:
             self.conf_dirs.append(self.home_dir)
 
+        # Add directories defined in the CDIST_PATH environment variable
+        if 'CDIST_PATH' in os.environ:
+            cdist_path_dirs = re.split(r'(?<!\\):', os.environ['CDIST_PATH'])
+            cdist_path_dirs.reverse()
+            self.conf_dirs.extend(cdist_path_dirs)
+
         # Add user supplied directories
         if self._add_conf_dirs:
             self.conf_dirs.extend(self._add_conf_dirs)
diff --git a/cdist/test/exec/local.py b/cdist/test/exec/local.py
index 687c13a5..6cb0c605 100644
--- a/cdist/test/exec/local.py
+++ b/cdist/test/exec/local.py
@@ -122,6 +122,25 @@ class LocalTestCase(test.CdistTestCase):
 
         self.assertTrue(os.path.isdir(our_type_dir))
 
+    def test_conf_dir_from_path_linking(self):
+        """Ensure that links are correctly created for types in conf directories which are defined in CDIST_PATH"""
+
+        test_type="__cdist_test_type"
+
+        os.environ['CDIST_PATH'] = conf_dir
+
+        link_test_local = local.Local(
+            target_host='localhost',
+            out_path=self.out_path,
+            exec_path=test.cdist_exec_path,
+        )
+
+        link_test_local._create_conf_path_and_link_conf_dirs()
+
+        our_type_dir = os.path.join(link_test_local.type_path, test_type)
+
+        self.assertTrue(os.path.isdir(our_type_dir))
+
     ### other tests
 
     def test_run_success(self):
diff --git a/docs/man/man1/cdist.text b/docs/man/man1/cdist.text
index b92fba18..c52e3696 100644
--- a/docs/man/man1/cdist.text
+++ b/docs/man/man1/cdist.text
@@ -14,7 +14,7 @@ cdist [-h] [-V]
 
 cdist banner
 
-cdist config [-h] [-d] [-V] [-c CDIST_HOME] [-i MANIFEST] [-p] [-s] host [host ...]
+cdist config [-h] [-d] [-V] [-c CONF_DIR] [-i MANIFEST] [-p] [-s] host [host ...]
 
 
 
@@ -43,9 +43,14 @@ Configure a system
 -h, --help::
     Show the help screen
 
--c CDIST_HOME, --cdist-home CDIST_HOME::
-    Instead of using the parent of the bin directory as cdist home,
-    use the specified directory
+-c CONF_DIR, --conf-dir CONF_DIR::
+    Add a configuration directory. Can be specified multiple times.
+    If configuration directories contain conflicting types, explorers or
+    manifests, then the last one found is used. Additionally this can also
+    be configured by setting the CDIST_PATH environment variable to a colon
+    delimited list of config directories. Directories given with the
+    --conf-dir argument have higher precedence over those set through the
+    environment variable.
 
 -d, --debug::
     Enable debug output

From 20091cf1e9f0c62e94bbf6e8a0be0ddc9fa1191f Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Sat, 1 Dec 2012 17:16:39 +0100
Subject: [PATCH 25/26] integrate CDIST_PATH

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 docs/changelog | 1 +
 1 file changed, 1 insertion(+)

diff --git a/docs/changelog b/docs/changelog
index ba73785c..9efe27c9 100644
--- a/docs/changelog
+++ b/docs/changelog
@@ -16,6 +16,7 @@ Changelog
 		change optional parameter "onboot" to boolean.
 	* New Type: __ssh_authorized_keys (Steven Armstrong)
 	* Remove Type __ssh_authorized_key: Superseeded by __ssh_authorized_keys
+	* Support for CDIST_PATH (Steven Armstrong)
 
 2.1.0pre8: 2012-11-15
 	* Type cleanup: __apt_ppa, __apt_ppa_update_index, __file, 

From 4d2b576553f317d267bed690939e44467aa231b1 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 3 Dec 2012 09:47:48 +0100
Subject: [PATCH 26/26] allow setting up version when running outside dir

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/build b/build
index 6fe8960f..d6c9a172 100755
--- a/build
+++ b/build
@@ -27,7 +27,7 @@
 #set -e
 
 basedir=${0%/*}
-version=$(git describe)
+version=$(cd "$basedir" && git describe)
 
 # Manpage and HTML
 A2XM="a2x -f manpage --no-xmllint -a encoding=UTF-8"