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'.