forked from ungleich-public/cdist
		
	Support disabling saving output streams
This commit is contained in:
		
					parent
					
						
							
								47399bfa9f
							
						
					
				
			
			
				commit
				
					
						a993e0f5a9
					
				
			
		
					 19 changed files with 460 additions and 43 deletions
				
			
		|  | @ -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).', | ||||
|  |  | |||
|  | @ -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: | ||||
|  |  | |||
|  | @ -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,6 +330,9 @@ 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) | ||||
|         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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -127,6 +127,7 @@ class Code(object): | |||
|                 '__object_name': cdist_object.name, | ||||
|             }) | ||||
|             message_prefix = cdist_object.name | ||||
|             if self.local.save_output_streams: | ||||
|                 stderr_path = os.path.join(cdist_object.stderr_path, | ||||
|                                            'gencode-' + which) | ||||
|                 with open(stderr_path, 'ba+') as stderr: | ||||
|  | @ -134,6 +135,10 @@ class Code(object): | |||
|                                                  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) | ||||
| 
 | ||||
|     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) | ||||
|         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.""" | ||||
|  |  | |||
|  | @ -154,6 +154,7 @@ class Manifest(object): | |||
|         message_prefix = "initialmanifest" | ||||
|         self.log.verbose("Running initial manifest " + initial_manifest) | ||||
|         which = "init" | ||||
|         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, \ | ||||
|  | @ -163,6 +164,11 @@ class Manifest(object): | |||
|                     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) | ||||
| 
 | ||||
|     def env_type_manifest(self, cdist_object): | ||||
|         type_manifest = os.path.join(self.local.type_path, | ||||
|  | @ -188,6 +194,7 @@ class Manifest(object): | |||
|         if os.path.isfile(type_manifest): | ||||
|             self.log.verbose("Running type manifest %s for object %s", | ||||
|                              type_manifest, cdist_object.name) | ||||
|             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, \ | ||||
|  | @ -197,3 +204,8 @@ class Manifest(object): | |||
|                         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) | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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,6 +311,7 @@ class Remote(object): | |||
| 
 | ||||
|         close_stdout = False | ||||
|         close_stderr = False | ||||
|         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 | ||||
|  | @ -335,6 +338,7 @@ class Remote(object): | |||
|                                       stderr=stderr) | ||||
|                 output = None | ||||
| 
 | ||||
|             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') | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										140
									
								
								cdist/test/capture_output_disabled/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								cdist/test/capture_output_disabled/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 <http://www.gnu.org/licenses/>. | ||||
| # | ||||
| # | ||||
| 
 | ||||
| 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() | ||||
							
								
								
									
										4
									
								
								cdist/test/capture_output_disabled/fixtures/conf/manifest/init
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										4
									
								
								cdist/test/capture_output_disabled/fixtures/conf/manifest/init
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| #!/bin/sh | ||||
| 
 | ||||
| echo "init: stdout" | ||||
| echo "init: stderr" >&2 | ||||
|  | @ -0,0 +1,6 @@ | |||
| #!/bin/sh | ||||
| 
 | ||||
| echo "gencode-local: stderr" >&2 | ||||
| 
 | ||||
| echo "echo \"code-local: stdout\"" | ||||
| echo "echo \"code-local: stderr\" >&2" | ||||
|  | @ -0,0 +1,6 @@ | |||
| #!/bin/sh | ||||
| 
 | ||||
| echo "gencode-remote: stderr" >&2 | ||||
| 
 | ||||
| echo "echo \"code-remote: stdout\"" | ||||
| echo "echo \"code-remote: stderr\" >&2" | ||||
|  | @ -0,0 +1,4 @@ | |||
| #!/bin/sh | ||||
| 
 | ||||
| echo "manifest: stdout" | ||||
| echo "manifest: stderr" >&2 | ||||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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. | ||||
|  |  | |||
|  | @ -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'. | ||||
|  |  | |||
							
								
								
									
										88
									
								
								docs/src/cdist-saving-output-streams.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								docs/src/cdist-saving-output-streams.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 <cdist-cache.html>`_. | ||||
| 
 | ||||
| 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 | ||||
|  | @ -31,6 +31,7 @@ Contents: | |||
|    cdist-best-practice | ||||
|    cdist-stages | ||||
|    cdist-cache | ||||
|    cdist-saving-output-streams | ||||
|    cdist-remote-exec-copy | ||||
|    cdist-hacker | ||||
|    cdist-troubleshooting | ||||
|  |  | |||
|  | @ -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'. | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue