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:
Nicolas De Loof
2026-08-20 11:17:11 +02:00
committed by Guillaume Lours
parent 3ee4b5c793
commit 24059c688c
28 changed files with 293 additions and 293 deletions
+7 -7
View File
@@ -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
View File
@@ -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) {
}
+9 -9
View File
@@ -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,
+2 -2
View File
@@ -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,
+3 -3
View File
@@ -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
}
}
+7 -7
View File
@@ -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
}
+8 -8
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+4 -4
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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
}
+6 -6
View File
@@ -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
+6 -6
View File
@@ -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
})
}
+5 -5
View File
@@ -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
View File
@@ -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)
+31 -31
View File
@@ -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
View File
@@ -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
}
+2 -2
View File
@@ -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
View File
@@ -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
}
+2 -2
View File
@@ -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
View File
@@ -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)
}
}
+4 -4
View File
@@ -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
View File
@@ -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)
+6 -6
View File
@@ -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
+2 -2
View File
@@ -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
View File
@@ -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"],
)
}