gitlab.com/ignitionrobotics/web/ign-go@v1.0.0-rc4/errors.go (about)

     1  package ign
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/pkg/errors"
     6  	"github.com/satori/go.uuid"
     7  	"net/http"
     8  )
     9  
    10  ///////////////////////
    11  // Database error codes
    12  ///////////////////////
    13  
    14  // ErrorNoDatabase is triggered when the database connection is unavailable
    15  const ErrorNoDatabase = 1000
    16  
    17  // ErrorDbDelete is triggered when the database was unable to delete a resource
    18  const ErrorDbDelete = 1001
    19  
    20  // ErrorDbSave is triggered when the database was unable to save a resource
    21  const ErrorDbSave = 1002
    22  
    23  // ErrorIDNotFound is triggered when a resource with the specified id is not
    24  // found in the database
    25  const ErrorIDNotFound = 1003
    26  
    27  // ErrorNameNotFound is triggered when a resource with the specified name is not
    28  // found in the database
    29  const ErrorNameNotFound = 1004
    30  
    31  // ErrorFileNotFound is triggered when a model's file with the specified name is not
    32  // found
    33  const ErrorFileNotFound = 1005
    34  
    35  ///////////////////
    36  // JSON error codes
    37  ///////////////////
    38  
    39  // ErrorMarshalJSON is triggered if there is an error marshalling data into JSON
    40  const ErrorMarshalJSON = 2000
    41  
    42  // ErrorUnmarshalJSON is triggered if there is an error unmarshalling JSON
    43  const ErrorUnmarshalJSON = 2001
    44  
    45  ///////////////////
    46  // Protobuf error codes
    47  ///////////////////
    48  
    49  // ErrorMarshalProto is triggered if there is an error marshalling data into protobuf
    50  const ErrorMarshalProto = 2500
    51  
    52  //////////////////////
    53  // Request error codes
    54  //////////////////////
    55  
    56  // ErrorIDNotInRequest is triggered when a id is not found in the request
    57  const ErrorIDNotInRequest = 3000
    58  
    59  // ErrorIDWrongFormat is triggered when an id is not in a valid format
    60  const ErrorIDWrongFormat = 3001
    61  
    62  // ErrorNameWrongFormat is triggered when a name is not in a valid format
    63  const ErrorNameWrongFormat = 3002
    64  
    65  // ErrorPayloadEmpty is triggered when payload is expected but is not found in
    66  // the request
    67  const ErrorPayloadEmpty = 3003
    68  
    69  // ErrorForm is triggered when an expected field is missing in a multipart
    70  // form request.
    71  const ErrorForm = 3004
    72  
    73  // ErrorUnexpectedID is triggered when the id of a file attached in a
    74  // request is not expected. E.g.: When the attached world file does not end in
    75  // ".world" during a world creation request.
    76  const ErrorUnexpectedID = 3005
    77  
    78  // ErrorUnknownSuffix is triggered when a suffix for content negotiation is not
    79  // recognized.
    80  const ErrorUnknownSuffix = 3006
    81  
    82  // ErrorUserNotInRequest is triggered when the user/team is not found in
    83  // the request.
    84  const ErrorUserNotInRequest = 3007
    85  
    86  // ErrorUserUnknown is triggered when the user/team does not exist on the
    87  // server
    88  const ErrorUserUnknown = 3008
    89  
    90  // ErrorMissingField is triggered when the JSON contained in a request does
    91  // not contain one or more required fields
    92  const ErrorMissingField = 3009
    93  
    94  // ErrorOwnerNotInRequest is triggered when an owner is not found in the request
    95  const ErrorOwnerNotInRequest = 3010
    96  
    97  // ErrorModelNotInRequest is triggered when a model is not found in the request
    98  const ErrorModelNotInRequest = 3011
    99  
   100  // ErrorFormMissingFiles is triggered when the expected "file" field is missing
   101  // in the multipart form request.
   102  const ErrorFormMissingFiles = 3012
   103  
   104  // ErrorFormInvalidValue is triggered when a given form field has an invalid
   105  // value.
   106  const ErrorFormInvalidValue = 3013
   107  
   108  // ErrorFormDuplicateFile is triggered when the POSTed model carries duplicate
   109  // file entries.
   110  const ErrorFormDuplicateFile = 3014
   111  
   112  // ErrorFormDuplicateModelName is triggered when the POSTed model carries duplicate
   113  // model name.
   114  const ErrorFormDuplicateModelName = 3015
   115  
   116  // ErrorInvalidPaginationRequest is triggered when the requested pagination is invalid.
   117  // eg. invalid page or per_page argument values.
   118  const ErrorInvalidPaginationRequest = 3016
   119  
   120  // ErrorPaginationPageNotFound is triggered when the requested page is empty / not found.
   121  const ErrorPaginationPageNotFound = 3017
   122  
   123  // ErrorFormDuplicateWorldName is triggered when the POSTed world carries duplicate
   124  // name.
   125  const ErrorFormDuplicateWorldName = 3018
   126  
   127  // ErrorWorldNotInRequest is triggered when a world is not found in the request
   128  const ErrorWorldNotInRequest = 3019
   129  
   130  // ErrorCollectionNotInRequest is triggered when a collection name is not found in the request
   131  const ErrorCollectionNotInRequest = 3020
   132  
   133  ////////////////////////////
   134  // Authorization error codes
   135  ////////////////////////////
   136  
   137  // ErrorAuthNoUser is triggered when there's no user in the database with the
   138  // claimed user ID.
   139  const ErrorAuthNoUser = 4000
   140  
   141  // ErrorAuthJWTInvalid is triggered when is not possible to get a user ID
   142  // from the JWT in the request
   143  const ErrorAuthJWTInvalid = 4001
   144  
   145  // ErrorUnauthorized is triggered when a user is not authorized to perform a
   146  // given action.
   147  const ErrorUnauthorized = 4002
   148  
   149  ////////////////////
   150  // Simulation error codes
   151  ////////////////////
   152  
   153  // ErrorLaunchGazebo is triggered when we cannot launch gazebo in the context of a simulation
   154  const ErrorLaunchGazebo = 5000
   155  
   156  // ErrorShutdownGazebo is triggered when there is an error during the process of
   157  // shutting down gazebo.
   158  const ErrorShutdownGazebo = 5001
   159  
   160  // ErrorSimGroupNotFound is triggered when a simulation Group ID is not found.
   161  const ErrorSimGroupNotFound = 5002
   162  
   163  // ErrorK8Create is triggered when there is an error creating a kubernetes resource
   164  const ErrorK8Create = 5003
   165  
   166  // ErrorK8Delete is triggered when there is an error deleting a kubernetes resource
   167  const ErrorK8Delete = 5004
   168  
   169  // ErrorLaunchingCloudInstance is triggered when there is an error launching a cloud
   170  // instance (eg. aws ec2)
   171  const ErrorLaunchingCloudInstance = 5005
   172  
   173  // ErrorStoppingCloudInstance is triggered when there is an error stopping or
   174  // terminating a cloud instance (eg. aws ec2)
   175  const ErrorStoppingCloudInstance = 5006
   176  
   177  // ErrorInvalidSimulationStatus is triggered when the simulation is not in a status
   178  // suitable for the requested operation. This error usually has a status extra argument.
   179  const ErrorInvalidSimulationStatus = 5007
   180  
   181  // ErrorLaunchingCloudInstanceNotEnoughResources is triggered when there are not enough
   182  // cloud instances to launch a simulation
   183  const ErrorLaunchingCloudInstanceNotEnoughResources = 5008
   184  
   185  ////////////////////
   186  // Queue error codes
   187  ////////////////////
   188  
   189  // ErrorQueueEmpty is triggered when a queue is empty
   190  const ErrorQueueEmpty = 6000
   191  
   192  // ErrorQueueIndexOutOfBounds is triggered when there is an attempt to access an index that does not exist.
   193  const ErrorQueueIndexOutOfBounds = 6001
   194  
   195  // ErrorQueueInternalChannelClosed is triggered when the queue's internal channel is closed.
   196  const ErrorQueueInternalChannelClosed = 6002
   197  
   198  // ErrorQueueSwapIndexesMatch is triggered when there is an attempt to swap the same element.
   199  const ErrorQueueSwapIndexesMatch = 6003
   200  
   201  // ErrorQueueMoveIndexFrontPosition is triggered when there is an attempt to move the front element to the front position
   202  const ErrorQueueMoveIndexFrontPosition = 6004
   203  
   204  // ErrorQueueMoveIndexBackPosition is triggered when there is an attempt to move the back element to the back position
   205  const ErrorQueueMoveIndexBackPosition = 6005
   206  
   207  // ErrorQueueTooManyListeners is triggered when there are too many listeners waiting for the next element from the queue.
   208  const ErrorQueueTooManyListeners = 6006
   209  
   210  ////////////////////
   211  // Other error codes
   212  ////////////////////
   213  
   214  // ErrorZipNotAvailable is triggered when the server does not have a zip file
   215  // for the requested resource
   216  const ErrorZipNotAvailable = 100000
   217  
   218  // ErrorResourceExists is triggered when the server cannot create a new resource
   219  // because the requested id already exists. E.g.: When the creation of a new
   220  // model is requested but the server already has a model with the same id.
   221  const ErrorResourceExists = 100001
   222  
   223  // ErrorCreatingDir is triggered when the server was unable to create a new
   224  // directory for a resource (no space on device or a temporary server problem).
   225  const ErrorCreatingDir = 100002
   226  
   227  // ErrorCreatingRepo is triggered when the server was unable to create a new
   228  // repository for a resource (no space on device or a temporary server problem).
   229  const ErrorCreatingRepo = 100003
   230  
   231  // ErrorCreatingFile is triggered when the server was unable to create a new
   232  // file for a resource (no space on device or a temporary server problem).
   233  const ErrorCreatingFile = 100004
   234  
   235  // ErrorUnzipping is triggered when the server was unable to unzip a zipped file
   236  const ErrorUnzipping = 100005
   237  
   238  // ErrorNonExistentResource is triggered when the server was unable to find a
   239  // resource.
   240  const ErrorNonExistentResource = 100006
   241  
   242  // ErrorRepo is triggered when the server was unable to handle repo command.
   243  const ErrorRepo = 100007
   244  
   245  // ErrorRemovingDir is triggered when the server was unable to remove a
   246  // directory.
   247  const ErrorRemovingDir = 100008
   248  
   249  // ErrorFileTree is triggered when there was a problem accessing the model's
   250  // files.
   251  const ErrorFileTree = 100009
   252  
   253  // ErrorVersionNotFound is triggered when the requested version of a resource is
   254  // not available
   255  const ErrorVersionNotFound = 100010
   256  
   257  // ErrorCastingID is triggered when casting an id fails.
   258  const ErrorCastingID = 100011
   259  
   260  // ErrorScheduler is triggered initializing a scheduler fails.
   261  const ErrorScheduler = 100012
   262  
   263  // ErrorUnexpected is used to represent unexpected or still uncategorized errors.
   264  const ErrorUnexpected = 150000
   265  
   266  // ErrMsg is serialized as JSON, and returned if the request does not succeed
   267  // TODO: consider making ErrMsg an 'error'
   268  type ErrMsg struct {
   269  	// Internal error code.
   270  	ErrCode int `json:"errcode"`
   271  	// HTTP status code.
   272  	StatusCode int `json:"-"`
   273  	// Error message.
   274  	Msg string `json:"msg"`
   275  	// Extra information/arguments associated to Error message.
   276  	Extra []string `json:"extra"`
   277  	// The root cause error
   278  	BaseError error `json:"-"`
   279  	// Generated ID for easy tracking in server logs
   280  	ErrID string `json:"errid"`
   281  	// Associated request Route, if applicable
   282  	Route string `json:"route"`
   283  	// Associated request User-Agent, if applicable
   284  	UserAgent string `json:"user-agent"`
   285  	// Associated request remote address, if applicable
   286  	RemoteAddress string `json:"remote-address"`
   287  }
   288  
   289  // LogString creates a verbose error string
   290  func (e *ErrMsg) LogString() string {
   291  	return fmt.Sprintf("[ErrID:%s][ErrCode:%d] %s. Extra: %v. [Route:%s]", e.ErrID, e.ErrCode, e.Msg, e.Extra, e.Route)
   292  }
   293  
   294  // NewErrorMessage is a convenience function that receives an error code
   295  // and returns a pointer to an ErrMsg.
   296  func NewErrorMessage(err int64) *ErrMsg {
   297  	em := ErrorMessage(err)
   298  	return &em
   299  }
   300  
   301  // WithStack wraps a given error with a stack trace if needed.
   302  func WithStack(base error) error {
   303  	// wrap the error with a stack trace, if needed.
   304  	type stackTracer interface {
   305  		StackTrace() errors.StackTrace
   306  	}
   307  	if _, ok := base.(stackTracer); !ok {
   308  		base = errors.WithStack(base)
   309  	}
   310  	return base
   311  }
   312  
   313  // NewErrorMessageWithBase receives an error code and a root error
   314  // and returns a pointer to an ErrMsg.
   315  func NewErrorMessageWithBase(err int64, base error) *ErrMsg {
   316  	em := NewErrorMessage(err)
   317  	em.BaseError = WithStack(base)
   318  	return em
   319  }
   320  
   321  // NewErrorMessageWithArgs receives an error code, a root error, and a slice
   322  // of extra arguments, and returns a pointer to an ErrMsg.
   323  func NewErrorMessageWithArgs(err int64, base error, extra []string) *ErrMsg {
   324  	em := NewErrorMessageWithBase(err, base)
   325  	em.Extra = extra
   326  	return em
   327  }
   328  
   329  // ErrorMessageOK creates an ErrMsg initialized with OK (default) values.
   330  func ErrorMessageOK() ErrMsg {
   331  	return ErrMsg{ErrCode: 0, StatusCode: http.StatusOK, Msg: ""}
   332  }
   333  
   334  // ErrorMessage receives an error code and generate an error message response
   335  func ErrorMessage(err int64) ErrMsg {
   336  
   337  	em := ErrorMessageOK()
   338  
   339  	em.ErrID = uuid.NewV4().String()
   340  
   341  	switch err {
   342  	case ErrorNoDatabase:
   343  		em.Msg = "Unable to connect to the database"
   344  		em.ErrCode = ErrorNoDatabase
   345  		em.StatusCode = http.StatusServiceUnavailable
   346  	case ErrorDbDelete:
   347  		em.Msg = "Unable to remove resource from the database"
   348  		em.ErrCode = ErrorDbDelete
   349  		em.StatusCode = http.StatusInternalServerError
   350  	case ErrorDbSave:
   351  		em.Msg = "Unable to save resource into the database"
   352  		em.ErrCode = ErrorDbSave
   353  		em.StatusCode = http.StatusInternalServerError
   354  	case ErrorIDNotFound:
   355  		em.Msg = "Requested id not found on server"
   356  		em.ErrCode = ErrorIDNotFound
   357  		em.StatusCode = http.StatusNotFound
   358  	case ErrorNameNotFound:
   359  		em.Msg = "Requested name not found on server"
   360  		em.ErrCode = ErrorNameNotFound
   361  		em.StatusCode = http.StatusNotFound
   362  	case ErrorFileNotFound:
   363  		em.Msg = "Requested file not found on server"
   364  		em.ErrCode = ErrorFileNotFound
   365  		em.StatusCode = http.StatusNotFound
   366  	case ErrorMarshalJSON:
   367  		em.Msg = "Unable to marshal the response into a JSON"
   368  		em.ErrCode = ErrorMarshalJSON
   369  		em.StatusCode = http.StatusInternalServerError
   370  	case ErrorUnmarshalJSON:
   371  		em.Msg = "Unable to decode JSON payload included in the request"
   372  		em.ErrCode = ErrorUnmarshalJSON
   373  		em.StatusCode = http.StatusBadRequest
   374  	case ErrorMarshalProto:
   375  		em.Msg = "Unable to marshal the response into a protobuf"
   376  		em.ErrCode = ErrorMarshalProto
   377  		em.StatusCode = http.StatusInternalServerError
   378  	case ErrorIDNotInRequest:
   379  		em.Msg = "ID not present in request"
   380  		em.ErrCode = ErrorIDNotInRequest
   381  		em.StatusCode = http.StatusBadRequest
   382  	case ErrorOwnerNotInRequest:
   383  		em.Msg = "Owner name not present in request"
   384  		em.ErrCode = ErrorOwnerNotInRequest
   385  		em.StatusCode = http.StatusBadRequest
   386  	case ErrorModelNotInRequest:
   387  		em.Msg = "Model name not present in request"
   388  		em.ErrCode = ErrorModelNotInRequest
   389  		em.StatusCode = http.StatusBadRequest
   390  	case ErrorWorldNotInRequest:
   391  		em.Msg = "World name not present in request"
   392  		em.ErrCode = ErrorWorldNotInRequest
   393  		em.StatusCode = http.StatusBadRequest
   394  	case ErrorIDWrongFormat:
   395  		em.Msg = "ID in request is in an invalid format"
   396  		em.ErrCode = ErrorIDWrongFormat
   397  		em.StatusCode = http.StatusBadRequest
   398  	case ErrorNameWrongFormat:
   399  		em.Msg = "Name in request is in an invalid format"
   400  		em.ErrCode = ErrorNameWrongFormat
   401  		em.StatusCode = http.StatusBadRequest
   402  	case ErrorPayloadEmpty:
   403  		em.Msg = "Payload empty in the request"
   404  		em.ErrCode = ErrorPayloadEmpty
   405  		em.StatusCode = http.StatusBadRequest
   406  	case ErrorForm:
   407  		em.Msg = "Missing field in the multipart form"
   408  		em.ErrCode = ErrorForm
   409  		em.StatusCode = http.StatusBadRequest
   410  	case ErrorFormMissingFiles:
   411  		em.Msg = "Missing file field, or empty list of files, in the multipart form"
   412  		em.ErrCode = ErrorFormMissingFiles
   413  		em.StatusCode = http.StatusBadRequest
   414  	case ErrorFormDuplicateFile:
   415  		em.Msg = "Duplicate file in multipart form"
   416  		em.ErrCode = ErrorFormDuplicateFile
   417  		em.StatusCode = http.StatusBadRequest
   418  	case ErrorFormDuplicateModelName:
   419  		em.Msg = "Duplicate model name"
   420  		em.ErrCode = ErrorFormDuplicateModelName
   421  		em.StatusCode = http.StatusBadRequest
   422  	case ErrorFormDuplicateWorldName:
   423  		em.Msg = "Duplicate world name"
   424  		em.ErrCode = ErrorFormDuplicateWorldName
   425  		em.StatusCode = http.StatusBadRequest
   426  	case ErrorInvalidPaginationRequest:
   427  		em.Msg = "Invalid pagination request"
   428  		em.ErrCode = ErrorInvalidPaginationRequest
   429  		em.StatusCode = http.StatusBadRequest
   430  	case ErrorPaginationPageNotFound:
   431  		em.Msg = "Page not found"
   432  		em.ErrCode = ErrorPaginationPageNotFound
   433  		em.StatusCode = http.StatusNotFound
   434  	case ErrorFormInvalidValue:
   435  		em.Msg = "Invalid value in field."
   436  		em.ErrCode = ErrorFormInvalidValue
   437  		em.StatusCode = http.StatusBadRequest
   438  	case ErrorUnexpectedID:
   439  		em.Msg = "Unexpected id included in your request"
   440  		em.ErrCode = ErrorUnexpectedID
   441  		em.StatusCode = http.StatusBadRequest
   442  	case ErrorUnknownSuffix:
   443  		em.Msg = "Unknown suffix requested"
   444  		em.ErrCode = ErrorUnknownSuffix
   445  		em.StatusCode = http.StatusBadRequest
   446  	case ErrorUserNotInRequest:
   447  		em.Msg = "User or team not present in the request"
   448  		em.ErrCode = ErrorUserNotInRequest
   449  		em.StatusCode = http.StatusBadRequest
   450  	case ErrorUserUnknown:
   451  		em.Msg = "Provided user or team does not exist on the server"
   452  		em.ErrCode = ErrorUserUnknown
   453  		em.StatusCode = http.StatusBadRequest
   454  	case ErrorMissingField:
   455  		em.Msg = "One or more required fields are missing"
   456  		em.ErrCode = ErrorMissingField
   457  		em.StatusCode = http.StatusBadRequest
   458  	case ErrorAuthNoUser:
   459  		em.Msg = "No user in server with the claimed identity"
   460  		em.ErrCode = ErrorAuthNoUser
   461  		em.StatusCode = http.StatusForbidden
   462  	case ErrorAuthJWTInvalid:
   463  		em.Msg = "Unable to process user ID from the JWT included in request"
   464  		em.ErrCode = ErrorAuthJWTInvalid
   465  		em.StatusCode = http.StatusForbidden
   466  	case ErrorUnauthorized:
   467  		em.Msg = "Unauthorized request"
   468  		em.ErrCode = ErrorUnauthorized
   469  		em.StatusCode = http.StatusUnauthorized
   470  	case ErrorQueueEmpty:
   471  		em.Msg = "Queue is empty"
   472  		em.ErrCode = ErrorQueueEmpty
   473  		em.StatusCode = http.StatusBadRequest
   474  	case ErrorQueueIndexOutOfBounds:
   475  		em.Msg = "Queue index is out of bounds"
   476  		em.ErrCode = ErrorQueueIndexOutOfBounds
   477  		em.StatusCode = http.StatusBadRequest
   478  	case ErrorQueueInternalChannelClosed:
   479  		em.Msg = "Queue's internal channel is closed"
   480  		em.ErrCode = ErrorQueueInternalChannelClosed
   481  		em.StatusCode = http.StatusLocked
   482  	case ErrorQueueSwapIndexesMatch:
   483  		em.Msg = "Cannot swap the same element in the queue"
   484  		em.ErrCode = ErrorQueueSwapIndexesMatch
   485  		em.StatusCode = http.StatusBadRequest
   486  	case ErrorQueueMoveIndexFrontPosition:
   487  		em.Msg = "Cannot move the first element to the front"
   488  		em.ErrCode = ErrorQueueMoveIndexFrontPosition
   489  		em.StatusCode = http.StatusBadRequest
   490  	case ErrorQueueMoveIndexBackPosition:
   491  		em.Msg = "Cannot move the last element to the back"
   492  		em.ErrCode = ErrorQueueMoveIndexBackPosition
   493  		em.StatusCode = http.StatusBadRequest
   494  	case ErrorQueueTooManyListeners:
   495  		em.Msg = "Too many dequeue listeners"
   496  		em.ErrCode = ErrorQueueTooManyListeners
   497  		em.StatusCode = http.StatusServiceUnavailable
   498  	case ErrorZipNotAvailable:
   499  		em.Msg = "Zip file not available for this resource"
   500  		em.ErrCode = ErrorZipNotAvailable
   501  		em.StatusCode = http.StatusServiceUnavailable
   502  	case ErrorResourceExists:
   503  		em.Msg = "A resource with the same id already exists"
   504  		em.ErrCode = ErrorResourceExists
   505  		em.StatusCode = http.StatusConflict
   506  	case ErrorCreatingDir:
   507  		em.Msg = "Unable to create a new directory for the resource"
   508  		em.ErrCode = ErrorCreatingDir
   509  		em.StatusCode = http.StatusInternalServerError
   510  	case ErrorCreatingRepo:
   511  		em.Msg = "Unable to create a new repository for the resource"
   512  		em.ErrCode = ErrorCreatingRepo
   513  		em.StatusCode = http.StatusInternalServerError
   514  	case ErrorCreatingFile:
   515  		em.Msg = "Unable to create a new file for the resource"
   516  		em.ErrCode = ErrorCreatingFile
   517  		em.StatusCode = http.StatusInternalServerError
   518  	case ErrorUnzipping:
   519  		em.Msg = "Unable to unzip a file"
   520  		em.ErrCode = ErrorUnzipping
   521  		em.StatusCode = http.StatusBadRequest
   522  	case ErrorNonExistentResource:
   523  		em.Msg = "Unable to find the requested resource"
   524  		em.ErrCode = ErrorNonExistentResource
   525  		em.StatusCode = http.StatusNotFound
   526  	case ErrorRepo:
   527  		em.Msg = "Unable to process repository command"
   528  		em.ErrCode = ErrorRepo
   529  		em.StatusCode = http.StatusServiceUnavailable
   530  	case ErrorRemovingDir:
   531  		em.Msg = "Unable to remove a resource directory"
   532  		em.ErrCode = ErrorRemovingDir
   533  		em.StatusCode = http.StatusInternalServerError
   534  	case ErrorFileTree:
   535  		em.Msg = "Unable to get files from model"
   536  		em.ErrCode = ErrorFileTree
   537  		em.StatusCode = http.StatusInternalServerError
   538  	case ErrorVersionNotFound:
   539  		em.Msg = "Requested version not found on server"
   540  		em.ErrCode = ErrorVersionNotFound
   541  		em.StatusCode = http.StatusNotFound
   542  	case ErrorLaunchGazebo:
   543  		em.Msg = "Could not launch gazebo"
   544  		em.ErrCode = ErrorLaunchGazebo
   545  		em.StatusCode = http.StatusInternalServerError
   546  	case ErrorShutdownGazebo:
   547  		em.Msg = "Could not shutdown gazebo"
   548  		em.ErrCode = ErrorShutdownGazebo
   549  		em.StatusCode = http.StatusInternalServerError
   550  	case ErrorSimGroupNotFound:
   551  		em.Msg = "Simulation GroupID not found"
   552  		em.ErrCode = ErrorSimGroupNotFound
   553  		em.StatusCode = http.StatusNotFound
   554  	case ErrorK8Create:
   555  		em.Msg = "Error creating kubernetes resource"
   556  		em.ErrCode = ErrorK8Create
   557  		em.StatusCode = http.StatusInternalServerError
   558  	case ErrorK8Delete:
   559  		em.Msg = "Error deleting kubernetes resource"
   560  		em.ErrCode = ErrorK8Delete
   561  		em.StatusCode = http.StatusInternalServerError
   562  	case ErrorLaunchingCloudInstance:
   563  		em.Msg = "Error launching ec2 instance"
   564  		em.ErrCode = ErrorLaunchingCloudInstance
   565  		em.StatusCode = http.StatusInternalServerError
   566  	case ErrorStoppingCloudInstance:
   567  		em.Msg = "Error stopping ec2 instance"
   568  		em.ErrCode = ErrorStoppingCloudInstance
   569  		em.StatusCode = http.StatusInternalServerError
   570  	case ErrorInvalidSimulationStatus:
   571  		em.Msg = "Invalid simulation status"
   572  		em.ErrCode = ErrorInvalidSimulationStatus
   573  		em.StatusCode = http.StatusBadRequest
   574  	case ErrorLaunchingCloudInstanceNotEnoughResources:
   575  		em.Msg = "Not enough ec2 instances available to launch simulation"
   576  		em.ErrCode = ErrorLaunchingCloudInstanceNotEnoughResources
   577  		em.StatusCode = http.StatusInternalServerError
   578  	case ErrorCastingID:
   579  		em.Msg = "Could not process the given ID"
   580  		em.ErrCode = ErrorCastingID
   581  		em.StatusCode = http.StatusInternalServerError
   582  	case ErrorScheduler:
   583  		em.Msg = "Could not initialize a scheduler"
   584  		em.ErrCode = ErrorScheduler
   585  		em.StatusCode = http.StatusInternalServerError
   586  	case ErrorUnexpected:
   587  		em.Msg = "Unexpected error"
   588  		em.ErrCode = ErrorUnexpected
   589  		em.StatusCode = http.StatusInternalServerError
   590  	}
   591  
   592  	em.BaseError = errors.New(em.Msg)
   593  	return em
   594  }