#3152 DNM: refactor to koji.exceptions and add "NoSuch" custom exceptions
Opened 2 years ago by ktdreyer. Modified 2 years ago
ktdreyer/koji exceptions  into  master

file modified
+28 -139
@@ -75,6 +75,34 @@ 

  __version__ = _version.__version__

  __version_info__ = _version.__version_info__

  

+ from koji.exceptions import (

+     PythonImportError,

+     GenericError,

+     LockError,

+     AuthError,

+     TagError,

+     ActionNotAllowed,

+     BuildError,

+     AuthLockError,

+     AuthExpired,

+     SequenceError,

+     RetryError,

+     PreBuildError,

+     PostBuildError,

+     BuildrootError,

+     FunctionDeprecated,

+     ServerOffline,

+     LiveCDError,

+     PluginError,

+     CallbackError,

+     ApplianceError,

+     ParameterError,

+     ImportError,

+     ConfigurationError,

+     LiveMediaError,

+     GSSAPIAuthError,

+ )

+ 

  try:

      import requests_gssapi as reqgssapi

  except ImportError:  # pragma: no cover
@@ -291,145 +319,6 @@ 

  DEFAULT_REQUEST_TIMEOUT = 60 * 60 * 12

  DEFAULT_AUTH_TIMEOUT = 60

  

- # BEGIN kojikamid dup #

- 

- # Exceptions

- PythonImportError = ImportError  # will be masked by koji's one

- 

- 

- class GenericError(Exception):

-     """Base class for our custom exceptions"""

-     faultCode = 1000

-     fromFault = False

- 

-     def __str__(self):

-         try:

-             return str(self.args[0]['args'][0])

-         except Exception:

-             try:

-                 return str(self.args[0])

-             except Exception:

-                 return str(self.__dict__)

- # END kojikamid dup #

- 

- 

- class LockError(GenericError):

-     """Raised when there is a lock conflict"""

-     faultCode = 1001

- 

- 

- class AuthError(GenericError):

-     """Raised when there is an error in authentication"""

-     faultCode = 1002

- 

- 

- class TagError(GenericError):

-     """Raised when a tagging operation fails"""

-     faultCode = 1003

- 

- 

- class ActionNotAllowed(GenericError):

-     """Raised when the session does not have permission to take some action"""

-     faultCode = 1004

- 

- # BEGIN kojikamid dup #

- 

- 

- class BuildError(GenericError):

-     """Raised when a build fails"""

-     faultCode = 1005

- # END kojikamid dup #

- 

- 

- class AuthLockError(AuthError):

-     """Raised when a lock prevents authentication"""

-     faultCode = 1006

- 

- 

- class AuthExpired(AuthError):

-     """Raised when a session has expired"""

-     faultCode = 1007

- 

- 

- class SequenceError(AuthError):

-     """Raised when requests are received out of sequence"""

-     faultCode = 1008

- 

- 

- class RetryError(AuthError):

-     """Raised when a request is received twice and cannot be rerun"""

-     faultCode = 1009

- 

- 

- class PreBuildError(BuildError):

-     """Raised when a build fails during pre-checks"""

-     faultCode = 1010

- 

- 

- class PostBuildError(BuildError):

-     """Raised when a build fails during post-checks"""

-     faultCode = 1011

- 

- 

- class BuildrootError(BuildError):

-     """Raised when there is an error with the buildroot"""

-     faultCode = 1012

- 

- 

- class FunctionDeprecated(GenericError):

-     """Raised by a deprecated function"""

-     faultCode = 1013

- 

- 

- class ServerOffline(GenericError):

-     """Raised when the server is offline"""

-     faultCode = 1014

- 

- 

- class LiveCDError(GenericError):

-     """Raised when LiveCD Image creation fails"""

-     faultCode = 1015

- 

- 

- class PluginError(GenericError):

-     """Raised when there is an error with a plugin"""

-     faultCode = 1016

- 

- 

- class CallbackError(PluginError):

-     """Raised when there is an error executing a callback"""

-     faultCode = 1017

- 

- 

- class ApplianceError(GenericError):

-     """Raised when Appliance Image creation fails"""

-     faultCode = 1018

- 

- 

- class ParameterError(GenericError):

-     """Raised when an rpc call receives incorrect arguments"""

-     faultCode = 1019

- 

- 

- class ImportError(GenericError):

-     """Raised when an import fails"""

-     faultCode = 1020

- 

- 

- class ConfigurationError(GenericError):

-     """Raised when load of koji configuration fails"""

-     faultCode = 1021

- 

- 

- class LiveMediaError(GenericError):

-     """Raised when LiveMedia Image creation fails"""

-     faultCode = 1022

- 

- 

- class GSSAPIAuthError(AuthError):

-     """Raised when GSSAPI issue in authentication"""

-     faultCode = 1023

- 

  

  class MultiCallInProgress(object):

      """

file added
+180
@@ -0,0 +1,180 @@ 

+ # Exceptions

+ PythonImportError = ImportError  # will be masked by koji's one

+ 

+ 

+ class GenericError(Exception):

+     """Base class for our custom exceptions"""

+     faultCode = 1000

+     fromFault = False

+ 

+     def __str__(self):

+         try:

+             return str(self.args[0]['args'][0])

+         except Exception:

+             try:

+                 return str(self.args[0])

+             except Exception:

+                 return str(self.__dict__)

+ 

+ 

+ class LockError(GenericError):

+     """Raised when there is a lock conflict"""

+     faultCode = 1001

+ 

+ 

+ class AuthError(GenericError):

+     """Raised when there is an error in authentication"""

+     faultCode = 1002

+ 

+ 

+ class TagError(GenericError):

+     """Raised when a tagging operation fails"""

+     faultCode = 1003

+ 

+ 

+ class ActionNotAllowed(GenericError):

+     """Raised when the session does not have permission to take some action"""

+     faultCode = 1004

+ 

+ 

+ class BuildError(GenericError):

+     """Raised when a build fails"""

+     faultCode = 1005

+ 

+ 

+ class AuthLockError(AuthError):

+     """Raised when a lock prevents authentication"""

+     faultCode = 1006

+ 

+ 

+ class AuthExpired(AuthError):

+     """Raised when a session has expired"""

+     faultCode = 1007

+ 

+ 

+ class SequenceError(AuthError):

+     """Raised when requests are received out of sequence"""

+     faultCode = 1008

+ 

+ 

+ class RetryError(AuthError):

+     """Raised when a request is received twice and cannot be rerun"""

+     faultCode = 1009

+ 

+ 

+ class PreBuildError(BuildError):

+     """Raised when a build fails during pre-checks"""

+     faultCode = 1010

+ 

+ 

+ class PostBuildError(BuildError):

+     """Raised when a build fails during post-checks"""

+     faultCode = 1011

+ 

+ 

+ class BuildrootError(BuildError):

+     """Raised when there is an error with the buildroot"""

+     faultCode = 1012

+ 

+ 

+ class FunctionDeprecated(GenericError):

+     """Raised by a deprecated function"""

+     faultCode = 1013

+ 

+ 

+ class ServerOffline(GenericError):

+     """Raised when the server is offline"""

+     faultCode = 1014

+ 

+ 

+ class LiveCDError(GenericError):

+     """Raised when LiveCD Image creation fails"""

+     faultCode = 1015

+ 

+ 

+ class PluginError(GenericError):

+     """Raised when there is an error with a plugin"""

+     faultCode = 1016

+ 

+ 

+ class CallbackError(PluginError):

+     """Raised when there is an error executing a callback"""

+     faultCode = 1017

+ 

+ 

+ class ApplianceError(GenericError):

+     """Raised when Appliance Image creation fails"""

+     faultCode = 1018

+ 

+ 

+ class ParameterError(GenericError):

+     """Raised when an rpc call receives incorrect arguments"""

+     faultCode = 1019

+ 

+ 

+ class ImportError(GenericError):

+     """Raised when an import fails"""

+     faultCode = 1020

+ 

+ 

+ class ConfigurationError(GenericError):

+     """Raised when load of koji configuration fails"""

+     faultCode = 1021

+ 

+ 

+ class LiveMediaError(GenericError):

+     """Raised when LiveMedia Image creation fails"""

+     faultCode = 1022

+ 

+ 

+ class GSSAPIAuthError(AuthError):

+     """Raised when GSSAPI issue in authentication"""

+     faultCode = 1023

+ 

+ 

+ class NoSuchArchive(object):

+     faultCode = 1024

+ 

+ 

+ class NoSuchBuild(object):

+     faultCode = 1025

+ 

+ 

+ class NoSuchChannel(object):

+     faultCode = 1026

+ 

+ 

+ class NoSuchContentGenerator(object):

+     faultCode = 1027

+ 

+ 

+ class NoSuchPackage(object):

+     faultCode = 1028

+ 

+ 

+ class NoSuchPermission(object):

+     faultCode = 1029

+ 

+ 

+ class NoSuchRPM(object):

+     faultCode = 1030

+ 

+ 

+ class NoSuchRepo(object):

+     faultCode = 1031

+ 

+ 

+ class NoSuchTag(object):

+     faultCode = 1032

+ 

+ 

+ class NoSuchTarget(object):

+     faultCode = 1033

+ 

+ 

+ class NoSuchTask(object):

+     faultCode = 1034

+ 

+ 

+ class NoSuchUser(object):

+     faultCode = 1035

The first commit moves Koji's custom exceptions classes to a dedicated koji.exceptions library. This organizes the code so it's easier to maintain, and matches patterns in other well-known projects, like requests.exceptions or cryptography.exceptions.

The second commit adds more custom exception classes. This will allow to programmatically determine the error causes from complex RPCs.

This commit simply defines the new classes and fault codes. Nothing in Koji's codebase uses these exceptions yet. We'll begin to raise these exceptions after this is widely deployed for clients in the field.

Fixes: https://pagure.io/koji/issue/3147

Marking DNM because I've not tested this yet, just posting for discussion.

tox does pass on my laptop, at least.

I discussed this with @cobrien . He pointed out that koji-smokey-dingo has an additional feature, a complaint attribute. https://github.com/obriencj/koji-smoky-dingo/blob/master/kojismokydingo/__init__.py

Currently each raise statement determines its own message string.

The purpose of complaint is that there is essentially always the same initial prefix to each message.

It means NoSuchBuild("foo-bar-baz") can be raised and caught at the very top of the client execution and turn into a No such build: foo-bar-baz with a single exception block (for example).

Metadata Update from @tkopecek:
- Pull-request tagged with: testing-ready

2 years ago

Metadata Update from @tkopecek:
- Pull-request untagged with: testing-ready

2 years ago

I've just noticed that "BEGIN kojikamid" logic is broken now. It needs to be wrapped in exceptions.py and added to vm/fix_kojikamid.sh. Basically kojikamid is a standalone script and needs everything needed implanted to it.

Ah, thanks, I did not know what that "BEGIN" logic was. I would like to learn the history of that sometime.

From https://github.com/ktdreyer/koji-ansible/issues/188, I think we should add DuplicateNameError and DuplicatePriorityError classes too.

Metadata Update from @tkopecek:
- Pull-request tagged with: no_qe

2 years ago

@ktdreyer do you want to continue to work on this one or should I create that fix_kojikamid part?

The kojikamid issue can be addressed by:

  • adding koji/exceptions.py to the list of files to check in fix_kojikamid.sh
  • propagating the # BEGIN/END kojikamid dup # lines

That said, I am concerned about the sudden inflation of highly specific exceptions here. We'd need to add a new exception every time we add a new datatype. For that matter, it doesn't look like we have a NoSuchX exception for all our existing data (e.g. host, external repo, btype, buildroot).

I think clearly the fault-to-exception situation is not where it needs to be, but I think it might need more than just more exceptions.

Metadata Update from @jcupova:
- Pull-request untagged with: no_qe

2 years ago
Metadata