Merge remote-tracking branch 'cdist/master'

This commit is contained in:
Steven Armstrong 2011-09-27 09:32:45 +02:00
commit b2f1d8e7c0
13 changed files with 452 additions and 374 deletions

View file

@ -27,8 +27,8 @@
#set -e #set -e
# Manpage and HTML # Manpage and HTML
A2XM="a2x -f manpage --no-xmllint" A2XM="a2x -f manpage --no-xmllint -a encoding=UTF-8"
A2XH="a2x -f xhtml --no-xmllint" A2XH="a2x -f xhtml --no-xmllint -a encoding=UTF-8"
# Developer webbase # Developer webbase
WEBDIR=$HOME/niconetz WEBDIR=$HOME/niconetz

View file

@ -5,7 +5,7 @@ Steven Armstrong <steven-cdist--@--armstrong.cc>
NAME NAME
---- ----
cdist-type__partition_msdos_apply cdist-type__partition_msdos_apply - Apply dos partition settings
DESCRIPTION DESCRIPTION

View file

@ -8,6 +8,289 @@
- and that ssh will wait for answer of prompt - and that ssh will wait for answer of prompt
- nasty if used in parallel mode (scroll up!) - nasty if used in parallel mode (scroll up!)
- rewrite cdist-stages, remove
- update man7!
- exec flag is not true for manifest anymore
SSH HINTS
---------
Control master, ssh agent
Everything you specify in manifests
# Intro of quickstart
#
cat << eof
$banner cdist version $__cdist_version
Welcome to the interactive guide to cdist!
This is the interactive tutorial and beginners help for cdist and here's
our schedule:
- Stages: How cdist operates
- Explorer: Explore facts of the target host
- Manifest: Map configurations to hosts
- Types: Bundled functionality
- Deploy a configuration to the local host!
eof
__prompt "$continue"
################################################################################
# Stages
#
cat << eof
To deploy configurations to a host, you call
cdist-deploy-to <hostname>
which makes calls to other scripts, which realise the so called "stages".
Usually you'll not notice this, but in case you want to debug or hack cdist,
you can run each stage on its own. Besides that, you just need to remember
that the command cdist-deploy-to is the main cdist command.
See also:
Source of cdist-deploy-to(1), cdist-stages(7)
eof
__prompt "$continue"
################################################################################
# Explorer
#
cat << eof
The first thing cdist always does is running different explorers on the
target host. The explorers can be found in the directory
${__cdist_explorer_dir}
An explorer is executed on the target host and its output is saved to a file.
You can use these files later to decide what or how to configure the host.
For a demonstration, we'll call the OS explorer locally now, but remember:
This is only for demonstration, normally it is run on the target host.
The os explorer will which either displays the detected operating system or
nothing if it does not know your OS.
See also:
cdist-explorer(7)
eof
explorer="${__cdist_explorer_dir}/os"
__prompt "Press enter to execute $explorer"
set -x
"$explorer"
set +x
################################################################################
# Manifest
#
cat << eof
The initial manifest is the entry point for cdist to find out, what you would
like to have configured. It is located at
${__cdist_manifest_init}
And can be as simple as
--------------------------------------------------------------------------------
__file /etc/cdist-configured --type file
--------------------------------------------------------------------------------
See also:
cdist-manifest(7)
eof
__prompt "$continue"
cat << eof
Let's take a deeper look at the initial manifest to understand what it means:
__file /etc/cdist-configured --type file
| | | \\
| | The parameter type \\ With the value file
| |
| |
| | This is the object id
|
__file is a so called "type"
This essentially looks like a standard command executed in the shell.
eof
__prompt "$continue"
cat << eof
And that's exactly true. Manifests are shell snippets that can use
types as commands with arguments. cdist prepends a special path
that contain links to the cdist-type-emulator, to \$PATH, so you
can use your types as a command.
This is also the reason why types should always be prefixed with
"__", to prevent collisions with existing binaries.
The object id is unique per type and used to prevent you from creating
the same object twice.
Parameters are type specific and are always specified as --parameter <value>.
See also:
cdist-type-build-emulation(1), cdist-type-emulator(1)
eof
__prompt "$continue"
################################################################################
# Types
#
cat << eof
Types are bundled functionality and are the main component of cdist.
If you want to have a feature x, you write the type __x. Types are stored in
${__cdist_type_dir}
And cdist ships with some types already!
See also:
cdist-type(7)
eof
__prompt "Press enter to see available types"
set -x
ls ${__cdist_type_dir}
set +x
cat << eof
Types consist of the following parts:
- ${__cdist_name_parameter} (${__cdist_name_parameter_required}/${__cdist_name_parameter_optional}
- ${__cdist_name_manifest}
- ${__cdist_name_explorer}
- ${__cdist_name_gencode}
eof
__prompt "$continue"
cat << eof
Every type must have a directory named ${__cdist_name_parameter}, which
contains required or optional parameters (in newline seperated files).
If an object of a specific type was created in the initial manifest,
the manifest of the type is run and may create other objects.
A type may have ${__cdist_name_explorer}, which are very similar to the
${__cdist_name_explorer} seen above, but with a different purpose:
They are specific to the type and are not relevant for other types.
You may use them for instance to find out details on the target host,
so you can decide what to do on the target host eventually.
After the ${__cdist_name_manifest} and the ${__cdist_name_explorer} of
a type have been run, ${__cdist_name_gencode} is executed, which creates
code to be executed on the target on stdout.
eof
__prompt "$continue"
################################################################################
# Deployment
#
cat << eof
Now you've got some basic knowledge about cdist, let's configure your a host!
Ensure that you have a ssh server running on the host and that you can login as root.
eof
__prompt "Enter hostname or press enter for localhost: "
if [ "$answer" ]; then
host="$answer"
else
host="localhost"
fi
manifestinit="conf/manifest/init"
cat << eof
I'll now setup $manifestinit, containing the following code:
--------------------------------------------------------------------------------
# Every machine becomes a marker, so sysadmins know that automatic
# configurations are happening
__file /etc/cdist-configured
case "\$__target_host" in
$host)
__link /tmp/cdist-testfile --source /etc/cdist-configured --type symbolic
__addifnosuchline /tmp/cdist-welcome --line "Welcome to cdist"
;;
esac
--------------------------------------------------------------------------------
WARNING: This will overwrite ${manifestinit}.
eof
cat > "$__cdist_abs_mydir/../$manifestinit" << eof
# Every machine becomes a marker, so sysadmins know that automatic
# configurations are happening
__file /etc/cdist-configured
case "\$__target_host" in
$host)
__link /tmp/cdist-testfile --source /etc/cdist-configured --type symbolic
__addifnosuchline /tmp/cdist-welcome --line "Welcome to cdist"
;;
esac
eof
chmod u+x "$__cdist_abs_mydir/../$manifestinit"
cmd="cdist-deploy-to $host"
__prompt "Press enter to run \"$cmd\""
# No quotes, we need field splitting
$cmd
################################################################################
# End
#
cat << eof
--------------------------------------------------------------------------------
That's it, this is the end of the cdist-quickstart.
I hope you've got some impression on how cdist works, here are again some
pointers on where to continue to read:
eof
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
- Initial install support - Initial install support

View file

@ -26,7 +26,7 @@ $__explorer/<explorer_name> (general and type explorer) or
$__type_explorer/<explorer name> (type explorer). $__type_explorer/<explorer name> (type explorer).
In case of significant errors, the explorer may exit non-zero and return an In case of significant errors, the explorer may exit non-zero and return an
error message on stderr, which will cause the cdist run to abort. error message on stderr, which will cause cdist to abort.
You can also use stderr for debugging purposes while developing a new You can also use stderr for debugging purposes while developing a new
explorer. explorer.

View file

@ -26,26 +26,12 @@ in the latest version, drop a mail to the cdist mailing list,
subject prefixed with "[BUG] ". subject prefixed with "[BUG] ".
UNDERSTANDING CDIST INTERNALS
-----------------------------
IF you are interested in how cdist internally works, you can open
bin/cdist-config and bin/cdist-deploy-to in your favorite editor and
read the scripts bin/cdist-deploy-to calls. The magnificent HACKERS_README
may be of great help as well.
CODING CONVENTIONS (EVERYWHERE) CODING CONVENTIONS (EVERYWHERE)
------------------------------- -------------------------------
If something should be better done or needs to fixed, add the word FIXME If something should be better done or needs to fixed, add the word FIXME
nearby, so grepping for FIXME gives all positions that need to be fixed. nearby, so grepping for FIXME gives all positions that need to be fixed.
CODING CONVENTIONS (CORE)
-------------------------
- All variables exported by cdist are prefixed with a double underscore (__)
- All cdist-internal variables are prefixed with __cdist_ and are generally not exported.
HOW TO SUBMIT STUFF FOR INCLUSION INTO UPSTREAM CDIST HOW TO SUBMIT STUFF FOR INCLUSION INTO UPSTREAM CDIST
----------------------------------------------------- -----------------------------------------------------
If you did some cool changes to cdist, which you value as a benefit for If you did some cool changes to cdist, which you value as a benefit for

View file

@ -32,11 +32,6 @@ explorers. Every existing explorer is run on the target and the output of all
explorers are copied back into the local cache. The results can be used by explorers are copied back into the local cache. The results can be used by
manifests and types. manifests and types.
Related documentation:
- cdist-explorer-run-global(1)
- cdist-remote-explorer-run(1)
- cdist-explorer(7)
STAGE 2: RUN THE INITIAL MANIFEST STAGE 2: RUN THE INITIAL MANIFEST
--------------------------------- ---------------------------------
@ -46,11 +41,6 @@ the objects as defined in the manifest for the specific host. In this stage,
no conflicts may occur, i.e. no object of the same type with the same id may no conflicts may occur, i.e. no object of the same type with the same id may
be created. be created.
Related documentation:
- cdist-manifest-run-init(1)
- cdist-manifest-run(1)
- cdist-manifest(7)
STAGE 3: OBJECT INFORMATION RETRIEVAL STAGE 3: OBJECT INFORMATION RETRIEVAL
------------------------------------- -------------------------------------
@ -59,12 +49,6 @@ transfered to the target host and executed. The results are transfered back
and can be used in the following stages to decide what changes need to be made and can be used in the following stages to decide what changes need to be made
on the target to implement the desired state. on the target to implement the desired state.
Related documentation:
- cdist-object-explorer-run(1)
- cdist-remote-explorer-run(1)
- cdist-type(7)
- cdist-explorer(7)
STAGE 4: RUN THE OBJECT MANIFEST STAGE 4: RUN THE OBJECT MANIFEST
-------------------------------- --------------------------------
@ -79,11 +63,6 @@ The newly created objects are merged back into the existing tree. No conflicts
may occur during the merge. A conflict would mean that two different objects may occur during the merge. A conflict would mean that two different objects
try to create the same object, which indicates a broken configuration. try to create the same object, which indicates a broken configuration.
Related documentation:
- cdist-object-manifest-run(1)
- cdist-manifest-run(1)
- cdist-type(7)
STAGE 5: CODE GENERATION STAGE 5: CODE GENERATION
------------------------ ------------------------
@ -92,29 +71,17 @@ gencode scripts. The gencode scripts generate the code to be executed on the
target on stdout. If the gencode executables fail, they must print diagnostic target on stdout. If the gencode executables fail, they must print diagnostic
messages on stderr and exit non-zero. messages on stderr and exit non-zero.
Related documentation:
- cdist-object-gencode-run(1)
- cdist-object-gencode(1)
- cdist-type(7)
STAGE 6: CODE EXECUTION STAGE 6: CODE EXECUTION
----------------------- -----------------------
For every object the resulting code from the previous stage is transferred to For every object the resulting code from the previous stage is transferred to
the target host and executed there to apply the configuration changes. the target host and executed there to apply the configuration changes.
Related documentation:
- cdist-object-code-run(1)
- cdist-code-run(1)
STAGE 7: CACHE STAGE 7: CACHE
-------------- --------------
The cache stores the information from the current run for later use. The cache stores the information from the current run for later use.
Related documentation:
- cdist-cache(1)
SUMMARY SUMMARY
------- -------
@ -126,8 +93,8 @@ in correct order.
SEE ALSO SEE ALSO
-------- --------
- cdist(1)
- cdist(7) - cdist(7)
- cdist-deploy-to(1)
- cdist-reference(7) - cdist-reference(7)

347
doc/man/man7/cdist-tutorial.text Executable file → Normal file
View file

@ -1,310 +1,83 @@
#!/bin/sh cdist-tutorial(7)
# =================
# 2010-2011 Nico Schottelius (nico-cdist at schottelius.org) Nico Schottelius <nico-cdist--@--schottelius.org>
#
# 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/>.
#
#
# Give the user an introduction into cdist
#
. cdist-config
set -eu
banner="cdist-quickstart>" NAME
continue="Press enter to continue or ctrl-c to abort." ----
create_continue="Press enter to create the described files/directories" cdist-tutorial - a guided introduction into cdist
__prompt()
{
echo -n "$banner" "$@"
read answer
}
################################################################################ INTRODUCTION
# Intro of quickstart ------------
# This tutorial is aimed at people learning cdist and shows
cat << eof typical approaches as well as gives an easy start into
$banner cdist version $__cdist_version the world of configuration management.
Welcome to the interactive guide to cdist! This tutorial assumes you are configuring **localhost**, because
This is the interactive tutorial and beginners help for cdist and here's it is always available. Just repace **localhost** with your target
our schedule: host for real life usage.
- Stages: How cdist operates
- Explorer: Explore facts of the target host
- Manifest: Map configurations to hosts
- Types: Bundled functionality
- Deploy a configuration to the local host!
eof
__prompt "$continue"
################################################################################ QUICK START
# Stages -----------
# For those who just want to configure a system with the
cat << eof cdist configuration management and do not need (or want)
to understand everything.
To deploy configurations to a host, you call Cdist uses **ssh** for communication and transportation
and usually logs into the **target host** as the
cdist-deploy-to <hostname> **root** user. So you need to configure the **ssh server**
of the target host to allow root logins: Edit
which makes calls to other scripts, which realise the so called "stages". the file **/etc/ssh/sshd_config** and add one of the following
Usually you'll not notice this, but in case you want to debug or hack cdist, lines:
you can run each stage on its own. Besides that, you just need to remember
that the command cdist-deploy-to is the main cdist command.
See also:
Source of cdist-deploy-to(1), cdist-stages(7)
eof
__prompt "$continue"
################################################################################
# Explorer
#
cat << eof
The first thing cdist always does is running different explorers on the
target host. The explorers can be found in the directory
${__cdist_explorer_dir}
An explorer is executed on the target host and its output is saved to a file.
You can use these files later to decide what or how to configure the host.
For a demonstration, we'll call the OS explorer locally now, but remember:
This is only for demonstration, normally it is run on the target host.
The os explorer will which either displays the detected operating system or
nothing if it does not know your OS.
See also:
cdist-explorer(7)
eof
explorer="${__cdist_explorer_dir}/os"
__prompt "Press enter to execute $explorer"
set -x
"$explorer"
set +x
################################################################################
# Manifest
#
cat << eof
The initial manifest is the entry point for cdist to find out, what you would
like to have configured. It is located at
${__cdist_manifest_init}
And can be as simple as
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
__file /etc/cdist-configured --type file # Allow login only via public key
PermitRootLogin without-password
# Allow login via password and public key
PermitRootLogin yes
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
See also: As cdist uses ssh intensively, it is recommended to setup authentication
with public keys:
cdist-manifest(7)
eof
__prompt "$continue"
cat << eof
Let's take a deeper look at the initial manifest to understand what it means:
__file /etc/cdist-configured --type file
| | | \\
| | The parameter type \\ With the value file
| |
| |
| | This is the object id
|
__file is a so called "type"
This essentially looks like a standard command executed in the shell.
eof
__prompt "$continue"
cat << eof
And that's exactly true. Manifests are shell snippets that can use
types as commands with arguments. cdist prepends a special path
that contain links to the cdist-type-emulator, to \$PATH, so you
can use your types as a command.
This is also the reason why types should always be prefixed with
"__", to prevent collisions with existing binaries.
The object id is unique per type and used to prevent you from creating
the same object twice.
Parameters are type specific and are always specified as --parameter <value>.
See also:
cdist-type-build-emulation(1), cdist-type-emulator(1)
eof
__prompt "$continue"
################################################################################
# Types
#
cat << eof
Types are bundled functionality and are the main component of cdist.
If you want to have a feature x, you write the type __x. Types are stored in
${__cdist_type_dir}
And cdist ships with some types already!
See also:
cdist-type(7)
eof
__prompt "Press enter to see available types"
set -x
ls ${__cdist_type_dir}
set +x
cat << eof
Types consist of the following parts:
- ${__cdist_name_parameter} (${__cdist_name_parameter_required}/${__cdist_name_parameter_optional}
- ${__cdist_name_manifest}
- ${__cdist_name_explorer}
- ${__cdist_name_gencode}
eof
__prompt "$continue"
cat << eof
Every type must have a directory named ${__cdist_name_parameter}, which
contains required or optional parameters (in newline seperated files).
If an object of a specific type was created in the initial manifest,
the manifest of the type is run and may create other objects.
A type may have ${__cdist_name_explorer}, which are very similar to the
${__cdist_name_explorer} seen above, but with a different purpose:
They are specific to the type and are not relevant for other types.
You may use them for instance to find out details on the target host,
so you can decide what to do on the target host eventually.
After the ${__cdist_name_manifest} and the ${__cdist_name_explorer} of
a type have been run, ${__cdist_name_gencode} is executed, which creates
code to be executed on the target on stdout.
eof
__prompt "$continue"
################################################################################
# Deployment
#
cat << eof
Now you've got some basic knowledge about cdist, let's configure your a host!
Ensure that you have a ssh server running on the host and that you can login as root.
eof
__prompt "Enter hostname or press enter for localhost: "
if [ "$answer" ]; then
host="$answer"
else
host="localhost"
fi
manifestinit="conf/manifest/init"
cat << eof
I'll now setup $manifestinit, containing the following code:
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
# Every machine becomes a marker, so sysadmins know that automatic # Generate pubkey pair as a normal user
# configurations are happening ssh-keygen
__file /etc/cdist-configured
case "\$__target_host" in # Copy pubkey over to target host
$host) ssh-copy-id root@localhost
__link /tmp/cdist-testfile --source /etc/cdist-configured --type symbolic
__addifnosuchline /tmp/cdist-welcome --line "Welcome to cdist"
;;
esac
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
WARNING: This will overwrite ${manifestinit}. As soon as you are able to login without passwort to the target host,
we can use cdist, to configure it. You can copy and paste the following
eof code into your shell to get started and configure localhost:
cat > "$__cdist_abs_mydir/../$manifestinit" << eof
# Every machine becomes a marker, so sysadmins know that automatic
# configurations are happening
__file /etc/cdist-configured
case "\$__target_host" in
$host)
__link /tmp/cdist-testfile --source /etc/cdist-configured --type symbolic
__addifnosuchline /tmp/cdist-welcome --line "Welcome to cdist"
;;
esac
eof
chmod u+x "$__cdist_abs_mydir/../$manifestinit"
cmd="cdist-deploy-to $host"
__prompt "Press enter to run \"$cmd\""
# No quotes, we need field splitting
$cmd
################################################################################
# End
#
cat << eof
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
That's it, this is the end of the cdist-quickstart. # Get cdist
git clone git://git.schottelius.org/cdist
I hope you've got some impression on how cdist works, here are again some # Create manifest (maps configuration to host(s)
pointers on where to continue to read: cd cdist
echo '__file /etc/cdist-configured' > conf/manifest/init
chmod 0700 conf/manifest/init
cdist(7), cdist-deploy-to(1), cdist-type(7), cdist-stages(7) # Configure localhost
./bin/cdist config localhost
eof # Find out that cdist created /etc/cdist-configured
ls -l /etc/cdist-configured
--------------------------------------------------------------------------------
The file 'conf/manifest/init' is usually the entry point for cdist,
to find out what to configure on which host. All manifests are
essentially shell scripts. Every manifest can use the types known to
cdist, which are usually underline prefixed (__).
SEE ALSO
--------
cdist(1), cdist-type(7), cdist-stages(7)

View file

@ -35,10 +35,6 @@ __file /etc/cdist-configured --type file
__package tree --state installed __package tree --state installed
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Internally cdist-type-emulator(1) will be called from cdist-manifest-run(1) to
save the given parameters into a cconfig database, so they can be accessed by
the manifest and gencode scripts of the type (see below).
A list of supported types can be found in the cdist-reference(7) manpage. A list of supported types can be found in the cdist-reference(7) manpage.
SINGLETON TYPES SINGLETON TYPES
@ -111,7 +107,7 @@ __package_$type "$@"
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
As you can see, the type can reference different environment variables, As you can see, the type can reference different environment variables,
which are documented in cdist-environment-variables(7). which are documented in cdist-reference(7).
Always ensure the manifest is executable, otherwise cdist will not be able Always ensure the manifest is executable, otherwise cdist will not be able
to execute it. to execute it.

View file

@ -35,12 +35,11 @@ pull mechanism (client requests configuration).
SEE ALSO SEE ALSO
-------- --------
- Website: http://www.nico.schottelius.org/software/cdist/[] - Website: http://www.nico.schottelius.org/software/cdist/[]
- cdist-best-practise(7)
- cdist-deploy-to(1)
- cdist-hacker(7) - cdist-hacker(7)
- cdist-manifest(7) - cdist-manifest(7)
- cdist-quickstart(1)
- cdist-type(7) - cdist-type(7)
- cdist(1)
- cdist(7)
COPYING COPYING

View file

@ -24,6 +24,7 @@ import logging
import os import os
import sys import sys
import cdist
import cdist.path import cdist.path
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -87,7 +88,7 @@ def emulator(argv):
try: try:
os.makedirs(param_out_dir, exist_ok=True) os.makedirs(param_out_dir, exist_ok=True)
except OSError as error: except OSError as error:
raise CdistError(param_out_dir + ": " + error.args[1]) raise cdist.Error(param_out_dir + ": " + error.args[1])
# Record parameter # Record parameter
params = vars(args) params = vars(args)
@ -105,11 +106,11 @@ def emulator(argv):
sys.exit(1) sys.exit(1)
else: else:
param_fd = open(file, "r") param_fd = open(file, "r")
param_old = param_fd.readlines() value_old = param_fd.readlines()
param_fd.close() param_fd.close()
if(param_old != param): if(value_old != value):
print("Parameter " + param + " differs: " + " ".join(param_old) + " vs. " + param) print("Parameter " + param + " differs: " + " ".join(value_old) + " vs. " + value)
print("Sources: " + " ".join(old_object_source) + " and " + object_source) print("Sources: " + " ".join(old_object_source) + " and " + object_source)
sys.exit(1) sys.exit(1)
else: else:

View file

@ -26,26 +26,26 @@ log = logging.getLogger(__name__)
import cdist import cdist
def shell_run_or_debug_fail(script, *args, **kargs): def shell_run_or_debug_fail(script, *args, remote_prefix=False, **kargs):
# Manually execute /bin/sh, because sh -e does what we want # Manually execute /bin/sh, because sh -e does what we want
# and sh -c -e does not exit if /bin/false called # and sh -c -e does not exit if /bin/false called
args[0][:0] = [ "/bin/sh", "-e" ] args[0][:0] = [ "/bin/sh", "-e" ]
remote = False if remote_prefix:
if "remote_prefix" in kargs: args[0][:0] = remote_prefix
remote = True
args[0][:0] = kargs["remote_prefix"]
del kargs["remote_prefix"]
log.debug("Shell exec cmd: %s", args) log.debug("Shell exec cmd: %s", args)
if 'env' in kargs:
log.debug("Shell exec env: %s", kargs['env']) log.debug("Shell exec env: %s", kargs['env'])
try: try:
subprocess.check_call(*args, **kargs) subprocess.check_call(*args, **kargs)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
log.error("Code that raised the error:\n") log.error("Code that raised the error:\n")
if remote: if remote_prefix:
# FIXME: included in Path! run_or_fail(["cat", script], remote_prefix=remote_prefix)
remote_cat(script)
else: else:
try: try:
script_fd = open(script) script_fd = open(script)
@ -58,11 +58,9 @@ def shell_run_or_debug_fail(script, *args, **kargs):
except OSError as error: except OSError as error:
raise cdist.Error(" ".join(*args) + ": " + error.args[1]) raise cdist.Error(" ".join(*args) + ": " + error.args[1])
def run_or_fail(*args, remote_prefix=False, **kargs):
def run_or_fail(*args, **kargs): if remote_prefix:
if "remote_prefix" in kargs: args[0][:0] = remote_prefix
args[0][:0] = kargs["remote_prefix"]
del kargs["remote_prefix"]
log.debug("Exec: " + " ".join(*args)) log.debug("Exec: " + " ".join(*args))
try: try:

View file

@ -125,10 +125,6 @@ class Path:
"""Create directory on remote side""" """Create directory on remote side"""
cdist.exec.run_or_fail(["mkdir", "-p", directory], remote_prefix=self.remote_prefix) cdist.exec.run_or_fail(["mkdir", "-p", directory], remote_prefix=self.remote_prefix)
def remote_cat(filename):
"""Use cat on the remote side for output"""
cdist.exec.run_or_fail(["cat", filename], remote_prefix=self.remote_prefix)
def remove_remote_dir(self, destination): def remove_remote_dir(self, destination):
cdist.exec.run_or_fail(["rm", "-rf", destination], remote_prefix=self.remote_prefix) cdist.exec.run_or_fail(["rm", "-rf", destination], remote_prefix=self.remote_prefix)

87
test.py
View file

@ -23,6 +23,8 @@
import os import os
import sys import sys
import shutil
import tempfile
import unittest import unittest
sys.path.insert(0, os.path.abspath( sys.path.insert(0, os.path.abspath(
@ -33,6 +35,38 @@ import cdist.config
import cdist.exec import cdist.exec
class Exec(unittest.TestCase): class Exec(unittest.TestCase):
def setUp(self):
"""Create shell code and co."""
self.temp_dir = tempfile.mkdtemp()
self.shell_false = os.path.join(self.temp_dir, "shell_false")
self.shell_true = os.path.join(self.temp_dir, "shell_true")
true_fd = open(self.shell_true, "w")
true_fd.writelines(["#!/bin/sh", "/bin/true"])
true_fd.close()
false_fd = open(self.shell_false, "w")
false_fd.writelines(["#!/bin/sh", "/bin/false"])
false_fd.close()
def tearDown(self):
shutil.rmtree(self.temp_dir)
def test_local_success_shell(self):
try:
cdist.exec.shell_run_or_debug_fail(self.shell_true, [self.shell_true])
except cdist.Error:
failed = True
else:
failed = False
self.assertFalse(failed)
def test_local_fail_shell(self):
self.assertRaises(cdist.Error, cdist.exec.shell_run_or_debug_fail,
self.shell_false, [self.shell_false])
def test_local_success(self): def test_local_success(self):
try: try:
cdist.exec.run_or_fail(["/bin/true"]) cdist.exec.run_or_fail(["/bin/true"])
@ -44,16 +78,61 @@ class Exec(unittest.TestCase):
self.assertFalse(failed) self.assertFalse(failed)
def test_local_fail(self): def test_local_fail(self):
self.assertRaises(cdist.Error, cdist.exec.run_or_fail, ["/bin/false"])
class Config(unittest.TestCase):
def setUp(self):
self.temp_dir = tempfile.mkdtemp()
self.init_manifest = os.path.join(self.temp_dir, "manifest")
self.config = cdist.config.Config("localhost",
initial_manifest=self.init_manifest)
def test_initial_manifest_different_parameter(self):
manifest_fd = open(self.init_manifest, "w")
manifest_fd.writelines(["#!/bin/sh\n",
"__file " + self.temp_dir + "--mode 0700\n",
"__file " + self.temp_dir + "--mode 0600\n",
])
manifest_fd.close()
self.assertRaises(cdist.Error, self.config.run_initial_manifest())
def test_initial_manifest_parameter_added(self):
manifest_fd = open(self.init_manifest, "w")
manifest_fd.writelines(["#!/bin/sh\n",
"__file " + self.temp_dir + '\n',
"__file " + self.temp_dir + "--mode 0600\n",
])
manifest_fd.close()
self.assertRaises(cdist.Error, self.config.run_initial_manifest())
def test_initial_manifest_parameter_removed(self):
manifest_fd = open(self.init_manifest, "w")
manifest_fd.writelines(["#!/bin/sh\n",
"__file " + self.temp_dir + "--mode 0600\n",
"__file " + self.temp_dir + "\n",
])
manifest_fd.close()
self.assertRaises(cdist.Error, self.config.run_initial_manifest())
def test_initial_manifest_parameter_twice(self):
manifest_fd = open(self.init_manifest, "w")
manifest_fd.writelines(["#!/bin/sh\n",
"__file " + self.temp_dir + "--mode 0600\n",
"__file " + self.temp_dir + "--mode 0600\n",
])
manifest_fd.close()
try: try:
cdist.exec.run_or_fail(["/bin/false"]) self.config.run_initial_manifest()
except cdist.Error: except cdist.Error:
failed = True failed = True
else: else:
failed = False failed = False
self.assertTrue(failed) self.assertFalse(failed)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()