2021-02-11 11:12:50 +01:00
|
|
|
/*
|
|
|
|
Copyright 2020 Docker Compose CLI authors
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package compose
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
"fmt"
|
2023-03-08 15:11:32 +00:00
|
|
|
"os"
|
2021-08-18 10:50:43 -03:00
|
|
|
"strings"
|
2021-02-11 11:12:50 +01:00
|
|
|
"testing"
|
|
|
|
|
2023-11-08 10:19:24 +01:00
|
|
|
"github.com/compose-spec/compose-go/v2/types"
|
2023-03-08 15:11:32 +00:00
|
|
|
"github.com/docker/cli/cli/streams"
|
2025-02-12 09:34:07 +01:00
|
|
|
"github.com/docker/docker/api/types/container"
|
2021-04-29 21:54:54 +02:00
|
|
|
"github.com/docker/docker/api/types/filters"
|
2023-12-05 10:59:26 +01:00
|
|
|
"github.com/docker/docker/api/types/image"
|
2024-06-07 17:57:54 +02:00
|
|
|
"github.com/docker/docker/api/types/network"
|
2021-04-29 21:54:54 +02:00
|
|
|
"github.com/docker/docker/api/types/volume"
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
"github.com/docker/docker/errdefs"
|
2023-12-13 14:01:36 +01:00
|
|
|
"go.uber.org/mock/gomock"
|
2021-02-15 13:54:55 +01:00
|
|
|
"gotest.tools/v3/assert"
|
networks: prevent issues due to duplicate names
Within the Docker API/engine, networks have unique IDs, and the
name is a friendly label/alias, which notably does NOT have any
guarantees around uniqueness (see moby/moby#18864 [^1]).
During day-to-day interactive/CLI Compose usage, this is rarely
an issue, as Compose itself isn't creating networks concurrently
across goroutines. However, if multiple Compose instances are
executed simultaneously (e.g. as part of a test suite that runs
in parallel), this can easily occur.
When it does happen, it's very confusing for users and resolving
it via the `docker` CLI is not straightforward either [^2].
There's two primary changes here:
* Pass `CheckDuplicates: true` to the Docker API when creating
networks to reduce the likelihood of Compose creating duplicates
in the first place
* On `down`, list networks using a name filter and then remove
them all by ID, as the Docker API will return an error if the
name alias is used and maps to more than one network
Hopefully, this provides a better UX, since the issue should be
less likely to occur, and if it does, it can now be resolved via
standard Compose workflow commands.
[^1]: https://github.com/moby/moby/issues/18864
[^2]: https://stackoverflow.com/questions/63776518/error-2-matches-found-based-on-name-network-nameofservice-default-is-ambiguo
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-06-21 16:25:42 -04:00
|
|
|
|
|
|
|
compose "github.com/docker/compose/v2/pkg/api"
|
|
|
|
"github.com/docker/compose/v2/pkg/mocks"
|
2021-02-11 11:12:50 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestDown(t *testing.T) {
|
|
|
|
mockCtrl := gomock.NewController(t)
|
|
|
|
defer mockCtrl.Finish()
|
2022-03-03 14:19:01 +01:00
|
|
|
|
2023-03-08 15:11:32 +00:00
|
|
|
api, cli := prepareMocks(mockCtrl)
|
2022-09-08 16:26:00 -04:00
|
|
|
tested := composeService{
|
|
|
|
dockerCli: cli,
|
|
|
|
}
|
2021-02-11 11:12:50 +01:00
|
|
|
|
2022-04-11 10:58:20 +02:00
|
|
|
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
|
2025-02-12 09:34:07 +01:00
|
|
|
[]container.Summary{
|
2021-09-20 08:16:59 +02:00
|
|
|
testContainer("service1", "123", false),
|
|
|
|
testContainer("service2", "456", false),
|
|
|
|
testContainer("service2", "789", false),
|
|
|
|
testContainer("service_orphan", "321", true),
|
|
|
|
}, nil)
|
2023-06-06 16:55:54 -04:00
|
|
|
api.EXPECT().VolumeList(
|
|
|
|
gomock.Any(),
|
|
|
|
volume.ListOptions{
|
|
|
|
Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
|
|
|
|
}).
|
2022-10-18 16:57:53 +02:00
|
|
|
Return(volume.ListResponse{}, nil)
|
2022-06-22 16:34:55 -04:00
|
|
|
|
|
|
|
// network names are not guaranteed to be unique, ensure Compose handles
|
|
|
|
// cleanup properly if duplicates are inadvertently created
|
2024-06-07 17:57:54 +02:00
|
|
|
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
|
|
|
|
Return([]network.Summary{
|
2023-05-31 20:46:23 +02:00
|
|
|
{ID: "abc123", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}},
|
|
|
|
{ID: "def456", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}},
|
2022-06-22 16:34:55 -04:00
|
|
|
}, nil)
|
2021-02-11 11:12:50 +01:00
|
|
|
|
2025-02-12 09:34:07 +01:00
|
|
|
stopOptions := container.StopOptions{}
|
2022-10-18 15:21:11 +02:00
|
|
|
api.EXPECT().ContainerStop(gomock.Any(), "123", stopOptions).Return(nil)
|
|
|
|
api.EXPECT().ContainerStop(gomock.Any(), "456", stopOptions).Return(nil)
|
|
|
|
api.EXPECT().ContainerStop(gomock.Any(), "789", stopOptions).Return(nil)
|
2021-02-11 11:12:50 +01:00
|
|
|
|
2025-02-12 09:34:07 +01:00
|
|
|
api.EXPECT().ContainerRemove(gomock.Any(), "123", container.RemoveOptions{Force: true}).Return(nil)
|
|
|
|
api.EXPECT().ContainerRemove(gomock.Any(), "456", container.RemoveOptions{Force: true}).Return(nil)
|
|
|
|
api.EXPECT().ContainerRemove(gomock.Any(), "789", container.RemoveOptions{Force: true}).Return(nil)
|
2021-02-11 11:12:50 +01:00
|
|
|
|
2024-06-07 17:57:54 +02:00
|
|
|
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{
|
2023-05-31 20:46:23 +02:00
|
|
|
Filters: filters.NewArgs(
|
|
|
|
projectFilter(strings.ToLower(testProject)),
|
|
|
|
networkFilter("default")),
|
2024-06-07 17:57:54 +02:00
|
|
|
}).Return([]network.Summary{
|
networks: prevent issues due to duplicate names
Within the Docker API/engine, networks have unique IDs, and the
name is a friendly label/alias, which notably does NOT have any
guarantees around uniqueness (see moby/moby#18864 [^1]).
During day-to-day interactive/CLI Compose usage, this is rarely
an issue, as Compose itself isn't creating networks concurrently
across goroutines. However, if multiple Compose instances are
executed simultaneously (e.g. as part of a test suite that runs
in parallel), this can easily occur.
When it does happen, it's very confusing for users and resolving
it via the `docker` CLI is not straightforward either [^2].
There's two primary changes here:
* Pass `CheckDuplicates: true` to the Docker API when creating
networks to reduce the likelihood of Compose creating duplicates
in the first place
* On `down`, list networks using a name filter and then remove
them all by ID, as the Docker API will return an error if the
name alias is used and maps to more than one network
Hopefully, this provides a better UX, since the issue should be
less likely to occur, and if it does, it can now be resolved via
standard Compose workflow commands.
[^1]: https://github.com/moby/moby/issues/18864
[^2]: https://stackoverflow.com/questions/63776518/error-2-matches-found-based-on-name-network-nameofservice-default-is-ambiguo
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-06-21 16:25:42 -04:00
|
|
|
{ID: "abc123", Name: "myProject_default"},
|
|
|
|
{ID: "def456", Name: "myProject_default"},
|
|
|
|
}, nil)
|
2024-06-07 17:57:54 +02:00
|
|
|
api.EXPECT().NetworkInspect(gomock.Any(), "abc123", gomock.Any()).Return(network.Inspect{ID: "abc123"}, nil)
|
|
|
|
api.EXPECT().NetworkInspect(gomock.Any(), "def456", gomock.Any()).Return(network.Inspect{ID: "def456"}, nil)
|
networks: prevent issues due to duplicate names
Within the Docker API/engine, networks have unique IDs, and the
name is a friendly label/alias, which notably does NOT have any
guarantees around uniqueness (see moby/moby#18864 [^1]).
During day-to-day interactive/CLI Compose usage, this is rarely
an issue, as Compose itself isn't creating networks concurrently
across goroutines. However, if multiple Compose instances are
executed simultaneously (e.g. as part of a test suite that runs
in parallel), this can easily occur.
When it does happen, it's very confusing for users and resolving
it via the `docker` CLI is not straightforward either [^2].
There's two primary changes here:
* Pass `CheckDuplicates: true` to the Docker API when creating
networks to reduce the likelihood of Compose creating duplicates
in the first place
* On `down`, list networks using a name filter and then remove
them all by ID, as the Docker API will return an error if the
name alias is used and maps to more than one network
Hopefully, this provides a better UX, since the issue should be
less likely to occur, and if it does, it can now be resolved via
standard Compose workflow commands.
[^1]: https://github.com/moby/moby/issues/18864
[^2]: https://stackoverflow.com/questions/63776518/error-2-matches-found-based-on-name-network-nameofservice-default-is-ambiguo
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-06-21 16:25:42 -04:00
|
|
|
api.EXPECT().NetworkRemove(gomock.Any(), "abc123").Return(nil)
|
|
|
|
api.EXPECT().NetworkRemove(gomock.Any(), "def456").Return(nil)
|
2021-02-11 11:12:50 +01:00
|
|
|
|
2021-08-18 10:50:43 -03:00
|
|
|
err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{})
|
2021-02-11 11:12:50 +01:00
|
|
|
assert.NilError(t, err)
|
|
|
|
}
|
|
|
|
|
2024-09-26 09:33:42 +03:00
|
|
|
func TestDownWithGivenServices(t *testing.T) {
|
|
|
|
mockCtrl := gomock.NewController(t)
|
|
|
|
defer mockCtrl.Finish()
|
|
|
|
|
|
|
|
api, cli := prepareMocks(mockCtrl)
|
|
|
|
tested := composeService{
|
|
|
|
dockerCli: cli,
|
|
|
|
}
|
|
|
|
|
|
|
|
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
|
2025-02-12 09:34:07 +01:00
|
|
|
[]container.Summary{
|
2024-09-26 09:33:42 +03:00
|
|
|
testContainer("service1", "123", false),
|
|
|
|
testContainer("service2", "456", false),
|
|
|
|
testContainer("service2", "789", false),
|
|
|
|
testContainer("service_orphan", "321", true),
|
|
|
|
}, nil)
|
|
|
|
api.EXPECT().VolumeList(
|
|
|
|
gomock.Any(),
|
|
|
|
volume.ListOptions{
|
|
|
|
Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
|
|
|
|
}).
|
|
|
|
Return(volume.ListResponse{}, nil)
|
|
|
|
|
|
|
|
// network names are not guaranteed to be unique, ensure Compose handles
|
|
|
|
// cleanup properly if duplicates are inadvertently created
|
|
|
|
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
|
|
|
|
Return([]network.Summary{
|
|
|
|
{ID: "abc123", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}},
|
|
|
|
{ID: "def456", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}},
|
|
|
|
}, nil)
|
|
|
|
|
2025-02-12 09:34:07 +01:00
|
|
|
stopOptions := container.StopOptions{}
|
2024-09-26 09:33:42 +03:00
|
|
|
api.EXPECT().ContainerStop(gomock.Any(), "123", stopOptions).Return(nil)
|
|
|
|
|
2025-02-12 09:34:07 +01:00
|
|
|
api.EXPECT().ContainerRemove(gomock.Any(), "123", container.RemoveOptions{Force: true}).Return(nil)
|
2024-09-26 09:33:42 +03:00
|
|
|
|
|
|
|
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{
|
|
|
|
Filters: filters.NewArgs(
|
|
|
|
projectFilter(strings.ToLower(testProject)),
|
|
|
|
networkFilter("default")),
|
|
|
|
}).Return([]network.Summary{
|
|
|
|
{ID: "abc123", Name: "myProject_default"},
|
|
|
|
}, nil)
|
|
|
|
api.EXPECT().NetworkInspect(gomock.Any(), "abc123", gomock.Any()).Return(network.Inspect{ID: "abc123"}, nil)
|
|
|
|
api.EXPECT().NetworkRemove(gomock.Any(), "abc123").Return(nil)
|
|
|
|
|
|
|
|
err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{
|
|
|
|
Services: []string{"service1", "not-running-service"},
|
|
|
|
})
|
|
|
|
assert.NilError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDownWithSpecifiedServiceButTheServicesAreNotRunning(t *testing.T) {
|
|
|
|
mockCtrl := gomock.NewController(t)
|
|
|
|
defer mockCtrl.Finish()
|
|
|
|
|
|
|
|
api, cli := prepareMocks(mockCtrl)
|
|
|
|
tested := composeService{
|
|
|
|
dockerCli: cli,
|
|
|
|
}
|
|
|
|
|
|
|
|
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
|
2025-02-12 09:34:07 +01:00
|
|
|
[]container.Summary{
|
2024-09-26 09:33:42 +03:00
|
|
|
testContainer("service1", "123", false),
|
|
|
|
testContainer("service2", "456", false),
|
|
|
|
testContainer("service2", "789", false),
|
|
|
|
testContainer("service_orphan", "321", true),
|
|
|
|
}, nil)
|
|
|
|
api.EXPECT().VolumeList(
|
|
|
|
gomock.Any(),
|
|
|
|
volume.ListOptions{
|
|
|
|
Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
|
|
|
|
}).
|
|
|
|
Return(volume.ListResponse{}, nil)
|
|
|
|
|
|
|
|
// network names are not guaranteed to be unique, ensure Compose handles
|
|
|
|
// cleanup properly if duplicates are inadvertently created
|
|
|
|
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
|
|
|
|
Return([]network.Summary{
|
|
|
|
{ID: "abc123", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}},
|
|
|
|
{ID: "def456", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}},
|
|
|
|
}, nil)
|
|
|
|
|
|
|
|
err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{
|
|
|
|
Services: []string{"not-running-service1", "not-running-service2"},
|
|
|
|
})
|
|
|
|
assert.NilError(t, err)
|
|
|
|
}
|
|
|
|
|
2021-02-11 11:12:50 +01:00
|
|
|
func TestDownRemoveOrphans(t *testing.T) {
|
|
|
|
mockCtrl := gomock.NewController(t)
|
|
|
|
defer mockCtrl.Finish()
|
2022-03-03 14:19:01 +01:00
|
|
|
|
2023-03-08 15:11:32 +00:00
|
|
|
api, cli := prepareMocks(mockCtrl)
|
2022-09-08 16:26:00 -04:00
|
|
|
tested := composeService{
|
|
|
|
dockerCli: cli,
|
|
|
|
}
|
2021-02-11 11:12:50 +01:00
|
|
|
|
2022-04-11 10:58:20 +02:00
|
|
|
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(true)).Return(
|
2025-02-12 09:34:07 +01:00
|
|
|
[]container.Summary{
|
2021-09-20 08:16:59 +02:00
|
|
|
testContainer("service1", "123", false),
|
|
|
|
testContainer("service2", "789", false),
|
|
|
|
testContainer("service_orphan", "321", true),
|
|
|
|
}, nil)
|
2023-06-06 16:55:54 -04:00
|
|
|
api.EXPECT().VolumeList(
|
|
|
|
gomock.Any(),
|
|
|
|
volume.ListOptions{
|
|
|
|
Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
|
|
|
|
}).
|
2022-10-18 16:57:53 +02:00
|
|
|
Return(volume.ListResponse{}, nil)
|
2024-06-07 17:57:54 +02:00
|
|
|
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
|
|
|
|
Return([]network.Summary{
|
2023-05-31 20:46:23 +02:00
|
|
|
{
|
|
|
|
Name: "myProject_default",
|
|
|
|
Labels: map[string]string{compose.NetworkLabel: "default"},
|
2024-12-10 10:30:37 +01:00
|
|
|
},
|
|
|
|
}, nil)
|
2021-02-11 11:12:50 +01:00
|
|
|
|
2025-02-12 09:34:07 +01:00
|
|
|
stopOptions := container.StopOptions{}
|
2022-10-18 15:21:11 +02:00
|
|
|
api.EXPECT().ContainerStop(gomock.Any(), "123", stopOptions).Return(nil)
|
|
|
|
api.EXPECT().ContainerStop(gomock.Any(), "789", stopOptions).Return(nil)
|
|
|
|
api.EXPECT().ContainerStop(gomock.Any(), "321", stopOptions).Return(nil)
|
2021-02-11 11:12:50 +01:00
|
|
|
|
2025-02-12 09:34:07 +01:00
|
|
|
api.EXPECT().ContainerRemove(gomock.Any(), "123", container.RemoveOptions{Force: true}).Return(nil)
|
|
|
|
api.EXPECT().ContainerRemove(gomock.Any(), "789", container.RemoveOptions{Force: true}).Return(nil)
|
|
|
|
api.EXPECT().ContainerRemove(gomock.Any(), "321", container.RemoveOptions{Force: true}).Return(nil)
|
2021-02-11 11:12:50 +01:00
|
|
|
|
2024-06-07 17:57:54 +02:00
|
|
|
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{
|
2023-05-31 20:46:23 +02:00
|
|
|
Filters: filters.NewArgs(
|
|
|
|
networkFilter("default"),
|
|
|
|
projectFilter(strings.ToLower(testProject)),
|
|
|
|
),
|
2024-06-07 17:57:54 +02:00
|
|
|
}).Return([]network.Summary{{ID: "abc123", Name: "myProject_default"}}, nil)
|
|
|
|
api.EXPECT().NetworkInspect(gomock.Any(), "abc123", gomock.Any()).Return(network.Inspect{ID: "abc123"}, nil)
|
networks: prevent issues due to duplicate names
Within the Docker API/engine, networks have unique IDs, and the
name is a friendly label/alias, which notably does NOT have any
guarantees around uniqueness (see moby/moby#18864 [^1]).
During day-to-day interactive/CLI Compose usage, this is rarely
an issue, as Compose itself isn't creating networks concurrently
across goroutines. However, if multiple Compose instances are
executed simultaneously (e.g. as part of a test suite that runs
in parallel), this can easily occur.
When it does happen, it's very confusing for users and resolving
it via the `docker` CLI is not straightforward either [^2].
There's two primary changes here:
* Pass `CheckDuplicates: true` to the Docker API when creating
networks to reduce the likelihood of Compose creating duplicates
in the first place
* On `down`, list networks using a name filter and then remove
them all by ID, as the Docker API will return an error if the
name alias is used and maps to more than one network
Hopefully, this provides a better UX, since the issue should be
less likely to occur, and if it does, it can now be resolved via
standard Compose workflow commands.
[^1]: https://github.com/moby/moby/issues/18864
[^2]: https://stackoverflow.com/questions/63776518/error-2-matches-found-based-on-name-network-nameofservice-default-is-ambiguo
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-06-21 16:25:42 -04:00
|
|
|
api.EXPECT().NetworkRemove(gomock.Any(), "abc123").Return(nil)
|
2021-02-11 11:12:50 +01:00
|
|
|
|
2021-08-18 10:50:43 -03:00
|
|
|
err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{RemoveOrphans: true})
|
2021-02-11 11:12:50 +01:00
|
|
|
assert.NilError(t, err)
|
|
|
|
}
|
2021-04-29 21:54:54 +02:00
|
|
|
|
|
|
|
func TestDownRemoveVolumes(t *testing.T) {
|
|
|
|
mockCtrl := gomock.NewController(t)
|
|
|
|
defer mockCtrl.Finish()
|
2022-03-03 14:19:01 +01:00
|
|
|
|
2023-03-08 15:11:32 +00:00
|
|
|
api, cli := prepareMocks(mockCtrl)
|
2022-09-08 16:26:00 -04:00
|
|
|
tested := composeService{
|
|
|
|
dockerCli: cli,
|
|
|
|
}
|
2021-04-29 21:54:54 +02:00
|
|
|
|
2022-04-11 10:58:20 +02:00
|
|
|
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
|
2025-02-12 09:34:07 +01:00
|
|
|
[]container.Summary{testContainer("service1", "123", false)}, nil)
|
2023-06-06 16:55:54 -04:00
|
|
|
api.EXPECT().VolumeList(
|
|
|
|
gomock.Any(),
|
|
|
|
volume.ListOptions{
|
|
|
|
Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
|
|
|
|
}).
|
2022-10-18 16:57:53 +02:00
|
|
|
Return(volume.ListResponse{
|
|
|
|
Volumes: []*volume.Volume{{Name: "myProject_volume"}},
|
2022-01-03 09:08:41 +01:00
|
|
|
}, nil)
|
2025-04-08 19:44:26 +02:00
|
|
|
api.EXPECT().VolumeInspect(gomock.Any(), "myProject_volume").
|
|
|
|
Return(volume.Volume{}, nil)
|
2024-06-07 17:57:54 +02:00
|
|
|
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
|
2022-03-14 15:14:03 +01:00
|
|
|
Return(nil, nil)
|
2021-04-29 21:54:54 +02:00
|
|
|
|
2025-02-12 09:34:07 +01:00
|
|
|
api.EXPECT().ContainerStop(gomock.Any(), "123", container.StopOptions{}).Return(nil)
|
|
|
|
api.EXPECT().ContainerRemove(gomock.Any(), "123", container.RemoveOptions{Force: true, RemoveVolumes: true}).Return(nil)
|
2021-04-29 21:54:54 +02:00
|
|
|
|
|
|
|
api.EXPECT().VolumeRemove(gomock.Any(), "myProject_volume", true).Return(nil)
|
|
|
|
|
2021-08-18 10:50:43 -03:00
|
|
|
err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{Volumes: true})
|
2021-04-29 21:54:54 +02:00
|
|
|
assert.NilError(t, err)
|
|
|
|
}
|
2022-08-04 16:01:10 +02:00
|
|
|
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
func TestDownRemoveImages(t *testing.T) {
|
2022-08-04 16:01:10 +02:00
|
|
|
mockCtrl := gomock.NewController(t)
|
|
|
|
defer mockCtrl.Finish()
|
|
|
|
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
opts := compose.DownOptions{
|
|
|
|
Project: &types.Project{
|
|
|
|
Name: strings.ToLower(testProject),
|
|
|
|
Services: types.Services{
|
2023-11-27 10:14:31 +01:00
|
|
|
"local-anonymous": {Name: "local-anonymous"},
|
|
|
|
"local-named": {Name: "local-named", Image: "local-named-image"},
|
|
|
|
"remote": {Name: "remote", Image: "remote-image"},
|
|
|
|
"remote-tagged": {Name: "remote-tagged", Image: "registry.example.com/remote-image-tagged:v1.0"},
|
|
|
|
"no-images-anonymous": {Name: "no-images-anonymous"},
|
|
|
|
"no-images-named": {Name: "no-images-named", Image: "missing-named-image"},
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2023-03-08 15:11:32 +00:00
|
|
|
api, cli := prepareMocks(mockCtrl)
|
2022-09-08 16:26:00 -04:00
|
|
|
tested := composeService{
|
|
|
|
dockerCli: cli,
|
|
|
|
}
|
2022-08-04 16:01:10 +02:00
|
|
|
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).
|
2025-02-12 09:34:07 +01:00
|
|
|
Return([]container.Summary{
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
testContainer("service1", "123", false),
|
|
|
|
}, nil).
|
|
|
|
AnyTimes()
|
|
|
|
|
2024-03-22 11:42:35 +01:00
|
|
|
api.EXPECT().ImageList(gomock.Any(), image.ListOptions{
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
Filters: filters.NewArgs(
|
|
|
|
projectFilter(strings.ToLower(testProject)),
|
|
|
|
filters.Arg("dangling", "false"),
|
|
|
|
),
|
2023-12-05 10:59:26 +01:00
|
|
|
}).Return([]image.Summary{
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
{
|
|
|
|
Labels: types.Labels{compose.ServiceLabel: "local-anonymous"},
|
|
|
|
RepoTags: []string{"testproject-local-anonymous:latest"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Labels: types.Labels{compose.ServiceLabel: "local-named"},
|
|
|
|
RepoTags: []string{"local-named-image:latest"},
|
|
|
|
},
|
|
|
|
}, nil).AnyTimes()
|
|
|
|
|
|
|
|
imagesToBeInspected := map[string]bool{
|
2022-09-13 14:39:51 +01:00
|
|
|
"testproject-local-anonymous": true,
|
|
|
|
"local-named-image": true,
|
|
|
|
"remote-image": true,
|
|
|
|
"testproject-no-images-anonymous": false,
|
|
|
|
"missing-named-image": false,
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
}
|
|
|
|
for img, exists := range imagesToBeInspected {
|
2025-02-12 09:34:07 +01:00
|
|
|
var resp image.InspectResponse
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
var err error
|
|
|
|
if exists {
|
|
|
|
resp.RepoTags = []string{img}
|
|
|
|
} else {
|
|
|
|
err = errdefs.NotFound(fmt.Errorf("test specified that image %q should not exist", img))
|
|
|
|
}
|
|
|
|
|
2025-02-12 09:34:07 +01:00
|
|
|
api.EXPECT().ImageInspect(gomock.Any(), img).
|
|
|
|
Return(resp, err).
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
AnyTimes()
|
|
|
|
}
|
|
|
|
|
2025-02-12 09:34:07 +01:00
|
|
|
api.EXPECT().ImageInspect(gomock.Any(), "registry.example.com/remote-image-tagged:v1.0").
|
|
|
|
Return(image.InspectResponse{RepoTags: []string{"registry.example.com/remote-image-tagged:v1.0"}}, nil).
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
AnyTimes()
|
|
|
|
|
|
|
|
localImagesToBeRemoved := []string{
|
|
|
|
"testproject-local-anonymous:latest",
|
2023-05-11 18:41:14 +02:00
|
|
|
"local-named-image:latest",
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
}
|
|
|
|
for _, img := range localImagesToBeRemoved {
|
|
|
|
// test calls down --rmi=local then down --rmi=all, so local images
|
|
|
|
// get "removed" 2x, while other images are only 1x
|
2024-03-22 11:42:35 +01:00
|
|
|
api.EXPECT().ImageRemove(gomock.Any(), img, image.RemoveOptions{}).
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
Return(nil, nil).
|
|
|
|
Times(2)
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Log("-> docker compose down --rmi=local")
|
|
|
|
opts.Images = "local"
|
|
|
|
err := tested.Down(context.Background(), strings.ToLower(testProject), opts)
|
|
|
|
assert.NilError(t, err)
|
2022-08-04 16:01:10 +02:00
|
|
|
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
otherImagesToBeRemoved := []string{
|
|
|
|
"remote-image:latest",
|
|
|
|
"registry.example.com/remote-image-tagged:v1.0",
|
|
|
|
}
|
|
|
|
for _, img := range otherImagesToBeRemoved {
|
2024-03-22 11:42:35 +01:00
|
|
|
api.EXPECT().ImageRemove(gomock.Any(), img, image.RemoveOptions{}).
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
Return(nil, nil).
|
|
|
|
Times(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Log("-> docker compose down --rmi=all")
|
|
|
|
opts.Images = "all"
|
|
|
|
err = tested.Down(context.Background(), strings.ToLower(testProject), opts)
|
2022-08-04 16:01:10 +02:00
|
|
|
assert.NilError(t, err)
|
|
|
|
}
|
|
|
|
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
func TestDownRemoveImages_NoLabel(t *testing.T) {
|
2022-08-04 16:01:10 +02:00
|
|
|
mockCtrl := gomock.NewController(t)
|
|
|
|
defer mockCtrl.Finish()
|
|
|
|
|
2023-03-08 15:11:32 +00:00
|
|
|
api, cli := prepareMocks(mockCtrl)
|
2022-09-08 16:26:00 -04:00
|
|
|
tested := composeService{
|
|
|
|
dockerCli: cli,
|
|
|
|
}
|
2022-08-04 16:01:10 +02:00
|
|
|
|
2025-02-12 09:34:07 +01:00
|
|
|
ctr := testContainer("service1", "123", false)
|
2022-08-04 16:01:10 +02:00
|
|
|
|
|
|
|
api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
|
2025-02-12 09:34:07 +01:00
|
|
|
[]container.Summary{ctr}, nil)
|
2022-08-04 16:01:10 +02:00
|
|
|
|
2023-06-06 16:55:54 -04:00
|
|
|
api.EXPECT().VolumeList(
|
|
|
|
gomock.Any(),
|
|
|
|
volume.ListOptions{
|
|
|
|
Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
|
|
|
|
}).
|
2022-10-18 16:57:53 +02:00
|
|
|
Return(volume.ListResponse{
|
|
|
|
Volumes: []*volume.Volume{{Name: "myProject_volume"}},
|
2022-08-04 16:01:10 +02:00
|
|
|
}, nil)
|
2024-06-07 17:57:54 +02:00
|
|
|
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
|
2022-08-04 16:01:10 +02:00
|
|
|
Return(nil, nil)
|
|
|
|
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
// ImageList returns no images for the project since they were unlabeled
|
|
|
|
// (created by an older version of Compose)
|
2024-03-22 11:42:35 +01:00
|
|
|
api.EXPECT().ImageList(gomock.Any(), image.ListOptions{
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
Filters: filters.NewArgs(
|
|
|
|
projectFilter(strings.ToLower(testProject)),
|
|
|
|
filters.Arg("dangling", "false"),
|
|
|
|
),
|
|
|
|
}).Return(nil, nil)
|
2022-08-04 16:01:10 +02:00
|
|
|
|
2025-02-12 09:34:07 +01:00
|
|
|
api.EXPECT().ImageInspect(gomock.Any(), "testproject-service1").
|
|
|
|
Return(image.InspectResponse{}, nil)
|
2022-08-04 16:01:10 +02:00
|
|
|
|
2025-02-12 09:34:07 +01:00
|
|
|
api.EXPECT().ContainerStop(gomock.Any(), "123", container.StopOptions{}).Return(nil)
|
|
|
|
api.EXPECT().ContainerRemove(gomock.Any(), "123", container.RemoveOptions{Force: true}).Return(nil)
|
2022-08-04 16:01:10 +02:00
|
|
|
|
2024-03-22 11:42:35 +01:00
|
|
|
api.EXPECT().ImageRemove(gomock.Any(), "testproject-service1:latest", image.RemoveOptions{}).Return(nil, nil)
|
2022-08-04 16:01:10 +02:00
|
|
|
|
build: label built images for reliable cleanup on `down`
When running `compose down`, the `--rmi` flag can be passed,
which currently supports two values:
* `local`: remove any _implicitly-named_ images that Compose
built
* `all` : remove any named images (locally-built or fetched
from a remote repo)
Removing images in the `local` case can be problematic, as it's
historically been done via a fair amount of inference over the
Compose model. Additionally, when using the "project-model"
(by passing `--project-name` instead of using a Compose file),
we're even more limited: if no containers for the project are
running, there's nothing to derive state from to perform the
inference on.
As a first pass, we started labeling _containers_ with the name
of the locally-built image associated with it (if any) in #9715.
Unfortunately, this still suffers from the aforementioned problems
around using actual state (i.e. the containers might no longer
exist) and meant that when operating in file mode (the default),
things did not behave as expected: the label is not available
in the project since it only exists at runtime.
Now, with these changes, Compose will label any images it builds
with project metadata. Upon cleanup during `down`, the engine
image API is queried for related images and matched up with the
services for the project. As a fallback for images built with
prior versions of Compose, the previous approach is still taken.
See also:
* https://github.com/docker/compose/issues/9655
* https://github.com/docker/compose/pull/9715
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-09-07 16:24:47 -04:00
|
|
|
err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{Images: "local"})
|
2022-08-04 16:01:10 +02:00
|
|
|
assert.NilError(t, err)
|
|
|
|
}
|
2023-03-08 15:11:32 +00:00
|
|
|
|
|
|
|
func prepareMocks(mockCtrl *gomock.Controller) (*mocks.MockAPIClient, *mocks.MockCli) {
|
|
|
|
api := mocks.NewMockAPIClient(mockCtrl)
|
|
|
|
cli := mocks.NewMockCli(mockCtrl)
|
|
|
|
cli.EXPECT().Client().Return(api).AnyTimes()
|
2024-06-07 17:57:54 +02:00
|
|
|
cli.EXPECT().Err().Return(streams.NewOut(os.Stderr)).AnyTimes()
|
2023-03-08 15:11:32 +00:00
|
|
|
cli.EXPECT().Out().Return(streams.NewOut(os.Stdout)).AnyTimes()
|
|
|
|
return api, cli
|
|
|
|
}
|