From 9c2068e94fc000b22f99e51ee9bf8da304d168eb Mon Sep 17 00:00:00 2001 From: Dmitry Shulyak Date: Fri, 17 Jul 2015 17:36:48 +0300 Subject: [PATCH 1/2] Use detailed error codes to handle puppet errors *warn_only* option will prevent fabric from failing with fatal error, error output will be like this: Warning: sudo() received nonzero return code 2 while executing 'puppet apply -vd /tmp/action.pp --detailed-exitcodes'! --- solar/solar/core/handlers/puppet.py | 32 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/solar/solar/core/handlers/puppet.py b/solar/solar/core/handlers/puppet.py index bd62eb86..917f8a03 100644 --- a/solar/solar/core/handlers/puppet.py +++ b/solar/solar/core/handlers/puppet.py @@ -9,20 +9,7 @@ import os from solar.core.log import log from solar.core.handlers.base import TempFileHandler from solar.core.provider import GitProvider - - -# TODO: -# puppet wont always return 0 on error, example: -# http://unix.stackexchange.com/questions/165333/how-to-get-non-zero-exit-code-from-puppet-when-configuration-cannot-be-applied - -# in fuel there is special handler based on puppet summary, but i think we can also use --detailed-exitcode -# https://docs.puppetlabs.com/references/3.6.2/man/agent.html -# --detailed-exitcodes -# Provide transaction information via exit codes. If this is enabled, an exit -# code of '2' means there were changes, an exit code of '4' means there were -# failures during the transaction, and an exit code of '6' means there were -# both changes and failures. - +from solar import errors class ResourceSSHMixin(object): @@ -48,6 +35,10 @@ class ResourceSSHMixin(object): fabric_api.shell_env(**kwargs['env']) ) + if 'warn_only' in kwargs: + managers.append( + fabric_api.warn_only()) + with nested(*managers): return executor(' '.join(args)) @@ -161,14 +152,21 @@ class Puppet(ResourceSSHMixin, TempFileHandler): self._scp_command(resource, action_file, '/tmp/action.pp') - self._ssh_command( + cmd = self._ssh_command( resource, - 'puppet', 'apply', '-vd', '/tmp/action.pp', + 'puppet', 'apply', '-vd', '/tmp/action.pp', '--detailed-exitcodes', env={ 'FACTER_resource_name': resource.name, }, - use_sudo=True + use_sudo=True, + warn_only=True, ) + # 0 - no changes, 2 - successfull changes + if cmd.return_code not in [0, 2]: + raise errors.SolarError( + 'Puppet for {} failed with {}'.format( + resource.name, cmd.return_code)) + return cmd def clone_manifests(self, resource): git = resource.args['git'].value From c84ae560895ee508a8a1cc10becac0d59973942f Mon Sep 17 00:00:00 2001 From: Dmitry Shulyak Date: Thu, 23 Jul 2015 10:31:33 +0300 Subject: [PATCH 2/2] Handle puppet error during remove as WARNING in example-puppet.py --- example-puppet.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/example-puppet.py b/example-puppet.py index 7f344aad..fb408765 100644 --- a/example-puppet.py +++ b/example-puppet.py @@ -7,6 +7,7 @@ from solar.core import resource from solar.core import signals from solar.core import validation from solar.core.resource import virtual_resource as vr +from solar import errors from solar.interfaces.db import get_db @@ -347,7 +348,10 @@ def undeploy(): resources = {r.name: r for r in resources} for name in to_remove: - actions.resource_action(resources[name], 'remove') + try: + actions.resource_action(resources[name], 'remove') + except errors.SolarError as e: + print 'WARNING: %s' % str(e) #actions.resource_action(resources['nova_keystone_service_endpoint'], 'remove' ) # actions.resource_action(resources['nova_network_puppet'], 'remove' )