Skip to content

Commit

Permalink
Merge pull request #345 from mykso/unique-tmp-dir
Browse files Browse the repository at this point in the history
Fix race condition when running multiple vendir from the same directory
  • Loading branch information
joaopapereira authored Jan 10, 2024
2 parents e4babdd + f9ac5a0 commit c1e3217
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 11 deletions.
7 changes: 5 additions & 2 deletions pkg/vendir/directory/directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
16 changes: 7 additions & 9 deletions pkg/vendir/directory/staging_dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
59 changes: 59 additions & 0 deletions test/e2e/concurrent_processes_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
})
}

0 comments on commit c1e3217

Please sign in to comment.