errors.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. package daemon
  2. import (
  3. "fmt"
  4. "strings"
  5. "syscall"
  6. "github.com/pkg/errors"
  7. "google.golang.org/grpc"
  8. )
  9. func errNotRunning(id string) error {
  10. return stateConflictError{errors.Errorf("Container %s is not running", id)}
  11. }
  12. func containerNotFound(id string) error {
  13. return objNotFoundError{"container", id}
  14. }
  15. func volumeNotFound(id string) error {
  16. return objNotFoundError{"volume", id}
  17. }
  18. func networkNotFound(id string) error {
  19. return objNotFoundError{"network", id}
  20. }
  21. type objNotFoundError struct {
  22. object string
  23. id string
  24. }
  25. func (e objNotFoundError) Error() string {
  26. return "No such " + e.object + ": " + e.id
  27. }
  28. func (e objNotFoundError) NotFound() {}
  29. type stateConflictError struct {
  30. cause error
  31. }
  32. func (e stateConflictError) Error() string {
  33. return e.cause.Error()
  34. }
  35. func (e stateConflictError) Cause() error {
  36. return e.cause
  37. }
  38. func (e stateConflictError) Conflict() {}
  39. func errContainerIsRestarting(containerID string) error {
  40. cause := errors.Errorf("Container %s is restarting, wait until the container is running", containerID)
  41. return stateConflictError{cause}
  42. }
  43. func errExecNotFound(id string) error {
  44. return objNotFoundError{"exec instance", id}
  45. }
  46. func errExecPaused(id string) error {
  47. cause := errors.Errorf("Container %s is paused, unpause the container before exec", id)
  48. return stateConflictError{cause}
  49. }
  50. type validationError struct {
  51. cause error
  52. }
  53. func (e validationError) Error() string {
  54. return e.cause.Error()
  55. }
  56. func (e validationError) InvalidParameter() {}
  57. func (e validationError) Cause() error {
  58. return e.cause
  59. }
  60. type notAllowedError struct {
  61. cause error
  62. }
  63. func (e notAllowedError) Error() string {
  64. return e.cause.Error()
  65. }
  66. func (e notAllowedError) Forbidden() {}
  67. func (e notAllowedError) Cause() error {
  68. return e.cause
  69. }
  70. type containerNotModifiedError struct {
  71. running bool
  72. }
  73. func (e containerNotModifiedError) Error() string {
  74. if e.running {
  75. return "Container is already started"
  76. }
  77. return "Container is already stopped"
  78. }
  79. func (e containerNotModifiedError) NotModified() {}
  80. type systemError struct {
  81. cause error
  82. }
  83. func (e systemError) Error() string {
  84. return e.cause.Error()
  85. }
  86. func (e systemError) SystemError() {}
  87. func (e systemError) Cause() error {
  88. return e.cause
  89. }
  90. type invalidIdentifier string
  91. func (e invalidIdentifier) Error() string {
  92. return fmt.Sprintf("invalid name or ID supplied: %q", string(e))
  93. }
  94. func (invalidIdentifier) InvalidParameter() {}
  95. type duplicateMountPointError string
  96. func (e duplicateMountPointError) Error() string {
  97. return "Duplicate mount point: " + string(e)
  98. }
  99. func (duplicateMountPointError) InvalidParameter() {}
  100. type containerFileNotFound struct {
  101. file string
  102. container string
  103. }
  104. func (e containerFileNotFound) Error() string {
  105. return "Could not find the file " + e.file + " in container " + e.container
  106. }
  107. func (containerFileNotFound) NotFound() {}
  108. type invalidFilter struct {
  109. filter string
  110. value interface{}
  111. }
  112. func (e invalidFilter) Error() string {
  113. msg := "Invalid filter '" + e.filter
  114. if e.value != nil {
  115. msg += fmt.Sprintf("=%s", e.value)
  116. }
  117. return msg + "'"
  118. }
  119. func (e invalidFilter) InvalidParameter() {}
  120. type unknownError struct {
  121. cause error
  122. }
  123. func (e unknownError) Error() string {
  124. return e.cause.Error()
  125. }
  126. func (unknownError) Unknown() {}
  127. func (e unknownError) Cause() error {
  128. return e.cause
  129. }
  130. type startInvalidConfigError string
  131. func (e startInvalidConfigError) Error() string {
  132. return string(e)
  133. }
  134. func (e startInvalidConfigError) InvalidParameter() {} // Is this right???
  135. func translateContainerdStartErr(cmd string, setExitCode func(int), err error) error {
  136. errDesc := grpc.ErrorDesc(err)
  137. contains := func(s1, s2 string) bool {
  138. return strings.Contains(strings.ToLower(s1), s2)
  139. }
  140. var retErr error = unknownError{errors.New(errDesc)}
  141. // if we receive an internal error from the initial start of a container then lets
  142. // return it instead of entering the restart loop
  143. // set to 127 for container cmd not found/does not exist)
  144. if contains(errDesc, cmd) &&
  145. (contains(errDesc, "executable file not found") ||
  146. contains(errDesc, "no such file or directory") ||
  147. contains(errDesc, "system cannot find the file specified")) {
  148. setExitCode(127)
  149. retErr = startInvalidConfigError(errDesc)
  150. }
  151. // set to 126 for container cmd can't be invoked errors
  152. if contains(errDesc, syscall.EACCES.Error()) {
  153. setExitCode(126)
  154. retErr = startInvalidConfigError(errDesc)
  155. }
  156. // attempted to mount a file onto a directory, or a directory onto a file, maybe from user specified bind mounts
  157. if contains(errDesc, syscall.ENOTDIR.Error()) {
  158. errDesc += ": Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type"
  159. setExitCode(127)
  160. retErr = startInvalidConfigError(errDesc)
  161. }
  162. // TODO: it would be nice to get some better errors from containerd so we can return better errors here
  163. return retErr
  164. }