diff --git a/pkg/vendir/directory/directory.go b/pkg/vendir/directory/directory.go index 8f580cf5..89448144 100644 --- a/pkg/vendir/directory/directory.go +++ b/pkg/vendir/directory/directory.go @@ -58,9 +58,12 @@ func createConfigDigest(contents ctlconf.DirectoryContents) (string, error) { func (d *Directory) Sync(syncOpts SyncOpts) (ctlconf.LockDirectory, error) { lockConfig := ctlconf.LockDirectory{Path: d.opts.Path} - stagingDir := NewStagingDir() + stagingDir, err := NewStagingDir() + if err != nil { + return lockConfig, err + } - err := stagingDir.Prepare() + err = stagingDir.Prepare() if err != nil { return lockConfig, err } diff --git a/pkg/vendir/directory/staging_dir.go b/pkg/vendir/directory/staging_dir.go index 1e82c590..f7340cf3 100644 --- a/pkg/vendir/directory/staging_dir.go +++ b/pkg/vendir/directory/staging_dir.go @@ -20,22 +20,20 @@ type StagingDir struct { incomingDir string } -func NewStagingDir() StagingDir { - rootDir := ".vendir-tmp" +func NewStagingDir() (StagingDir, error) { + rootDir, err := os.MkdirTemp(".", ".vendir-tmp-") + if err != nil { + return StagingDir{}, err + } return StagingDir{ rootDir: rootDir, stagingDir: filepath.Join(rootDir, "staging"), incomingDir: filepath.Join(rootDir, "incoming"), - } + }, nil } func (d StagingDir) Prepare() error { - err := d.cleanUpAll() - if err != nil { - return err - } - - err = os.MkdirAll(d.stagingDir, 0700) + err := os.MkdirAll(d.stagingDir, 0700) if err != nil { return fmt.Errorf("Creating staging dir '%s': %s", d.stagingDir, err) } diff --git a/test/e2e/concurrent_processes_test.go b/test/e2e/concurrent_processes_test.go new file mode 100644 index 00000000..06ca7dd1 --- /dev/null +++ b/test/e2e/concurrent_processes_test.go @@ -0,0 +1,59 @@ +// Copyright 2023 VMware, Inc. +// SPDX-License-Identifier: Apache-2.0 + +package e2e + +import ( + "fmt" + "os" + "strings" + "sync" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestConcurrentProcesses(t *testing.T) { + env := BuildEnv(t) + logger := Logger{} + vendir := Vendir{t, env.BinaryPath, logger} + tmpRoot := t.TempDir() + processes := 2 + + yaml := ` +apiVersion: vendir.k14s.io/v1alpha1 +kind: Config +directories: +- path: vendor/dest-%d + contents: + - path: . + git: + url: https://github.com/carvel-dev/ytt + ref: v0.27.x + depth: 1 + includePaths: + - README.md + - pkg/version/version.go` + + logger.Section("execute several vendir processes concurrently", func() { + wg := sync.WaitGroup{} + for i := 0; i < processes; i++ { + wg.Add(1) + go func(n int, t *testing.T, wg *sync.WaitGroup) { + defer wg.Done() + // RunWithOpts invokes t.Fatal on error + vendir.RunWithOpts( + []string{"sync", "-f", "-"}, + RunOpts{ + Dir: tmpRoot, + StdinReader: strings.NewReader(fmt.Sprintf(yaml, n)), + }) + }(i, t, &wg) + } + wg.Wait() + for i := 0; i < processes; i++ { + _, err := os.Stat(fmt.Sprintf("%s/vendor/dest-%d/README.md", tmpRoot, i)) + require.NoError(t, err) + } + }) +}