mirror of
https://github.com/docker/compose.git
synced 2026-10-12 02:13:08 +00:00
chore: explicit, unique, greppable names for internal identifiers
Rename-only change, no behavior difference, no exported identifier renamed (only parameter names of a few exported functions, which are not part of the Go API). - names that hide what a value is: parameters holding a *name* or *ID* while named like the object — project→projectName, service→serviceName, container→containerID — so string vs struct is readable at every call site without opening the signature - misleading receivers: monitor methods used c (reads as client/container/CLI) → m; jsonWriter used p while its ttyWriter sibling uses w → w - cryptic abbreviations with non-trivial scope: nw (meant both network.Summary and types.NetworkConfig) → network/networkConfig, svc → service/serviceName/serviceCopy, oc/ocs → observedContainer(s), cnts → serviceContainers, cnx → attachResponse - container.Summary loop variables unified on ctr (was a c/ctr mix); fillBindMounts also dropped its p/s/m single-letters, one of which was shadowed by a loop variable of a different type - option-struct identifiers unified on options (opts remains only for variadic functional options); ambiguous ones get a precise name (bindOptions, networkCreateOptions, projectOptionsFns) Signed-off-by: Nicolas De Loof <[email protected]>
This commit is contained in:
committed by
Guillaume Lours
parent
3ee4b5c793
commit
24059c688c
+7
-7
@@ -134,16 +134,16 @@ func runPs(ctx context.Context, dockerCli command.Cli, backendOptions *BackendOp
|
||||
})
|
||||
|
||||
if opts.Quiet {
|
||||
for _, c := range containers {
|
||||
_, _ = fmt.Fprintln(dockerCli.Out(), c.ID)
|
||||
for _, ctr := range containers {
|
||||
_, _ = fmt.Fprintln(dockerCli.Out(), ctr.ID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if opts.Services {
|
||||
services := []string{}
|
||||
for _, c := range containers {
|
||||
s := c.Service
|
||||
for _, ctr := range containers {
|
||||
s := ctr.Service
|
||||
if !slices.Contains(services, s) {
|
||||
services = append(services, s)
|
||||
}
|
||||
@@ -170,9 +170,9 @@ func runPs(ctx context.Context, dockerCli command.Cli, backendOptions *BackendOp
|
||||
|
||||
func filterByStatus(containers []api.ContainerSummary, statuses []string) []api.ContainerSummary {
|
||||
var filtered []api.ContainerSummary
|
||||
for _, c := range containers {
|
||||
if slices.Contains(statuses, string(c.State)) {
|
||||
filtered = append(filtered, c)
|
||||
for _, ctr := range containers {
|
||||
if slices.Contains(statuses, string(ctr.State)) {
|
||||
filtered = append(filtered, ctr)
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
|
||||
+7
-7
@@ -49,12 +49,12 @@ type jsonMessage struct {
|
||||
Percent int `json:"percent,omitempty"`
|
||||
}
|
||||
|
||||
func (p *jsonWriter) Start(ctx context.Context, operation string) {
|
||||
func (w *jsonWriter) Start(ctx context.Context, operation string) {
|
||||
}
|
||||
|
||||
func (p *jsonWriter) Event(e api.Resource) {
|
||||
func (w *jsonWriter) Event(e api.Resource) {
|
||||
message := &jsonMessage{
|
||||
DryRun: p.dryRun,
|
||||
DryRun: w.dryRun,
|
||||
Tail: false,
|
||||
ID: e.ID,
|
||||
Status: e.StatusText(),
|
||||
@@ -67,15 +67,15 @@ func (p *jsonWriter) Event(e api.Resource) {
|
||||
}
|
||||
marshal, err := json.Marshal(message)
|
||||
if err == nil {
|
||||
_, _ = fmt.Fprintln(p.out, string(marshal))
|
||||
_, _ = fmt.Fprintln(w.out, string(marshal))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *jsonWriter) On(events ...api.Resource) {
|
||||
func (w *jsonWriter) On(events ...api.Resource) {
|
||||
for _, e := range events {
|
||||
p.Event(e)
|
||||
w.Event(e)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *jsonWriter) Done(_ string, _ bool) {
|
||||
func (w *jsonWriter) Done(_ string, _ bool) {
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ func (s *composeService) attach(ctx context.Context, project *types.Project, lis
|
||||
containers.sorted() // This enforces predictable colors assignment
|
||||
|
||||
var names []string
|
||||
for _, c := range containers {
|
||||
names = append(names, getContainerNameWithoutProject(c))
|
||||
for _, ctr := range containers {
|
||||
names = append(names, getContainerNameWithoutProject(ctr))
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintf(s.stdout(), "Attaching to %s\n", strings.Join(names, ", "))
|
||||
@@ -96,8 +96,8 @@ func (s *composeService) doAttachContainer(ctx context.Context, service, id, nam
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *composeService) attachContainerStreams(ctx context.Context, container string, tty bool, stdout, stderr io.WriteCloser) error {
|
||||
streamOut, err := s.getContainerStreams(ctx, container)
|
||||
func (s *composeService) attachContainerStreams(ctx context.Context, containerID string, tty bool, stdout, stderr io.WriteCloser) error {
|
||||
streamOut, err := s.getContainerStreams(ctx, containerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -123,15 +123,15 @@ func (s *composeService) attachContainerStreams(ctx context.Context, container s
|
||||
_, err = stdcopy.StdCopy(stdout, stderr, streamOut)
|
||||
}
|
||||
if err != nil && !errors.Is(err, io.EOF) {
|
||||
logrus.Debugf("stream copy error for container %s: %v", container, err)
|
||||
logrus.Debugf("stream copy error for container %s: %v", containerID, err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *composeService) getContainerStreams(ctx context.Context, container string) (io.ReadCloser, error) {
|
||||
cnx, err := s.apiClient().ContainerAttach(ctx, container, client.ContainerAttachOptions{
|
||||
func (s *composeService) getContainerStreams(ctx context.Context, containerID string) (io.ReadCloser, error) {
|
||||
attachResponse, err := s.apiClient().ContainerAttach(ctx, containerID, client.ContainerAttachOptions{
|
||||
Stream: true,
|
||||
Stdin: false,
|
||||
Stdout: true,
|
||||
@@ -139,12 +139,12 @@ func (s *composeService) getContainerStreams(ctx context.Context, container stri
|
||||
Logs: false,
|
||||
})
|
||||
if err == nil {
|
||||
stdout := ContainerStdout{HijackedResponse: cnx.HijackedResponse}
|
||||
stdout := ContainerStdout{HijackedResponse: attachResponse.HijackedResponse}
|
||||
return stdout, nil
|
||||
}
|
||||
|
||||
// Fallback to logs API
|
||||
logs, err := s.apiClient().ContainerLogs(ctx, container, client.ContainerLogsOptions{
|
||||
logs, err := s.apiClient().ContainerLogs(ctx, containerID, client.ContainerLogsOptions{
|
||||
ShowStdout: true,
|
||||
ShowStderr: true,
|
||||
Follow: true,
|
||||
|
||||
@@ -285,10 +285,10 @@ func (s *composeService) getLocalImagesDigests(ctx context.Context, project *typ
|
||||
//
|
||||
// Finally, standard proxy variables based on the Docker client configuration are added, but will not overwrite
|
||||
// any values if already present.
|
||||
func resolveAndMergeBuildArgs(proxyConfig map[string]string, project *types.Project, service types.ServiceConfig, opts api.BuildOptions) types.MappingWithEquals {
|
||||
func resolveAndMergeBuildArgs(proxyConfig map[string]string, project *types.Project, service types.ServiceConfig, options api.BuildOptions) types.MappingWithEquals {
|
||||
result := make(types.MappingWithEquals).
|
||||
OverrideBy(service.Build.Args).
|
||||
OverrideBy(opts.Args).
|
||||
OverrideBy(options.Args).
|
||||
Resolve(envResolver(project.Environment))
|
||||
|
||||
// proxy arguments do NOT override and should NOT have env resolution applied,
|
||||
|
||||
@@ -51,12 +51,12 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
|
||||
// Not using bake, additional_context: service:xx is implemented by building images in dependency order
|
||||
project, err := project.WithServicesTransform(func(serviceName string, service types.ServiceConfig) (types.ServiceConfig, error) {
|
||||
if service.Build != nil {
|
||||
for _, c := range service.Build.AdditionalContexts {
|
||||
if t, found := strings.CutPrefix(c, types.ServicePrefix); found {
|
||||
for _, additionalContext := range service.Build.AdditionalContexts {
|
||||
if targetService, found := strings.CutPrefix(additionalContext, types.ServicePrefix); found {
|
||||
if service.DependsOn == nil {
|
||||
service.DependsOn = map[string]types.ServiceDependency{}
|
||||
}
|
||||
service.DependsOn[t] = types.ServiceDependency{
|
||||
service.DependsOn[targetService] = types.ServiceDependency{
|
||||
Condition: "build", // non-canonical, but will force dependency graph ordering
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,17 +365,17 @@ func (s *composeService) projectFromName(containers Containers, projectName stri
|
||||
return project, fmt.Errorf("no container found for project %q: %w", projectName, api.ErrNotFound)
|
||||
}
|
||||
set := types.Services{}
|
||||
for _, c := range containers {
|
||||
serviceLabel, ok := c.Labels[api.ServiceLabel]
|
||||
for _, ctr := range containers {
|
||||
serviceLabel, ok := ctr.Labels[api.ServiceLabel]
|
||||
if !ok {
|
||||
serviceLabel = getCanonicalContainerName(c)
|
||||
serviceLabel = getCanonicalContainerName(ctr)
|
||||
}
|
||||
service, ok := set[serviceLabel]
|
||||
if !ok {
|
||||
service = types.ServiceConfig{
|
||||
Name: serviceLabel,
|
||||
Image: c.Image,
|
||||
Labels: c.Labels,
|
||||
Image: ctr.Image,
|
||||
Labels: ctr.Labels,
|
||||
}
|
||||
}
|
||||
service.Scale = increment(service.Scale)
|
||||
@@ -433,10 +433,10 @@ func increment(scale *int) *int {
|
||||
}
|
||||
|
||||
func (s *composeService) actualVolumes(ctx context.Context, projectName string) (types.Volumes, error) {
|
||||
opts := client.VolumeListOptions{
|
||||
options := client.VolumeListOptions{
|
||||
Filters: projectFilter(projectName),
|
||||
}
|
||||
volumes, err := s.apiClient().VolumeList(ctx, opts)
|
||||
volumes, err := s.apiClient().VolumeList(ctx, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -42,9 +42,9 @@ const (
|
||||
oneOffOnly
|
||||
)
|
||||
|
||||
func (s *composeService) getContainers(ctx context.Context, project string, oneOff oneOff, all bool, selectedServices ...string) (Containers, error) {
|
||||
func (s *composeService) getContainers(ctx context.Context, projectName string, oneOff oneOff, all bool, selectedServices ...string) (Containers, error) {
|
||||
res, err := s.apiClient().ContainerList(ctx, client.ContainerListOptions{
|
||||
Filters: getDefaultFilters(project, oneOff, selectedServices...),
|
||||
Filters: getDefaultFilters(projectName, oneOff, selectedServices...),
|
||||
All: all,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -64,9 +64,9 @@ func (s *composeService) getContainersByService(ctx context.Context, projectName
|
||||
return nil, err
|
||||
}
|
||||
result := map[string]Containers{}
|
||||
for _, c := range all.filter(isNotOneOff) {
|
||||
svc := c.Labels[api.ServiceLabel]
|
||||
result[svc] = append(result[svc], c)
|
||||
for _, ctr := range all.filter(isNotOneOff) {
|
||||
serviceName := ctr.Labels[api.ServiceLabel]
|
||||
result[serviceName] = append(result[serviceName], ctr)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
@@ -169,9 +169,9 @@ func isNotRunning(c container.Summary) bool {
|
||||
// filter return Containers with elements to match predicate
|
||||
func (containers Containers) filter(predicates ...containerPredicate) Containers {
|
||||
var filtered Containers
|
||||
for _, c := range containers {
|
||||
if matches(c, predicates...) {
|
||||
filtered = append(filtered, c)
|
||||
for _, ctr := range containers {
|
||||
if matches(ctr, predicates...) {
|
||||
filtered = append(filtered, ctr)
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
|
||||
+19
-19
@@ -312,14 +312,14 @@ func shouldWaitForDependency(serviceName string, dependencyConfig types.ServiceD
|
||||
|
||||
func nextContainerNumber(containers []container.Summary) int {
|
||||
maxNumber := 0
|
||||
for _, c := range containers {
|
||||
s, ok := c.Labels[api.ContainerNumberLabel]
|
||||
for _, ctr := range containers {
|
||||
s, ok := ctr.Labels[api.ContainerNumberLabel]
|
||||
if !ok {
|
||||
logrus.Warnf("container %s is missing %s label", c.ID, api.ContainerNumberLabel)
|
||||
logrus.Warnf("container %s is missing %s label", ctr.ID, api.ContainerNumberLabel)
|
||||
}
|
||||
n, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
logrus.Warnf("container %s has invalid %s label: %s", c.ID, api.ContainerNumberLabel, s)
|
||||
logrus.Warnf("container %s has invalid %s label: %s", ctr.ID, api.ContainerNumberLabel, s)
|
||||
continue
|
||||
}
|
||||
if n > maxNumber {
|
||||
@@ -330,11 +330,11 @@ func nextContainerNumber(containers []container.Summary) int {
|
||||
}
|
||||
|
||||
func (s *composeService) createContainer(ctx context.Context, project *types.Project, service types.ServiceConfig,
|
||||
name string, number int, opts createOptions,
|
||||
name string, number int, options createOptions,
|
||||
) (ctr container.Summary, err error) {
|
||||
eventName := "Container " + name
|
||||
s.events.On(creatingEvent(eventName))
|
||||
ctr, err = s.createMobyContainer(ctx, project, service, name, number, nil, opts)
|
||||
ctr, err = s.createMobyContainer(ctx, project, service, name, number, nil, options)
|
||||
if err != nil {
|
||||
if ctx.Err() == nil {
|
||||
s.events.On(api.Resource{
|
||||
@@ -353,10 +353,10 @@ func (s *composeService) createContainer(ctx context.Context, project *types.Pro
|
||||
var startMx sync.Mutex
|
||||
|
||||
func (s *composeService) createMobyContainer(ctx context.Context, project *types.Project, service types.ServiceConfig,
|
||||
name string, number int, inherit *container.Summary, opts createOptions,
|
||||
name string, number int, inherit *container.Summary, options createOptions,
|
||||
) (container.Summary, error) {
|
||||
var created container.Summary
|
||||
cfgs, err := s.getCreateConfigs(ctx, project, service, number, inherit, opts)
|
||||
cfgs, err := s.getCreateConfigs(ctx, project, service, number, inherit, options)
|
||||
if err != nil {
|
||||
return created, err
|
||||
}
|
||||
@@ -407,7 +407,7 @@ func (s *composeService) createMobyContainer(ctx context.Context, project *types
|
||||
// primary network already configured as part of ContainerCreate
|
||||
continue
|
||||
}
|
||||
epSettings, err := createEndpointSettings(project, service, number, networkKey, cfgs.Links, opts.UseNetworkAliases)
|
||||
epSettings, err := createEndpointSettings(project, service, number, networkKey, cfgs.Links, options.UseNetworkAliases)
|
||||
if err != nil {
|
||||
_, _ = s.apiClient().ContainerRemove(ctx, response.ID, client.ContainerRemoveOptions{Force: true})
|
||||
return created, err
|
||||
@@ -454,12 +454,12 @@ func (s *composeService) getLinks(ctx context.Context, projectName string, servi
|
||||
if !ok {
|
||||
linkName = linkServiceName
|
||||
}
|
||||
cnts, err := getServiceContainers(linkServiceName)
|
||||
serviceContainers, err := getServiceContainers(linkServiceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range cnts {
|
||||
containerName := getCanonicalContainerName(c)
|
||||
for _, ctr := range serviceContainers {
|
||||
containerName := getCanonicalContainerName(ctr)
|
||||
links = append(links,
|
||||
format(containerName, linkName),
|
||||
format(containerName, linkServiceName+api.Separator+strconv.Itoa(number)),
|
||||
@@ -469,12 +469,12 @@ func (s *composeService) getLinks(ctx context.Context, projectName string, servi
|
||||
}
|
||||
|
||||
if service.Labels[api.OneoffLabel] == "True" {
|
||||
cnts, err := getServiceContainers(service.Name)
|
||||
serviceContainers, err := getServiceContainers(service.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range cnts {
|
||||
containerName := getCanonicalContainerName(c)
|
||||
for _, ctr := range serviceContainers {
|
||||
containerName := getCanonicalContainerName(ctr)
|
||||
links = append(links,
|
||||
format(containerName, service.Name),
|
||||
format(containerName, strings.TrimPrefix(containerName, projectName+api.Separator)),
|
||||
@@ -494,8 +494,8 @@ func (s *composeService) getLinks(ctx context.Context, projectName string, servi
|
||||
}
|
||||
|
||||
func (s *composeService) isServiceHealthy(ctx context.Context, containers Containers, fallbackRunning bool) (bool, error) {
|
||||
for _, c := range containers {
|
||||
res, err := s.apiClient().ContainerInspect(ctx, c.ID, client.ContainerInspectOptions{})
|
||||
for _, ctr := range containers {
|
||||
res, err := s.apiClient().ContainerInspect(ctx, ctr.ID, client.ContainerInspectOptions{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -530,8 +530,8 @@ func (s *composeService) isServiceHealthy(ctx context.Context, containers Contai
|
||||
}
|
||||
|
||||
func (s *composeService) isServiceCompleted(ctx context.Context, containers Containers) (bool, int, error) {
|
||||
for _, c := range containers {
|
||||
res, err := s.apiClient().ContainerInspect(ctx, c.ID, client.ContainerInspectOptions{})
|
||||
for _, ctr := range containers {
|
||||
res, err := s.apiClient().ContainerInspect(ctx, ctr.ID, client.ContainerInspectOptions{})
|
||||
if err != nil {
|
||||
return false, 0, err
|
||||
}
|
||||
|
||||
+6
-6
@@ -55,7 +55,7 @@ func (s *composeService) copy(ctx context.Context, projectName string, options a
|
||||
|
||||
var direction copyDirection
|
||||
var serviceName string
|
||||
var copyFunc func(ctx context.Context, containerID string, srcPath string, dstPath string, opts api.CopyOptions) error
|
||||
var copyFunc func(ctx context.Context, containerID string, srcPath string, dstPath string, options api.CopyOptions) error
|
||||
if srcService != "" {
|
||||
direction |= fromService
|
||||
serviceName = srcService
|
||||
@@ -142,7 +142,7 @@ func (s *composeService) listContainersTargetedForCopy(ctx context.Context, proj
|
||||
}
|
||||
}
|
||||
|
||||
func (s *composeService) copyToContainer(ctx context.Context, containerID string, srcPath string, dstPath string, opts api.CopyOptions) error {
|
||||
func (s *composeService) copyToContainer(ctx context.Context, containerID string, srcPath string, dstPath string, options api.CopyOptions) error {
|
||||
var err error
|
||||
if srcPath != "-" {
|
||||
// Get an absolute source path.
|
||||
@@ -208,7 +208,7 @@ func (s *composeService) copyToContainer(ctx context.Context, containerID string
|
||||
}
|
||||
} else {
|
||||
// Prepare source copy info.
|
||||
srcInfo, err := archive.CopyInfoSourcePath(srcPath, opts.FollowLink)
|
||||
srcInfo, err := archive.CopyInfoSourcePath(srcPath, options.FollowLink)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -248,12 +248,12 @@ func (s *composeService) copyToContainer(ctx context.Context, containerID string
|
||||
DestinationPath: resolvedDstPath,
|
||||
Content: content,
|
||||
AllowOverwriteDirWithFile: false,
|
||||
CopyUIDGID: opts.CopyUIDGID,
|
||||
CopyUIDGID: options.CopyUIDGID,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *composeService) copyFromContainer(ctx context.Context, containerID, srcPath, dstPath string, opts api.CopyOptions) error {
|
||||
func (s *composeService) copyFromContainer(ctx context.Context, containerID, srcPath, dstPath string, options api.CopyOptions) error {
|
||||
var err error
|
||||
if dstPath != "-" {
|
||||
// Get an absolute destination path.
|
||||
@@ -269,7 +269,7 @@ func (s *composeService) copyFromContainer(ctx context.Context, containerID, src
|
||||
|
||||
// if client requests to follow symbol link, then must decide target file to be copied
|
||||
var rebaseName string
|
||||
if opts.FollowLink {
|
||||
if options.FollowLink {
|
||||
var srcStat container.PathStat
|
||||
res, err := s.apiClient().ContainerStatPath(ctx, containerID, client.ContainerStatPathOptions{
|
||||
Path: srcPath,
|
||||
|
||||
+42
-42
@@ -59,9 +59,9 @@ type createConfigs struct {
|
||||
Links []string
|
||||
}
|
||||
|
||||
func (s *composeService) Create(ctx context.Context, project *types.Project, createOpts api.CreateOptions) error {
|
||||
func (s *composeService) Create(ctx context.Context, project *types.Project, options api.CreateOptions) error {
|
||||
return Run(ctx, func(ctx context.Context) error {
|
||||
return s.create(ctx, project, createOpts)
|
||||
return s.create(ctx, project, options)
|
||||
}, "create", s.events)
|
||||
}
|
||||
|
||||
@@ -132,12 +132,12 @@ func (s *composeService) create(ctx context.Context, project *types.Project, opt
|
||||
}
|
||||
|
||||
func prepareNetworks(project *types.Project) {
|
||||
for k, nw := range project.Networks {
|
||||
nw.CustomLabels = nw.CustomLabels.
|
||||
for k, networkConfig := range project.Networks {
|
||||
networkConfig.CustomLabels = networkConfig.CustomLabels.
|
||||
Add(api.NetworkLabel, k).
|
||||
Add(api.ProjectLabel, project.Name).
|
||||
Add(api.VersionLabel, api.ComposeVersion)
|
||||
project.Networks[k] = nw
|
||||
project.Networks[k] = networkConfig
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,11 +151,11 @@ func prepareNetworks(project *types.Project) {
|
||||
// this function performs no mutation on them.
|
||||
func (s *composeService) checkExternalNetworks(ctx context.Context, project *types.Project) (map[string]string, error) {
|
||||
external := map[string]string{}
|
||||
for k, nw := range project.Networks {
|
||||
if !nw.External {
|
||||
for k, networkConfig := range project.Networks {
|
||||
if !networkConfig.External {
|
||||
continue
|
||||
}
|
||||
id, err := s.resolveExternalNetwork(ctx, &nw)
|
||||
id, err := s.resolveExternalNetwork(ctx, &networkConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -170,20 +170,20 @@ func (s *composeService) checkExternalNetworks(ctx context.Context, project *typ
|
||||
// (see discoverUnmanagedNetworks); the warning tells the user to set
|
||||
// `external: true` to make the intent explicit.
|
||||
func warnUnmanagedNetworks(project *types.Project, observed *ObservedState) {
|
||||
for k, nw := range project.Networks {
|
||||
if nw.External {
|
||||
for k, networkConfig := range project.Networks {
|
||||
if networkConfig.External {
|
||||
continue
|
||||
}
|
||||
obs, _, ok := observed.selectNetwork(k, nw.Name)
|
||||
obs, _, ok := observed.selectNetwork(k, networkConfig.Name)
|
||||
if !ok || obs.ProjectName == project.Name {
|
||||
continue
|
||||
}
|
||||
if obs.ProjectName == "" {
|
||||
logrus.Warnf("a network with name %s exists but was not created by compose.\n"+
|
||||
"Set `external: true` to use an existing network", nw.Name)
|
||||
"Set `external: true` to use an existing network", networkConfig.Name)
|
||||
} else {
|
||||
logrus.Warnf("a network with name %s exists but was not created for project %q.\n"+
|
||||
"Set `external: true` to use an existing network", nw.Name, project.Name)
|
||||
"Set `external: true` to use an existing network", networkConfig.Name, project.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,9 +254,9 @@ func (s *composeService) getCreateConfigs(ctx context.Context,
|
||||
service types.ServiceConfig,
|
||||
number int,
|
||||
inherit *container.Summary,
|
||||
opts createOptions,
|
||||
options createOptions,
|
||||
) (createConfigs, error) {
|
||||
labels := opts.Labels
|
||||
labels := options.Labels
|
||||
hash, err := ServiceHash(service)
|
||||
if err != nil {
|
||||
return createConfigs{}, err
|
||||
@@ -316,8 +316,8 @@ func (s *composeService) getCreateConfigs(ctx context.Context,
|
||||
ExposedPorts: exposedPorts,
|
||||
Tty: tty,
|
||||
OpenStdin: stdinOpen,
|
||||
StdinOnce: opts.AttachStdin && stdinOpen,
|
||||
AttachStdin: opts.AttachStdin,
|
||||
StdinOnce: options.AttachStdin && stdinOpen,
|
||||
AttachStdin: options.AttachStdin,
|
||||
AttachStderr: true,
|
||||
AttachStdout: true,
|
||||
Cmd: runCmd,
|
||||
@@ -350,7 +350,7 @@ func (s *composeService) getCreateConfigs(ctx context.Context,
|
||||
if err != nil {
|
||||
return createConfigs{}, err
|
||||
}
|
||||
networkMode, networkingConfig, err := defaultNetworkSettings(p, service, number, links, opts.UseNetworkAliases, apiVersion)
|
||||
networkMode, networkingConfig, err := defaultNetworkSettings(p, service, number, links, options.UseNetworkAliases, apiVersion)
|
||||
if err != nil {
|
||||
return createConfigs{}, err
|
||||
}
|
||||
@@ -383,7 +383,7 @@ func (s *composeService) getCreateConfigs(ctx context.Context,
|
||||
}
|
||||
|
||||
hostConfig := container.HostConfig{
|
||||
AutoRemove: opts.AutoRemove,
|
||||
AutoRemove: options.AutoRemove,
|
||||
Annotations: service.Annotations,
|
||||
Binds: binds,
|
||||
Mounts: mounts,
|
||||
@@ -1163,37 +1163,37 @@ func (s *composeService) buildContainerMountOptions(ctx context.Context, p types
|
||||
return values, nil
|
||||
}
|
||||
|
||||
func fillBindMounts(p types.Project, s types.ServiceConfig, m map[string]mount.Mount) (map[string]mount.Mount, error) {
|
||||
for _, v := range s.Volumes {
|
||||
bindMount, err := buildMount(p, v)
|
||||
func fillBindMounts(project types.Project, service types.ServiceConfig, mounts map[string]mount.Mount) (map[string]mount.Mount, error) {
|
||||
for _, volume := range service.Volumes {
|
||||
bindMount, err := buildMount(project, volume)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m[bindMount.Target] = bindMount
|
||||
mounts[bindMount.Target] = bindMount
|
||||
}
|
||||
|
||||
secrets, err := buildContainerSecretMounts(p, s)
|
||||
secretMounts, err := buildContainerSecretMounts(project, service)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, s := range secrets {
|
||||
if _, found := m[s.Target]; found {
|
||||
for _, secretMount := range secretMounts {
|
||||
if _, found := mounts[secretMount.Target]; found {
|
||||
continue
|
||||
}
|
||||
m[s.Target] = s
|
||||
mounts[secretMount.Target] = secretMount
|
||||
}
|
||||
|
||||
configs, err := buildContainerConfigMounts(p, s)
|
||||
configMounts, err := buildContainerConfigMounts(project, service)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range configs {
|
||||
if _, found := m[c.Target]; found {
|
||||
for _, configMount := range configMounts {
|
||||
if _, found := mounts[configMount.Target]; found {
|
||||
continue
|
||||
}
|
||||
m[c.Target] = c
|
||||
mounts[configMount.Target] = configMount
|
||||
}
|
||||
return m, nil
|
||||
return mounts, nil
|
||||
}
|
||||
|
||||
func buildContainerConfigMounts(p types.Project, s types.ServiceConfig) ([]mount.Mount, error) {
|
||||
@@ -1403,19 +1403,19 @@ func buildBindOption(bind *types.ServiceVolumeBind) *mount.BindOptions {
|
||||
if bind == nil {
|
||||
return nil
|
||||
}
|
||||
opts := &mount.BindOptions{
|
||||
bindOptions := &mount.BindOptions{
|
||||
Propagation: mount.Propagation(bind.Propagation),
|
||||
CreateMountpoint: bool(bind.CreateHostPath),
|
||||
}
|
||||
switch bind.Recursive {
|
||||
case "disabled":
|
||||
opts.NonRecursive = true
|
||||
bindOptions.NonRecursive = true
|
||||
case "writable":
|
||||
opts.ReadOnlyNonRecursive = true
|
||||
bindOptions.ReadOnlyNonRecursive = true
|
||||
case "readonly":
|
||||
opts.ReadOnlyForceRecursive = true
|
||||
bindOptions.ReadOnlyForceRecursive = true
|
||||
}
|
||||
return opts
|
||||
return bindOptions
|
||||
}
|
||||
|
||||
// createNetwork creates the given (managed) network with its compose labels and
|
||||
@@ -1443,7 +1443,7 @@ func (s *composeService) createNetwork(ctx context.Context, n *types.NetworkConf
|
||||
return err
|
||||
}
|
||||
n.CustomLabels = n.CustomLabels.Add(api.ConfigHashLabel, hash)
|
||||
createOpts := client.NetworkCreateOptions{
|
||||
networkCreateOptions := client.NetworkCreateOptions{
|
||||
Labels: mergeLabels(n.Labels, n.CustomLabels),
|
||||
Driver: n.Driver,
|
||||
Options: n.DriverOpts,
|
||||
@@ -1455,11 +1455,11 @@ func (s *composeService) createNetwork(ctx context.Context, n *types.NetworkConf
|
||||
}
|
||||
|
||||
if n.Ipam.Driver != "" || len(n.Ipam.Config) > 0 {
|
||||
createOpts.IPAM = &network.IPAM{}
|
||||
networkCreateOptions.IPAM = &network.IPAM{}
|
||||
}
|
||||
|
||||
if n.Ipam.Driver != "" {
|
||||
createOpts.IPAM.Driver = n.Ipam.Driver
|
||||
networkCreateOptions.IPAM.Driver = n.Ipam.Driver
|
||||
}
|
||||
|
||||
for _, ipamConfig := range n.Ipam.Config {
|
||||
@@ -1467,13 +1467,13 @@ func (s *composeService) createNetwork(ctx context.Context, n *types.NetworkConf
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
createOpts.IPAM.Config = append(createOpts.IPAM.Config, c)
|
||||
networkCreateOptions.IPAM.Config = append(networkCreateOptions.IPAM.Config, c)
|
||||
}
|
||||
|
||||
networkEventName := fmt.Sprintf("Network %s", n.Name)
|
||||
s.events.On(creatingEvent(networkEventName))
|
||||
|
||||
if _, err := s.apiClient().NetworkCreate(ctx, n.Name, createOpts); err != nil {
|
||||
if _, err := s.apiClient().NetworkCreate(ctx, n.Name, networkCreateOptions); err != nil {
|
||||
// A concurrent `docker compose up|run` may have created the same network
|
||||
// between the observed-state snapshot and now. Treat the resulting
|
||||
// conflict as success rather than failing hard, mirroring the retry the
|
||||
|
||||
@@ -286,10 +286,10 @@ func NewGraph(project *types.Project, initialStatus ServiceStatus) (*Graph, erro
|
||||
}
|
||||
|
||||
// NewVertex is the constructor function for the Vertex
|
||||
func NewVertex(key string, service string, initialStatus ServiceStatus) *Vertex {
|
||||
func NewVertex(key string, serviceName string, initialStatus ServiceStatus) *Vertex {
|
||||
return &Vertex{
|
||||
Key: key,
|
||||
Service: service,
|
||||
Service: serviceName,
|
||||
Status: initialStatus,
|
||||
Parents: map[string]*Vertex{},
|
||||
Children: map[string]*Vertex{},
|
||||
@@ -297,11 +297,11 @@ func NewVertex(key string, service string, initialStatus ServiceStatus) *Vertex
|
||||
}
|
||||
|
||||
// AddVertex adds a vertex to the Graph
|
||||
func (g *Graph) AddVertex(key string, service string, initialStatus ServiceStatus) {
|
||||
func (g *Graph) AddVertex(key string, serviceName string, initialStatus ServiceStatus) {
|
||||
g.lock.Lock()
|
||||
defer g.lock.Unlock()
|
||||
|
||||
v := NewVertex(key, service, initialStatus)
|
||||
v := NewVertex(key, serviceName, initialStatus)
|
||||
g.Vertices[key] = v
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -216,8 +216,8 @@ func (s *composeService) removeNetwork(ctx context.Context, composeNetworkName s
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nw := nwInspect.Network
|
||||
if len(nw.Containers) > 0 {
|
||||
inspectedNetwork := nwInspect.Network
|
||||
if len(inspectedNetwork.Containers) > 0 {
|
||||
s.events.On(newEvent(eventName, api.Warning, "Resource is still in use"))
|
||||
found++
|
||||
continue
|
||||
|
||||
@@ -103,13 +103,13 @@ func (exec *planExecutor) execCreateContainer(ctx context.Context, node *PlanNod
|
||||
labels = labels.Add(api.ContainerReplaceLabel, replacedName)
|
||||
}
|
||||
|
||||
opts := createOptions{
|
||||
options := createOptions{
|
||||
AutoRemove: false,
|
||||
AttachStdin: false,
|
||||
UseNetworkAliases: true,
|
||||
Labels: labels,
|
||||
}
|
||||
ctr, err := exec.compose.createMobyContainer(ctx, exec.project, service, op.Name, op.Number, op.Inherited, opts)
|
||||
ctr, err := exec.compose.createMobyContainer(ctx, exec.project, service, op.Name, op.Number, op.Inherited, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -76,23 +76,23 @@ func (s *composeService) createProjectFromContainers(containers []container.Summ
|
||||
project.Name = projectName
|
||||
}
|
||||
|
||||
for _, c := range containers {
|
||||
for _, ctr := range containers {
|
||||
// if the container is from a previous Compose application, use the existing service name
|
||||
serviceLabel, ok := c.Labels[api.ServiceLabel]
|
||||
serviceLabel, ok := ctr.Labels[api.ServiceLabel]
|
||||
if !ok {
|
||||
serviceLabel = getCanonicalContainerName(c)
|
||||
serviceLabel = getCanonicalContainerName(ctr)
|
||||
}
|
||||
service, ok := services[serviceLabel]
|
||||
if !ok {
|
||||
service = types.ServiceConfig{
|
||||
Name: serviceLabel,
|
||||
Image: c.Image,
|
||||
Labels: c.Labels,
|
||||
Image: ctr.Image,
|
||||
Labels: ctr.Labels,
|
||||
}
|
||||
}
|
||||
service.Scale = increment(service.Scale)
|
||||
|
||||
inspect, err := s.apiClient().ContainerInspect(context.Background(), c.ID, client.ContainerInspectOptions{})
|
||||
inspect, err := s.apiClient().ContainerInspect(context.Background(), ctr.ID, client.ContainerInspectOptions{})
|
||||
if err != nil {
|
||||
services[serviceLabel] = service
|
||||
continue
|
||||
|
||||
@@ -52,9 +52,9 @@ func (s *composeService) Images(ctx context.Context, projectName string, options
|
||||
var containers []container.Summary
|
||||
if len(options.Services) > 0 {
|
||||
// filter service containers
|
||||
for _, c := range allContainers.Items {
|
||||
if slices.Contains(options.Services, c.Labels[api.ServiceLabel]) {
|
||||
containers = append(containers, c)
|
||||
for _, ctr := range allContainers.Items {
|
||||
if slices.Contains(options.Services, ctr.Labels[api.ServiceLabel]) {
|
||||
containers = append(containers, ctr)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -72,15 +72,15 @@ func (s *composeService) Images(ctx context.Context, projectName string, options
|
||||
summary := map[string]api.ImageSummary{}
|
||||
var mux sync.Mutex
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
for _, c := range containers {
|
||||
for _, ctr := range containers {
|
||||
eg.Go(func() error {
|
||||
img, err := s.containerImageSummary(ctx, c, withPlatform)
|
||||
img, err := s.containerImageSummary(ctx, ctr, withPlatform)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mux.Lock()
|
||||
defer mux.Unlock()
|
||||
summary[getCanonicalContainerName(c)] = img
|
||||
summary[getCanonicalContainerName(ctr)] = img
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ func (s *composeService) createRemoteLoaders(options api.ProjectLoadOptions) []l
|
||||
|
||||
// buildProjectOptions constructs compose-go ProjectOptions from API options
|
||||
func (s *composeService) buildProjectOptions(options api.ProjectLoadOptions, remoteLoaders []loader.ResourceLoader) (*cli.ProjectOptions, error) {
|
||||
opts := []cli.ProjectOptionsFn{
|
||||
projectOptionsFns := []cli.ProjectOptionsFn{
|
||||
cli.WithWorkingDirectory(options.WorkingDir),
|
||||
cli.WithOsEnv,
|
||||
}
|
||||
@@ -87,16 +87,16 @@ func (s *composeService) buildProjectOptions(options api.ProjectLoadOptions, rem
|
||||
// Add PWD if not present
|
||||
if _, present := os.LookupEnv("PWD"); !present {
|
||||
if pwd, err := os.Getwd(); err == nil {
|
||||
opts = append(opts, cli.WithEnv([]string{"PWD=" + pwd}))
|
||||
projectOptionsFns = append(projectOptionsFns, cli.WithEnv([]string{"PWD=" + pwd}))
|
||||
}
|
||||
}
|
||||
|
||||
// Add remote loaders
|
||||
for _, r := range remoteLoaders {
|
||||
opts = append(opts, cli.WithResourceLoader(r))
|
||||
projectOptionsFns = append(projectOptionsFns, cli.WithResourceLoader(r))
|
||||
}
|
||||
|
||||
opts = append(opts,
|
||||
projectOptionsFns = append(projectOptionsFns,
|
||||
// Load PWD/.env if present and no explicit --env-file has been set
|
||||
cli.WithEnvFiles(options.EnvFiles...),
|
||||
// read dot env file to populate project environment
|
||||
@@ -113,7 +113,7 @@ func (s *composeService) buildProjectOptions(options api.ProjectLoadOptions, rem
|
||||
cli.WithName(options.ProjectName),
|
||||
)
|
||||
|
||||
return cli.NewProjectOptions(options.ConfigPaths, append(options.ProjectOptionsFns, opts...)...)
|
||||
return cli.NewProjectOptions(options.ConfigPaths, append(options.ProjectOptionsFns, projectOptionsFns...)...)
|
||||
}
|
||||
|
||||
// postProcessProject applies post-loading transformations to the project
|
||||
|
||||
+11
-11
@@ -30,10 +30,10 @@ import (
|
||||
"github.com/docker/compose/v5/pkg/api"
|
||||
)
|
||||
|
||||
func (s *composeService) List(ctx context.Context, opts api.ListOptions) ([]api.Stack, error) {
|
||||
func (s *composeService) List(ctx context.Context, options api.ListOptions) ([]api.Stack, error) {
|
||||
list, err := s.apiClient().ContainerList(ctx, client.ContainerListOptions{
|
||||
Filters: make(client.Filters).Add("label", api.ProjectLabel).Add("label", api.ConfigHashLabel),
|
||||
All: opts.All,
|
||||
All: options.All,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -68,10 +68,10 @@ func containersToStacks(containers []container.Summary) ([]api.Stack, error) {
|
||||
func combinedConfigFiles(containers []container.Summary) (string, error) {
|
||||
configFiles := []string{}
|
||||
|
||||
for _, c := range containers {
|
||||
files, ok := c.Labels[api.ConfigFilesLabel]
|
||||
for _, ctr := range containers {
|
||||
files, ok := ctr.Labels[api.ConfigFilesLabel]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("no label %q set on container %q of compose project", api.ConfigFilesLabel, c.ID)
|
||||
return "", fmt.Errorf("no label %q set on container %q of compose project", api.ConfigFilesLabel, ctr.ID)
|
||||
}
|
||||
|
||||
for f := range strings.SplitSeq(files, ",") {
|
||||
@@ -86,8 +86,8 @@ func combinedConfigFiles(containers []container.Summary) (string, error) {
|
||||
|
||||
func containerToState(containers []container.Summary) []string {
|
||||
statuses := []string{}
|
||||
for _, c := range containers {
|
||||
statuses = append(statuses, string(c.State))
|
||||
for _, ctr := range containers {
|
||||
statuses = append(statuses, string(ctr.State))
|
||||
}
|
||||
return statuses
|
||||
}
|
||||
@@ -118,17 +118,17 @@ func combinedStatus(statuses []string) string {
|
||||
func groupContainerByLabel(containers []container.Summary, labelName string) (map[string][]container.Summary, []string, error) {
|
||||
containersByLabel := map[string][]container.Summary{}
|
||||
keys := []string{}
|
||||
for _, c := range containers {
|
||||
label, ok := c.Labels[labelName]
|
||||
for _, ctr := range containers {
|
||||
label, ok := ctr.Labels[labelName]
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("no label %q set on container %q of compose project", labelName, c.ID)
|
||||
return nil, nil, fmt.Errorf("no label %q set on container %q of compose project", labelName, ctr.ID)
|
||||
}
|
||||
labelContainers, ok := containersByLabel[label]
|
||||
if !ok {
|
||||
labelContainers = []container.Summary{}
|
||||
keys = append(keys, label)
|
||||
}
|
||||
labelContainers = append(labelContainers, c)
|
||||
labelContainers = append(labelContainers, ctr)
|
||||
containersByLabel[label] = labelContainers
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
@@ -159,40 +159,40 @@ func (s *composeService) collectObservedState(ctx context.Context, project *type
|
||||
}
|
||||
|
||||
knownServices := map[string]bool{}
|
||||
for _, svc := range project.Services {
|
||||
knownServices[svc.Name] = true
|
||||
state.Containers[svc.Name] = nil // ensure key exists even if empty
|
||||
for _, service := range project.Services {
|
||||
knownServices[service.Name] = true
|
||||
state.Containers[service.Name] = nil // ensure key exists even if empty
|
||||
}
|
||||
for _, ds := range project.DisabledServices {
|
||||
knownServices[ds.Name] = true
|
||||
}
|
||||
|
||||
for _, c := range raw {
|
||||
svcName := c.Labels[api.ServiceLabel]
|
||||
if isNotOneOff(c) && knownServices[svcName] {
|
||||
state.Containers[svcName] = append(state.Containers[svcName], toObservedContainer(c))
|
||||
} else if isOrphaned(project)(c) {
|
||||
state.Orphans = append(state.Orphans, toObservedContainer(c))
|
||||
for _, ctr := range raw {
|
||||
svcName := ctr.Labels[api.ServiceLabel]
|
||||
if isNotOneOff(ctr) && knownServices[svcName] {
|
||||
state.Containers[svcName] = append(state.Containers[svcName], toObservedContainer(ctr))
|
||||
} else if isOrphaned(project)(ctr) {
|
||||
state.Orphans = append(state.Orphans, toObservedContainer(ctr))
|
||||
}
|
||||
}
|
||||
|
||||
// --- Networks ---
|
||||
nwList, err := s.apiClient().NetworkList(ctx, client.NetworkListOptions{
|
||||
networkList, err := s.apiClient().NetworkList(ctx, client.NetworkListOptions{
|
||||
Filters: projectFilter(project.Name),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, nw := range nwList.Items {
|
||||
key := nw.Labels[api.NetworkLabel]
|
||||
for _, network := range networkList.Items {
|
||||
key := network.Labels[api.NetworkLabel]
|
||||
if key == "" {
|
||||
continue
|
||||
}
|
||||
state.Networks[key] = append(state.Networks[key], ObservedNetwork{
|
||||
ID: nw.ID,
|
||||
Name: nw.Name,
|
||||
ConfigHash: nw.Labels[api.ConfigHashLabel],
|
||||
ProjectName: nw.Labels[api.ProjectLabel],
|
||||
ID: network.ID,
|
||||
Name: network.Name,
|
||||
ConfigHash: network.Labels[api.ConfigHashLabel],
|
||||
ProjectName: network.Labels[api.ProjectLabel],
|
||||
})
|
||||
}
|
||||
|
||||
@@ -235,14 +235,14 @@ func (s *composeService) collectObservedState(ctx context.Context, project *type
|
||||
// warnUnmanagedNetworks for the accompanying user warning.
|
||||
func (s *composeService) discoverUnmanagedNetworks(ctx context.Context, project *types.Project, state *ObservedState) error {
|
||||
for _, key := range project.NetworkNames() {
|
||||
nw := project.Networks[key]
|
||||
if nw.External {
|
||||
networkConfig := project.Networks[key]
|
||||
if networkConfig.External {
|
||||
continue
|
||||
}
|
||||
if len(state.Networks[key]) > 0 {
|
||||
continue
|
||||
}
|
||||
inspected, err := s.apiClient().NetworkInspect(ctx, nw.Name, client.NetworkInspectOptions{})
|
||||
inspected, err := s.apiClient().NetworkInspect(ctx, networkConfig.Name, client.NetworkInspectOptions{})
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
continue // absent: it will be created by the reconciliation plan
|
||||
@@ -251,7 +251,7 @@ func (s *composeService) discoverUnmanagedNetworks(ctx context.Context, project
|
||||
}
|
||||
// NetworkInspect matches on ID prefix, so guard against a partial match
|
||||
// (e.g. a network whose ID starts with the requested name).
|
||||
if inspected.Network.Name != nw.Name && inspected.Network.ID != nw.Name {
|
||||
if inspected.Network.Name != networkConfig.Name && inspected.Network.ID != networkConfig.Name {
|
||||
continue
|
||||
}
|
||||
state.Networks[key] = append(state.Networks[key], ObservedNetwork{
|
||||
@@ -348,8 +348,8 @@ func (s *ObservedState) setResolvedNetworks(networks map[string]string, project
|
||||
// Only external networks are passed here; they carry no compose label and so
|
||||
// are absent from the collected state, hence a plain append.
|
||||
for key, id := range networks {
|
||||
nw := project.Networks[key]
|
||||
s.Networks[key] = append(s.Networks[key], ObservedNetwork{ID: id, Name: nw.Name})
|
||||
networkConfig := project.Networks[key]
|
||||
s.Networks[key] = append(s.Networks[key], ObservedNetwork{ID: id, Name: networkConfig.Name})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,10 +379,10 @@ func emitRunningEvents(project *types.Project, observed *ObservedState, plan *Pl
|
||||
}
|
||||
}
|
||||
|
||||
for _, svc := range project.Services {
|
||||
for _, oc := range observed.Containers[svc.Name] {
|
||||
if oc.State == container.StateRunning && !planned[oc.ID] {
|
||||
events.On(newEvent("Container "+oc.Name, api.Done, api.StatusRunning))
|
||||
for _, service := range project.Services {
|
||||
for _, observedContainer := range observed.Containers[service.Name] {
|
||||
if observedContainer.State == container.StateRunning && !planned[observedContainer.ID] {
|
||||
events.On(newEvent("Container "+observedContainer.Name, api.Done, api.StatusRunning))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -404,12 +404,12 @@ func (s *ObservedState) containersByService() map[string]Containers {
|
||||
return map[string]Containers{}
|
||||
}
|
||||
result := make(map[string]Containers, len(s.Containers))
|
||||
for svc, ocs := range s.Containers {
|
||||
summaries := make(Containers, len(ocs))
|
||||
for i, oc := range ocs {
|
||||
summaries[i] = oc.Summary
|
||||
for serviceName, observedContainers := range s.Containers {
|
||||
summaries := make(Containers, len(observedContainers))
|
||||
for i, observedContainer := range observedContainers {
|
||||
summaries[i] = observedContainer.Summary
|
||||
}
|
||||
result[svc] = summaries
|
||||
result[serviceName] = summaries
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
+2
-2
@@ -26,9 +26,9 @@ import (
|
||||
"github.com/docker/compose/v5/pkg/api"
|
||||
)
|
||||
|
||||
func (s *composeService) Port(ctx context.Context, projectName string, service string, port uint16, options api.PortOptions) (string, int, error) {
|
||||
func (s *composeService) Port(ctx context.Context, projectName string, serviceName string, port uint16, options api.PortOptions) (string, int, error) {
|
||||
projectName = strings.ToLower(projectName)
|
||||
ctr, err := s.getSpecifiedContainer(ctx, projectName, oneOffInclude, false, service, options.Index)
|
||||
ctr, err := s.getSpecifiedContainer(ctx, projectName, oneOffInclude, false, serviceName, options.Index)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
|
||||
@@ -417,8 +417,8 @@ func sortedMapKeys[V any](m map[string]V) []string {
|
||||
}
|
||||
|
||||
func (f *envCheckFindings) hasEnvFinding() bool {
|
||||
for _, svc := range f.services {
|
||||
if svc.hasEnvFile || len(svc.suspiciousKeys) > 0 {
|
||||
for _, serviceFindings := range f.services {
|
||||
if serviceFindings.hasEnvFile || len(serviceFindings.suspiciousKeys) > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
+39
-39
@@ -225,13 +225,13 @@ func (r *reconciler) reconcileNetworks() error {
|
||||
}
|
||||
|
||||
// planCreateNetwork adds a single CreateNetwork node and records it for dependency tracking.
|
||||
func (r *reconciler) planCreateNetwork(key string, nw *types.NetworkConfig, cause string) {
|
||||
func (r *reconciler) planCreateNetwork(key string, networkConfig *types.NetworkConfig, cause string) {
|
||||
r.networkNodes[key] = r.plan.addNode(Operation{
|
||||
Type: OpCreateNetwork,
|
||||
ResourceID: fmt.Sprintf("network:%s", key),
|
||||
Cause: cause,
|
||||
Name: nw.Name,
|
||||
Network: nw,
|
||||
Name: networkConfig.Name,
|
||||
Network: networkConfig,
|
||||
}, "")
|
||||
}
|
||||
|
||||
@@ -435,8 +435,8 @@ func (r *reconciler) planRecreateVolumes(keys []string) {
|
||||
// Collect the services (and their containers) mounting any diverged volume.
|
||||
serviceSet := map[string]bool{}
|
||||
for _, key := range keys {
|
||||
for _, svc := range r.servicesUsingVolume(key) {
|
||||
serviceSet[svc] = true
|
||||
for _, serviceName := range r.servicesUsingVolume(key) {
|
||||
serviceSet[serviceName] = true
|
||||
}
|
||||
}
|
||||
services := sortedKeys(serviceSet)
|
||||
@@ -499,9 +499,9 @@ func (r *reconciler) planRecreateVolumes(keys []string) {
|
||||
// executor hashed against at create time, whereas clearing here is purely a
|
||||
// scheduling concern carried by the plan's dependency edges. The two
|
||||
// intentionally diverge; do not "fix" one to match the other.
|
||||
for _, svc := range services {
|
||||
r.recreatedServices[svc] = true
|
||||
r.observed.Containers[svc] = nil
|
||||
for _, serviceName := range services {
|
||||
r.recreatedServices[serviceName] = true
|
||||
r.observed.Containers[serviceName] = nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -510,9 +510,9 @@ func (r *reconciler) planRecreateVolumes(keys []string) {
|
||||
func (r *reconciler) servicesUsingNetwork(networkKey string) []string {
|
||||
var names []string
|
||||
for _, key := range sortedKeys(r.project.Services) {
|
||||
svc := r.project.Services[key]
|
||||
if _, ok := svc.Networks[networkKey]; ok {
|
||||
names = append(names, svc.Name)
|
||||
service := r.project.Services[key]
|
||||
if _, ok := service.Networks[networkKey]; ok {
|
||||
names = append(names, service.Name)
|
||||
}
|
||||
}
|
||||
return names
|
||||
@@ -533,10 +533,10 @@ func (r *reconciler) servicesUsingVolume(volumeKey string) []string {
|
||||
inSet := map[string]bool{}
|
||||
// Seed with services that mount the volume directly.
|
||||
for _, key := range sortedKeys(r.project.Services) {
|
||||
svc := r.project.Services[key]
|
||||
for _, v := range svc.Volumes {
|
||||
service := r.project.Services[key]
|
||||
for _, v := range service.Volumes {
|
||||
if v.Source == volumeKey {
|
||||
inSet[svc.Name] = true
|
||||
inSet[service.Name] = true
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -547,17 +547,17 @@ func (r *reconciler) servicesUsingVolume(volumeKey string) []string {
|
||||
for {
|
||||
added := false
|
||||
for _, key := range sortedKeys(r.project.Services) {
|
||||
svc := r.project.Services[key]
|
||||
if inSet[svc.Name] {
|
||||
service := r.project.Services[key]
|
||||
if inSet[service.Name] {
|
||||
continue
|
||||
}
|
||||
for _, vf := range svc.VolumesFrom {
|
||||
for _, vf := range service.VolumesFrom {
|
||||
if strings.HasPrefix(vf, types.ContainerPrefix) {
|
||||
continue
|
||||
}
|
||||
name, _, _ := strings.Cut(vf, ":")
|
||||
if inSet[name] {
|
||||
inSet[svc.Name] = true
|
||||
inSet[service.Name] = true
|
||||
added = true
|
||||
break
|
||||
}
|
||||
@@ -574,8 +574,8 @@ func (r *reconciler) servicesUsingVolume(volumeKey string) []string {
|
||||
// service names.
|
||||
func (r *reconciler) containersForServices(services []string) []ObservedContainer {
|
||||
var result []ObservedContainer
|
||||
for _, svc := range services {
|
||||
result = append(result, r.observed.Containers[svc]...)
|
||||
for _, serviceName := range services {
|
||||
result = append(result, r.observed.Containers[serviceName]...)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -642,13 +642,13 @@ func (r *reconciler) reconcileService(service types.ServiceConfig) error {
|
||||
return nil
|
||||
}
|
||||
if service.Provider != nil {
|
||||
svc := service
|
||||
serviceCopy := service
|
||||
deps := r.infrastructureDeps(service)
|
||||
node := r.plan.addNode(Operation{
|
||||
Type: OpRunProvider,
|
||||
ResourceID: fmt.Sprintf("provider:%s", service.Name),
|
||||
Cause: "provider service",
|
||||
Service: &svc,
|
||||
Service: &serviceCopy,
|
||||
}, "", deps...)
|
||||
r.serviceNodes[service.Name] = node
|
||||
return nil
|
||||
@@ -733,12 +733,12 @@ func (r *reconciler) reconcileService(service types.ServiceConfig) error {
|
||||
for i := 0; i < expected-actual; i++ {
|
||||
number := nextNum + i
|
||||
name := getContainerName(r.project.Name, service, number)
|
||||
svc := service // copy for pointer stability
|
||||
serviceCopy := service // copy for pointer stability
|
||||
lastNode = r.plan.addNode(Operation{
|
||||
Type: OpCreateContainer,
|
||||
ResourceID: fmt.Sprintf("service:%s:%d", service.Name, number),
|
||||
Cause: "no existing container",
|
||||
Service: &svc,
|
||||
Service: &serviceCopy,
|
||||
Number: number,
|
||||
Name: name,
|
||||
}, "", infraDeps...)
|
||||
@@ -780,17 +780,17 @@ func (r *reconciler) mustRecreate(expected types.ServiceConfig, expectedHash str
|
||||
}
|
||||
|
||||
// parentNamespaceRecreated reports whether any namespace- or volume-sharing
|
||||
// parent of svc has at least one container scheduled for recreation. The
|
||||
// parent set is derived from svc itself (network_mode/ipc/pid and volumes_from)
|
||||
// parent of service has at least one container scheduled for recreation. The
|
||||
// parent set is derived from service itself (network_mode/ipc/pid and volumes_from)
|
||||
// rather than depends_on, so the cascade fires only when a stale
|
||||
// "container:<id>" reference would otherwise be left behind.
|
||||
func (r *reconciler) parentNamespaceRecreated(svc types.ServiceConfig) bool {
|
||||
for _, mode := range []string{svc.NetworkMode, svc.Ipc, svc.Pid} {
|
||||
func (r *reconciler) parentNamespaceRecreated(service types.ServiceConfig) bool {
|
||||
for _, mode := range []string{service.NetworkMode, service.Ipc, service.Pid} {
|
||||
if name := getDependentServiceFromMode(mode); name != "" && r.recreatedServices[name] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, vol := range svc.VolumesFrom {
|
||||
for _, vol := range service.VolumesFrom {
|
||||
if strings.HasPrefix(vol, types.ContainerPrefix) {
|
||||
continue
|
||||
}
|
||||
@@ -809,11 +809,11 @@ func (r *reconciler) parentNamespaceRecreated(svc types.ServiceConfig) bool {
|
||||
// it cannot match the persisted hash either way, so recreation is forced.
|
||||
//
|
||||
// Only fields mutated by resolveServiceReferences need defensive copying.
|
||||
// svc.Networks (a map) is left shared because resolveServiceReferences does
|
||||
// service.Networks (a map) is left shared because resolveServiceReferences does
|
||||
// not touch it; revisit if that changes.
|
||||
func serviceHashWithResolvedRefs(svc types.ServiceConfig, containers map[string]Containers) (string, error) {
|
||||
resolved := svc
|
||||
resolved.VolumesFrom = slices.Clone(svc.VolumesFrom)
|
||||
func serviceHashWithResolvedRefs(service types.ServiceConfig, containers map[string]Containers) (string, error) {
|
||||
resolved := service
|
||||
resolved.VolumesFrom = slices.Clone(service.VolumesFrom)
|
||||
_ = resolveServiceReferences(&resolved, containers)
|
||||
return ServiceHash(resolved)
|
||||
}
|
||||
@@ -875,7 +875,7 @@ func (r *reconciler) planRecreateContainer(service types.ServiceConfig, oc *Obse
|
||||
resID := fmt.Sprintf("service:%s:%d", service.Name, oc.Number)
|
||||
group := fmt.Sprintf("recreate:%s:%d", service.Name, oc.Number)
|
||||
tmpName := fmt.Sprintf("%s_%s", oc.ID[:min(12, len(oc.ID))], getContainerName(r.project.Name, service, oc.Number))
|
||||
svc := service // copy for pointer stability
|
||||
serviceCopy := service // copy for pointer stability
|
||||
|
||||
// Stop dependents first
|
||||
depStopNodes := r.planStopDependents(service)
|
||||
@@ -893,7 +893,7 @@ func (r *reconciler) planRecreateContainer(service types.ServiceConfig, oc *Obse
|
||||
Type: OpCreateContainer,
|
||||
ResourceID: resID,
|
||||
Cause: "config changed (tmpName)",
|
||||
Service: &svc,
|
||||
Service: &serviceCopy,
|
||||
Inherited: inherited,
|
||||
Number: oc.Number,
|
||||
Name: tmpName,
|
||||
@@ -1055,10 +1055,10 @@ func (r *reconciler) reconcileOrphans() {
|
||||
// observedSummaries returns the raw container.Summary list for a service,
|
||||
// needed by nextContainerNumber which expects []container.Summary.
|
||||
func (r *reconciler) observedSummaries(serviceName string) []container.Summary {
|
||||
ocs := r.observed.Containers[serviceName]
|
||||
result := make([]container.Summary, len(ocs))
|
||||
for i, oc := range ocs {
|
||||
result[i] = oc.Summary
|
||||
observedContainers := r.observed.Containers[serviceName]
|
||||
result := make([]container.Summary, len(observedContainers))
|
||||
for i, observedContainer := range observedContainers {
|
||||
result[i] = observedContainer.Summary
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ func (s *composeService) Remove(ctx context.Context, projectName string, options
|
||||
}
|
||||
|
||||
var names []string
|
||||
for _, c := range stoppedContainers {
|
||||
names = append(names, getCanonicalContainerName(c))
|
||||
for _, ctr := range stoppedContainers {
|
||||
names = append(names, getCanonicalContainerName(ctr))
|
||||
}
|
||||
|
||||
if len(names) == 0 {
|
||||
|
||||
+43
-43
@@ -41,8 +41,8 @@ type prepareRunResult struct {
|
||||
created container.Summary
|
||||
}
|
||||
|
||||
func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts api.RunOptions) (int, error) {
|
||||
result, err := s.prepareRun(ctx, project, opts)
|
||||
func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, options api.RunOptions) (int, error) {
|
||||
result, err := s.prepareRun(ctx, project, options)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -68,8 +68,8 @@ func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.
|
||||
}
|
||||
|
||||
err = cmd.RunStart(ctx, s.dockerCli, &cmd.StartOptions{
|
||||
OpenStdin: !opts.Detach && opts.Interactive,
|
||||
Attach: !opts.Detach,
|
||||
OpenStdin: !options.Detach && options.Interactive,
|
||||
Attach: !options.Detach,
|
||||
Containers: []string{result.containerID},
|
||||
DetachKeys: s.configFile().DetachKeys,
|
||||
})
|
||||
@@ -119,7 +119,7 @@ func (s *composeService) runPostStartHooksOnEvent(ctx context.Context, container
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *composeService) prepareRun(ctx context.Context, project *types.Project, opts api.RunOptions) (prepareRunResult, error) {
|
||||
func (s *composeService) prepareRun(ctx context.Context, project *types.Project, options api.RunOptions) (prepareRunResult, error) {
|
||||
// Temporary implementation of use_api_socket until we get actual support inside docker engine
|
||||
project, err := s.useAPISocket(project)
|
||||
if err != nil {
|
||||
@@ -127,20 +127,20 @@ func (s *composeService) prepareRun(ctx context.Context, project *types.Project,
|
||||
}
|
||||
|
||||
err = Run(ctx, func(ctx context.Context) error {
|
||||
return s.startDependencies(ctx, project, opts)
|
||||
return s.startDependencies(ctx, project, options)
|
||||
}, "run", s.events)
|
||||
if err != nil {
|
||||
return prepareRunResult{}, err
|
||||
}
|
||||
|
||||
service, err := project.GetService(opts.Service)
|
||||
service, err := project.GetService(options.Service)
|
||||
if err != nil {
|
||||
return prepareRunResult{}, err
|
||||
}
|
||||
|
||||
applyRunOptions(project, &service, opts)
|
||||
applyRunOptions(project, &service, options)
|
||||
|
||||
if err := s.stdin().CheckTty(opts.Interactive, service.Tty); err != nil {
|
||||
if err := s.stdin().CheckTty(options.Interactive, service.Tty); err != nil {
|
||||
return prepareRunResult{}, err
|
||||
}
|
||||
|
||||
@@ -159,8 +159,8 @@ func (s *composeService) prepareRun(ctx context.Context, project *types.Project,
|
||||
Add(api.OneoffLabel, "True")
|
||||
|
||||
// Only ensure image exists for the target service, dependencies were already handled by startDependencies
|
||||
buildOpts := prepareBuildOptions(opts)
|
||||
if err := s.ensureImagesExists(ctx, project, buildOpts, opts.QuietPull); err != nil { // all dependencies already checked, but might miss service img
|
||||
buildOpts := prepareBuildOptions(options)
|
||||
if err := s.ensureImagesExists(ctx, project, buildOpts, options.QuietPull); err != nil { // all dependencies already checked, but might miss service img
|
||||
return prepareRunResult{}, err
|
||||
}
|
||||
|
||||
@@ -169,15 +169,15 @@ func (s *composeService) prepareRun(ctx context.Context, project *types.Project,
|
||||
return prepareRunResult{}, err
|
||||
}
|
||||
|
||||
if !opts.NoDeps {
|
||||
if !options.NoDeps {
|
||||
if err := s.waitDependencies(ctx, project, service.Name, service.DependsOn, observedState, 0); err != nil {
|
||||
return prepareRunResult{}, err
|
||||
}
|
||||
}
|
||||
createOpts := createOptions{
|
||||
AutoRemove: opts.AutoRemove,
|
||||
AttachStdin: opts.Interactive,
|
||||
UseNetworkAliases: opts.UseNetworkAliases,
|
||||
AutoRemove: options.AutoRemove,
|
||||
AttachStdin: options.Interactive,
|
||||
UseNetworkAliases: options.UseNetworkAliases,
|
||||
Labels: mergeLabels(service.Labels, service.CustomLabels),
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ func (s *composeService) prepareRun(ctx context.Context, project *types.Project,
|
||||
return prepareRunResult{}, err
|
||||
}
|
||||
|
||||
err = s.ensureModels(ctx, project, opts.QuietPull)
|
||||
err = s.ensureModels(ctx, project, options.QuietPull)
|
||||
if err != nil {
|
||||
return prepareRunResult{}, err
|
||||
}
|
||||
@@ -213,47 +213,47 @@ func (s *composeService) prepareRun(ctx context.Context, project *types.Project,
|
||||
}, err
|
||||
}
|
||||
|
||||
func prepareBuildOptions(opts api.RunOptions) *api.BuildOptions {
|
||||
if opts.Build == nil {
|
||||
func prepareBuildOptions(options api.RunOptions) *api.BuildOptions {
|
||||
if options.Build == nil {
|
||||
return nil
|
||||
}
|
||||
// Create a copy of build options and restrict to only the target service
|
||||
buildOptsCopy := *opts.Build
|
||||
buildOptsCopy.Services = []string{opts.Service}
|
||||
return &buildOptsCopy
|
||||
buildOptionsCopy := *options.Build
|
||||
buildOptionsCopy.Services = []string{options.Service}
|
||||
return &buildOptionsCopy
|
||||
}
|
||||
|
||||
func applyRunOptions(project *types.Project, service *types.ServiceConfig, opts api.RunOptions) {
|
||||
service.Tty = opts.Tty
|
||||
service.StdinOpen = opts.Interactive
|
||||
service.ContainerName = opts.Name
|
||||
func applyRunOptions(project *types.Project, service *types.ServiceConfig, options api.RunOptions) {
|
||||
service.Tty = options.Tty
|
||||
service.StdinOpen = options.Interactive
|
||||
service.ContainerName = options.Name
|
||||
|
||||
if len(opts.Command) > 0 {
|
||||
service.Command = opts.Command
|
||||
if len(options.Command) > 0 {
|
||||
service.Command = options.Command
|
||||
}
|
||||
if opts.User != "" {
|
||||
service.User = opts.User
|
||||
if options.User != "" {
|
||||
service.User = options.User
|
||||
}
|
||||
|
||||
if len(opts.CapAdd) > 0 {
|
||||
service.CapAdd = append(service.CapAdd, opts.CapAdd...)
|
||||
service.CapDrop = slices.DeleteFunc(service.CapDrop, func(e string) bool { return slices.Contains(opts.CapAdd, e) })
|
||||
if len(options.CapAdd) > 0 {
|
||||
service.CapAdd = append(service.CapAdd, options.CapAdd...)
|
||||
service.CapDrop = slices.DeleteFunc(service.CapDrop, func(e string) bool { return slices.Contains(options.CapAdd, e) })
|
||||
}
|
||||
if len(opts.CapDrop) > 0 {
|
||||
service.CapDrop = append(service.CapDrop, opts.CapDrop...)
|
||||
service.CapAdd = slices.DeleteFunc(service.CapAdd, func(e string) bool { return slices.Contains(opts.CapDrop, e) })
|
||||
if len(options.CapDrop) > 0 {
|
||||
service.CapDrop = append(service.CapDrop, options.CapDrop...)
|
||||
service.CapAdd = slices.DeleteFunc(service.CapAdd, func(e string) bool { return slices.Contains(options.CapDrop, e) })
|
||||
}
|
||||
if opts.WorkingDir != "" {
|
||||
service.WorkingDir = opts.WorkingDir
|
||||
if options.WorkingDir != "" {
|
||||
service.WorkingDir = options.WorkingDir
|
||||
}
|
||||
if opts.Entrypoint != nil {
|
||||
service.Entrypoint = opts.Entrypoint
|
||||
if len(opts.Command) == 0 {
|
||||
if options.Entrypoint != nil {
|
||||
service.Entrypoint = options.Entrypoint
|
||||
if len(options.Command) == 0 {
|
||||
service.Command = []string{}
|
||||
}
|
||||
}
|
||||
if len(opts.Environment) > 0 {
|
||||
cmdEnv := types.NewMappingWithEquals(opts.Environment)
|
||||
if len(options.Environment) > 0 {
|
||||
cmdEnv := types.NewMappingWithEquals(options.Environment)
|
||||
serviceOverrideEnv := cmdEnv.Resolve(func(s string) (string, bool) {
|
||||
v, ok := envResolver(project.Environment)(s)
|
||||
return v, ok
|
||||
@@ -263,7 +263,7 @@ func applyRunOptions(project *types.Project, service *types.ServiceConfig, opts
|
||||
}
|
||||
service.Environment.OverrideBy(serviceOverrideEnv)
|
||||
}
|
||||
for k, v := range opts.Labels {
|
||||
for k, v := range options.Labels {
|
||||
service.Labels = service.Labels.Add(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
// ReplaceExtendsFile changes value for service.extends.file in input yaml stream, preserving formatting
|
||||
func ReplaceExtendsFile(in []byte, service string, value string) ([]byte, error) {
|
||||
func ReplaceExtendsFile(in []byte, serviceName string, value string) ([]byte, error) {
|
||||
var doc yaml.Node
|
||||
err := yaml.Unmarshal(in, &doc)
|
||||
if err != nil {
|
||||
@@ -42,7 +42,7 @@ func ReplaceExtendsFile(in []byte, service string, value string) ([]byte, error)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
target, err := getMapping(services, service)
|
||||
target, err := getMapping(services, serviceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -62,7 +62,7 @@ func ReplaceExtendsFile(in []byte, service string, value string) ([]byte, error)
|
||||
}
|
||||
|
||||
// ReplaceEnvFile changes value for service.extends.env_file in input yaml stream, preserving formatting
|
||||
func ReplaceEnvFile(in []byte, service string, i int, value string) ([]byte, error) {
|
||||
func ReplaceEnvFile(in []byte, serviceName string, i int, value string) ([]byte, error) {
|
||||
var doc yaml.Node
|
||||
err := yaml.Unmarshal(in, &doc)
|
||||
if err != nil {
|
||||
@@ -81,7 +81,7 @@ func ReplaceEnvFile(in []byte, service string, i int, value string) ([]byte, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
target, err := getMapping(services, service)
|
||||
target, err := getMapping(services, serviceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+11
-11
@@ -29,7 +29,7 @@ import (
|
||||
// maps a service with the services it depends on
|
||||
type vizGraph map[*types.ServiceConfig][]*types.ServiceConfig
|
||||
|
||||
func (s *composeService) Viz(_ context.Context, project *types.Project, opts api.VizOptions) (string, error) {
|
||||
func (s *composeService) Viz(_ context.Context, project *types.Project, options api.VizOptions) (string, error) {
|
||||
graph := make(vizGraph)
|
||||
for _, service := range project.Services {
|
||||
graph[&service] = make([]*types.ServiceConfig, 0, len(service.DependsOn))
|
||||
@@ -50,12 +50,12 @@ func (s *composeService) Viz(_ context.Context, project *types.Project, opts api
|
||||
|
||||
// graph layout
|
||||
// dot is the perfect layout for this use case since graph is directed and hierarchical
|
||||
graphBuilder.WriteString(opts.Indentation + "layout=dot;\n")
|
||||
graphBuilder.WriteString(options.Indentation + "layout=dot;\n")
|
||||
|
||||
addNodes(&graphBuilder, graph, project.Name, &opts)
|
||||
addNodes(&graphBuilder, graph, project.Name, &options)
|
||||
graphBuilder.WriteByte('\n')
|
||||
|
||||
addEdges(&graphBuilder, graph, &opts)
|
||||
addEdges(&graphBuilder, graph, &options)
|
||||
graphBuilder.WriteString("}\n")
|
||||
|
||||
return graphBuilder.String(), nil
|
||||
@@ -63,17 +63,17 @@ func (s *composeService) Viz(_ context.Context, project *types.Project, opts api
|
||||
|
||||
// addNodes adds the corresponding graphviz representation of all the nodes in the given graph to the graphBuilder
|
||||
// returns the same graphBuilder
|
||||
func addNodes(graphBuilder *strings.Builder, graph vizGraph, projectName string, opts *api.VizOptions) *strings.Builder {
|
||||
func addNodes(graphBuilder *strings.Builder, graph vizGraph, projectName string, options *api.VizOptions) *strings.Builder {
|
||||
for serviceNode := range graph {
|
||||
// write:
|
||||
// "service name" [style="filled" label<<font point-size="15">service name</font>
|
||||
graphBuilder.WriteString(opts.Indentation)
|
||||
graphBuilder.WriteString(options.Indentation)
|
||||
writeQuoted(graphBuilder, serviceNode.Name)
|
||||
graphBuilder.WriteString(" [style=\"filled\" label=<<font point-size=\"15\">")
|
||||
graphBuilder.WriteString(serviceNode.Name)
|
||||
graphBuilder.WriteString("</font>")
|
||||
|
||||
if opts.IncludeNetworks && len(serviceNode.Networks) > 0 {
|
||||
if options.IncludeNetworks && len(serviceNode.Networks) > 0 {
|
||||
graphBuilder.WriteString("<font point-size=\"10\">")
|
||||
graphBuilder.WriteString("<br/><br/><b>Networks:</b>")
|
||||
for _, networkName := range serviceNode.NetworksByPriority() {
|
||||
@@ -83,7 +83,7 @@ func addNodes(graphBuilder *strings.Builder, graph vizGraph, projectName string,
|
||||
graphBuilder.WriteString("</font>")
|
||||
}
|
||||
|
||||
if opts.IncludePorts && len(serviceNode.Ports) > 0 {
|
||||
if options.IncludePorts && len(serviceNode.Ports) > 0 {
|
||||
graphBuilder.WriteString("<font point-size=\"10\">")
|
||||
graphBuilder.WriteString("<br/><br/><b>Ports:</b>")
|
||||
for _, portConfig := range serviceNode.Ports {
|
||||
@@ -104,7 +104,7 @@ func addNodes(graphBuilder *strings.Builder, graph vizGraph, projectName string,
|
||||
graphBuilder.WriteString("</font>")
|
||||
}
|
||||
|
||||
if opts.IncludeImageName {
|
||||
if options.IncludeImageName {
|
||||
graphBuilder.WriteString("<font point-size=\"10\">")
|
||||
graphBuilder.WriteString("<br/><br/><b>Image:</b><br/>")
|
||||
graphBuilder.WriteString(api.GetImageNameOrDefault(*serviceNode, projectName))
|
||||
@@ -119,10 +119,10 @@ func addNodes(graphBuilder *strings.Builder, graph vizGraph, projectName string,
|
||||
|
||||
// addEdges adds the corresponding graphviz representation of all edges in the given graph to the graphBuilder
|
||||
// returns the same graphBuilder
|
||||
func addEdges(graphBuilder *strings.Builder, graph vizGraph, opts *api.VizOptions) *strings.Builder {
|
||||
func addEdges(graphBuilder *strings.Builder, graph vizGraph, options *api.VizOptions) *strings.Builder {
|
||||
for parent, children := range graph {
|
||||
for _, child := range children {
|
||||
graphBuilder.WriteString(opts.Indentation)
|
||||
graphBuilder.WriteString(options.Indentation)
|
||||
writeQuoted(graphBuilder, parent.Name)
|
||||
graphBuilder.WriteString(" -> ")
|
||||
writeQuoted(graphBuilder, child.Name)
|
||||
|
||||
@@ -26,9 +26,9 @@ import (
|
||||
"github.com/docker/compose/v5/pkg/api"
|
||||
)
|
||||
|
||||
func (s *composeService) Volumes(ctx context.Context, project string, options api.VolumesOptions) ([]api.VolumesSummary, error) {
|
||||
func (s *composeService) Volumes(ctx context.Context, projectName string, options api.VolumesOptions) ([]api.VolumesSummary, error) {
|
||||
allContainers, err := s.apiClient().ContainerList(ctx, client.ContainerListOptions{
|
||||
Filters: projectFilter(project),
|
||||
Filters: projectFilter(projectName),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -38,9 +38,9 @@ func (s *composeService) Volumes(ctx context.Context, project string, options ap
|
||||
|
||||
if len(options.Services) > 0 {
|
||||
// filter service containers
|
||||
for _, c := range allContainers.Items {
|
||||
if slices.Contains(options.Services, c.Labels[api.ServiceLabel]) {
|
||||
containers = append(containers, c)
|
||||
for _, ctr := range allContainers.Items {
|
||||
if slices.Contains(options.Services, ctr.Labels[api.ServiceLabel]) {
|
||||
containers = append(containers, ctr)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -48,7 +48,7 @@ func (s *composeService) Volumes(ctx context.Context, project string, options ap
|
||||
}
|
||||
|
||||
volumesResponse, err := s.apiClient().VolumeList(ctx, client.VolumeListOptions{
|
||||
Filters: projectFilter(project),
|
||||
Filters: projectFilter(projectName),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -637,7 +637,7 @@ func (s *composeService) exec(ctx context.Context, project *types.Project, servi
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, c := range containers {
|
||||
for _, ctr := range containers {
|
||||
eg.Go(func() error {
|
||||
exec := ccli.NewExecOptions()
|
||||
exec.User = x.User
|
||||
@@ -651,7 +651,7 @@ func (s *composeService) exec(ctx context.Context, project *types.Project, servi
|
||||
return err
|
||||
}
|
||||
}
|
||||
return ccli.RunExec(ctx, s.dockerCli, c.ID, exec)
|
||||
return ccli.RunExec(ctx, s.dockerCli, ctr.ID, exec)
|
||||
})
|
||||
}
|
||||
return nil
|
||||
|
||||
+5
-5
@@ -30,14 +30,14 @@ import (
|
||||
func RequireServiceState(t testing.TB, cli *CLI, service string, state string) {
|
||||
t.Helper()
|
||||
psRes := cli.RunDockerComposeCmd(t, "ps", "--all", "--format=json", service)
|
||||
var svc map[string]any
|
||||
assert.NilError(t, json.Unmarshal([]byte(psRes.Stdout()), &svc),
|
||||
var serviceState map[string]any
|
||||
assert.NilError(t, json.Unmarshal([]byte(psRes.Stdout()), &serviceState),
|
||||
"Invalid `compose ps` JSON: command output: %s",
|
||||
psRes.Combined())
|
||||
|
||||
assert.Assert(t, is.Equal(service, svc["Service"]), "Found ps output for unexpected service")
|
||||
assert.Assert(t, is.Equal(strings.ToLower(state), strings.ToLower(svc["State"].(string))),
|
||||
assert.Assert(t, is.Equal(service, serviceState["Service"]), "Found ps output for unexpected service")
|
||||
assert.Assert(t, is.Equal(strings.ToLower(state), strings.ToLower(serviceState["State"].(string))),
|
||||
"Service %q (%s) not in expected state",
|
||||
service, svc["Name"],
|
||||
service, serviceState["Name"],
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user