From fd8e10e12adaf9c4dce88868ea26bb5ee859db8e Mon Sep 17 00:00:00 2001
From: Darko Poljak <darko.poljak@gmail.com>
Date: Fri, 3 Jun 2016 12:20:28 +0200
Subject: [PATCH 1/2] Improve error reporting for local and remote run.

---
 cdist/__init__.py    |  4 ++--
 cdist/exec/local.py  | 13 ++++++++-----
 cdist/exec/remote.py | 13 ++++++++-----
 cdist/exec/util.py   | 39 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 57 insertions(+), 12 deletions(-)
 create mode 100644 cdist/exec/util.py

diff --git a/cdist/__init__.py b/cdist/__init__.py
index 4454a3ac..e789499c 100644
--- a/cdist/__init__.py
+++ b/cdist/__init__.py
@@ -41,8 +41,8 @@ BANNER = """
    "P'        ""         ""
 """
 
-REMOTE_COPY = "scp -o User=root -q"
-REMOTE_EXEC = "ssh -o User=root -q"
+REMOTE_COPY = "scp -o User=root"
+REMOTE_EXEC = "ssh -o User=root"
 
 class Error(Exception):
     """Base exception class for this project"""
diff --git a/cdist/exec/local.py b/cdist/exec/local.py
index c0554831..15f49a89 100644
--- a/cdist/exec/local.py
+++ b/cdist/exec/local.py
@@ -33,6 +33,7 @@ import tempfile
 import cdist
 import cdist.message
 from cdist import core
+import cdist.exec.util as exec_util
 
 class Local(object):
     """Execute commands locally.
@@ -203,12 +204,14 @@ class Local(object):
             env.update(message.env)
 
         try:
+            output = exec_util.call_get_output(command, env=env)
+            self.log.debug("Local output: {}".format(output))
             if return_output:
-                return subprocess.check_output(command, env=env).decode()
-            else:
-                subprocess.check_call(command, env=env)
-        except subprocess.CalledProcessError:
-            raise cdist.Error("Command failed: " + " ".join(command))
+                return output.decode()
+        except subprocess.CalledProcessError as e:
+            raise cdist.Error("Command failed: " + " ".join(command)
+                    + " with returncode: {} and output: {}".format(
+                        e.returncode, e.output))
         except OSError as error:
             raise cdist.Error(" ".join(command) + ": " + error.args[1])
         finally:
diff --git a/cdist/exec/remote.py b/cdist/exec/remote.py
index 77e2c8be..c78f02cb 100644
--- a/cdist/exec/remote.py
+++ b/cdist/exec/remote.py
@@ -26,6 +26,7 @@ import sys
 import glob
 import subprocess
 import logging
+import cdist.exec.util as exec_util
 
 import cdist
 
@@ -167,12 +168,14 @@ class Remote(object):
 
         self.log.debug("Remote run: %s", command)
         try:
+            output = exec_util.call_get_output(command, env=os_environ)
+            self.log.debug("Remote output: {}".format(output))
             if return_output:
-                return subprocess.check_output(command, env=os_environ).decode()
-            else:
-                subprocess.check_call(command, env=os_environ)
-        except subprocess.CalledProcessError:
-            raise cdist.Error("Command failed: " + " ".join(command))
+                return output.decode()
+        except subprocess.CalledProcessError as e:
+            raise cdist.Error("Command failed: " + " ".join(command)
+                    + " with returncode: {} and output: {}".format(
+                        e.returncode, e.output))
         except OSError as error:
             raise cdist.Error(" ".join(command) + ": " + error.args[1])
         except UnicodeDecodeError:
diff --git a/cdist/exec/util.py b/cdist/exec/util.py
new file mode 100644
index 00000000..983f455c
--- /dev/null
+++ b/cdist/exec/util.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+#
+# 2016 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 subprocess
+from tempfile import TemporaryFile
+
+import cdist
+
+def call_get_output(command, env=None):
+    """Run the given command with the given environment.
+    Return the stdout and stderr output as a byte string.
+    """
+    assert isinstance(command, (list, tuple)), "list or tuple argument expected, got: {}".format(command)
+
+    with TemporaryFile() as fout:
+        subprocess.check_call(command, env=env,
+                stdout=fout, stderr=subprocess.STDOUT)
+        fout.seek(0)
+        output = fout.read()
+
+    return output

From 88b20610cbed739a8d6b7e6edda05457d7ffdf6e Mon Sep 17 00:00:00 2001
From: Darko Poljak <darko.poljak@gmail.com>
Date: Mon, 6 Jun 2016 22:21:17 +0200
Subject: [PATCH 2/2] Update changelog.

---
 docs/changelog | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/docs/changelog b/docs/changelog
index dada1d90..b0a8be4c 100644
--- a/docs/changelog
+++ b/docs/changelog
@@ -1,6 +1,9 @@
 Changelog
 ---------
 
+next:
+	* Core: Improve error reporting for local and remote run command (Darko Poljak)
+
 4.1.0: 2016-05-27
 	* Documentation: Migrate to reStructuredText format and sphinx (Darko Poljak)
 	* Core: Add -f option to read additional hosts from file/stdin (Darko Poljak)