mirror of
https://github.com/docker/compose.git
synced 2026-10-12 02:13:08 +00:00
golangci-lint: enable perfsprint linter
Signed-off-by: Sebastiaan van Stijn <[email protected]>
This commit is contained in:
committed by
Guillaume Lours
parent
e9491499f1
commit
063ef45da1
@@ -27,6 +27,7 @@ linters:
|
||||
- misspell
|
||||
- nakedret
|
||||
- nolintlint
|
||||
- perfsprint
|
||||
- revive
|
||||
- staticcheck
|
||||
- testifylint
|
||||
|
||||
@@ -718,13 +718,13 @@ func selectEventProcessor(dockerCli command.Cli, progress, ansi string, detached
|
||||
}
|
||||
case display.ModeTTY:
|
||||
if ansi == "never" {
|
||||
return nil, fmt.Errorf("can't use --progress tty while ANSI support is disabled")
|
||||
return nil, errors.New("can't use --progress tty while ANSI support is disabled")
|
||||
}
|
||||
display.Mode = display.ModeTTY
|
||||
return display.Full(dockerCli.Err(), stdinfo(dockerCli), detached), nil
|
||||
case display.ModePlain:
|
||||
if ansi == "always" {
|
||||
return nil, fmt.Errorf("can't use --progress plain while ANSI support is forced")
|
||||
return nil, errors.New("can't use --progress plain while ANSI support is forced")
|
||||
}
|
||||
display.Mode = display.ModePlain
|
||||
return display.Plain(dockerCli.Err()), nil
|
||||
|
||||
@@ -18,6 +18,7 @@ package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strconv"
|
||||
@@ -63,10 +64,10 @@ func createCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *Bac
|
||||
PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
|
||||
opts.pullChanged = cmd.Flags().Changed("pull")
|
||||
if opts.Build && opts.noBuild {
|
||||
return fmt.Errorf("--build and --no-build are incompatible")
|
||||
return errors.New("--build and --no-build are incompatible")
|
||||
}
|
||||
if opts.forceRecreate && opts.noRecreate {
|
||||
return fmt.Errorf("--force-recreate and --no-recreate are incompatible")
|
||||
return errors.New("--force-recreate and --no-recreate are incompatible")
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
|
||||
+2
-2
@@ -19,8 +19,8 @@ package compose
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
"github.com/docker/cli/cli"
|
||||
@@ -133,7 +133,7 @@ func runExec(ctx context.Context, dockerCli command.Cli, backendOptions *Backend
|
||||
}
|
||||
exitCode, err := backend.Exec(ctx, projectName, execOpts)
|
||||
if exitCode != 0 {
|
||||
errMsg := fmt.Sprintf("exit status %d", exitCode)
|
||||
errMsg := "exit status " + strconv.Itoa(exitCode)
|
||||
if err != nil && err.Error() != "" {
|
||||
errMsg = err.Error()
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
@@ -58,7 +59,7 @@ func generateCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *B
|
||||
func runGenerate(ctx context.Context, dockerCli command.Cli, backendOptions *BackendOptions, opts generateOptions, containers []string) error {
|
||||
_, _ = fmt.Fprintln(os.Stderr, "generate command is EXPERIMENTAL")
|
||||
if len(containers) == 0 {
|
||||
return fmt.Errorf("at least one container must be specified")
|
||||
return errors.New("at least one container must be specified")
|
||||
}
|
||||
|
||||
backend, err := compose.NewComposeService(dockerCli, backendOptions.Options...)
|
||||
|
||||
@@ -18,6 +18,7 @@ package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@@ -169,7 +170,7 @@ func promptForInterpolatedVariables(ctx context.Context, dockerCli command.Cli,
|
||||
}
|
||||
|
||||
if !confirmed {
|
||||
return fmt.Errorf("operation cancelled by user")
|
||||
return errors.New("operation cancelled by user")
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -292,7 +293,7 @@ func confirmRemoteIncludes(dockerCli command.Cli, options buildOptions, assumeYe
|
||||
return err
|
||||
}
|
||||
if !confirmed {
|
||||
return fmt.Errorf("operation cancelled by user")
|
||||
return errors.New("operation cancelled by user")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+4
-4
@@ -18,7 +18,7 @@ package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"errors"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
@@ -168,7 +168,7 @@ func runCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *Backen
|
||||
options.Command = args[1:]
|
||||
}
|
||||
if len(options.publish) > 0 && options.servicePorts {
|
||||
return fmt.Errorf("--service-ports and --publish are incompatible")
|
||||
return errors.New("--service-ports and --publish are incompatible")
|
||||
}
|
||||
if cmd.Flags().Changed("entrypoint") {
|
||||
command, err := shellwords.Parse(options.entrypoint)
|
||||
@@ -179,7 +179,7 @@ func runCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *Backen
|
||||
}
|
||||
if cmd.Flags().Changed("tty") {
|
||||
if cmd.Flags().Changed("no-tty") {
|
||||
return fmt.Errorf("--tty and --no-tty can't be used together")
|
||||
return errors.New("--tty and --no-tty can't be used together")
|
||||
} else {
|
||||
options.noTty = !ttyFlag
|
||||
}
|
||||
@@ -303,7 +303,7 @@ func runRun(ctx context.Context, backend api.Compose, project *types.Project, op
|
||||
for _, s := range options.labels {
|
||||
key, val, ok := strings.Cut(s, "=")
|
||||
if !ok {
|
||||
return fmt.Errorf("label must be set as KEY=VALUE")
|
||||
return errors.New("label must be set as KEY=VALUE")
|
||||
}
|
||||
labels[key] = val
|
||||
}
|
||||
|
||||
+11
-11
@@ -138,7 +138,7 @@ func upCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *Backend
|
||||
up.resolveNavigationMenu(dockerCli)
|
||||
|
||||
if !p.All && len(project.Services) == 0 {
|
||||
return fmt.Errorf("no service selected")
|
||||
return errors.New("no service selected")
|
||||
}
|
||||
|
||||
return runUp(ctx, dockerCli, backendOptions, create, up, build, project, services)
|
||||
@@ -188,41 +188,41 @@ func upCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *Backend
|
||||
|
||||
func validateFlags(up *upOptions, create *createOptions) error {
|
||||
if up.waitTimeout < 0 {
|
||||
return fmt.Errorf("--wait-timeout must be a non-negative integer")
|
||||
return errors.New("--wait-timeout must be a non-negative integer")
|
||||
}
|
||||
if up.exitCodeFrom != "" && !up.cascadeFail {
|
||||
up.cascadeStop = true
|
||||
}
|
||||
if up.cascadeStop && up.cascadeFail {
|
||||
return fmt.Errorf("--abort-on-container-failure cannot be combined with --abort-on-container-exit")
|
||||
return errors.New("--abort-on-container-failure cannot be combined with --abort-on-container-exit")
|
||||
}
|
||||
if up.wait {
|
||||
if up.attachDependencies || up.cascadeStop || len(up.attach) > 0 {
|
||||
return fmt.Errorf("--wait cannot be combined with --abort-on-container-exit, --attach or --attach-dependencies")
|
||||
return errors.New("--wait cannot be combined with --abort-on-container-exit, --attach or --attach-dependencies")
|
||||
}
|
||||
up.Detach = true
|
||||
}
|
||||
if create.Build && create.noBuild {
|
||||
return fmt.Errorf("--build and --no-build are incompatible")
|
||||
return errors.New("--build and --no-build are incompatible")
|
||||
}
|
||||
if up.Detach && (up.attachDependencies || up.cascadeStop || up.cascadeFail || len(up.attach) > 0 || up.watch) {
|
||||
if up.wait {
|
||||
return fmt.Errorf("--wait cannot be combined with --abort-on-container-exit, --abort-on-container-failure, --attach, --attach-dependencies or --watch")
|
||||
return errors.New("--wait cannot be combined with --abort-on-container-exit, --abort-on-container-failure, --attach, --attach-dependencies or --watch")
|
||||
} else {
|
||||
return fmt.Errorf("--detach cannot be combined with --abort-on-container-exit, --abort-on-container-failure, --attach, --attach-dependencies or --watch")
|
||||
return errors.New("--detach cannot be combined with --abort-on-container-exit, --abort-on-container-failure, --attach, --attach-dependencies or --watch")
|
||||
}
|
||||
}
|
||||
if create.noInherit && create.noRecreate {
|
||||
return fmt.Errorf("--no-recreate and --renew-anon-volumes are incompatible")
|
||||
return errors.New("--no-recreate and --renew-anon-volumes are incompatible")
|
||||
}
|
||||
if create.forceRecreate && create.noRecreate {
|
||||
return fmt.Errorf("--force-recreate and --no-recreate are incompatible")
|
||||
return errors.New("--force-recreate and --no-recreate are incompatible")
|
||||
}
|
||||
if create.recreateDeps && create.noRecreate {
|
||||
return fmt.Errorf("--always-recreate-deps and --no-recreate are incompatible")
|
||||
return errors.New("--always-recreate-deps and --no-recreate are incompatible")
|
||||
}
|
||||
if create.noBuild && up.watch {
|
||||
return fmt.Errorf("--no-build and --watch are incompatible")
|
||||
return errors.New("--no-build and --watch are incompatible")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ func (c *ContainerContext) Mounts() string {
|
||||
|
||||
// LocalVolumes returns the number of volumes using the "local" volume driver.
|
||||
func (c *ContainerContext) LocalVolumes() string {
|
||||
return fmt.Sprintf("%d", c.c.LocalVolumes)
|
||||
return strconv.Itoa(c.c.LocalVolumes)
|
||||
}
|
||||
|
||||
// Networks returns a comma-separated string of networks that the container is
|
||||
|
||||
@@ -61,7 +61,7 @@ func (ke *KeyboardError) printError(height int, info string) {
|
||||
func (ke *KeyboardError) addError(prefix string, err error) {
|
||||
ke.timeStart = time.Now()
|
||||
|
||||
prefix = ansiColor(CYAN, fmt.Sprintf("%s →", prefix), BOLD)
|
||||
prefix = ansiColor(CYAN, prefix+" →", BOLD)
|
||||
errorString := fmt.Sprintf("%s %s", prefix, err.Error())
|
||||
|
||||
ke.err = errors.New(errorString)
|
||||
@@ -210,10 +210,10 @@ func (lk *LogKeyboard) openDockerDesktop(ctx context.Context, project *types.Pro
|
||||
go func() {
|
||||
_ = tracing.EventWrapFuncForErrGroup(ctx, "menu/gui", tracing.SpanOptions{},
|
||||
func(ctx context.Context) error {
|
||||
link := fmt.Sprintf("docker-desktop://dashboard/apps/%s", project.Name)
|
||||
link := "docker-desktop://dashboard/apps/" + project.Name
|
||||
err := open.Run(link)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("could not open Docker Desktop")
|
||||
err = errors.New("could not open Docker Desktop")
|
||||
lk.keyboardError("View", err)
|
||||
}
|
||||
return err
|
||||
@@ -228,10 +228,10 @@ func (lk *LogKeyboard) openDDComposeUI(ctx context.Context, project *types.Proje
|
||||
go func() {
|
||||
_ = tracing.EventWrapFuncForErrGroup(ctx, "menu/gui/composeview", tracing.SpanOptions{},
|
||||
func(ctx context.Context) error {
|
||||
link := fmt.Sprintf("docker-desktop://dashboard/docker-compose/%s", project.Name)
|
||||
link := "docker-desktop://dashboard/docker-compose/" + project.Name
|
||||
err := open.Run(link)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("could not open Docker Desktop Compose UI")
|
||||
err = errors.New("could not open Docker Desktop Compose UI")
|
||||
lk.keyboardError("View Config", err)
|
||||
}
|
||||
return err
|
||||
@@ -264,7 +264,7 @@ func (lk *LogKeyboard) openDDWatchDocs(ctx context.Context, project *types.Proje
|
||||
link := fmt.Sprintf("docker-desktop://dashboard/docker-compose/%s/watch", project.Name)
|
||||
err := open.Run(link)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("could not open Docker Desktop Compose UI")
|
||||
err = errors.New("could not open Docker Desktop Compose UI")
|
||||
lk.keyboardError("Watch Docs", err)
|
||||
}
|
||||
return err
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package locker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
@@ -30,6 +29,6 @@ func NewPidfile(projectName string) (*Pidfile, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
path := filepath.Join(run, fmt.Sprintf("%s.pid", projectName))
|
||||
path := filepath.Join(run, projectName+".pid")
|
||||
return &Pidfile{path: path}, nil
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ package memnet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"errors"
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
@@ -28,12 +28,12 @@ import (
|
||||
const maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path)
|
||||
|
||||
func dialNamedPipe(_ context.Context, _ string) (net.Conn, error) {
|
||||
return nil, fmt.Errorf("named pipes are only available on Windows")
|
||||
return nil, errors.New("named pipes are only available on Windows")
|
||||
}
|
||||
|
||||
func validateSocketPath(addr string) error {
|
||||
if len(addr) > maxUnixSocketPathSize {
|
||||
return fmt.Errorf("socket address is too long: %s", addr)
|
||||
return errors.New("socket address is too long: " + addr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ package tracing
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
hex "encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -192,5 +192,5 @@ func projectHash(p *types.Project) (string, bool) {
|
||||
return "", false
|
||||
}
|
||||
d := sha256.Sum256(projData)
|
||||
return fmt.Sprintf("%x", d), true
|
||||
return hex.EncodeToString(d[:]), true
|
||||
}
|
||||
|
||||
@@ -485,7 +485,7 @@ func (s *composeService) getBuildxPlugin() (*manager.Plugin, error) {
|
||||
}
|
||||
|
||||
if buildx.Version == "" {
|
||||
return nil, fmt.Errorf("failed to get version of buildx")
|
||||
return nil, errors.New("failed to get version of buildx")
|
||||
}
|
||||
|
||||
if versions.LessThan(buildx.Version[1:], buildxMinVersion) {
|
||||
@@ -647,12 +647,12 @@ func (s *composeService) dryRunBake(cfg bakeConfig) map[string]string {
|
||||
s.events.On(api.Resource{
|
||||
ID: name + " ==>",
|
||||
Status: api.Done,
|
||||
Text: fmt.Sprintf("==> writing image %s", dryRunUUID),
|
||||
Text: "==> writing image " + dryRunUUID,
|
||||
})
|
||||
s.events.On(api.Resource{
|
||||
ID: name + " ==> ==>",
|
||||
Status: api.Done,
|
||||
Text: fmt.Sprintf(`naming to %s`, target.Tags[0]),
|
||||
Text: "naming to " + target.Tags[0],
|
||||
})
|
||||
bakeResponse[name] = dryRunUUID
|
||||
}
|
||||
|
||||
@@ -232,19 +232,19 @@ func (s *composeService) doBuildImage(ctx context.Context, project *types.Projec
|
||||
// doesn't implement
|
||||
func checkClassicBuilderSupported(service types.ServiceConfig) error {
|
||||
if len(service.Build.Platforms) > 1 {
|
||||
return fmt.Errorf("the classic builder doesn't support multi-arch build; building with BuildKit requires the buildx Docker CLI plugin, and DOCKER_BUILDKIT must not be set to 0")
|
||||
return errors.New("the classic builder doesn't support multi-arch build; building with BuildKit requires the buildx Docker CLI plugin, and DOCKER_BUILDKIT must not be set to 0")
|
||||
}
|
||||
if service.Build.Privileged {
|
||||
return fmt.Errorf("the classic builder doesn't support privileged mode; building with BuildKit requires the buildx Docker CLI plugin, and DOCKER_BUILDKIT must not be set to 0")
|
||||
return errors.New("the classic builder doesn't support privileged mode; building with BuildKit requires the buildx Docker CLI plugin, and DOCKER_BUILDKIT must not be set to 0")
|
||||
}
|
||||
if len(service.Build.AdditionalContexts) > 0 {
|
||||
return fmt.Errorf("the classic builder doesn't support additional contexts; building with BuildKit requires the buildx Docker CLI plugin, and DOCKER_BUILDKIT must not be set to 0")
|
||||
return errors.New("the classic builder doesn't support additional contexts; building with BuildKit requires the buildx Docker CLI plugin, and DOCKER_BUILDKIT must not be set to 0")
|
||||
}
|
||||
if len(service.Build.SSH) > 0 {
|
||||
return fmt.Errorf("the classic builder doesn't support SSH keys; building with BuildKit requires the buildx Docker CLI plugin, and DOCKER_BUILDKIT must not be set to 0")
|
||||
return errors.New("the classic builder doesn't support SSH keys; building with BuildKit requires the buildx Docker CLI plugin, and DOCKER_BUILDKIT must not be set to 0")
|
||||
}
|
||||
if len(service.Build.Secrets) > 0 {
|
||||
return fmt.Errorf("the classic builder doesn't support secrets; building with BuildKit requires the buildx Docker CLI plugin, and DOCKER_BUILDKIT must not be set to 0")
|
||||
return errors.New("the classic builder doesn't support secrets; building with BuildKit requires the buildx Docker CLI plugin, and DOCKER_BUILDKIT must not be set to 0")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -260,7 +260,7 @@ func prepareClassicBuildContext(specifiedContext, dockerfileName string, progBuf
|
||||
bctx := &classicBuildContext{cleanup: func() {}}
|
||||
switch contextType {
|
||||
case build.ContextTypeStdin:
|
||||
return nil, fmt.Errorf("building from STDIN is not supported")
|
||||
return nil, errors.New("building from STDIN is not supported")
|
||||
case build.ContextTypeLocal:
|
||||
bctx.contextDir, bctx.relDockerfile, err = build.GetContextFromLocalDir(specifiedContext, dockerfileName)
|
||||
if err != nil {
|
||||
|
||||
@@ -18,7 +18,6 @@ package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/moby/moby/client"
|
||||
@@ -71,7 +70,7 @@ func (s *composeService) commit(ctx context.Context, projectName string, options
|
||||
|
||||
s.events.On(api.Resource{
|
||||
ID: name,
|
||||
Text: fmt.Sprintf("Committed as %s", response.ID),
|
||||
Text: "Committed as " + response.ID,
|
||||
Status: api.Done,
|
||||
})
|
||||
|
||||
|
||||
@@ -526,7 +526,7 @@ func (s *composeService) RuntimeAPIVersion(ctx context.Context) (string, error)
|
||||
|
||||
version := cli.ClientVersion()
|
||||
if version == "" {
|
||||
return "", fmt.Errorf("docker client returned empty version after successful API negotiation")
|
||||
return "", errors.New("docker client returned empty version after successful API negotiation")
|
||||
}
|
||||
|
||||
s.runtimeAPIVersion.val = version
|
||||
|
||||
@@ -1452,7 +1452,7 @@ func (s *composeService) createNetwork(ctx context.Context, n *types.NetworkConf
|
||||
EnableIPv4: n.EnableIPv4,
|
||||
}
|
||||
|
||||
networkEventName := fmt.Sprintf("Network %s", n.Name)
|
||||
networkEventName := "Network " + n.Name
|
||||
s.events.On(creatingEvent(networkEventName))
|
||||
|
||||
if _, err := s.apiClient().NetworkCreate(ctx, n.Name, networkCreateOptions); err != nil {
|
||||
@@ -1523,7 +1523,7 @@ func (s *composeService) resolveExternalNetwork(ctx context.Context, n *types.Ne
|
||||
}
|
||||
|
||||
func (s *composeService) createVolume(ctx context.Context, volume types.VolumeConfig) error {
|
||||
eventName := fmt.Sprintf("Volume %s", volume.Name)
|
||||
eventName := "Volume " + volume.Name
|
||||
s.events.On(creatingEvent(eventName))
|
||||
hash, err := VolumeHash(volume)
|
||||
if err != nil {
|
||||
|
||||
@@ -18,8 +18,8 @@ package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
@@ -62,12 +62,10 @@ func TestTraversalWithMultipleParents(t *testing.T) {
|
||||
Services: types.Services{"dependent": dependent},
|
||||
}
|
||||
|
||||
for i := 1; i <= 100; i++ {
|
||||
name := fmt.Sprintf("svc_%d", i)
|
||||
for i := range 100 {
|
||||
name := "svc_" + strconv.Itoa(i+1)
|
||||
dependent.DependsOn[name] = types.ServiceDependency{}
|
||||
|
||||
svc := types.ServiceConfig{Name: name}
|
||||
project.Services[name] = svc
|
||||
project.Services[name] = types.ServiceConfig{Name: name}
|
||||
}
|
||||
|
||||
svc := make(chan string, 10)
|
||||
@@ -262,7 +260,7 @@ func TestBuildGraph(t *testing.T) {
|
||||
}
|
||||
|
||||
graph, err := NewGraph(&project, ServiceStopped)
|
||||
assert.NilError(t, err, fmt.Sprintf("failed to build graph for: %s", tC.desc))
|
||||
assert.NilError(t, err, "failed to build graph for: "+tC.desc)
|
||||
|
||||
for k, vertex := range graph.Vertices {
|
||||
expected, ok := tC.expectedVertices[k]
|
||||
@@ -312,7 +310,7 @@ func TestBuildGraphDependsOn(t *testing.T) {
|
||||
}
|
||||
|
||||
graph, err := NewGraph(&project, ServiceStopped)
|
||||
assert.NilError(t, err, fmt.Sprintf("failed to build graph for: %s", tC.desc))
|
||||
assert.NilError(t, err, "failed to build graph for: "+tC.desc)
|
||||
|
||||
for k, vertex := range graph.Vertices {
|
||||
expected, ok := tC.expectedVertices[k]
|
||||
|
||||
+2
-2
@@ -232,7 +232,7 @@ func (s *composeService) removeNetwork(ctx context.Context, composeNetworkName s
|
||||
return nil
|
||||
}
|
||||
|
||||
eventName := fmt.Sprintf("Network %s", name)
|
||||
eventName := "Network " + name
|
||||
s.events.On(removingEvent(eventName))
|
||||
|
||||
var found int
|
||||
@@ -277,7 +277,7 @@ func (s *composeService) removeNetwork(ctx context.Context, composeNetworkName s
|
||||
}
|
||||
|
||||
func (s *composeService) removeVolume(ctx context.Context, id string) error {
|
||||
resource := fmt.Sprintf("Volume %s", id)
|
||||
resource := "Volume " + id
|
||||
|
||||
_, err := s.apiClient().VolumeInspect(ctx, id, client.VolumeInspectOptions{})
|
||||
if errdefs.IsNotFound(err) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
@@ -669,7 +670,7 @@ func TestDownHookContainerRemovalFailureIsNonFatal(t *testing.T) {
|
||||
// Removal fails — Down must still return nil.
|
||||
api.EXPECT().ContainerRemove(gomock.Any(), "hook-2",
|
||||
client.ContainerRemoveOptions{Force: true, RemoveVolumes: true}).
|
||||
Return(client.ContainerRemoveResult{}, fmt.Errorf("daemon busy"))
|
||||
Return(client.ContainerRemoveResult{}, errors.New("daemon busy"))
|
||||
|
||||
err = tested.Down(t.Context(), strings.ToLower(testProject), compose.DownOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
@@ -19,7 +19,7 @@ package compose
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
@@ -233,11 +233,11 @@ func TestExecutePlanConcurrentRemovesCacheCoherence(t *testing.T) {
|
||||
ctrs := make([]container.Summary, replicas)
|
||||
for i := range ctrs {
|
||||
ctrs[i] = container.Summary{
|
||||
ID: fmt.Sprintf("c%d", i),
|
||||
Names: []string{fmt.Sprintf("/test-web-%d", i+1)},
|
||||
ID: "c" + strconv.Itoa(i),
|
||||
Names: []string{"/test-web-" + strconv.Itoa(i+1)},
|
||||
Labels: map[string]string{
|
||||
api.ServiceLabel: "web",
|
||||
api.ContainerNumberLabel: fmt.Sprintf("%d", i+1),
|
||||
api.ContainerNumberLabel: strconv.Itoa(i + 1),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -268,13 +268,13 @@ func TestExecutePlanConcurrentRemovesCacheCoherence(t *testing.T) {
|
||||
for i := range ctrs {
|
||||
stop := plan.addNode(Operation{
|
||||
Type: OpStopContainer,
|
||||
ResourceID: fmt.Sprintf("service:web:%d", i+1),
|
||||
ResourceID: "service:web:" + strconv.Itoa(i+1),
|
||||
Cause: "scale down",
|
||||
Container: &ctrs[i],
|
||||
}, "")
|
||||
plan.addNode(Operation{
|
||||
Type: OpRemoveContainer,
|
||||
ResourceID: fmt.Sprintf("service:web:%d", i+1),
|
||||
ResourceID: "service:web:" + strconv.Itoa(i+1),
|
||||
Cause: "scale down",
|
||||
Container: &ctrs[i],
|
||||
}, "", stop)
|
||||
|
||||
@@ -18,6 +18,7 @@ package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
@@ -45,7 +46,7 @@ func (s *composeService) export(ctx context.Context, projectName string, options
|
||||
|
||||
if options.Output == "" {
|
||||
if s.stdout().IsTerminal() {
|
||||
return fmt.Errorf("output option is required when exporting to terminal")
|
||||
return errors.New("output option is required when exporting to terminal")
|
||||
}
|
||||
} else if err := command.ValidateOutputPath(options.Output); err != nil {
|
||||
return fmt.Errorf("failed to export container: %w", err)
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
@@ -460,7 +460,7 @@ func TestRunHook_CopyError(t *testing.T) {
|
||||
// Build a pipe whose read side immediately returns a hard error, simulating
|
||||
// an I/O failure mid-stream rather than a clean EOF.
|
||||
pr, pw := io.Pipe()
|
||||
_ = pw.CloseWithError(fmt.Errorf("simulated I/O failure"))
|
||||
_ = pw.CloseWithError(errors.New("simulated I/O failure"))
|
||||
|
||||
// Use net.Pipe() only for the Conn field (Close); reads come from pr.
|
||||
serverConn, clientConn := net.Pipe()
|
||||
@@ -524,7 +524,7 @@ func TestRunHook_ExecCreateError(t *testing.T) {
|
||||
|
||||
mockAPI.EXPECT().
|
||||
ExecCreate(gomock.Any(), "ctr-1", gomock.Any()).
|
||||
Return(client.ExecCreateResult{}, fmt.Errorf("exec create failed"))
|
||||
Return(client.ExecCreateResult{}, errors.New("exec create failed"))
|
||||
|
||||
s, err := NewComposeService(mockCli)
|
||||
assert.NilError(t, err)
|
||||
@@ -552,7 +552,7 @@ func TestRunHook_ExecAttachError(t *testing.T) {
|
||||
Return(client.ExecCreateResult{ID: "exec-1"}, nil)
|
||||
mockAPI.EXPECT().
|
||||
ExecAttach(gomock.Any(), "exec-1", gomock.Any()).
|
||||
Return(client.ExecAttachResult{}, fmt.Errorf("exec attach failed"))
|
||||
Return(client.ExecAttachResult{}, errors.New("exec attach failed"))
|
||||
|
||||
s, err := NewComposeService(mockCli)
|
||||
assert.NilError(t, err)
|
||||
@@ -590,7 +590,7 @@ func TestRunHook_ExecInspectError(t *testing.T) {
|
||||
|
||||
mockAPI.EXPECT().
|
||||
ExecInspect(gomock.Any(), "exec-1", gomock.Any()).
|
||||
Return(client.ExecInspectResult{}, fmt.Errorf("inspect failed"))
|
||||
Return(client.ExecInspectResult{}, errors.New("inspect failed"))
|
||||
|
||||
s, err := NewComposeService(mockCli)
|
||||
assert.NilError(t, err)
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"slices"
|
||||
@@ -82,7 +83,7 @@ func (s *composeService) newModelAPI(project *types.Project) (*modelAPI, error)
|
||||
dockerModel, err := manager.GetPlugin("model", s.dockerCli, &cobra.Command{})
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
return nil, fmt.Errorf("'models' support requires Docker Model plugin")
|
||||
return nil, errors.New("'models' support requires Docker Model plugin")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ func (s *composeService) setupPluginCommand(ctx context.Context, project *types.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
args := []string{"compose", fmt.Sprintf("--project-name=%s", project.Name), command}
|
||||
args := []string{"compose", "--project-name=" + project.Name, command}
|
||||
for k, v := range provider.Options {
|
||||
for _, value := range v {
|
||||
if _, ok := currentCommandMetadata.GetParameter(k); commandMetadataIsEmpty || ok {
|
||||
|
||||
@@ -19,7 +19,7 @@ package compose
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"errors"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -301,7 +301,7 @@ func TestPreStart_ContainerCreateFailurePropagates(t *testing.T) {
|
||||
|
||||
scan := expectEmptyOrphanScan(apiClient)
|
||||
apiClient.EXPECT().ContainerCreate(gomock.Any(), gomock.Any()).
|
||||
Return(client.ContainerCreateResult{}, fmt.Errorf("no such image: missing:latest")).After(scan)
|
||||
Return(client.ContainerCreateResult{}, errors.New("no such image: missing:latest")).After(scan)
|
||||
|
||||
err := tested.runPreStart(t.Context(), project, service, ctr, func(api.ContainerEvent) {})
|
||||
assert.ErrorContains(t, err, "no such image")
|
||||
@@ -328,7 +328,7 @@ func TestPreStart_ContainerStartFailurePropagates(t *testing.T) {
|
||||
logs1 := apiClient.EXPECT().ContainerLogs(gomock.Any(), "hook-1", gomock.Any()).
|
||||
Return(emptyLogs(), nil).After(wait1)
|
||||
start1 := apiClient.EXPECT().ContainerStart(gomock.Any(), "hook-1", gomock.Any()).
|
||||
Return(client.ContainerStartResult{}, fmt.Errorf("daemon: container start failed")).After(logs1)
|
||||
Return(client.ContainerStartResult{}, errors.New("daemon: container start failed")).After(logs1)
|
||||
// AutoRemove never fires when start fails, so the hook must drop the ghost
|
||||
// container explicitly. This is distinct from the success-path removal
|
||||
// (RemoveVolumes:true) — the never-started container has no logs to preserve.
|
||||
@@ -404,7 +404,7 @@ func TestWaitPreStart_RaceRealErrorAndResult(t *testing.T) {
|
||||
resultC := make(chan container.WaitResponse, 1)
|
||||
errC := make(chan error, 1)
|
||||
resultC <- container.WaitResponse{StatusCode: 0}
|
||||
errC <- fmt.Errorf("daemon: connection lost")
|
||||
errC <- errors.New("daemon: connection lost")
|
||||
waitRes := client.ContainerWaitResult{Result: resultC, Error: errC}
|
||||
err := waitPreStart(t.Context(), "web", 0, waitRes)
|
||||
assert.ErrorContains(t, err, "connection lost")
|
||||
@@ -691,7 +691,7 @@ func TestPreStart_SuccessRemoveFailureIsNonFatal(t *testing.T) {
|
||||
// Simulate a removal failure.
|
||||
apiClient.EXPECT().
|
||||
ContainerRemove(gomock.Any(), "hook-1", client.ContainerRemoveOptions{RemoveVolumes: true}).
|
||||
Return(client.ContainerRemoveResult{}, fmt.Errorf("already removed"))
|
||||
Return(client.ContainerRemoveResult{}, errors.New("already removed"))
|
||||
|
||||
// The hook succeeded; the service must start even if removal failed.
|
||||
err := tested.runPreStart(t.Context(), project, service, ctr, nil)
|
||||
@@ -778,7 +778,7 @@ func TestPreStart_StreamLogsError_NilListener(t *testing.T) {
|
||||
Return(waitResultExit(0))
|
||||
// ContainerLogs fails; nil listener → no warning event, done closed immediately.
|
||||
apiClient.EXPECT().ContainerLogs(gomock.Any(), "hook-1", gomock.Any()).
|
||||
Return(nil, fmt.Errorf("logs: connection refused"))
|
||||
Return(nil, errors.New("logs: connection refused"))
|
||||
apiClient.EXPECT().ContainerStart(gomock.Any(), "hook-1", gomock.Any()).
|
||||
Return(client.ContainerStartResult{}, nil)
|
||||
expectSuccessRemove(apiClient, "hook-1")
|
||||
@@ -809,7 +809,7 @@ func TestPreStart_StreamLogsError_WithListener(t *testing.T) {
|
||||
apiClient.EXPECT().ContainerWait(gomock.Any(), "hook-1", gomock.Any()).
|
||||
Return(waitResultExit(0))
|
||||
apiClient.EXPECT().ContainerLogs(gomock.Any(), "hook-1", gomock.Any()).
|
||||
Return(nil, fmt.Errorf("logs: daemon unavailable"))
|
||||
Return(nil, errors.New("logs: daemon unavailable"))
|
||||
apiClient.EXPECT().ContainerStart(gomock.Any(), "hook-1", gomock.Any()).
|
||||
Return(client.ContainerStartResult{}, nil)
|
||||
expectSuccessRemove(apiClient, "hook-1")
|
||||
@@ -917,7 +917,7 @@ func TestPreStart_ConnectExtraNetworksFails(t *testing.T) {
|
||||
|
||||
apiClient.EXPECT().
|
||||
NetworkConnect(gomock.Any(), "proj_extra", gomock.Any()).
|
||||
Return(client.NetworkConnectResult{}, fmt.Errorf("network not found"))
|
||||
Return(client.NetworkConnectResult{}, errors.New("network not found"))
|
||||
|
||||
err := tested.connectPreStartExtraNetworks(t.Context(), project, service, "ctr-id", "proj_default")
|
||||
assert.ErrorContains(t, err, "network not found")
|
||||
@@ -947,10 +947,10 @@ func TestPreStart_ContainerStartFailureAndRemoveFails(t *testing.T) {
|
||||
logs1 := apiClient.EXPECT().ContainerLogs(gomock.Any(), "hook-1", gomock.Any()).
|
||||
Return(emptyLogs(), nil)
|
||||
start1 := apiClient.EXPECT().ContainerStart(gomock.Any(), "hook-1", gomock.Any()).
|
||||
Return(client.ContainerStartResult{}, fmt.Errorf("start failed")).After(logs1)
|
||||
Return(client.ContainerStartResult{}, errors.New("start failed")).After(logs1)
|
||||
// Both the start AND the cleanup removal fail.
|
||||
apiClient.EXPECT().ContainerRemove(gomock.Any(), "hook-1", client.ContainerRemoveOptions{Force: true, RemoveVolumes: true}).
|
||||
Return(client.ContainerRemoveResult{}, fmt.Errorf("removal failed")).After(start1)
|
||||
Return(client.ContainerRemoveResult{}, errors.New("removal failed")).After(start1)
|
||||
|
||||
err := tested.runPreStart(t.Context(), project, service, ctr, nil)
|
||||
// The original start error must be returned, not the removal error.
|
||||
@@ -975,7 +975,7 @@ func TestPreStart_OrphanScanFails(t *testing.T) {
|
||||
|
||||
// ContainerList fails → Warnf in runPreStart; hook still proceeds.
|
||||
apiClient.EXPECT().ContainerList(gomock.Any(), gomock.Any()).
|
||||
Return(client.ContainerListResult{}, fmt.Errorf("daemon unavailable"))
|
||||
Return(client.ContainerListResult{}, errors.New("daemon unavailable"))
|
||||
apiClient.EXPECT().ContainerCreate(gomock.Any(), gomock.Any()).
|
||||
Return(client.ContainerCreateResult{ID: "hook-1"}, nil)
|
||||
apiClient.EXPECT().ContainerWait(gomock.Any(), "hook-1", gomock.Any()).
|
||||
@@ -1012,7 +1012,7 @@ func TestPreStart_OrphanRemovalFails(t *testing.T) {
|
||||
Return(client.ContainerListResult{Items: []container.Summary{orphan}}, nil)
|
||||
apiClient.EXPECT().
|
||||
ContainerRemove(gomock.Any(), "orphan-123", client.ContainerRemoveOptions{Force: true, RemoveVolumes: true}).
|
||||
Return(client.ContainerRemoveResult{}, fmt.Errorf("permission denied"))
|
||||
Return(client.ContainerRemoveResult{}, errors.New("permission denied"))
|
||||
// Hook still runs and succeeds.
|
||||
apiClient.EXPECT().ContainerCreate(gomock.Any(), gomock.Any()).
|
||||
Return(client.ContainerCreateResult{ID: "hook-1"}, nil)
|
||||
@@ -1059,7 +1059,7 @@ func TestPreStart_OldAPINetworkConnectFails(t *testing.T) {
|
||||
Return(client.ContainerCreateResult{ID: "hook-1"}, nil).After(scan)
|
||||
// NetworkConnect for the secondary network fails.
|
||||
apiClient.EXPECT().NetworkConnect(gomock.Any(), "proj_extra", gomock.Any()).
|
||||
Return(client.NetworkConnectResult{}, fmt.Errorf("network not found"))
|
||||
Return(client.NetworkConnectResult{}, errors.New("network not found"))
|
||||
// The never-started container is cleaned up (Force:true).
|
||||
apiClient.EXPECT().
|
||||
ContainerRemove(gomock.Any(), "hook-1", client.ContainerRemoveOptions{Force: true, RemoveVolumes: true}).
|
||||
@@ -1098,11 +1098,11 @@ func TestPreStart_OldAPINetworkConnectAndRemoveFails(t *testing.T) {
|
||||
apiClient.EXPECT().ContainerCreate(gomock.Any(), gomock.Any()).
|
||||
Return(client.ContainerCreateResult{ID: "hook-1"}, nil).After(scan)
|
||||
apiClient.EXPECT().NetworkConnect(gomock.Any(), "proj_extra", gomock.Any()).
|
||||
Return(client.NetworkConnectResult{}, fmt.Errorf("network not found"))
|
||||
Return(client.NetworkConnectResult{}, errors.New("network not found"))
|
||||
// Cleanup removal also fails → Warnf; original error is still returned.
|
||||
apiClient.EXPECT().
|
||||
ContainerRemove(gomock.Any(), "hook-1", client.ContainerRemoveOptions{Force: true, RemoveVolumes: true}).
|
||||
Return(client.ContainerRemoveResult{}, fmt.Errorf("removal also failed"))
|
||||
Return(client.ContainerRemoveResult{}, errors.New("removal also failed"))
|
||||
|
||||
err := tested.runPreStart(t.Context(), project, service, ctr, nil)
|
||||
assert.ErrorContains(t, err, "network not found")
|
||||
@@ -1139,7 +1139,7 @@ func TestPreStart_RuntimeAPIVersionError(t *testing.T) {
|
||||
// createPreStartContainer calls RuntimeAPIVersion → Ping fails.
|
||||
apiClient.EXPECT().
|
||||
Ping(gomock.Any(), client.PingOptions{NegotiateAPIVersion: true}).
|
||||
Return(client.PingResult{}, fmt.Errorf("daemon unreachable"))
|
||||
Return(client.PingResult{}, errors.New("daemon unreachable"))
|
||||
|
||||
err = s.runPreStart(t.Context(), project, service, ctr, nil)
|
||||
assert.ErrorContains(t, err, "daemon unreachable")
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/DefangLabs/secret-detector/pkg/detectors/keyword"
|
||||
@@ -610,7 +611,7 @@ func buildEnvPromptMessage(services map[string]*serviceEnvFindings) string {
|
||||
if keys := f.sortedSuspiciousKeys(); len(keys) > 0 {
|
||||
quoted := make([]string, len(keys))
|
||||
for i, k := range keys {
|
||||
quoted[i] = fmt.Sprintf("%q", k)
|
||||
quoted[i] = strconv.Quote(k)
|
||||
}
|
||||
fmt.Fprintf(&b, " service %q: literal value for %s\n", name, strings.Join(quoted, ", "))
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ func (r *reconciler) reconcileNetworks() error {
|
||||
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),
|
||||
ResourceID: "network:" + key,
|
||||
Cause: cause,
|
||||
Name: networkConfig.Name,
|
||||
Network: networkConfig,
|
||||
@@ -299,7 +299,7 @@ func (r *reconciler) planRecreateNetworks(keys []string) {
|
||||
|
||||
removeNode := r.plan.addNode(Operation{
|
||||
Type: OpRemoveNetwork,
|
||||
ResourceID: fmt.Sprintf("network:%s", key),
|
||||
ResourceID: "network:" + key,
|
||||
Cause: removeCause,
|
||||
Name: observed.Name,
|
||||
BestEffort: rename,
|
||||
@@ -311,7 +311,7 @@ func (r *reconciler) planRecreateNetworks(keys []string) {
|
||||
}
|
||||
createNode := r.plan.addNode(Operation{
|
||||
Type: OpCreateNetwork,
|
||||
ResourceID: fmt.Sprintf("network:%s", key),
|
||||
ResourceID: "network:" + key,
|
||||
Cause: createCause,
|
||||
Name: desired.Name,
|
||||
Network: &desired,
|
||||
@@ -403,7 +403,7 @@ func (r *reconciler) reconcileVolumes() error {
|
||||
func (r *reconciler) planCreateVolume(key string, vol *types.VolumeConfig, cause string) {
|
||||
r.volumeNodes[key] = r.plan.addNode(Operation{
|
||||
Type: OpCreateVolume,
|
||||
ResourceID: fmt.Sprintf("volume:%s", key),
|
||||
ResourceID: "volume:" + key,
|
||||
Cause: cause,
|
||||
Name: vol.Name,
|
||||
Volume: vol,
|
||||
@@ -477,13 +477,13 @@ func (r *reconciler) planRecreateVolumes(keys []string) {
|
||||
desired := r.project.Volumes[key]
|
||||
removeVolNode := r.plan.addNode(Operation{
|
||||
Type: OpRemoveVolume,
|
||||
ResourceID: fmt.Sprintf("volume:%s", key),
|
||||
ResourceID: "volume:" + key,
|
||||
Cause: "config hash diverged",
|
||||
Name: r.resolvedVolumes[key].Name,
|
||||
}, "", removeNodes...)
|
||||
createVolNode := r.plan.addNode(Operation{
|
||||
Type: OpCreateVolume,
|
||||
ResourceID: fmt.Sprintf("volume:%s", key),
|
||||
ResourceID: "volume:" + key,
|
||||
Cause: "recreate after config change",
|
||||
Name: desired.Name,
|
||||
Volume: &desired,
|
||||
@@ -649,7 +649,7 @@ func (r *reconciler) reconcileService(service types.ServiceConfig) error {
|
||||
deps := r.infrastructureDeps(service)
|
||||
node := r.plan.addNode(Operation{
|
||||
Type: OpRunProvider,
|
||||
ResourceID: fmt.Sprintf("provider:%s", service.Name),
|
||||
ResourceID: "provider:" + service.Name,
|
||||
Cause: "provider service",
|
||||
Service: &serviceCopy,
|
||||
}, "", deps...)
|
||||
@@ -1051,14 +1051,14 @@ func (r *reconciler) reconcileOrphans() {
|
||||
for i, oc := range r.observed.Orphans {
|
||||
stopNode := r.plan.addNode(Operation{
|
||||
Type: OpStopContainer,
|
||||
ResourceID: fmt.Sprintf("orphan:%s", oc.Name),
|
||||
ResourceID: "orphan:" + oc.Name,
|
||||
Cause: "orphaned container",
|
||||
Container: &r.observed.Orphans[i].Summary,
|
||||
Timeout: r.options.Timeout,
|
||||
}, "")
|
||||
r.plan.addNode(Operation{
|
||||
Type: OpRemoveContainer,
|
||||
ResourceID: fmt.Sprintf("orphan:%s", oc.Name),
|
||||
ResourceID: "orphan:" + oc.Name,
|
||||
Cause: "orphaned container",
|
||||
Container: &r.observed.Orphans[i].Summary,
|
||||
}, "", stopNode)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -511,7 +512,7 @@ func TestReconcileVolumes_DivergedPromptMessage(t *testing.T) {
|
||||
func TestReconcileVolumes_DivergedPromptError(t *testing.T) {
|
||||
project, observed := divergedVolumeProject(t, 1, 1)
|
||||
|
||||
boom := func(_ string, _ bool) (bool, error) { return false, fmt.Errorf("boom") }
|
||||
boom := func(_ string, _ bool) (bool, error) { return false, errors.New("boom") }
|
||||
_, err := reconcile(t.Context(), project, observed, defaultReconcileOptions(), boom)
|
||||
assert.ErrorContains(t, err, "boom")
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ func (s *composeService) Remove(ctx context.Context, projectName string, options
|
||||
return api.ErrNoResources
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("Going to remove %s", strings.Join(names, ", "))
|
||||
msg := "Going to remove " + strings.Join(names, ", ")
|
||||
if options.Force {
|
||||
_, _ = fmt.Fprintln(s.stdout(), msg)
|
||||
} else {
|
||||
|
||||
@@ -189,7 +189,7 @@ func (s *composeService) waitDependencies(ctx context.Context, project *types.Pr
|
||||
}
|
||||
err := eg.Wait()
|
||||
if errors.Is(err, context.DeadlineExceeded) {
|
||||
return fmt.Errorf("timeout waiting for dependencies")
|
||||
return errors.New("timeout waiting for dependencies")
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -299,12 +299,12 @@ func (s *composeService) checkDependencyCompleted(ctx context.Context, dep strin
|
||||
if !config.Required {
|
||||
// optional -> mark as skipped & don't propagate error
|
||||
s.events.On(containerReasonEvents(waitingFor, skippedEvent,
|
||||
fmt.Sprintf("optional dependency %s", messageSuffix))...)
|
||||
"optional dependency "+messageSuffix)...)
|
||||
logrus.Warnf("optional dependency %s", messageSuffix)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("service %s", messageSuffix)
|
||||
msg := "service " + messageSuffix
|
||||
s.events.On(containerEvents(waitingFor, func(s string) api.Resource {
|
||||
return errorEventf(s, "service %s", messageSuffix)
|
||||
})...)
|
||||
|
||||
@@ -18,6 +18,7 @@ package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"strings"
|
||||
@@ -695,7 +696,7 @@ func TestCreateMobyContainerLegacyAPI_NetworkConnectFailure(t *testing.T) {
|
||||
Return(client.ContainerCreateResult{ID: "an-id"}, nil)
|
||||
|
||||
// NetworkConnect fails
|
||||
connectErr := fmt.Errorf("network connect failed")
|
||||
connectErr := errors.New("network connect failed")
|
||||
apiClient.EXPECT().NetworkConnect(gomock.Any(), gomock.Eq("a-moby-name"), gomock.Any()).
|
||||
Return(client.NetworkConnectResult{}, connectErr)
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ func NewWatcher(project *types.Project, options api.UpOptions, w WatchFunc, cons
|
||||
}
|
||||
}
|
||||
// none of the services is eligible to watch
|
||||
return nil, fmt.Errorf("none of the selected services is configured for watch, see https://docs.docker.com/compose/how-tos/file-watch/")
|
||||
return nil, errors.New("none of the selected services is configured for watch, see https://docs.docker.com/compose/how-tos/file-watch/")
|
||||
}
|
||||
|
||||
// ensure state changes are atomic
|
||||
@@ -236,7 +236,7 @@ func (s *composeService) watch(ctx context.Context, project *types.Project, opti
|
||||
}
|
||||
|
||||
if len(paths) == 0 {
|
||||
return nil, fmt.Errorf("none of the selected services is configured for watch, consider setting a 'develop' section")
|
||||
return nil, errors.New("none of the selected services is configured for watch, consider setting a 'develop' section")
|
||||
}
|
||||
|
||||
watcher, err := watch.NewWatcher(paths)
|
||||
@@ -543,7 +543,7 @@ func (t tarDockerClient) Exec(ctx context.Context, containerID string, cmd []str
|
||||
return errors.New("process still running")
|
||||
}
|
||||
if execResult.ExitCode != 0 {
|
||||
return fmt.Errorf("exit code %d", execResult.ExitCode)
|
||||
return errors.New("exit code " + strconv.Itoa(execResult.ExitCode))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -300,7 +301,7 @@ func (d *DryRunClient) VolumeRemove(ctx context.Context, volumeID string, option
|
||||
func (d *DryRunClient) ExecCreate(ctx context.Context, container string, config client.ExecCreateOptions) (client.ExecCreateResult, error) {
|
||||
b := make([]byte, 32)
|
||||
_, _ = rand.Read(b)
|
||||
id := fmt.Sprintf("%x", b)
|
||||
id := hex.EncodeToString(b)
|
||||
d.execs.Store(id, execDetails{
|
||||
container: container,
|
||||
command: config.Cmd,
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
@@ -49,7 +48,7 @@ func TestBridgeConvertOutputNotEmptyDeclined(t *testing.T) {
|
||||
|
||||
s.Step("convert without confirmation leaves the non-empty output directory untouched",
|
||||
ComposeCmd("bridge", "convert", "--output", outDir,
|
||||
"--transformation", fmt.Sprintf("docker/compose-bridge-kubernetes:%s", bridgeImageVersion)).MayFail(),
|
||||
"--transformation", "docker/compose-bridge-kubernetes:"+bridgeImageVersion).MayFail(),
|
||||
ExitCode(1),
|
||||
FileContains(guardFile, "do not delete me"))
|
||||
}
|
||||
@@ -60,7 +59,7 @@ func TestBridgeConvertOutputNotEmptyConfirmed(t *testing.T) {
|
||||
|
||||
s.Step("convert --yes wipes the stale content and regenerates the output",
|
||||
ComposeCmd("bridge", "convert", "--output", outDir, "--yes",
|
||||
"--transformation", fmt.Sprintf("docker/compose-bridge-kubernetes:%s", bridgeImageVersion)),
|
||||
"--transformation", "docker/compose-bridge-kubernetes:"+bridgeImageVersion),
|
||||
FileAbsent(guardFile),
|
||||
FileExists(filepath.Join(outDir, "base", "0-"+s.Project()+"-namespace.yaml")))
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -39,7 +38,7 @@ func TestConvertAndTransformList(t *testing.T) {
|
||||
t.Run("kubernetes manifests", func(t *testing.T) {
|
||||
kubedir := filepath.Join(tmpDir, "kubernetes")
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/bridge/compose.yaml", "--project-name", projectName, "bridge", "convert",
|
||||
"--output", kubedir, "--transformation", fmt.Sprintf("docker/compose-bridge-kubernetes:%s", bridgeImageVersion))
|
||||
"--output", kubedir, "--transformation", "docker/compose-bridge-kubernetes:"+bridgeImageVersion)
|
||||
assert.NilError(t, res.Error)
|
||||
assert.Equal(t, res.ExitCode, 0)
|
||||
res = c.RunCmd(t, "diff", "-r", kubedir, "./fixtures/bridge/expected-kubernetes")
|
||||
@@ -49,7 +48,7 @@ func TestConvertAndTransformList(t *testing.T) {
|
||||
t.Run("helm charts", func(t *testing.T) {
|
||||
helmDir := filepath.Join(tmpDir, "helm")
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/bridge/compose.yaml", "--project-name", projectName, "bridge", "convert",
|
||||
"--output", helmDir, "--transformation", fmt.Sprintf("docker/compose-bridge-helm:%s", bridgeImageVersion))
|
||||
"--output", helmDir, "--transformation", "docker/compose-bridge-helm:"+bridgeImageVersion)
|
||||
assert.NilError(t, res.Error)
|
||||
assert.Equal(t, res.ExitCode, 0)
|
||||
res = c.RunCmd(t, "diff", "-r", helmDir, "./fixtures/bridge/expected-helm")
|
||||
@@ -69,7 +68,7 @@ func TestConvertBuildOnlyService(t *testing.T) {
|
||||
outDir := t.TempDir()
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/bridge-build-only/compose.yaml", "--project-name", "bridge-build-only", "bridge", "convert",
|
||||
"--output", outDir, "--transformation", fmt.Sprintf("docker/compose-bridge-kubernetes:%s", bridgeImageVersion))
|
||||
"--output", outDir, "--transformation", "docker/compose-bridge-kubernetes:"+bridgeImageVersion)
|
||||
assert.NilError(t, res.Error)
|
||||
assert.Equal(t, res.ExitCode, 0)
|
||||
|
||||
|
||||
+18
-16
@@ -23,11 +23,13 @@ package e2e
|
||||
// test-specific logic), and are named after the observable they assert.
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -67,7 +69,7 @@ func OutputContains(sub string) Check {
|
||||
name: fmt.Sprintf("output contains %q", sub),
|
||||
fn: func(ctx *CheckContext) error {
|
||||
if !strings.Contains(ctx.result.Combined(), sub) {
|
||||
return fmt.Errorf("not found in output")
|
||||
return errors.New("not found in output")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
@@ -82,7 +84,7 @@ func StdoutContains(sub string) Check {
|
||||
name: fmt.Sprintf("stdout contains %q", sub),
|
||||
fn: func(ctx *CheckContext) error {
|
||||
if !strings.Contains(ctx.result.Stdout(), sub) {
|
||||
return fmt.Errorf("not found in stdout")
|
||||
return errors.New("not found in stdout")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
@@ -97,7 +99,7 @@ func OutputMatches(pattern string) Check {
|
||||
name: fmt.Sprintf("output matches %q", pattern),
|
||||
fn: func(ctx *CheckContext) error {
|
||||
if !re.MatchString(ctx.result.Stdout()) {
|
||||
return fmt.Errorf("no match in stdout")
|
||||
return errors.New("no match in stdout")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
@@ -127,7 +129,7 @@ func StderrContains(sub string) Check {
|
||||
name: fmt.Sprintf("stderr contains %q", sub),
|
||||
fn: func(ctx *CheckContext) error {
|
||||
if !strings.Contains(ctx.result.Stderr(), sub) {
|
||||
return fmt.Errorf("not found in stderr")
|
||||
return errors.New("not found in stderr")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
@@ -140,7 +142,7 @@ func OutputNotContains(sub string) Check {
|
||||
name: fmt.Sprintf("output does not contain %q", sub),
|
||||
fn: func(ctx *CheckContext) error {
|
||||
if strings.Contains(ctx.result.Combined(), sub) {
|
||||
return fmt.Errorf("found in output")
|
||||
return errors.New("found in output")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
@@ -220,7 +222,7 @@ func ServiceState(service, state string) Check {
|
||||
fn: func(ctx *CheckContext) error {
|
||||
containers := ctx.curr.service(service)
|
||||
if len(containers) == 0 {
|
||||
return fmt.Errorf("service has no container")
|
||||
return errors.New("service has no container")
|
||||
}
|
||||
for _, c := range containers {
|
||||
if c.State != state {
|
||||
@@ -264,7 +266,7 @@ func ReplicaNumbers(service string, numbers ...int) Check {
|
||||
slices.Sort(actual)
|
||||
var expected []string
|
||||
for _, n := range numbers {
|
||||
expected = append(expected, fmt.Sprint(n))
|
||||
expected = append(expected, strconv.Itoa(n))
|
||||
}
|
||||
slices.Sort(expected)
|
||||
if !slices.Equal(actual, expected) {
|
||||
@@ -353,7 +355,7 @@ func ServiceHealthy(service string) Check {
|
||||
fn: func(ctx *CheckContext) error {
|
||||
containers := ctx.curr.service(service)
|
||||
if len(containers) == 0 {
|
||||
return fmt.Errorf("service has no container")
|
||||
return errors.New("service has no container")
|
||||
}
|
||||
for _, c := range containers {
|
||||
res := icmd.RunCmd(ctx.scenario.cli.NewDockerCmd(ctx.scenario.t,
|
||||
@@ -378,7 +380,7 @@ func OneOffState(service, state string) Check {
|
||||
fn: func(ctx *CheckContext) error {
|
||||
containers := ctx.curr.oneOffs(service)
|
||||
if len(containers) == 0 {
|
||||
return fmt.Errorf("service has no one-off container")
|
||||
return errors.New("service has no one-off container")
|
||||
}
|
||||
for _, c := range containers {
|
||||
if c.State != state {
|
||||
@@ -399,7 +401,7 @@ func OneOffsUntouched(service string) Check {
|
||||
fn: func(ctx *CheckContext) error {
|
||||
before, after := ctx.prev.oneOffs(service), ctx.curr.oneOffs(service)
|
||||
if len(before) == 0 {
|
||||
return fmt.Errorf("service had no one-off container before the step")
|
||||
return errors.New("service had no one-off container before the step")
|
||||
}
|
||||
if !slices.Equal(containerIDs(before), containerIDs(after)) {
|
||||
return fmt.Errorf("one-off containers changed: %v -> %v", containerIDs(before), containerIDs(after))
|
||||
@@ -424,7 +426,7 @@ func OneOffsRemoved(service string) Check {
|
||||
name: fmt.Sprintf("one-offs of service %q removed", service),
|
||||
fn: func(ctx *CheckContext) error {
|
||||
if len(ctx.prev.oneOffs(service)) == 0 {
|
||||
return fmt.Errorf("service had no one-off container before the step")
|
||||
return errors.New("service had no one-off container before the step")
|
||||
}
|
||||
var names []string
|
||||
for _, c := range ctx.curr.oneOffs(service) {
|
||||
@@ -464,7 +466,7 @@ func FileExists(path string) Check {
|
||||
return err
|
||||
}
|
||||
if info.Size() == 0 {
|
||||
return fmt.Errorf("file is empty")
|
||||
return errors.New("file is empty")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
@@ -496,7 +498,7 @@ func FileAbsent(path string) Check {
|
||||
name: fmt.Sprintf("file %q is absent", path),
|
||||
fn: func(ctx *CheckContext) error {
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
return fmt.Errorf("file still exists")
|
||||
return errors.New("file still exists")
|
||||
} else if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
@@ -512,7 +514,7 @@ func LabelSet(service, key string) Check {
|
||||
fn: func(ctx *CheckContext) error {
|
||||
containers := ctx.curr.service(service)
|
||||
if len(containers) == 0 {
|
||||
return fmt.Errorf("service has no container")
|
||||
return errors.New("service has no container")
|
||||
}
|
||||
for _, c := range containers {
|
||||
if c.Labels[key] == "" {
|
||||
@@ -555,7 +557,7 @@ func LabelUnchanged(service, key string) Check {
|
||||
fn: func(ctx *CheckContext) error {
|
||||
before, after := ctx.prev.service(service), ctx.curr.service(service)
|
||||
if len(before) == 0 || len(after) == 0 {
|
||||
return fmt.Errorf("service has no container to compare")
|
||||
return errors.New("service has no container to compare")
|
||||
}
|
||||
if before[0].Labels[key] != after[0].Labels[key] {
|
||||
return fmt.Errorf("label changed: %q -> %q", before[0].Labels[key], after[0].Labels[key])
|
||||
@@ -573,7 +575,7 @@ func RunsOnPlatform(service, platform string) Check {
|
||||
fn: func(ctx *CheckContext) error {
|
||||
containers := ctx.curr.service(service)
|
||||
if len(containers) == 0 {
|
||||
return fmt.Errorf("service has no container")
|
||||
return errors.New("service has no container")
|
||||
}
|
||||
res := icmd.RunCmd(ctx.scenario.cli.NewDockerCmd(ctx.scenario.t, "inspect", "--format",
|
||||
"{{.ImageManifestDescriptor.Platform.OS}}/{{.ImageManifestDescriptor.Platform.Architecture}}",
|
||||
|
||||
@@ -282,7 +282,7 @@ func (c *CLI) BaseEnvironment() []string {
|
||||
_, filename, _, _ := runtime.Caller(0)
|
||||
root := filepath.Join(filepath.Dir(filename), "..", "..")
|
||||
coverdir = filepath.Join(root, coverdir)
|
||||
env = append(env, fmt.Sprintf("GOCOVERDIR=%s", coverdir))
|
||||
env = append(env, "GOCOVERDIR="+coverdir)
|
||||
}
|
||||
return env
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ package e2e
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -203,7 +204,7 @@ func doTest(t *testing.T, svcName string) {
|
||||
waitForFlush := func() {
|
||||
b := make([]byte, 32)
|
||||
_, _ = rand.Read(b)
|
||||
sentinelVal := fmt.Sprintf("%x", b)
|
||||
sentinelVal := hex.EncodeToString(b)
|
||||
writeDataFile("wait.txt", sentinelVal)
|
||||
poll.WaitOn(t, checkFileContents("/app/data/wait.txt", sentinelVal))
|
||||
}
|
||||
|
||||
+3
-2
@@ -19,6 +19,7 @@ package remote
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -49,7 +50,7 @@ const (
|
||||
func validatePathInBase(base, unsafePath string) error {
|
||||
// Reject paths with path separators regardless of OS
|
||||
if strings.ContainsAny(unsafePath, "\\/") {
|
||||
return fmt.Errorf("invalid OCI artifact")
|
||||
return errors.New("invalid OCI artifact")
|
||||
}
|
||||
|
||||
// Join the base with the untrusted path
|
||||
@@ -64,7 +65,7 @@ func validatePathInBase(base, unsafePath string) error {
|
||||
|
||||
// Check if the target directory is the same as base directory
|
||||
if cleanTargetDir != cleanBase {
|
||||
return fmt.Errorf("invalid OCI artifact")
|
||||
return errors.New("invalid OCI artifact")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -120,7 +120,7 @@ func absPatterns(absRoot string, patterns []string) []string {
|
||||
}
|
||||
absPattern := pPath
|
||||
if isExclusion {
|
||||
absPattern = fmt.Sprintf("!%s", pPath)
|
||||
absPattern = "!" + pPath
|
||||
}
|
||||
absPatterns = append(absPatterns, absPattern)
|
||||
}
|
||||
|
||||
+1
-2
@@ -18,7 +18,6 @@ package watch
|
||||
|
||||
import (
|
||||
"expvar"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
@@ -30,7 +29,7 @@ type FileEvent string
|
||||
|
||||
func NewFileEvent(p string) FileEvent {
|
||||
if !filepath.IsAbs(p) {
|
||||
panic(fmt.Sprintf("NewFileEvent only accepts absolute paths. Actual: %s", p))
|
||||
panic("NewFileEvent only accepts absolute paths. Actual: " + p)
|
||||
}
|
||||
return FileEvent(p)
|
||||
}
|
||||
|
||||
+2
-1
@@ -17,6 +17,7 @@
|
||||
package watch
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -25,7 +26,7 @@ import (
|
||||
func greatestExistingAncestor(path string) (string, error) {
|
||||
if path == string(filepath.Separator) ||
|
||||
path == fmt.Sprintf("%s%s", filepath.VolumeName(path), string(filepath.Separator)) {
|
||||
return "", fmt.Errorf("cannot watch root directory")
|
||||
return "", errors.New("cannot watch root directory")
|
||||
}
|
||||
|
||||
_, err := os.Stat(path)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
package watch
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
@@ -301,7 +302,7 @@ func newWatcher(paths []string) (Notify, error) {
|
||||
fsw, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "too many open files") && runtime.GOOS == "linux" {
|
||||
return nil, fmt.Errorf("hit OS limits creating a watcher.\n" +
|
||||
return nil, errors.New("hit OS limits creating a watcher.\n" +
|
||||
"Run 'sysctl fs.inotify.max_user_instances' to check your inotify limits.\n" +
|
||||
"To raise them, run 'sudo sysctl fs.inotify.max_user_instances=1024'")
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ func TestDontWatchEachFile(t *testing.T) {
|
||||
}
|
||||
|
||||
for i := range 100 {
|
||||
f.WriteFile(f.JoinPath(initialDir, fmt.Sprintf("%d", i)), "initial data")
|
||||
f.WriteFile(f.JoinPath(initialDir, strconv.Itoa(i)), "initial data")
|
||||
}
|
||||
|
||||
f.watch(watched)
|
||||
@@ -80,7 +80,7 @@ func TestDontWatchEachFile(t *testing.T) {
|
||||
}
|
||||
|
||||
for i := range 100 {
|
||||
f.WriteFile(f.JoinPath(inplaceDir, fmt.Sprintf("%d", i)), "inplace data")
|
||||
f.WriteFile(f.JoinPath(inplaceDir, strconv.Itoa(i)), "inplace data")
|
||||
}
|
||||
|
||||
f.fsync()
|
||||
@@ -99,7 +99,7 @@ func TestDontWatchEachFile(t *testing.T) {
|
||||
}
|
||||
|
||||
for i := range 100 {
|
||||
f.WriteFile(f.JoinPath(stagedDir, fmt.Sprintf("%d", i)), "staged data")
|
||||
f.WriteFile(f.JoinPath(stagedDir, strconv.Itoa(i)), "staged data")
|
||||
}
|
||||
|
||||
if err := os.Rename(staged, f.JoinPath(watched, "staged")); err != nil {
|
||||
@@ -115,7 +115,7 @@ func TestDontWatchEachFile(t *testing.T) {
|
||||
n, err := inotifyNodes()
|
||||
assert.NilError(t, err)
|
||||
if n > 10 {
|
||||
t.Fatalf("watching more than 10 files: %d", n)
|
||||
t.Fatal("watching more than 10 files:", n)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,14 +147,14 @@ func TestDontRecurseWhenWatchingParentsOfNonExistentFiles(t *testing.T) {
|
||||
|
||||
excludedDir := f.JoinPath(watched, "excluded")
|
||||
for i := range 10 {
|
||||
f.WriteFile(f.JoinPath(excludedDir, fmt.Sprintf("%d", i), "data.txt"), "initial data")
|
||||
f.WriteFile(f.JoinPath(excludedDir, strconv.Itoa(i), "data.txt"), "initial data")
|
||||
}
|
||||
f.fsync()
|
||||
|
||||
n, err := inotifyNodes()
|
||||
assert.NilError(t, err)
|
||||
if n > 5 {
|
||||
t.Fatalf("watching more than 5 files: %d", n)
|
||||
t.Fatal("watching more than 5 files:", n)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user