From 54815e2b29ae2642f17c600a3c7afa1e24262d7d Mon Sep 17 00:00:00 2001 From: Steven Armstrong Date: Thu, 29 Aug 2013 22:32:26 +0200 Subject: [PATCH] implement cdist install Signed-off-by: Steven Armstrong --- cdist/config.py | 1 - cdist/core/cdist_type.py | 5 ++ cdist/emulator.py | 2 +- cdist/install.py | 37 ++++++++++ cdist/test/cdist_type/__init__.py | 10 +++ docs/dev/todo/steven | 118 ------------------------------ scripts/cdist | 5 ++ 7 files changed, 58 insertions(+), 120 deletions(-) create mode 100644 cdist/install.py delete mode 100644 docs/dev/todo/steven diff --git a/cdist/config.py b/cdist/config.py index 3f8a7fc6..59cf339a 100644 --- a/cdist/config.py +++ b/cdist/config.py @@ -158,7 +158,6 @@ class Config(object): self.local.save_cache() self.log.info("Finished successful run in %s seconds", time.time() - start_time) - def object_list(self): """Short name for object list retrieval""" for cdist_object in core.CdistObject.list_objects(self.local.object_path, diff --git a/cdist/core/cdist_type.py b/cdist/core/cdist_type.py index 46e126f9..ff1ebaec 100644 --- a/cdist/core/cdist_type.py +++ b/cdist/core/cdist_type.py @@ -101,6 +101,11 @@ class CdistType(object): """Check whether a type is a singleton.""" return os.path.isfile(os.path.join(self.absolute_path, "singleton")) + @property + def is_install(self): + """Check whether a type is used for installation (if not: for configuration)""" + return os.path.isfile(os.path.join(self.absolute_path, "install")) + @property def explorers(self): """Return a list of available explorers""" diff --git a/cdist/emulator.py b/cdist/emulator.py index b70ef956..b8f7b10b 100644 --- a/cdist/emulator.py +++ b/cdist/emulator.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # 2011-2013 Nico Schottelius (nico-cdist at schottelius.org) -# 2012 Steven Armstrong (steven-cdist at armstrong.cc) +# 2012-2013 Steven Armstrong (steven-cdist at armstrong.cc) # # This file is part of cdist. # diff --git a/cdist/install.py b/cdist/install.py new file mode 100644 index 00000000..4530029a --- /dev/null +++ b/cdist/install.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# 2013 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 . +# +# + +import cdist.config +import cdist.core + + +class Install(cdist.config.Config): + def object_list(self): + """Short name for object list retrieval. + In install mode, we only care about install objects. + """ + for cdist_object in cdist.core.CdistObject.list_objects(self.local.object_path, + self.local.type_path): + if cdist_object.cdist_type.is_install: + yield cdist_object + else: + self.log.debug("Running in install mode, ignoring non install object: {0}".format(cdist_object)) diff --git a/cdist/test/cdist_type/__init__.py b/cdist/test/cdist_type/__init__.py index 79f824d3..8cc1f2e4 100644 --- a/cdist/test/cdist_type/__init__.py +++ b/cdist/test/cdist_type/__init__.py @@ -106,6 +106,16 @@ class TypeTestCase(test.CdistTestCase): cdist_type = core.CdistType(base_path, '__not_singleton') self.assertFalse(cdist_type.is_singleton) + def test_install_is_install(self): + base_path = fixtures + cdist_type = core.CdistType(base_path, '__install') + self.assertTrue(cdist_type.is_install) + + def test_not_install_is_install(self): + base_path = fixtures + cdist_type = core.CdistType(base_path, '__not_install') + self.assertFalse(cdist_type.is_install) + def test_with_explorers(self): base_path = fixtures cdist_type = core.CdistType(base_path, '__with_explorers') diff --git a/docs/dev/todo/steven b/docs/dev/todo/steven deleted file mode 100644 index 2aacaa42..00000000 --- a/docs/dev/todo/steven +++ /dev/null @@ -1,118 +0,0 @@ -autorequire: - - objects defined in type manifests should be automatically prerequisites of the current object - - __foo/some-id - __other other-id --state present - => require="__other/other-id" __foo/some-id - - -metaparameters: - - steal the metaparameters from puppet: - - # I have to be there before the other one - __directory /etc/ssh \ - --before __file/etc/ssh/sshd_config - - # the other one has to be there before me - __file /etc/ssh/sshd_config \ - --after __directory/etc/ssh - - # if I change, tell the other one about it - __file /etc/ssh/sshd_config \ - --notify __init_script/etc/rc.d/sshd - - # whenever the other one changes, I want to know - __init_script /etc/rc.d/sshd \ - --subscribe __file/etc/ssh/sshd_config - - - how does a type react to a received 'event'? - - maybe something like: - __some_type/ - manifest - ... - gencode-refresh - ... - - gencode-refresh -> code-refresh -> ssh $target sh -e code-refresh - - - - -logging: - - logging from type emulator without clobbering stdout - maybe implement logging server as described here [1] - [1] http://docs.python.org/py3k/howto/logging-cookbook.html#configuration-server-example - - - use different logger to limit output to current area of interest, - e.g. - explorer.$target_host: explorer related messages for the run for $target_host - manifest.$target_host: manifest related messages for the run for $target_host - ... - then one could filter e.g. on explorer.* - - - more granular debug output, - [2] http://blog.ooz.ie/2011/03/python-logging-extending-standard.html - - - -tests: - - __init__(): - - sets up env: __target_host - - run_initial_manifest(): - - parameter is actually used (from __init__) - - ensure changing the manifest actually runs a different manifest - -> give ConfigInstall Constructor different manifest - -> different manifest is executed. - - test all submitted (from core to type manifest) variables: - - ENVIRONMENT - - they are set - - they contain the correct values - - run_type_manifest(): - - test all submitted (from core to type manifest) variables: - - ENVIRONMENT - - they are set - - they contain the correct values - - same tests as for test_initial_manifest_*? - - run_manifest(): - - test all submitted variables: - - ENVIRONMENT - - including __debug, if debug - - they are set - - they contain the correct values - - does $require work? - - check that exception raised, if manifest is not existent - - object_run(): - - ensure no object is run twice - - ensure requirements are taken into account? - - and order of run is adjusted - - check (from extern?) that all needed variables are setup - - ensure no code-{local, remote} is created, - if gencode is not producing code - - ensure THAT code-{local, remote} contains what gencode created - - abort if gencode-* fails - - abort if code-* fails - - abort == raise(FooException) - - gencode-*: ensure ENVIRONMENT is setup correctly - - run_type_explorer() - - ensure ALL type explores have been run - - ensure output is saved to correct path - - ensure a type with {0,1,2} explorers works ? - - none, one, multiple - - ensure ENVIRONMENT is setup correctly - - fails if ANY of the given explorer fails - - run_global_explorers(): - - ensure ALL type explores have been run - - ensure output is saved to correct path - - ensure a type with {0,1,2} explorers works ? - - none, one, multiple - - ensure ENVIRONMENT is setup correctly - - fails if ANY of the given explorer fails - -Code fixes needed: - - - shutil, os.mkdir, etc. everywhere: catch/reraise exceptions correctly diff --git a/scripts/cdist b/scripts/cdist index 39449666..31bd7373 100755 --- a/scripts/cdist +++ b/scripts/cdist @@ -26,6 +26,7 @@ def commandline(): import cdist.banner import cdist.config + import cdist.install import cdist.shell # Construct parser others can reuse @@ -90,6 +91,10 @@ def commandline(): help='Select shell to use, defaults to current shell') parser['shell'].set_defaults(func=cdist.shell.Shell.commandline) + # Install + parser['install'] = parser['sub'].add_parser('install', + parents=[parser['loglevel'], parser['config']]) + parser['install'].set_defaults(func=cdist.install.Install.commandline) for p in parser: parser[p].epilog = "Get cdist at http://www.nico.schottelius.org/software/cdist/"