errors.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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 nameConflictError struct {
  51. id string
  52. name string
  53. }
  54. func (e nameConflictError) Error() string {
  55. return fmt.Sprintf("Conflict. The container name %q is already in use by container %q. You have to remove (or rename) that container to be able to reuse that name.", e.name, e.id)
  56. }
  57. func (nameConflictError) Conflict() {}
  58. type validationError struct {
  59. cause error
  60. }
  61. func (e validationError) Error() string {
  62. return e.cause.Error()
  63. }
  64. func (e validationError) InvalidParameter() {}
  65. func (e validationError) Cause() error {
  66. return e.cause
  67. }
  68. type notAllowedError struct {
  69. cause error
  70. }
  71. func (e notAllowedError) Error() string {
  72. return e.cause.Error()
  73. }
  74. func (e notAllowedError) Forbidden() {}
  75. func (e notAllowedError) Cause() error {
  76. return e.cause
  77. }
  78. type containerNotModifiedError struct {
  79. running bool
  80. }
  81. func (e containerNotModifiedError) Error() string {
  82. if e.running {
  83. return "Container is already started"
  84. }
  85. return "Container is already stopped"
  86. }
  87. func (e containerNotModifiedError) NotModified() {}
  88. type systemError struct {
  89. cause error
  90. }
  91. func (e systemError) Error() string {
  92. return e.cause.Error()
  93. }
  94. func (e systemError) SystemError() {}
  95. func (e systemError) Cause() error {
  96. return e.cause
  97. }
  98. type invalidIdentifier string
  99. func (e invalidIdentifier) Error() string {
  100. return fmt.Sprintf("invalid name or ID supplied: %q", string(e))
  101. }
  102. func (invalidIdentifier) InvalidParameter() {}
  103. type duplicateMountPointError string
  104. func (e duplicateMountPointError) Error() string {
  105. return "Duplicate mount point: " + string(e)
  106. }
  107. func (duplicateMountPointError) InvalidParameter() {}
  108. type containerFileNotFound struct {
  109. file string
  110. container string
  111. }
  112. func (e containerFileNotFound) Error() string {
  113. return "Could not find the file " + e.file + " in container " + e.container
  114. }
  115. func (containerFileNotFound) NotFound() {}
  116. type invalidFilter struct {
  117. filter string
  118. value interface{}
  119. }
  120. func (e invalidFilter) Error() string {
  121. msg := "Invalid filter '" + e.filter
  122. if e.value != nil {
  123. msg += fmt.Sprintf("=%s", e.value)
  124. }
  125. return msg + "'"
  126. }
  127. func (e invalidFilter) InvalidParameter() {}
  128. type unknownError struct {
  129. cause error
  130. }
  131. func (e unknownError) Error() string {
  132. return e.cause.Error()
  133. }
  134. func (unknownError) Unknown() {}
  135. func (e unknownError) Cause() error {
  136. return e.cause
  137. }
  138. type startInvalidConfigError string
  139. func (e startInvalidConfigError) Error() string {
  140. return string(e)
  141. }
  142. func (e startInvalidConfigError) InvalidParameter() {} // Is this right???
  143. func translateContainerdStartErr(cmd string, setExitCode func(int), err error) error {
  144. errDesc := grpc.ErrorDesc(err)
  145. contains := func(s1, s2 string) bool {
  146. return strings.Contains(strings.ToLower(s1), s2)
  147. }
  148. var retErr error = unknownError{errors.New(errDesc)}
  149. // if we receive an internal error from the initial start of a container then lets
  150. // return it instead of entering the restart loop
  151. // set to 127 for container cmd not found/does not exist)
  152. if contains(errDesc, cmd) &&
  153. (contains(errDesc, "executable file not found") ||
  154. contains(errDesc, "no such file or directory") ||
  155. contains(errDesc, "system cannot find the file specified")) {
  156. setExitCode(127)
  157. retErr = startInvalidConfigError(errDesc)
  158. }
  159. // set to 126 for container cmd can't be invoked errors
  160. if contains(errDesc, syscall.EACCES.Error()) {
  161. setExitCode(126)
  162. retErr = startInvalidConfigError(errDesc)
  163. }
  164. // attempted to mount a file onto a directory, or a directory onto a file, maybe from user specified bind mounts
  165. if contains(errDesc, syscall.ENOTDIR.Error()) {
  166. 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"
  167. setExitCode(127)
  168. retErr = startInvalidConfigError(errDesc)
  169. }
  170. // TODO: it would be nice to get some better errors from containerd so we can return better errors here
  171. return retErr
  172. }