Commit graph

33 commits

Author SHA1 Message Date
Sebastiaan van Stijn
69cf2ad6a5
daemon: cleanupContainer: don't fail if container is already stopped
Saw this failure in a flaky test, and I wondered why we consider this an
error condition;

    === RUN   TestKillWithStopSignalAndRestartPolicies
        main_test.go:32: assertion failed: error is not nil: Error response from daemon: Could not kill running container 668f62511f4aa62357269cd405cff1fbe295b7f6d5011e7cfed434e3072330b7, cannot remove - Container 668f62511f4aa62357269cd405cff1fbe295b7f6d5011e7cfed434e3072330b7 is not running: failed to remove 668f62511f4aa62357269cd405cff1fbe295b7f6d5011e7cfed434e3072330b7
    --- FAIL: TestKillWithStopSignalAndRestartPolicies (0.84s)
    === RUN   TestKillWithStopSignalAndRestartPolicies/same-signal-disables-restart-policy
        --- PASS: TestKillWithStopSignalAndRestartPolicies/same-signal-disables-restart-policy (0.42s)
    === RUN   TestKillWithStopSignalAndRestartPolicies/different-signal-keep-restart-policy
        --- PASS: TestKillWithStopSignalAndRestartPolicies/different-signal-keep-restart-policy (0.23s)

In the above;

1. `Error response from daemon: Could not kill running container 668f62511f4aa62357269cd405cff1fbe295b7f6d5011e7cfed434e3072330b7`
2. `cannot remove - Container 668f62511f4aa62357269cd405cff1fbe295b7f6d5011e7cfed434e3072330b7 is not running`
3. `failed to remove 668f62511f4aa62357269cd405cff1fbe295b7f6d5011e7cfed434e3072330b7`

So it looks like the removal fails because we couldn't kill the container
because it was already stopped, which may be a race condition where the first
check shows the container to be running (but may already be in process to be
removed or killed. In either case, we probably shouldn't fail the removal if
the container is already stopped.

This patch adds a `isNotRunning()` utility, so that we can ignore this case,
and proceed with the removal.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-23 15:47:43 +02:00
Sebastiaan van Stijn
80d158e0de
daemon: remove containerNotModifiedError
Removing this type, because:

- containerNotModifiedError is not an actual error, and abstracting it away
  was hiding some of these details. It also wasn't used as a sentinel error
  anywhere, so doesn't have to be its own type.
- Defining a type just to toggle the error-message between "not running"
  and "not stopped" felt a bit over-the-top, as each variant was only used once.
- So  "it only had one job", and it didn't even do that right; it produced
  capitalized error messages, which makes linters unhappy.

So, let's just inline what it does in the two places it was used.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-11 21:28:06 +02:00
Brian Goff
73db49f8ef
Merge pull request #44003 from vvoland/invalidfilter 2023-02-22 16:24:47 +00:00
Cory Snider
713e02e03e daemon: handle EISDIR error from runtime
Go 1.20 made a change to the behaviour of package "os/exec" which was
not mentioned in the release notes:
2b8f214094
Attempts to execute a directory now return syscall.EISDIR instead of
syscall.EACCESS. Check for EISDIR errors from the runtime and fudge the
returned error message to maintain compatibility with existing versions
of docker/cli when using a version of runc compiled with Go 1.20+.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2023-02-15 13:06:04 -05:00
Paweł Gronowski
a654cbfd2f
Use GetBoolOrDefault to remove duplicated invalidFilter usages
The pattern of parsing bool was repeated across multiple files and
caused the duplication of the invalidFilter error helper.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2023-01-26 16:28:53 +01:00
Sebastiaan van Stijn
42f1be8030
daemon: translateContainerdStartErr(): rename to setExitCodeFromError()
This should hopefully make it slightly clearer what it does.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-12-28 09:27:42 +01:00
Sebastiaan van Stijn
83dd99177f
daemon: translateContainerdStartErr(): use exit code 128 as default
After further looking at the code, it appears that the default exit-code
for unknown (other) errors is 128 (set in `defer`).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-12-28 09:27:42 +01:00
Sebastiaan van Stijn
46dae0b8bb
daemon: translateContainerdStartErr(): use early return for errors
These matches were overwriting the previous "match", so reversing the
order in which they're tried so that we can return early.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-12-28 09:27:42 +01:00
Sebastiaan van Stijn
4e750caf96
daemon: translateContainerdStartErr(): extract detecting wrong cmd
To make the code slightly more readable, and slightly DRY.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-12-28 09:27:42 +01:00
Sebastiaan van Stijn
a756fa60ef
daemon: translateContainerdStartErr(): use const/enum for exit-statuses
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-12-28 09:27:41 +01:00
Sebastiaan van Stijn
2cf09c5446
daemon: translateContainerdStartErr(): remove unused cmd argument
This argument was no longer used since commit 225e046d9d

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-12-28 09:27:41 +01:00
Sebastiaan van Stijn
bdb878ab2c
filters: lowercase error
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-03-18 09:44:53 +01:00
Brian Goff
225e046d9d Error string match: do not match command path
Whether or not the command path is in the error message is a an
implementation detail.
For example, on Windows the only reason this ever matched was because it
dumped the entire container config into the error message, but this had
nothing to do with the actual error.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2021-04-14 23:03:18 +00:00
John Howard
a3eda72f71
Merge pull request #38541 from Microsoft/jjh/containerd
Windows: Experimental: ContainerD runtime
2019-03-19 21:09:19 -07:00
Tibor Vass
8f936ae8cf Add DeviceRequests to HostConfig to support NVIDIA GPUs
This patch hard-codes support for NVIDIA GPUs.
In a future patch it should move out into its own Device Plugin.

Signed-off-by: Tibor Vass <tibor@docker.com>
2019-03-18 17:19:45 +00:00
John Howard
32acc76b1a Windows: Fix handle leaks/logging if init proc start fails
Signed-off-by: John Howard <jhoward@microsoft.com>

Fixes #38719

Fixes some subtle bugs on Windows

 - Fixes https://github.com/moby/moby/issues/38719. This one is the most important
   as failure to start the init process in a Windows container will cause leaked
   handles. (ie where the `ctr.hcsContainer.CreateProcess(...)` call fails).
   The solution to the leak is to split out the `reapContainer` part of `reapProcess`
   into a separate function. This ensures HCS resources are cleaned up correctly and
   not leaked.

 - Ensuring the reapProcess goroutine is started immediately the process
   is actually started, so we don't leak in the case of failures such as
   from `newIOFromProcess` or `attachStdio`

 - libcontainerd on Windows (local, not containerd) was not sending the EventCreate
   back to the monitor on Windows. Just LCOW. This was just an oversight from
   refactoring a couple of years ago by Mikael as far as I can tell. Technically
   not needed for functionality except for the logging being missing, but is correct.
2019-03-12 18:41:55 -07:00
Sebastiaan van Stijn
72b0b0387d
Replace deprecated grpc.ErrorDesc() and grpc.Code() calls
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-12-30 12:34:28 +01:00
Brian Goff
e4b6adc88e Extract volume interaction to a volumes service
This cleans up some of the package API's used for interacting with
volumes, and simplifies management.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2018-05-25 14:21:07 -04:00
Daniel Nephin
4f0d95fa6e Add canonical import comment
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2018-02-05 16:51:57 -05:00
Brian Goff
d453fe35b9 Move api/errdefs to errdefs
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2018-01-11 21:21:43 -05:00
Brian Goff
87a12421a9 Add helpers to create errdef errors
Instead of having to create a bunch of custom error types that are doing
nothing but wrapping another error in sub-packages, use a common helper
to create errors of the requested type.

e.g. instead of re-implementing this over and over:

```go
type notFoundError struct {
  cause error
}

func(e notFoundError) Error() string {
  return e.cause.Error()
}

func(e notFoundError) NotFound() {}

func(e notFoundError) Cause() error {
  return e.cause
}
```

Packages can instead just do:

```
  errdefs.NotFound(err)
```

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2018-01-11 21:21:43 -05:00
Yong Tang
b249ccb115 Update and use FindNetwork on Windows.
Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
2018-01-07 03:32:37 +00:00
Flavio Crisciani
51cea0a53c
Restore error type in FindNetwork
The error type libnetwork.ErrNoSuchNetwork is used in the controller
to retry the network creation as a managed network though the manager.
The change of the type was breaking the logic causing the network to
not being created anymore so that no new container on that network
was able to be launched
Added unit test

Signed-off-by: Flavio Crisciani <flavio.crisciani@docker.com>
2017-11-29 11:22:57 -08:00
Kenfe-Mickael Laventure
ddae20c032
Update libcontainerd to use containerd 1.0
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
2017-10-20 07:11:37 -07:00
Sebastiaan van Stijn
e424343b43
Fix conflicting container name producint 400 error instead of 409
Commit ebcb7d6b40 removed string checking
for error messages, in favor of typed errors.

In this change, the status code for conflicting container  names
changed from 409 to 400 (validationError).

This patch add a `nameConflictError`, changing the status code to
409 as it was in older versions.

With this change applied, the correct 409 status is returned:

```bash
$ docker create --name c1 busybox
```

```bash
$ curl --unix-socket /var/run/docker.sock -v -XPOST -H"Content-Type: application/json" -d'{"Image":"busybox"}' http://localhost/containers/create?name=c1
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying /var/run/docker.sock...
* Connected to localhost (/var/run/docker.sock) port 80 (#0)
> POST /containers/create?name=c1 HTTP/1.1
> Host: localhost
> User-Agent: curl/7.52.1
> Accept: */*
> Content-Type: application/json
> Content-Length: 19
>
* upload completely sent off: 19 out of 19 bytes
< HTTP/1.1 409 Conflict
< Api-Version: 1.33
< Content-Type: application/json
< Docker-Experimental: false
< Ostype: linux
< Server: Docker/17.06.0-dev (linux)
< Date: Thu, 28 Sep 2017 15:07:23 GMT
< Content-Length: 229
<
{"message":"Conflict. The container name \"/c1\" is already in use by container \"ed2efdc806c1883954e677eb9ab8cbc7e286c9c5934ef6724fd5d93c56744923\". You have to remove (or rename) that container to be able to reuse that name."}
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2017-10-04 20:39:45 +02:00
Brian Goff
ebcb7d6b40 Remove string checking in API error handling
Use strongly typed errors to set HTTP status codes.
Error interfaces are defined in the api/errors package and errors
returned from controllers are checked against these interfaces.

Errors can be wraeped in a pkg/errors.Causer, as long as somewhere in the
line of causes one of the interfaces is implemented. The special error
interfaces take precedence over Causer, meaning if both Causer and one
of the new error interfaces are implemented, the Causer is not
traversed.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2017-08-15 16:01:11 -04:00
Yuanhong Peng
4a6cbf9bcb Return an empty stats if "container not found"
If we get "container not found" error from containerd, it's possibly
because that this container has already been stopped. It will be ok to
ignore this error and just return an empty stats.

Signed-off-by: Yuanhong Peng <pengyuanhong@huawei.com>
2017-07-10 16:30:48 +08:00
Derek McGowan
3a1279393f
Use distribution reference
Remove forked reference package. Use normalized named values
everywhere and familiar functions to convert back to familiar
strings for UX and storage compatibility.

Enforce that the source repository in the distribution metadata
is always a normalized string, ignore invalid values which are not.
Update distribution tests to use normalized values.

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
2017-02-07 11:08:37 -08:00
Daniel Nephin
c452e1bfe6 Move errors/ to api/errors
Using:
        gomvpkg -from github.com/docker/docker/errors
                -to github.com/docker/docker/api/errors
                -vcs_mv_cmd "git mv {{.Src}} {{.Dst}}"

Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-09-16 12:27:13 -04:00
David Calavera
a793564b25 Remove static errors from errors package.
Moving all strings to the errors package wasn't a good idea after all.

Our custom implementation of Go errors predates everything that's nice
and good about working with errors in Go. Take as an example what we
have to do to get an error message:

```go
func GetErrorMessage(err error) string {
	switch err.(type) {
	case errcode.Error:
		e, _ := err.(errcode.Error)
		return e.Message

	case errcode.ErrorCode:
		ec, _ := err.(errcode.ErrorCode)
		return ec.Message()

	default:
		return err.Error()
	}
}
```

This goes against every good practice for Go development. The language already provides a simple, intuitive and standard way to get error messages, that is calling the `Error()` method from an error. Reinventing the error interface is a mistake.

Our custom implementation also makes very hard to reason about errors, another nice thing about Go. I found several (>10) error declarations that we don't use anywhere. This is a clear sign about how little we know about the errors we return. I also found several error usages where the number of arguments was different than the parameters declared in the error, another clear example of how difficult is to reason about errors.

Moreover, our custom implementation didn't really make easier for people to return custom HTTP status code depending on the errors. Again, it's hard to reason about when to set custom codes and how. Take an example what we have to do to extract the message and status code from an error before returning a response from the API:

```go
	switch err.(type) {
	case errcode.ErrorCode:
		daError, _ := err.(errcode.ErrorCode)
		statusCode = daError.Descriptor().HTTPStatusCode
		errMsg = daError.Message()

	case errcode.Error:
		// For reference, if you're looking for a particular error
		// then you can do something like :
		//   import ( derr "github.com/docker/docker/errors" )
		//   if daError.ErrorCode() == derr.ErrorCodeNoSuchContainer { ... }

		daError, _ := err.(errcode.Error)
		statusCode = daError.ErrorCode().Descriptor().HTTPStatusCode
		errMsg = daError.Message

	default:
		// This part of will be removed once we've
		// converted everything over to use the errcode package

		// FIXME: this is brittle and should not be necessary.
		// If we need to differentiate between different possible error types,
		// we should create appropriate error types with clearly defined meaning
		errStr := strings.ToLower(err.Error())
		for keyword, status := range map[string]int{
			"not found":             http.StatusNotFound,
			"no such":               http.StatusNotFound,
			"bad parameter":         http.StatusBadRequest,
			"conflict":              http.StatusConflict,
			"impossible":            http.StatusNotAcceptable,
			"wrong login/password":  http.StatusUnauthorized,
			"hasn't been activated": http.StatusForbidden,
		} {
			if strings.Contains(errStr, keyword) {
				statusCode = status
				break
			}
		}
	}
```

You can notice two things in that code:

1. We have to explain how errors work, because our implementation goes against how easy to use Go errors are.
2. At no moment we arrived to remove that `switch` statement that was the original reason to use our custom implementation.

This change removes all our status errors from the errors package and puts them back in their specific contexts.
IT puts the messages back with their contexts. That way, we know right away when errors used and how to generate their messages.
It uses custom interfaces to reason about errors. Errors that need to response with a custom status code MUST implementent this simple interface:

```go
type errorWithStatus interface {
	HTTPErrorStatusCode() int
}
```

This interface is very straightforward to implement. It also preserves Go errors real behavior, getting the message is as simple as using the `Error()` method.

I included helper functions to generate errors that use custom status code in `errors/errors.go`.

By doing this, we remove the hard dependency we have eeverywhere to our custom errors package. Yes, you can use it as a helper to generate error, but it's still very easy to generate errors without it.

Please, read this fantastic blog post about errors in Go: http://dave.cheney.net/2014/12/24/inspecting-errors

Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-02-26 15:49:09 -05:00
Tonis Tiigi
2655954c2d Add own reference package wrapper
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2015-12-16 11:58:52 -08:00
Tonis Tiigi
4352da7803 Update daemon and docker core to use new content addressable storage
Add distribution package for managing pulls and pushes. This is based on
the old code in the graph package, with major changes to work with the
new image/layer model.

Add v1 migration code.

Update registry, api/*, and daemon packages to use the reference
package's types where applicable.

Update daemon package to use image/layer/tag stores instead of the graph
package

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2015-11-24 09:40:25 -08:00
Alexander Morozov
d4a8d09d1a Do not rely on string comparison in truncindex
Signed-off-by: Alexander Morozov <lk4d4@docker.com>
2015-11-04 11:34:05 -08:00