From a993e0f5a98a1a9f6fb6768043412e36523a1a63 Mon Sep 17 00:00:00 2001 From: Darko Poljak Date: Wed, 7 Feb 2018 18:12:15 +0100 Subject: [PATCH] Support disabling saving output streams --- cdist/argparse.py | 4 + cdist/config.py | 6 +- cdist/configuration.py | 10 +- cdist/core/code.py | 32 ++-- cdist/core/manifest.py | 36 +++-- cdist/exec/local.py | 7 +- cdist/exec/remote.py | 22 +-- .../test/capture_output_disabled/__init__.py | 140 ++++++++++++++++++ .../fixtures/conf/manifest/init | 4 + .../gencode-local | 6 + .../gencode-remote | 6 + .../__write_to_stdout_and_stderr/manifest | 4 + .../__write_to_stdout_and_stderr/singleton | 0 cdist/test/configuration/__init__.py | 113 ++++++++++++++ docs/src/cdist-cache.rst | 6 +- docs/src/cdist-configuration.rst | 5 + docs/src/cdist-saving-output-streams.rst | 88 +++++++++++ docs/src/index.rst | 1 + docs/src/man1/cdist.rst | 13 +- 19 files changed, 460 insertions(+), 43 deletions(-) create mode 100644 cdist/test/capture_output_disabled/__init__.py create mode 100755 cdist/test/capture_output_disabled/fixtures/conf/manifest/init create mode 100755 cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/gencode-local create mode 100755 cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/gencode-remote create mode 100755 cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/manifest create mode 100644 cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/singleton create mode 100644 docs/src/cdist-saving-output-streams.rst diff --git a/cdist/argparse.py b/cdist/argparse.py index 5bce1b76..2ec28121 100644 --- a/cdist/argparse.py +++ b/cdist/argparse.py @@ -251,6 +251,10 @@ def get_parsers(): 'default.'), action='store', dest='parallel', const=multiprocessing.cpu_count()) + parser['config_args'].add_argument( + '-S', '--disable-saving-output-streams', + help='Disable saving output streams.', + action='store_false', dest='save_output_streams', default=True) parser['config_args'].add_argument( '-s', '--sequential', help='Operate on multiple hosts sequentially (default).', diff --git a/cdist/config.py b/cdist/config.py index dc73830c..be39de22 100644 --- a/cdist/config.py +++ b/cdist/config.py @@ -345,7 +345,8 @@ class Config(object): cache_path_pattern=args.cache_path_pattern, quiet_mode=args.quiet, configuration=configuration, - exec_path=sys.argv[0]) + exec_path=sys.argv[0], + save_output_streams=args.save_output_streams) remote = cdist.exec.remote.Remote( target_host=target_host, @@ -356,7 +357,8 @@ class Config(object): archiving_mode=args.use_archiving, configuration=configuration, stdout_base_path=local.stdout_base_path, - stderr_base_path=local.stderr_base_path) + stderr_base_path=local.stderr_base_path, + save_output_streams=args.save_output_streams) cleanup_cmds = [] if cleanup_cmd: diff --git a/cdist/configuration.py b/cdist/configuration.py index 8600cb0c..2a253e7f 100644 --- a/cdist/configuration.py +++ b/cdist/configuration.py @@ -248,6 +248,7 @@ _ARG_OPTION_MAPPING = { 'parallel': 'parallel', 'verbose': 'verbosity', 'use_archiving': 'archiving', + 'save_output_streams': 'save_output_streams', } @@ -285,6 +286,7 @@ class Configuration(metaclass=Singleton): 'parallel': JobsOption('parallel'), 'verbosity': VerbosityOption(), 'archiving': ArchivingOption(), + 'save_output_streams': BooleanOption('save_output_streams'), }, } @@ -328,7 +330,10 @@ class Configuration(metaclass=Singleton): config_files=default_config_files, singleton=True): self.command_line_args = command_line_args self.args = self._convert_args(command_line_args) - self.env = env + if env is None: + self.env = {} + else: + self.env = env self.config_files = config_files self.config = self._get_config() @@ -403,7 +408,8 @@ class Configuration(metaclass=Singleton): for option in self.ARG_OPTION_MAPPING: if option in args: dst_opt = self.ARG_OPTION_MAPPING[option] - if args[option]: + option_object = self.CONFIG_FILE_OPTIONS['GLOBAL'][dst_opt] + if args[option] or isinstance(option_object, BooleanOption): d[dst_opt] = args[option] return d diff --git a/cdist/core/code.py b/cdist/core/code.py index 65d095cf..670029ed 100644 --- a/cdist/core/code.py +++ b/cdist/core/code.py @@ -127,13 +127,18 @@ class Code(object): '__object_name': cdist_object.name, }) message_prefix = cdist_object.name - stderr_path = os.path.join(cdist_object.stderr_path, - 'gencode-' + which) - with open(stderr_path, 'ba+') as stderr: + if self.local.save_output_streams: + stderr_path = os.path.join(cdist_object.stderr_path, + 'gencode-' + which) + with open(stderr_path, 'ba+') as stderr: + return self.local.run_script(script, env=env, + return_output=True, + message_prefix=message_prefix, + stderr=stderr) + else: return self.local.run_script(script, env=env, return_output=True, - message_prefix=message_prefix, - stderr=stderr) + message_prefix=message_prefix) def run_gencode_local(self, cdist_object): """Run the gencode-local script for the given cdist object.""" @@ -157,12 +162,17 @@ class Code(object): which_exec = getattr(self, which) script = os.path.join(which_exec.object_path, getattr(cdist_object, 'code_%s_path' % which)) - stderr_path = os.path.join(cdist_object.stderr_path, 'code-' + which) - stdout_path = os.path.join(cdist_object.stdout_path, 'code-' + which) - with open(stderr_path, 'ba+') as stderr, \ - open(stdout_path, 'ba+') as stdout: - return which_exec.run_script(script, env=env, stdout=stdout, - stderr=stderr) + if which_exec.save_output_streams: + stderr_path = os.path.join(cdist_object.stderr_path, + 'code-' + which) + stdout_path = os.path.join(cdist_object.stdout_path, + 'code-' + which) + with open(stderr_path, 'ba+') as stderr, \ + open(stdout_path, 'ba+') as stdout: + return which_exec.run_script(script, env=env, stdout=stdout, + stderr=stderr) + else: + return which_exec.run_script(script, env=env) def run_code_local(self, cdist_object): """Run the code-local script for the given cdist object.""" diff --git a/cdist/core/manifest.py b/cdist/core/manifest.py index 12b5b005..938ad8b8 100644 --- a/cdist/core/manifest.py +++ b/cdist/core/manifest.py @@ -154,15 +154,21 @@ class Manifest(object): message_prefix = "initialmanifest" self.log.verbose("Running initial manifest " + initial_manifest) which = "init" - stderr_path = os.path.join(self.local.stderr_base_path, which) - stdout_path = os.path.join(self.local.stdout_base_path, which) - with open(stderr_path, 'ba+') as stderr, \ - open(stdout_path, 'ba+') as stdout: + if self.local.save_output_streams: + stderr_path = os.path.join(self.local.stderr_base_path, which) + stdout_path = os.path.join(self.local.stdout_base_path, which) + with open(stderr_path, 'ba+') as stderr, \ + open(stdout_path, 'ba+') as stdout: + self.local.run_script( + initial_manifest, + env=self.env_initial_manifest(initial_manifest), + message_prefix=message_prefix, + stdout=stdout, stderr=stderr) + else: self.local.run_script( initial_manifest, env=self.env_initial_manifest(initial_manifest), - message_prefix=message_prefix, - stdout=stdout, stderr=stderr) + message_prefix=message_prefix) def env_type_manifest(self, cdist_object): type_manifest = os.path.join(self.local.type_path, @@ -188,12 +194,18 @@ class Manifest(object): if os.path.isfile(type_manifest): self.log.verbose("Running type manifest %s for object %s", type_manifest, cdist_object.name) - stderr_path = os.path.join(cdist_object.stderr_path, which) - stdout_path = os.path.join(cdist_object.stdout_path, which) - with open(stderr_path, 'ba+') as stderr, \ - open(stdout_path, 'ba+') as stdout: + if self.local.save_output_streams: + stderr_path = os.path.join(cdist_object.stderr_path, which) + stdout_path = os.path.join(cdist_object.stdout_path, which) + with open(stderr_path, 'ba+') as stderr, \ + open(stdout_path, 'ba+') as stdout: + self.local.run_script( + type_manifest, + env=self.env_type_manifest(cdist_object), + message_prefix=message_prefix, + stdout=stdout, stderr=stderr) + else: self.local.run_script( type_manifest, env=self.env_type_manifest(cdist_object), - message_prefix=message_prefix, - stdout=stdout, stderr=stderr) + message_prefix=message_prefix) diff --git a/cdist/exec/local.py b/cdist/exec/local.py index eec79399..a50fe072 100644 --- a/cdist/exec/local.py +++ b/cdist/exec/local.py @@ -56,7 +56,8 @@ class Local(object): add_conf_dirs=None, cache_path_pattern=None, quiet_mode=False, - configuration=None): + configuration=None, + save_output_streams=True): self.target_host = target_host if target_host_tags is None: @@ -75,6 +76,7 @@ class Local(object): self.configuration = configuration else: self.configuration = {} + self.save_output_streams = save_output_streams self._init_log() self._init_permissions() @@ -213,7 +215,7 @@ class Local(object): "list or tuple argument expected, got: %s" % command) quiet = self.quiet_mode or quiet_mode - do_save_output = save_output and not quiet + do_save_output = save_output and not quiet and self.save_output_streams close_stdout = False close_stderr = False @@ -256,7 +258,6 @@ class Local(object): if do_save_output: util.log_std_fd(self.log, command, stderr, 'Local stderr') util.log_std_fd(self.log, command, stdout, 'Local stdout') - return output except subprocess.CalledProcessError as e: util.handle_called_process_error(e, command) diff --git a/cdist/exec/remote.py b/cdist/exec/remote.py index 8fcd0981..b75905ba 100644 --- a/cdist/exec/remote.py +++ b/cdist/exec/remote.py @@ -65,7 +65,8 @@ class Remote(object): archiving_mode=None, configuration=None, stdout_base_path=None, - stderr_base_path=None): + stderr_base_path=None, + save_output_streams=True): self.target_host = target_host self._exec = remote_exec self._copy = remote_copy @@ -80,6 +81,7 @@ class Remote(object): self.configuration = configuration else: self.configuration = {} + self.save_output_streams = save_output_streams self.stdout_base_path = stdout_base_path self.stderr_base_path = stderr_base_path @@ -309,12 +311,13 @@ class Remote(object): close_stdout = False close_stderr = False - if not return_output and stdout is None: - stdout = util.get_std_fd(self.stdout_base_path, 'remote') - close_stdout = True - if stderr is None: - stderr = util.get_std_fd(self.stderr_base_path, 'remote') - close_stderr = True + if self.save_output_streams: + if not return_output and stdout is None: + stdout = util.get_std_fd(self.stdout_base_path, 'remote') + close_stdout = True + if stderr is None: + stderr = util.get_std_fd(self.stderr_base_path, 'remote') + close_stderr = True # export target_host, target_hostname, target_fqdn # for use in __remote_{exec,copy} scripts @@ -335,8 +338,9 @@ class Remote(object): stderr=stderr) output = None - util.log_std_fd(self.log, command, stderr, 'Remote stderr') - util.log_std_fd(self.log, command, stdout, 'Remote stdout') + if self.save_output_streams: + util.log_std_fd(self.log, command, stderr, 'Remote stderr') + util.log_std_fd(self.log, command, stdout, 'Remote stdout') return output except subprocess.CalledProcessError as e: diff --git a/cdist/test/capture_output_disabled/__init__.py b/cdist/test/capture_output_disabled/__init__.py new file mode 100644 index 00000000..828e80f1 --- /dev/null +++ b/cdist/test/capture_output_disabled/__init__.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +# +# 2018 Darko Poljak (darko.poljak at gmail.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 . +# +# + +import os +import shutil + +import cdist +from cdist import core +from cdist import test +from cdist.exec import local +from cdist.exec import remote +from cdist.core import code +from cdist.core import manifest + +import os.path as op +my_dir = op.abspath(op.dirname(__file__)) +fixtures = op.join(my_dir, 'fixtures') +conf_dir = op.join(fixtures, 'conf') + + +class CaptureOutputDisabledTestCase(test.CdistTestCase): + + def setUp(self): + # logging.root.setLevel(logging.TRACE) + save_output_streams = False + self.temp_dir = self.mkdtemp() + + self.local_dir = os.path.join(self.temp_dir, "local") + self.hostdir = cdist.str_hash(self.target_host[0]) + self.host_base_path = os.path.join(self.local_dir, self.hostdir) + os.makedirs(self.host_base_path) + self.local = local.Local( + target_host=self.target_host, + target_host_tags=None, + base_root_path=self.host_base_path, + host_dir_name=self.hostdir, + exec_path=cdist.test.cdist_exec_path, + add_conf_dirs=[conf_dir], + save_output_streams=save_output_streams) + self.local.create_files_dirs() + + self.remote_dir = self.mkdtemp() + remote_exec = self.remote_exec + remote_copy = self.remote_copy + self.remote = remote.Remote( + target_host=self.target_host, + remote_exec=remote_exec, + remote_copy=remote_copy, + base_path=self.remote_dir, + stdout_base_path=self.local.stdout_base_path, + stderr_base_path=self.local.stderr_base_path, + save_output_streams=save_output_streams) + self.remote.create_files_dirs() + + self.code = code.Code(self.target_host, self.local, self.remote) + + self.manifest = manifest.Manifest(self.target_host, self.local) + + self.cdist_type = core.CdistType(self.local.type_path, + '__write_to_stdout_and_stderr') + self.cdist_object = core.CdistObject(self.cdist_type, + self.local.object_path, + self.local.object_marker_name, + '') + self.cdist_object.create() + self.output_dirs = { + 'object': { + 'stdout': os.path.join(self.cdist_object.absolute_path, + 'stdout'), + 'stderr': os.path.join(self.cdist_object.absolute_path, + 'stderr'), + }, + 'init': { + 'stdout': os.path.join(self.local.base_path, 'stdout'), + 'stderr': os.path.join(self.local.base_path, 'stderr'), + }, + } + + def tearDown(self): + shutil.rmtree(self.local_dir) + shutil.rmtree(self.remote_dir) + shutil.rmtree(self.temp_dir) + + def _test_output(self, which, target, streams=('stdout', 'stderr')): + for stream in streams: + stream_path = os.path.join(self.output_dirs[target][stream], which) + if os.path.exists(stream_path): + with open(stream_path, 'r') as fd: + _is = fd.read() + self.assertEqual("", _is) + # else ok when not exists + + def test_capture_code_output_disabled(self): + self.cdist_object.code_local = self.code.run_gencode_local( + self.cdist_object) + self._test_output('gencode-local', 'object', ('stderr',)) + + self.code.run_code_local(self.cdist_object) + self._test_output('code-local', 'object') + + self.cdist_object.code_remote = self.code.run_gencode_remote( + self.cdist_object) + self._test_output('gencode-remote', 'object', ('stderr',)) + + self.code.transfer_code_remote(self.cdist_object) + self.code.run_code_remote(self.cdist_object) + self._test_output('code-remote', 'object') + + def test_capture_manifest_output_disabled(self): + self.manifest.run_type_manifest(self.cdist_object) + self._test_output('manifest', 'object') + + def test_capture_init_manifest_output_disabled(self): + initial_manifest = os.path.join(conf_dir, 'manifest', 'init') + self.manifest.run_initial_manifest(initial_manifest) + self._test_output('init', 'init') + + +if __name__ == "__main__": + import unittest + + unittest.main() diff --git a/cdist/test/capture_output_disabled/fixtures/conf/manifest/init b/cdist/test/capture_output_disabled/fixtures/conf/manifest/init new file mode 100755 index 00000000..68d7da97 --- /dev/null +++ b/cdist/test/capture_output_disabled/fixtures/conf/manifest/init @@ -0,0 +1,4 @@ +#!/bin/sh + +echo "init: stdout" +echo "init: stderr" >&2 diff --git a/cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/gencode-local b/cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/gencode-local new file mode 100755 index 00000000..1946dbd3 --- /dev/null +++ b/cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/gencode-local @@ -0,0 +1,6 @@ +#!/bin/sh + +echo "gencode-local: stderr" >&2 + +echo "echo \"code-local: stdout\"" +echo "echo \"code-local: stderr\" >&2" diff --git a/cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/gencode-remote b/cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/gencode-remote new file mode 100755 index 00000000..f713b932 --- /dev/null +++ b/cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/gencode-remote @@ -0,0 +1,6 @@ +#!/bin/sh + +echo "gencode-remote: stderr" >&2 + +echo "echo \"code-remote: stdout\"" +echo "echo \"code-remote: stderr\" >&2" diff --git a/cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/manifest b/cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/manifest new file mode 100755 index 00000000..4f122f25 --- /dev/null +++ b/cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/manifest @@ -0,0 +1,4 @@ +#!/bin/sh + +echo "manifest: stdout" +echo "manifest: stderr" >&2 diff --git a/cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/singleton b/cdist/test/capture_output_disabled/fixtures/conf/type/__write_to_stdout_and_stderr/singleton new file mode 100644 index 00000000..e69de29b diff --git a/cdist/test/configuration/__init__.py b/cdist/test/configuration/__init__.py index b44fd17c..4ce3d29d 100644 --- a/cdist/test/configuration/__init__.py +++ b/cdist/test/configuration/__init__.py @@ -300,6 +300,7 @@ class ConfigurationTestCase(test.CdistTestCase): expected = { 'conf_dir': ['/usr/local/cdist1', ], 'verbosity': 3, + 'beta': False, } args_dict = vars(args) d = config._read_args_config(args_dict) @@ -1167,6 +1168,118 @@ class ConfigurationTestCase(test.CdistTestCase): configuration = cc.Configuration(args, env=env, config_files=()) + def test_configuration_disable_saving_output_streams1(self): + config = configparser.ConfigParser() + config['GLOBAL'] = { + 'save_output_streams': 'True', + } + + global_config_file = os.path.join(fixtures, 'cdist-global.cfg') + with open(global_config_file, 'w') as f: + config.write(f) + + expected_config_dict = { + 'GLOBAL': { + 'save_output_streams': True, + 'verbosity': 0, + }, + } + + config_files = (global_config_file, ) + + # bypass singleton so we can test further + cc.Configuration.instance = None + + args = argparse.Namespace() + args.save_output_streams = True + configuration = cc.Configuration(args, env=None, + config_files=config_files) + self.assertEqual(configuration.config, expected_config_dict) + + def test_configuration_disable_saving_output_streams2(self): + config = configparser.ConfigParser() + config['GLOBAL'] = { + 'save_output_streams': 'False', + } + + global_config_file = os.path.join(fixtures, 'cdist-global.cfg') + with open(global_config_file, 'w') as f: + config.write(f) + + expected_config_dict = { + 'GLOBAL': { + 'save_output_streams': True, + 'verbosity': 0, + }, + } + + config_files = (global_config_file, ) + + # bypass singleton so we can test further + cc.Configuration.instance = None + + args = argparse.Namespace() + args.save_output_streams = True + configuration = cc.Configuration(args, env=None, + config_files=config_files) + self.assertEqual(configuration.config, expected_config_dict) + + def test_configuration_disable_saving_output_streams3(self): + config = configparser.ConfigParser() + config['GLOBAL'] = { + 'save_output_streams': 'False', + } + + global_config_file = os.path.join(fixtures, 'cdist-global.cfg') + with open(global_config_file, 'w') as f: + config.write(f) + + expected_config_dict = { + 'GLOBAL': { + 'save_output_streams': False, + 'verbosity': 0, + }, + } + + config_files = (global_config_file, ) + + # bypass singleton so we can test further + cc.Configuration.instance = None + + args = argparse.Namespace() + args.save_output_streams = False + configuration = cc.Configuration(args, env=None, + config_files=config_files) + self.assertEqual(configuration.config, expected_config_dict) + + def test_configuration_disable_saving_output_streams4(self): + config = configparser.ConfigParser() + config['GLOBAL'] = { + 'save_output_streams': 'True', + } + + global_config_file = os.path.join(fixtures, 'cdist-global.cfg') + with open(global_config_file, 'w') as f: + config.write(f) + + expected_config_dict = { + 'GLOBAL': { + 'save_output_streams': False, + 'verbosity': 0, + }, + } + + config_files = (global_config_file, ) + + # bypass singleton so we can test further + cc.Configuration.instance = None + + args = argparse.Namespace() + args.save_output_streams = False + configuration = cc.Configuration(args, env=None, + config_files=config_files) + self.assertEqual(configuration.config, expected_config_dict) + if __name__ == "__main__": import unittest diff --git a/docs/src/cdist-cache.rst b/docs/src/cdist-cache.rst index b4335db9..0e5361ee 100644 --- a/docs/src/cdist-cache.rst +++ b/docs/src/cdist-cache.rst @@ -87,10 +87,12 @@ state this type execution state ('done' when finished) stderr - directory containing type's gencode-* and code-* stderr stream outputs + directory containing type's manifest, gencode-* and code-* stderr stream + outputs stdin this type stdin content stdout - directory containing type's gencode-* and code-* stdout stream outputs. + directory containing type's manifest, gencode-* and code-* stdout stream + outputs. diff --git a/docs/src/cdist-configuration.rst b/docs/src/cdist-configuration.rst index e53c818f..a66ddf7c 100644 --- a/docs/src/cdist-configuration.rst +++ b/docs/src/cdist-configuration.rst @@ -88,6 +88,11 @@ The possible keywords and their meanings are as follows: :strong:`remote_shell` Shell command at remote host used for remote execution. +:strong:`save_output_streams` + Enable/disable saving output streams (enabled by default). + It recognizes boolean values from 'yes'/'no', 'on'/'off', 'true'/'false' + and '1'/'0'. + :strong:`verbosity` Set verbosity level. Valid values are: 'ERROR', 'WARNING', 'INFO', 'VERBOSE', 'DEBUG', 'TRACE' and 'OFF'. diff --git a/docs/src/cdist-saving-output-streams.rst b/docs/src/cdist-saving-output-streams.rst new file mode 100644 index 00000000..28067cac --- /dev/null +++ b/docs/src/cdist-saving-output-streams.rst @@ -0,0 +1,88 @@ +Saving output streams +===================== + +Description +----------- +Since version 4.8.0 cdist, by default, saves output streams to local cache. +Saving output streams is implemented because important information was lost +during a config run, hidden in all other output. +Now all created output is bound to the context where it was produced. + +Saving output streams include stdout and stderr of init manifest, remote +commands and for each object stdout and stderr of manifest, gencode-* and code-*. +Output stream files are created only if some output is produced. For more info +on these cache files see `Local cache overview `_. + +Also, in case of an error, cdist can now exit and show all information it has +about the error. + +For example: + +.. code-block:: sh + + $ ./bin/cdist config -v -i ~/.cdist/manifest/init-output-streams $(cat ~/ungleich/data/opennebula-debian9-test ) + INFO: 185.203.112.42: Starting configuration run + INFO: 185.203.112.42: Processing __myline/test + ERROR: 185.203.112.42: Command failed: '/bin/sh -e /tmp/tmpow6cwemh/75ee6a79e32da093da23fe4a13dd104b/data/object/__myline/test/.cdist-kisrqlpw/code-local' + return code: 1 + ---- BEGIN stdout ---- + ---- END stdout ---- + + Error processing object '__myline/test' + ======================================== + name: __myline/test + path: /tmp/tmpow6cwemh/75ee6a79e32da093da23fe4a13dd104b/data/object/__myline/test/.cdist-kisrqlpw + source: /home/darko/.cdist/manifest/init-output-streams + type: /tmp/tmpow6cwemh/75ee6a79e32da093da23fe4a13dd104b/data/conf/type/__myline + + ---- BEGIN manifest:stderr ---- + myline manifest stderr + + ---- END manifest:stderr ---- + + ---- BEGIN gencode-remote:stderr ---- + test gencode-remote error + + ---- END gencode-remote:stderr ---- + + ---- BEGIN code-local:stderr ---- + error + + ---- END code-local:stderr ---- + + ERROR: cdist: Failed to configure the following hosts: 185.203.112.42 + +Upon successful run execution state is saved to local cache and temporary +directory is removed. +In case of an error temporary directory is not removed and can be further +discovered. + +There is also an option :strong:`-S/--disable-saving-output-streams` for +disabling saving output streams. In this case error reporting can look +like this: + +.. code-block:: sh + + $ ./bin/cdist config -v -S -i ~/.cdist/manifest/init-output-streams $(cat ~/ungleich/data/opennebula-debian9-test ) + INFO: 185.203.112.42: Starting configuration run + test stdout output streams + test stderr output streams + myline manifest stdout + myline manifest stderr + test gencode-remote error + INFO: 185.203.112.42: Processing __myline/test + error + ERROR: 185.203.112.42: Command failed: '/bin/sh -e /tmp/tmpzomy0wis/75ee6a79e32da093da23fe4a13dd104b/data/object/__myline/test/.cdist-n566pqut/code-local' + return code: 1 + ---- BEGIN stdout ---- + ---- END stdout ---- + + Error processing object '__myline/test' + ======================================== + name: __myline/test + path: /tmp/tmpzomy0wis/75ee6a79e32da093da23fe4a13dd104b/data/object/__myline/test/.cdist-n566pqut + source: /home/darko/.cdist/manifest/init-output-streams + type: /tmp/tmpzomy0wis/75ee6a79e32da093da23fe4a13dd104b/data/conf/type/__myline + + + ERROR: cdist: Failed to configure the following hosts: 185.203.112.42 diff --git a/docs/src/index.rst b/docs/src/index.rst index efbc3cb9..5d0bb537 100644 --- a/docs/src/index.rst +++ b/docs/src/index.rst @@ -31,6 +31,7 @@ Contents: cdist-best-practice cdist-stages cdist-cache + cdist-saving-output-streams cdist-remote-exec-copy cdist-hacker cdist-troubleshooting diff --git a/docs/src/man1/cdist.rst b/docs/src/man1/cdist.rst index ea66c37e..8c6ca549 100644 --- a/docs/src/man1/cdist.rst +++ b/docs/src/man1/cdist.rst @@ -21,7 +21,7 @@ SYNOPSIS [-j [JOBS]] [-n] [-o OUT_PATH] [-R [{tar,tgz,tbz2,txz}]] [-r REMOTE_OUT_DIR] [--remote-copy REMOTE_COPY] [--remote-exec REMOTE_EXEC] [-I INVENTORY_DIR] [-A] [-a] - [-f HOSTFILE] [-p [HOST_MAX]] [-s] [-t] + [-f HOSTFILE] [-p [HOST_MAX]] [-S] [-s] [-t] [host [host ...]] cdist install [-h] [-l LOGLEVEL] [-q] [-v] [-b] [-g CONFIG_FILE] @@ -29,7 +29,7 @@ SYNOPSIS [-j [JOBS]] [-n] [-o OUT_PATH] [-R [{tar,tgz,tbz2,txz}]] [-r REMOTE_OUT_DIR] [--remote-copy REMOTE_COPY] [--remote-exec REMOTE_EXEC] [-I INVENTORY_DIR] [-A] [-a] - [-f HOSTFILE] [-p [HOST_MAX]] [-s] [-t] + [-f HOSTFILE] [-p [HOST_MAX]] [-S] [-s] [-t] [host [host ...]] cdist inventory [-h] [-l LOGLEVEL] [-q] [-v] [-b] [-g CONFIG_FILE] @@ -200,6 +200,10 @@ Install command is currently in beta. Directory to save cdist output in on the target host. +.. option:: -S, --disable-saving-output-streams + + Disable saving output streams. + .. option:: -s, --sequential Operate on multiple hosts sequentially (default). @@ -561,6 +565,11 @@ The possible keywords and their meanings are as follows: :strong:`remote_shell` Shell command at remote host used for remote execution. +:strong:`save_output_streams` + Enable/disable saving output streams (enabled by default). + It recognizes boolean values from 'yes'/'no', 'on'/'off', 'true'/'false' + and '1'/'0'. + :strong:`verbosity` Set verbosity level. Valid values are: 'ERROR', 'WARNING', 'INFO', 'VERBOSE', 'DEBUG', 'TRACE' and 'OFF'.