diff --git a/Asm/Ansible/Command/AbstractAnsibleCommand.php b/Asm/Ansible/Command/AbstractAnsibleCommand.php index d3e6829..33c4479 100644 --- a/Asm/Ansible/Command/AbstractAnsibleCommand.php +++ b/Asm/Ansible/Command/AbstractAnsibleCommand.php @@ -34,6 +34,8 @@ abstract class AbstractAnsibleCommand private array $baseOptions; + private bool $useStdoutForError; + /** * @param ProcessBuilderInterface $processBuilder * @param LoggerInterface|null $logger @@ -44,6 +46,7 @@ public function __construct(ProcessBuilderInterface $processBuilder, LoggerInter $this->options = []; $this->parameters = []; $this->baseOptions = []; + $this->useStdoutForError = false; $this->setLogger($logger ?? new NullLogger()); } @@ -183,7 +186,7 @@ protected function runProcess(?callable $callback): int|string // if no callback is set, and the process is not successful, we return the output if (false === $process->isSuccessful()) { - return $process->getErrorOutput(); + return $this->useStdoutForError ? $process->getOutput() : $process->getErrorOutput(); } // if no callback is set, and the process is successful, we return the output @@ -210,4 +213,14 @@ protected function getProcessCommandline(Process $process): string return sprintf('%s %s', implode(' ', $vars), $commandline); } + + /** + * in case ansible explicitly is in json mode, this will be set to be able to get error outputs + * + * @return void + */ + protected function useStdoutForError(): void + { + $this->useStdoutForError = true; + } } diff --git a/Asm/Ansible/Command/AnsiblePlaybook.php b/Asm/Ansible/Command/AnsiblePlaybook.php index 46e8895..a1c8c92 100644 --- a/Asm/Ansible/Command/AnsiblePlaybook.php +++ b/Asm/Ansible/Command/AnsiblePlaybook.php @@ -408,6 +408,7 @@ public function colors(bool $colors = true): AnsiblePlaybookInterface public function json(): AnsiblePlaybookInterface { $this->processBuilder->setEnv('ANSIBLE_STDOUT_CALLBACK', 'json'); + $this->useStdoutForError(); return $this; } diff --git a/Tests/Asm/Ansible/Command/AnsiblePlaybookTest.php b/Tests/Asm/Ansible/Command/AnsiblePlaybookTest.php index 83fb8ee..32cc499 100644 --- a/Tests/Asm/Ansible/Command/AnsiblePlaybookTest.php +++ b/Tests/Asm/Ansible/Command/AnsiblePlaybookTest.php @@ -888,6 +888,38 @@ public function testReturnsErrorOutputIfProcessWasNotSuccessful(): void self::assertEquals('error output', $playbook->execute()); } + public function testReturnsErrorOutputIfProcessWasNotSuccessfulInJsonMode(): void + { + $builder = $this->createMock(ProcessBuilderInterface::class); + $builder + ->expects(self::once()) + ->method('setArguments') + ->willReturnSelf(); + $builder + ->expects(self::once()) + ->method('getProcess') + ->willReturn($process = $this->createMock(Process::class)); + $process + ->expects(self::once()) + ->method('run'); + $process + ->expects(self::once()) + ->method('isSuccessful') + ->willReturn(false); + $process + ->expects(self::once()) + ->method('getOutput') + ->willReturn('{ "error": "error output" }'); + $process + ->expects(self::never()) + ->method('getErrorOutput'); + + $playbook = new AnsiblePlaybook($builder); + $playbook->json(); + + self::assertEquals('{ "error": "error output" }', $playbook->execute()); + } + public function testReturnsNormalOutputIfProcessWasSuccessful(): void { $builder = $this->createMock(ProcessBuilderInterface::class);