errors.go 5.2 KB

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