diff --git a/doc/man/cdist-reference.text.sh b/doc/man/cdist-reference.text.sh index 81e58ab2..a76e7941 100755 --- a/doc/man/cdist-reference.text.sh +++ b/doc/man/cdist-reference.text.sh @@ -101,12 +101,15 @@ conf/type//gencode-local:: conf/type//gencode-remote:: Used to generate code to be executed on the client. -conf/type//parameters/required:: +conf/type//parameter/required:: Parameters required by type, \n seperated list. -conf/type//parameters/optional:: +conf/type//parameter/optional:: Parameters optionally accepted by type, \n seperated list. +conf/type//parameter/boolean:: + Boolean parameters accepted by type, \n seperated list. + conf/type//explorer:: Location of the type specific explorers. This directory is referenced by the variable __type_explorer (see below). diff --git a/doc/man/man7/cdist-type.text b/doc/man/man7/cdist-type.text index 48d412f1..1147511e 100644 --- a/doc/man/man7/cdist-type.text +++ b/doc/man/man7/cdist-type.text @@ -40,7 +40,7 @@ A list of supported types can be found in the cdist-reference(7) manpage. SINGLETON TYPES --------------- -If a type is flagged as a singleton, it may be used only +If a type is flagged as a singleton, it may be used only once per host. This is useful for types which can be used only once on a system. Singleton types do not take an object name as argument. @@ -72,15 +72,42 @@ To begin a new type, just create the directory **conf/type/__NAME**. DEFINING PARAMETERS ------------------- -Every type consists of optional and required parameters, which must -be created in a newline seperated file in ***parameters/required*** and -***parameters/optional***. If either or both missing, the type will have -no required, no optional or no parameters at all. +Every type consists of required, optional and boolean parameters, which must +be created in a newline seperated file in ***parameter/required***, +***parameter/optional*** and ***parameter/boolean***. If either is missing, +the type will have no required, no optional, no boolean or no parameters at +all. Example: -------------------------------------------------------------------------------- echo servername >> conf/type/__nginx_vhost/parameter/required echo logdirectory >> conf/type/__nginx_vhost/parameter/optional +echo use_ssl >> conf/type/__nginx_vhost/parameter/boolean +-------------------------------------------------------------------------------- + + +USING PARAMETERS +---------------- +The parameters given to a type can be accessed and used in all type scripts +(e.g manifest, gencode-*, explorer/*). Note that boolean parameters are +represented by file existence. File exists -> True, +file does not exist -> False + +Example: (e.g. in conf/type/__nginx_vhost/manifest) +-------------------------------------------------------------------------------- +# required parameter +servername="$(cat "$__object/parameter/servername")" + +# optional parameter +if [ -f "$__object/parameter/logdirectory" ]; then + logdirectory="$(cat "$__object/parameter/logdirectory")" +fi + +# boolean parameter +if [ -f "$__object/parameter/use_ssl" ]; then + # file exists -> True + # do some fancy ssl stuff +fi -------------------------------------------------------------------------------- @@ -116,7 +143,7 @@ SINGLETON - ONLY INSTANCE ONLY ------------------------------ If you want to ensure that a type can only be used once per target, you can mark it as a singleton: Just create the (empty) file "singleton" in your type -directory: +directory: -------------------------------------------------------------------------------- touch conf/type/__NAME/singleton @@ -128,7 +155,7 @@ This will also change the way your type must be called: __YOURTYPE --parameter value -------------------------------------------------------------------------------- -As you can see, the object ID is omitted, because it does not make any sense, +As you can see, the object ID is omitted, because it does not make any sense, if your type can be used only once. diff --git a/lib/cdist/core/cdist_type.py b/lib/cdist/core/cdist_type.py index 55609e7e..1d2472c4 100644 --- a/lib/cdist/core/cdist_type.py +++ b/lib/cdist/core/cdist_type.py @@ -82,6 +82,7 @@ class CdistType(object): self.__explorers = None self.__required_parameters = None self.__optional_parameters = None + self.__boolean_parameters = None def __repr__(self): return '' % self.name @@ -144,3 +145,19 @@ class CdistType(object): finally: self.__optional_parameters = parameters return self.__optional_parameters + + @property + def boolean_parameters(self): + """Return a list of boolean parameters""" + if not self.__boolean_parameters: + parameters = [] + try: + with open(os.path.join(self.absolute_path, "parameter", "boolean")) as fd: + for line in fd: + parameters.append(line.strip()) + except EnvironmentError: + # error ignored + pass + finally: + self.__boolean_parameters = parameters + return self.__boolean_parameters diff --git a/lib/cdist/emulator.py b/lib/cdist/emulator.py index 6d6050e8..c4b84feb 100644 --- a/lib/cdist/emulator.py +++ b/lib/cdist/emulator.py @@ -87,7 +87,7 @@ class Emulator(object): def commandline(self): """Parse command line""" - parser = argparse.ArgumentParser(add_help=False) + parser = argparse.ArgumentParser(add_help=False, argument_default=argparse.SUPPRESS) for parameter in self.cdist_type.optional_parameters: argument = "--" + parameter @@ -95,6 +95,9 @@ class Emulator(object): for parameter in self.cdist_type.required_parameters: argument = "--" + parameter parser.add_argument(argument, dest=parameter, action='store', required=True) + for parameter in self.cdist_type.boolean_parameters: + argument = "--" + parameter + parser.add_argument(argument, dest=parameter, action='store_const', const='') # If not singleton support one positional parameter if not self.cdist_type.is_singleton: diff --git a/lib/cdist/test/emulator/__init__.py b/lib/cdist/test/emulator/__init__.py index f1ea5832..370d3d82 100644 --- a/lib/cdist/test/emulator/__init__.py +++ b/lib/cdist/test/emulator/__init__.py @@ -126,7 +126,7 @@ class AutoRequireEmulatorTestCase(test.CdistTestCase): self.assertEqual(sorted(cdist_object.requirements), sorted(expected)) -class ArgumentsWithDashesTestCase(test.CdistTestCase): +class ArgumentsTestCase(test.CdistTestCase): def setUp(self): self.temp_dir = self.mkdtemp() @@ -159,3 +159,59 @@ class ArgumentsWithDashesTestCase(test.CdistTestCase): cdist_type = core.CdistType(self.local.type_path, '__arguments_with_dashes') cdist_object = core.CdistObject(cdist_type, self.local.object_path, 'some-id') self.assertTrue('with-dash' in cdist_object.parameters) + + def test_boolean(self): + type_name = '__arguments_boolean' + object_id = 'some-id' + argv = [type_name, object_id, '--boolean1'] + os.environ.update(self.env) + emu = emulator.Emulator(argv) + emu.run() + + cdist_type = core.CdistType(self.local.type_path, type_name) + cdist_object = core.CdistObject(cdist_type, self.local.object_path, object_id) + self.assertTrue('boolean1' in cdist_object.parameters) + self.assertFalse('boolean2' in cdist_object.parameters) + # empty file -> True + self.assertTrue(cdist_object.parameters['boolean1'] == '') + + def test_required(self): + type_name = '__arguments_required' + object_id = 'some-id' + value = 'some value' + argv = [type_name, object_id, '--required1', value, '--required2', value] + os.environ.update(self.env) + emu = emulator.Emulator(argv) + emu.run() + + cdist_type = core.CdistType(self.local.type_path, type_name) + cdist_object = core.CdistObject(cdist_type, self.local.object_path, object_id) + self.assertTrue('required1' in cdist_object.parameters) + self.assertTrue('required2' in cdist_object.parameters) + self.assertEqual(cdist_object.parameters['required1'], value) + self.assertEqual(cdist_object.parameters['required2'], value) + +# def test_required_missing(self): +# type_name = '__arguments_required' +# object_id = 'some-id' +# value = 'some value' +# argv = [type_name, object_id, '--required1', value] +# os.environ.update(self.env) +# emu = emulator.Emulator(argv) +# +# self.assertRaises(SystemExit, emu.run) + + def test_optional(self): + type_name = '__arguments_optional' + object_id = 'some-id' + value = 'some value' + argv = [type_name, object_id, '--optional1', value] + os.environ.update(self.env) + emu = emulator.Emulator(argv) + emu.run() + + cdist_type = core.CdistType(self.local.type_path, type_name) + cdist_object = core.CdistObject(cdist_type, self.local.object_path, object_id) + self.assertTrue('optional1' in cdist_object.parameters) + self.assertFalse('optional2' in cdist_object.parameters) + self.assertEqual(cdist_object.parameters['optional1'], value) diff --git a/lib/cdist/test/emulator/fixtures/conf/type/__arguments_boolean/parameter/boolean b/lib/cdist/test/emulator/fixtures/conf/type/__arguments_boolean/parameter/boolean new file mode 100644 index 00000000..3215c409 --- /dev/null +++ b/lib/cdist/test/emulator/fixtures/conf/type/__arguments_boolean/parameter/boolean @@ -0,0 +1,2 @@ +boolean1 +boolean2 diff --git a/lib/cdist/test/emulator/fixtures/conf/type/__arguments_optional/parameter/optional b/lib/cdist/test/emulator/fixtures/conf/type/__arguments_optional/parameter/optional new file mode 100644 index 00000000..31647628 --- /dev/null +++ b/lib/cdist/test/emulator/fixtures/conf/type/__arguments_optional/parameter/optional @@ -0,0 +1 @@ +optional1 diff --git a/lib/cdist/test/emulator/fixtures/conf/type/__arguments_required/parameter/required b/lib/cdist/test/emulator/fixtures/conf/type/__arguments_required/parameter/required new file mode 100644 index 00000000..e0fba2c9 --- /dev/null +++ b/lib/cdist/test/emulator/fixtures/conf/type/__arguments_required/parameter/required @@ -0,0 +1,2 @@ +required1 +required2 diff --git a/lib/cdist/test/type/__init__.py b/lib/cdist/test/type/__init__.py index 2ef14a4c..5e774aa9 100644 --- a/lib/cdist/test/type/__init__.py +++ b/lib/cdist/test/type/__init__.py @@ -145,3 +145,14 @@ class TypeTestCase(test.CdistTestCase): base_path = fixtures cdist_type = core.CdistType(base_path, '__without_optional_parameters') self.assertEqual(cdist_type.optional_parameters, []) + + def test_with_boolean_parameters(self): + base_path = fixtures + cdist_type = core.CdistType(base_path, '__with_boolean_parameters') + self.assertEqual(cdist_type.boolean_parameters, ['boolean1', 'boolean2']) + + def test_without_boolean_parameters(self): + base_path = fixtures + cdist_type = core.CdistType(base_path, '__without_boolean_parameters') + self.assertEqual(cdist_type.boolean_parameters, []) + diff --git a/lib/cdist/test/type/fixtures/__with_boolean_parameters/parameter/boolean b/lib/cdist/test/type/fixtures/__with_boolean_parameters/parameter/boolean new file mode 100644 index 00000000..3215c409 --- /dev/null +++ b/lib/cdist/test/type/fixtures/__with_boolean_parameters/parameter/boolean @@ -0,0 +1,2 @@ +boolean1 +boolean2 diff --git a/lib/cdist/test/type/fixtures/__without_boolean_parameters/.keep b/lib/cdist/test/type/fixtures/__without_boolean_parameters/.keep new file mode 100644 index 00000000..e69de29b