diff --git a/build.sh b/build.sh
index 021fb480..6a91ff3d 100755
--- a/build.sh
+++ b/build.sh
@@ -127,11 +127,18 @@ case "$1" in
;;
test)
- python3 -m unittest discover test 'test_*.py'
+ PYTHONPATH=$PYTHONPATH:$(pwd -P)/lib \
+ python3 -m cdist.test
+ ;;
+
+ test-install)
+ PYTHONPATH=$PYTHONPATH:$(pwd -P)/lib \
+ python3 -m unittest cdist.test.test_install
;;
test-all)
- python3 -m unittest discover test '*.py'
+ PYTHONPATH=$PYTHONPATH:$(pwd -P)/lib \
+ python3 -m unittest discover lib/cdist/test '*.py'
;;
*)
diff --git a/doc/dev/logs/2011-10-04 b/doc/dev/logs/2011-10-04
new file mode 100644
index 00000000..f3bb852d
--- /dev/null
+++ b/doc/dev/logs/2011-10-04
@@ -0,0 +1,3 @@
+Testing for single tests:
+ PYTHONPATH=$PYTHONPATH:$(pwd -P)/lib python3 -m unittest cdist.test.test_install.Install.test_explorer_ran
+
diff --git a/doc/dev/logs/2011-10-05 b/doc/dev/logs/2011-10-05
new file mode 100644
index 00000000..39fc48a2
--- /dev/null
+++ b/doc/dev/logs/2011-10-05
@@ -0,0 +1,116 @@
+Config/Install/Deploy/Run:
+ target host
+ remote_cmd_prefix - ssh user@bla sudo foo?????
+ remote_cp_prefix - cp statt scp oder so
+
+ debug -> env für alles += __debug
+
+
+Storage/Metaobject/Tree? == Path?
+ base_dir?
+ nimmt objekte
+
+ Sammelt Objekte
+
+ Ist prepared hier?
+
+Object
+ "Infos" / Datenhalde
+
+ Base_Dir-Abhängigkeit? - wo
+
+ out_dir - wo speichern
+
+ nur eigenes verzeichnis interessant?
+ -> nicht für shell code / aka gencode!
+ -> __global abhängigkeit
+
+ object.gencode()?
+
+ hast du type-explorer?
+ ja?
+ führe JEDEN remote aus
+ speichere ausgabe in object
+ nein:
+ fertig
+ hast du gencode-{local,remote}?
+ ja?
+ führe local oder remote aus
+ speichere ausgabe in s/^gen//
+ nein:
+ fertig
+
+ hast du code-{local,remote}?
+ ja?
+ führe local oder remote aus
+ nein:
+ fertig
+
+ ich habe ...
+ object_id
+ type
+ type.singleton() == False -> require object_id
+ parameter gegeben
+ requirements / order
+
+ type_explorer := methode zum ausführen?
+
+ cdist.object.Object(type, id)
+
+ methoden:
+ gen_code
+ code
+ run_manifest
+ manifest == ort
+
+Type
+ singleton: ja / nein
+ install: ja / nein
+ type_explorer := liste
+
+ optional_parameter
+ required_parameter
+
+ TypeExplorer
+ verwandt oder == explorer
+ Verwandschaft klären!
+
+ sehr abhängig von base_dir!
+ - welche gibt es?
+ - was für optionen haben sie
+
+ cdist.type.Type("/path/to/type")
+ Tree/Path vieh, das liste von $_ speichert
+ Einfach iterieren
+
+
+
+Explorer
+ execute(env)
+ env == __explorer -> nur im explorer
+
+z.B. BaseExplorer oder andersherum GlobalExplorer
+
+Manifest
+
+Exec
+ wrapper um auszuführen,
+ error handling,
+ output redirection (variable, file, beides, socat :-)
+
+
+--------------------------------------------------------------------------------
+
+- base_dir (conf/, type, ...)
+- manifest (initiale)
+ $methode_mit_inhalt_von_manifest?
+ run_manifest(code)
+ ob sinnvoll?
+ geht auch mit stdin oder datei
+
+ stdin -> muss in tmp-datei, für sh -e?
+-
+--------------------------------------------------------------------------------
+
+save output of shell in buffer instead of displaying?
+ -> freedom to decide whether to display or not!
diff --git a/lib/cdist/config.py b/lib/cdist/config.py
index 51615c28..fcc9ed7e 100644
--- a/lib/cdist/config.py
+++ b/lib/cdist/config.py
@@ -22,274 +22,12 @@
import datetime
import logging
-import os
-import stat
-import sys
-
log = logging.getLogger(__name__)
-import cdist.emulator
-import cdist.path
+import cdist.config_install
-CODE_HEADER = "#!/bin/sh -e\n"
-
-class Config:
- """Cdist main class to hold arbitrary data"""
-
- def __init__(self, target_host,
- initial_manifest=False,
- remote_user="root",
- home=None,
- exec_path=sys.argv[0],
- debug=False):
-
- self.target_host = target_host
- self.debug = debug
- self.remote_user = remote_user
- self.exec_path = exec_path
-
- # FIXME: broken - construct elsewhere!
- self.remote_prefix = ["ssh", self.remote_user + "@" + self.target_host]
-
- self.path = cdist.path.Path(self.target_host,
- initial_manifest=initial_manifest,
- remote_user=self.remote_user,
- remote_prefix=self.remote_prefix,
- base_dir=home,
- debug=debug)
-
- self.objects_prepared = []
-
- def cleanup(self):
- self.path.cleanup()
-
- def run_global_explores(self):
- """Run global explorers"""
- log.info("Running global explorers")
- explorers = self.path.list_global_explorers()
- if(len(explorers) == 0):
- raise CdistError("No explorers found in", self.path.global_explorer_dir)
-
- self.path.transfer_global_explorers()
- for explorer in explorers:
- output = self.path.global_explorer_output_path(explorer)
- output_fd = open(output, mode='w')
- cmd = []
- cmd.append("__explorer=" + cdist.path.REMOTE_GLOBAL_EXPLORER_DIR)
- cmd.append(self.path.remote_global_explorer_path(explorer))
-
- cdist.exec.run_or_fail(cmd, stdout=output_fd, remote_prefix=self.remote_prefix)
- output_fd.close()
-
- def run_type_explorer(self, cdist_object):
- """Run type specific explorers for objects"""
-
- type = self.path.get_type_from_object(cdist_object)
- self.path.transfer_type_explorers(type)
-
- cmd = []
- cmd.append("__explorer=" + cdist.path.REMOTE_GLOBAL_EXPLORER_DIR)
- cmd.append("__type_explorer=" + self.path.remote_type_explorer_dir(type))
- cmd.append("__object=" + self.path.remote_object_dir(cdist_object))
- cmd.append("__object_id=" + self.path.get_object_id_from_object(cdist_object))
- cmd.append("__object_fq=" + cdist_object)
-
- # Need to transfer at least the parameters for objects to be useful
- self.path.transfer_object_parameter(cdist_object)
-
- explorers = self.path.list_type_explorers(type)
- for explorer in explorers:
- remote_cmd = cmd + [os.path.join(self.path.remote_type_explorer_dir(type), explorer)]
- output = os.path.join(self.path.type_explorer_output_dir(cdist_object), explorer)
- output_fd = open(output, mode='w')
- log.debug("%s exploring %s using %s storing to %s",
- cdist_object, explorer, remote_cmd, output)
-
- cdist.exec.run_or_fail(remote_cmd, stdout=output_fd, remote_prefix=self.remote_prefix)
- output_fd.close()
-
- def link_emulator(self):
- """Link emulator to types"""
- cdist.emulator.link(self.exec_path,
- self.path.bin_dir, self.path.list_types())
-
- def init_deploy(self):
- """Ensure the base directories are cleaned up"""
- log.debug("Creating clean directory structure")
-
- self.path.remove_remote_dir(cdist.path.REMOTE_BASE_DIR)
- self.path.remote_mkdir(cdist.path.REMOTE_BASE_DIR)
- self.link_emulator()
-
- def run_initial_manifest(self):
- """Run the initial manifest"""
- log.info("Running initial manifest %s", self.path.initial_manifest)
- env = { "__manifest" : self.path.manifest_dir }
- self.run_manifest(self.path.initial_manifest, extra_env=env)
-
- def run_type_manifest(self, cdist_object):
- """Run manifest for a specific object"""
- type = self.path.get_type_from_object(cdist_object)
- manifest = self.path.type_dir(type, "manifest")
-
- log.debug("%s: Running %s", cdist_object, manifest)
- if os.path.exists(manifest):
- env = { "__object" : self.path.object_dir(cdist_object),
- "__object_id": self.path.get_object_id_from_object(cdist_object),
- "__object_fq": cdist_object,
- "__type": self.path.type_dir(type)
- }
- self.run_manifest(manifest, extra_env=env)
-
- def run_manifest(self, manifest, extra_env=None):
- """Run a manifest"""
- log.debug("Running manifest %s, env=%s", manifest, extra_env)
- env = os.environ.copy()
- env['PATH'] = self.path.bin_dir + ":" + env['PATH']
-
- # Information required in every manifest
- env['__target_host'] = self.target_host
- env['__global'] = self.path.out_dir
-
- # Submit debug flag to manifest, can be used by emulator and types
- if self.debug:
- env['__debug'] = "yes"
-
- # Required for recording source
- env['__cdist_manifest'] = manifest
-
- # Required to find types
- env['__cdist_type_base_dir'] = self.path.type_base_dir
-
- # Other environment stuff
- if extra_env:
- env.update(extra_env)
-
- cdist.exec.shell_run_or_debug_fail(manifest, [manifest], env=env)
-
- def object_run(self, cdist_object, mode):
- """Run gencode or code for an object"""
- log.debug("Running %s from %s", mode, cdist_object)
- file=os.path.join(self.path.object_dir(cdist_object), "require")
- requirements = cdist.path.file_to_list(file)
- type = self.path.get_type_from_object(cdist_object)
-
- for requirement in requirements:
- log.debug("Object %s requires %s", cdist_object, requirement)
- self.object_run(requirement, mode=mode)
-
- #
- # Setup env Variable:
- #
- env = os.environ.copy()
- env['__target_host'] = self.target_host
- env['__global'] = self.path.out_dir
- env["__object"] = self.path.object_dir(cdist_object)
- env["__object_id"] = self.path.get_object_id_from_object(cdist_object)
- env["__object_fq"] = cdist_object
- env["__type"] = self.path.type_dir(type)
-
- if mode == "gencode":
- paths = [
- self.path.type_dir(type, "gencode-local"),
- self.path.type_dir(type, "gencode-remote")
- ]
- for bin in paths:
- if os.path.isfile(bin):
- # omit "gen" from gencode and use it for output base
- outfile=os.path.join(self.path.object_dir(cdist_object),
- os.path.basename(bin)[3:])
-
- outfile_fd = open(outfile, "w")
-
- # Need to flush to ensure our write is done before stdout write
- outfile_fd.write(CODE_HEADER)
- outfile_fd.flush()
-
- cdist.exec.shell_run_or_debug_fail(bin, [bin], env=env, stdout=outfile_fd)
- outfile_fd.close()
-
- status = os.stat(outfile)
-
- # Remove output if empty, else make it executable
- if status.st_size == len(CODE_HEADER):
- os.unlink(outfile)
- else:
- # Add header and make executable - identically to 0o700
- os.chmod(outfile, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
-
- # Mark object as changed
- open(os.path.join(self.path.object_dir(cdist_object), "changed"), "w").close()
-
-
- if mode == "code":
- local_dir = self.path.object_dir(cdist_object)
- remote_dir = self.path.remote_object_dir(cdist_object)
-
- bin = os.path.join(local_dir, "code-local")
- if os.path.isfile(bin):
- cdist.exec.run_or_fail([bin])
-
-
- local_remote_code = os.path.join(local_dir, "code-remote")
- remote_remote_code = os.path.join(remote_dir, "code-remote")
- if os.path.isfile(local_remote_code):
- self.path.transfer_file(local_remote_code, remote_remote_code)
- # FIXME: remote_prefix
- cdist.exec.run_or_fail([remote_remote_code], remote_prefix=self.remote_prefix)
-
- def stage_prepare(self):
- """Do everything for a deploy, minus the actual code stage"""
- self.init_deploy()
- self.run_global_explores()
- self.run_initial_manifest()
-
- log.info("Running object manifests and type explorers")
-
- old_objects = []
- objects = self.path.list_objects()
-
- # Continue process until no new objects are created anymore
- while old_objects != objects:
- old_objects = list(objects)
- for cdist_object in objects:
- if cdist_object in self.objects_prepared:
- log.debug("Skipping rerun of object %s", cdist_object)
- continue
- else:
- self.run_type_explorer(cdist_object)
- self.run_type_manifest(cdist_object)
- self.objects_prepared.append(cdist_object)
-
- objects = self.path.list_objects()
-
- def stage_run(self):
- """The final (and real) step of deployment"""
- log.info("Generating and executing code")
- # Now do the final steps over the existing objects
- for cdist_object in self.path.list_objects():
- log.debug("Run object: %s", cdist_object)
- self.object_run(cdist_object, mode="gencode")
- self.object_run(cdist_object, mode="code")
-
- def deploy_to(self):
- """Mimic the old deploy to: Deploy to one host"""
- log.info("Deploying to " + self.target_host)
- time_start = datetime.datetime.now()
-
- self.stage_prepare()
- self.stage_run()
-
- time_end = datetime.datetime.now()
- duration = time_end - time_start
- log.info("Finished run of %s in %s seconds",
- self.target_host,
- duration.total_seconds())
-
- def deploy_and_cleanup(self):
- """Do what is most often done: deploy & cleanup"""
- self.deploy_to()
- self.cleanup()
+class Config(cdist.config_install.ConfigInstall):
+ pass
def config(args):
"""Configure remote system"""
diff --git a/lib/cdist/config_install.py b/lib/cdist/config_install.py
new file mode 100644
index 00000000..cd8ea720
--- /dev/null
+++ b/lib/cdist/config_install.py
@@ -0,0 +1,293 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# 2010-2011 Nico Schottelius (nico-cdist at 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 .
+#
+#
+
+import datetime
+import logging
+import os
+import stat
+import sys
+
+import cdist.emulator
+import cdist.path
+
+log = logging.getLogger(__name__)
+
+CODE_HEADER = "#!/bin/sh -e\n"
+
+class ConfigInstall:
+ """Class to hold install and config methods"""
+
+ def __init__(self, target_host,
+ initial_manifest=False,
+ remote_user="root",
+ home=None,
+ exec_path=sys.argv[0],
+ debug=False):
+
+ self.target_host = target_host
+ self.debug = debug
+ self.remote_user = remote_user
+ self.exec_path = exec_path
+
+ # FIXME: broken - construct elsewhere!
+ self.remote_prefix = ["ssh", self.remote_user + "@" + self.target_host]
+
+ self.path = cdist.path.Path(self.target_host,
+ initial_manifest=initial_manifest,
+ remote_user=self.remote_user,
+ remote_prefix=self.remote_prefix,
+ base_dir=home,
+ debug=debug)
+
+ self.objects_prepared = []
+
+ def cleanup(self):
+ self.path.cleanup()
+
+ def run_global_explores(self):
+ """Run global explorers"""
+ log.info("Running global explorers")
+ explorers = self.path.list_global_explorers()
+ if(len(explorers) == 0):
+ raise CdistError("No explorers found in", self.path.global_explorer_dir)
+
+ self.path.transfer_global_explorers()
+ for explorer in explorers:
+ output = self.path.global_explorer_output_path(explorer)
+ output_fd = open(output, mode='w')
+ cmd = []
+ cmd.append("__explorer=" + cdist.path.REMOTE_GLOBAL_EXPLORER_DIR)
+ cmd.append(self.path.remote_global_explorer_path(explorer))
+
+ cdist.exec.run_or_fail(cmd, stdout=output_fd, remote_prefix=self.remote_prefix)
+ output_fd.close()
+
+ def run_type_explorer(self, cdist_object):
+ """Run type specific explorers for objects"""
+
+ type = self.path.get_type_from_object(cdist_object)
+ self.path.transfer_type_explorers(type)
+
+ cmd = []
+ cmd.append("__explorer=" + cdist.path.REMOTE_GLOBAL_EXPLORER_DIR)
+ cmd.append("__type_explorer=" + self.path.remote_type_explorer_dir(type))
+ cmd.append("__object=" + self.path.remote_object_dir(cdist_object))
+ cmd.append("__object_id=" + self.path.get_object_id_from_object(cdist_object))
+ cmd.append("__object_fq=" + cdist_object)
+
+ # Need to transfer at least the parameters for objects to be useful
+ self.path.transfer_object_parameter(cdist_object)
+
+ explorers = self.path.list_type_explorers(type)
+ for explorer in explorers:
+ remote_cmd = cmd + [os.path.join(self.path.remote_type_explorer_dir(type), explorer)]
+ output = os.path.join(self.path.type_explorer_output_dir(cdist_object), explorer)
+ output_fd = open(output, mode='w')
+ log.debug("%s exploring %s using %s storing to %s",
+ cdist_object, explorer, remote_cmd, output)
+
+ cdist.exec.run_or_fail(remote_cmd, stdout=output_fd, remote_prefix=self.remote_prefix)
+ output_fd.close()
+
+ def link_emulator(self):
+ """Link emulator to types"""
+ cdist.emulator.link(self.exec_path,
+ self.path.bin_dir, self.path.list_types())
+
+ def init_deploy(self):
+ """Ensure the base directories are cleaned up"""
+ log.debug("Creating clean directory structure")
+
+ self.path.remove_remote_dir(cdist.path.REMOTE_BASE_DIR)
+ self.path.remote_mkdir(cdist.path.REMOTE_BASE_DIR)
+ self.link_emulator()
+
+ def run_initial_manifest(self):
+ """Run the initial manifest"""
+ log.info("Running initial manifest %s", self.path.initial_manifest)
+ env = { "__manifest" : self.path.manifest_dir }
+ self.run_manifest(self.path.initial_manifest, extra_env=env)
+
+ def run_type_manifest(self, cdist_object):
+ """Run manifest for a specific object"""
+ type = self.path.get_type_from_object(cdist_object)
+ manifest = self.path.type_dir(type, "manifest")
+
+ log.debug("%s: Running %s", cdist_object, manifest)
+ if os.path.exists(manifest):
+ env = { "__object" : self.path.object_dir(cdist_object),
+ "__object_id": self.path.get_object_id_from_object(cdist_object),
+ "__object_fq": cdist_object,
+ "__type": self.path.type_dir(type)
+ }
+ self.run_manifest(manifest, extra_env=env)
+
+ def run_manifest(self, manifest, extra_env=None):
+ """Run a manifest"""
+ log.debug("Running manifest %s, env=%s", manifest, extra_env)
+ env = os.environ.copy()
+ env['PATH'] = self.path.bin_dir + ":" + env['PATH']
+
+ # Information required in every manifest
+ env['__target_host'] = self.target_host
+ env['__global'] = self.path.out_dir
+
+ # Submit debug flag to manifest, can be used by emulator and types
+ if self.debug:
+ env['__debug'] = "yes"
+
+ # Required for recording source
+ env['__cdist_manifest'] = manifest
+
+ # Required to find types
+ env['__cdist_type_base_dir'] = self.path.type_base_dir
+
+ # Other environment stuff
+ if extra_env:
+ env.update(extra_env)
+
+ cdist.exec.shell_run_or_debug_fail(manifest, [manifest], env=env)
+
+ def object_run(self, cdist_object, mode):
+ """Run gencode or code for an object"""
+ log.debug("Running %s from %s", mode, cdist_object)
+ file=os.path.join(self.path.object_dir(cdist_object), "require")
+ requirements = cdist.path.file_to_list(file)
+ type = self.path.get_type_from_object(cdist_object)
+
+ for requirement in requirements:
+ log.debug("Object %s requires %s", cdist_object, requirement)
+ self.object_run(requirement, mode=mode)
+
+ #
+ # Setup env Variable:
+ #
+ env = os.environ.copy()
+ env['__target_host'] = self.target_host
+ env['__global'] = self.path.out_dir
+ env["__object"] = self.path.object_dir(cdist_object)
+ env["__object_id"] = self.path.get_object_id_from_object(cdist_object)
+ env["__object_fq"] = cdist_object
+ env["__type"] = self.path.type_dir(type)
+
+ if mode == "gencode":
+ paths = [
+ self.path.type_dir(type, "gencode-local"),
+ self.path.type_dir(type, "gencode-remote")
+ ]
+ for bin in paths:
+ if os.path.isfile(bin):
+ # omit "gen" from gencode and use it for output base
+ outfile=os.path.join(self.path.object_dir(cdist_object),
+ os.path.basename(bin)[3:])
+
+ outfile_fd = open(outfile, "w")
+
+ # Need to flush to ensure our write is done before stdout write
+ # FIXME: CODE_HEADER needed in our sh -e scenario????
+ outfile_fd.write(CODE_HEADER)
+ outfile_fd.flush()
+
+ cdist.exec.shell_run_or_debug_fail(bin, [bin], env=env, stdout=outfile_fd)
+ outfile_fd.close()
+
+ status = os.stat(outfile)
+
+ # Remove output if empty, else make it executable
+ if status.st_size == len(CODE_HEADER):
+ os.unlink(outfile)
+ else:
+ # Add header and make executable - identically to 0o700
+ os.chmod(outfile, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
+
+ # Mark object as changed
+ open(os.path.join(self.path.object_dir(cdist_object), "changed"), "w").close()
+
+
+ if mode == "code":
+ local_dir = self.path.object_dir(cdist_object)
+ remote_dir = self.path.remote_object_dir(cdist_object)
+
+ bin = os.path.join(local_dir, "code-local")
+ if os.path.isfile(bin):
+ cdist.exec.run_or_fail([bin])
+
+
+ local_remote_code = os.path.join(local_dir, "code-remote")
+ remote_remote_code = os.path.join(remote_dir, "code-remote")
+ if os.path.isfile(local_remote_code):
+ self.path.transfer_file(local_remote_code, remote_remote_code)
+ # FIXME: remote_prefix
+ cdist.exec.run_or_fail([remote_remote_code], remote_prefix=self.remote_prefix)
+
+ def stage_prepare(self):
+ """Do everything for a deploy, minus the actual code stage"""
+ self.init_deploy()
+ self.run_global_explores()
+ self.run_initial_manifest()
+
+ log.info("Running object manifests and type explorers")
+
+ old_objects = []
+ objects = self.path.list_objects()
+
+ # Continue process until no new objects are created anymore
+ while old_objects != objects:
+ old_objects = list(objects)
+ for cdist_object in objects:
+ if cdist_object in self.objects_prepared:
+ log.debug("Skipping rerun of object %s", cdist_object)
+ continue
+ else:
+ self.run_type_explorer(cdist_object)
+ self.run_type_manifest(cdist_object)
+ self.objects_prepared.append(cdist_object)
+
+ objects = self.path.list_objects()
+
+ def stage_run(self):
+ """The final (and real) step of deployment"""
+ log.info("Generating and executing code")
+ # Now do the final steps over the existing objects
+ for cdist_object in self.path.list_objects():
+ log.debug("Run object: %s", cdist_object)
+ self.object_run(cdist_object, mode="gencode")
+ self.object_run(cdist_object, mode="code")
+
+ def deploy_to(self):
+ """Mimic the old deploy to: Deploy to one host"""
+ log.info("Deploying to " + self.target_host)
+ time_start = datetime.datetime.now()
+
+ self.stage_prepare()
+ self.stage_run()
+
+ time_end = datetime.datetime.now()
+ duration = time_end - time_start
+ log.info("Finished run of %s in %s seconds",
+ self.target_host,
+ duration.total_seconds())
+
+ def deploy_and_cleanup(self):
+ """Do what is most often done: deploy & cleanup"""
+ self.deploy_to()
+ self.cleanup()
diff --git a/lib/cdist/install.py b/lib/cdist/install.py
index 98b388ec..5a35626d 100644
--- a/lib/cdist/install.py
+++ b/lib/cdist/install.py
@@ -22,8 +22,14 @@
import logging
+import cdist.config_install
+
log = logging.getLogger(__name__)
+
+Class Install(cdist.config_install.ConfigInstall):
+ pass
+
def install(args):
"""Install remote system"""
process = {}
diff --git a/lib/cdist/path.py b/lib/cdist/path.py
index e416c42d..2dd9dcf1 100644
--- a/lib/cdist/path.py
+++ b/lib/cdist/path.py
@@ -175,8 +175,14 @@ class Path:
return list
def list_types(self):
+ """Retuns list of types"""
return os.listdir(self.type_base_dir)
+ def is_install_type(self, type):
+ """Check whether a type is used for installation (if not: for configuration)"""
+ marker = os.path.join(self.type_dir(type), "install")
+ return os.path.isfile(marker)
+
def list_object_paths(self, starting_point):
"""Return list of paths of existing objects"""
object_paths = []
diff --git a/lib/cdist/test/__init__.py b/lib/cdist/test/__init__.py
new file mode 100644
index 00000000..f614fa05
--- /dev/null
+++ b/lib/cdist/test/__init__.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# 2011 Nico Schottelius (nico-cdist at 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 .
+#
+#
+
+
+import os
+import subprocess
+import unittest
+
+cdist_commands=["banner", "config", "install"]
+
+cdist_exec_path = os.path.abspath(
+ os.path.join(os.path.dirname(os.path.realpath(__file__)), "../../bin/cdist"))
+
+def exec():
+ print(cdist_exec_path)
+
+#class UI(unittest.TestCase):
+# def test_banner(self):
+# self.assertEqual(subprocess.call([cdist_exec_path, "banner"]), 0)
+#
+# def test_help(self):
+# for cmd in cdist_commands:
+# self.assertEqual(subprocess.call([cdist_exec_path, cmd, "-h"]), 0)
+#
+# # FIXME: mockup needed
+# def test_config_localhost(self):
+# for cmd in cdist_commands:
+# self.assertEqual(subprocess.call([cdist_exec_path, "config", "localhost"]), 0)
diff --git a/lib/cdist/test/__main__.py b/lib/cdist/test/__main__.py
new file mode 100644
index 00000000..3b31a2cd
--- /dev/null
+++ b/lib/cdist/test/__main__.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# 2011 Nico Schottelius (nico-cdist at 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 .
+#
+#
+
+
+import os
+import sys
+import cdist.test
+import unittest
+
+#class UI(unittest.TestCase):
+# def test_banner(self):
+# self.assertEqual(subprocess.call([cdist_exec_path, "banner"]), 0)
+#
+# def test_help(self):
+# for cmd in cdist_commands:
+# self.assertEqual(subprocess.call([cdist_exec_path, cmd, "-h"]), 0)
+#
+# # FIXME: mockup needed
+# def test_config_localhost(self):
+# for cmd in cdist_commands:
+# self.assertEqual(subprocess.call([cdist_exec_path, "config", "localhost"]), 0)
+
+print(cdist.test.cdist_exec_path)
+print(sys.argv)
+
+suite = unittest.defaultTestLoader.discover(os.path.dirname(__file__))
+unittest.TextTestRunner(verbosity=1).run(suite)
diff --git a/test/nico_ui.py b/lib/cdist/test/nico_ui.py
old mode 100755
new mode 100644
similarity index 100%
rename from test/nico_ui.py
rename to lib/cdist/test/nico_ui.py
diff --git a/test/test_config.py b/lib/cdist/test/test_config.py
similarity index 100%
rename from test/test_config.py
rename to lib/cdist/test/test_config.py
diff --git a/test/test_exec.py b/lib/cdist/test/test_exec.py
old mode 100755
new mode 100644
similarity index 100%
rename from test/test_exec.py
rename to lib/cdist/test/test_exec.py
diff --git a/lib/cdist/test/test_install.py b/lib/cdist/test/test_install.py
new file mode 100644
index 00000000..9cfae066
--- /dev/null
+++ b/lib/cdist/test/test_install.py
@@ -0,0 +1,129 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# 2011 Nico Schottelius (nico-cdist at 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 .
+#
+#
+
+import os
+import sys
+import tempfile
+import unittest
+
+sys.path.insert(0, os.path.abspath(
+ os.path.join(os.path.dirname(os.path.realpath(__file__)), '../lib')))
+
+import cdist.config
+
+cdist_exec_path = os.path.abspath(
+ os.path.join(os.path.dirname(os.path.realpath(__file__)), "bin/cdist"))
+
+
+class Install(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,
+ exec_path=cdist_exec_path)
+ self.config.link_emulator()
+
+### NEW FOR INSTALL ############################################################
+
+ def test_explorer_ran(self):
+ """Check that all explorers returned a result"""
+ self.config.run_global_explores()
+ explorers = self.config.path.list_global_explorers()
+
+ for explorer in explorers:
+ output = self.config.path.global_explorer_output_path(explorer)
+ self.assertTrue(os.path.isfile(output))
+
+ def test_manifest_uses_install_types_only(self):
+ """Check that objects created from manifest are only of install type"""
+ manifest_fd = open(self.init_manifest, "w")
+ manifest_fd.writelines(["#!/bin/sh\n",
+ "__file " + self.temp_dir + " --mode 0700\n",
+ "__partition_msdos /dev/null --type 82\n",
+ ])
+ manifest_fd.close()
+
+ self.config.run_initial_manifest()
+
+ # FIXME: check that only __partition_msdos objects are created!
+
+ self.assertFalse(failed)
+
+
+### OLD FROM CONFIG ############################################################
+ 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_non_existent_command(self):
+ manifest_fd = open(self.init_manifest, "w")
+ manifest_fd.writelines(["#!/bin/sh\n",
+ "thereisdefinitelynosuchcommend"])
+ 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:
+ self.config.run_initial_manifest()
+ except cdist.Error:
+ failed = True
+ else:
+ failed = False
+
+ self.assertFalse(failed)
+
+
diff --git a/lib/cdist/test/test_path.py b/lib/cdist/test/test_path.py
new file mode 100644
index 00000000..f86c8fad
--- /dev/null
+++ b/lib/cdist/test/test_path.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# 2011 Nico Schottelius (nico-cdist at 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 .
+#
+#
+
+import os
+import shutil
+import sys
+import tempfile
+import unittest
+
+import cdist.path
+import cdist.test
+
+class Path(unittest.TestCase):
+ def setUp(self):
+ self.temp_dir = tempfile.mkdtemp()
+ self.init_manifest = os.path.join(self.temp_dir, "manifest")
+ self.path = cdist.path.Path("localhost", "root", "ssh root@localhost",
+ initial_manifest=self.init_manifest,
+ base_dir=self.temp_dir)
+
+ os.mkdir(self.path.conf_dir)
+ os.mkdir(self.path.type_base_dir)
+
+ self.install_type_name = "__install_test"
+ self.config_type_name = "__config_test"
+
+ # Create install type
+ self.install_type = os.path.join(self.path.type_base_dir, self.install_type_name)
+ os.mkdir(self.install_type)
+ open(os.path.join(self.install_type, "install"), "w").close()
+
+ # Create config type
+ self.config_type = os.path.join(self.path.type_base_dir, self.config_type_name)
+ os.mkdir(self.config_type)
+
+ def tearDown(self):
+ self.path.cleanup()
+ shutil.rmtree(self.temp_dir)
+
+ def test_type_detection(self):
+ """Check that a type is identified as install or configuration correctly"""
+
+ self.assertTrue(self.path.is_install_type(self.install_type))
+ self.assertFalse(self.path.is_install_type(self.config_type))
+
+ def test_manifest_uses_install_types_only(self):
+ """Check that objects created from manifest are only of install type"""
+ manifest_fd = open(self.init_manifest, "w")
+ manifest_fd.writelines(["#!/bin/sh\n",
+ self.install_type_name + "testid\n",
+ self.config_type_name + "testid\n",
+ ])
+ manifest_fd.close()
+
+ self.install.run_initial_manifest()
+
+ # FIXME: check that only __partition_msdos objects are created!
+
+ self.assertFalse(failed)