From 2d5faff6a1b6e06e42ecac0d9a3ee95346635fe6 Mon Sep 17 00:00:00 2001 From: Martin Hickey Date: Fri, 4 Oct 2019 17:28:02 +0100 Subject: [PATCH] Create file locking directory if it does not exist (#6555) * Create file locking directory if it does not exist As Helm v3 uses lazy creation for configuration then directories and files are not created until required. File locking when doing repo add was introduced in v2 and ported to v3 in #6492. It locks on the config directory where the repo file resides and therefore needs the directory to be created if it doesn't exist. This fix adds the directory if need be, Signed-off-by: Martin Hickey * Add unit test Signed-off-by: Martin Hickey --- cmd/helm/repo_add.go | 7 +++++++ cmd/helm/repo_add_test.go | 12 ++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cmd/helm/repo_add.go b/cmd/helm/repo_add.go index 96162499f..a28bb82a1 100644 --- a/cmd/helm/repo_add.go +++ b/cmd/helm/repo_add.go @@ -22,6 +22,7 @@ import ( "io" "io/ioutil" "os" + "path/filepath" "time" "github.com/gofrs/flock" @@ -78,6 +79,12 @@ func newRepoAddCmd(out io.Writer) *cobra.Command { } func (o *repoAddOptions) run(out io.Writer) error { + //Ensure the file directory exists as it is required for file locking + err := os.MkdirAll(filepath.Dir(o.repoFile), os.ModePerm) + if err != nil && !os.IsExist(err) { + return err + } + // Lock the repository file for concurrent goroutines or processes synchronization fileLock := flock.New(o.repoFile) lockCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) diff --git a/cmd/helm/repo_add_test.go b/cmd/helm/repo_add_test.go index c53f3bd65..1ac61fba8 100644 --- a/cmd/helm/repo_add_test.go +++ b/cmd/helm/repo_add_test.go @@ -92,15 +92,23 @@ func TestRepoAdd(t *testing.T) { func TestRepoAddConcurrentGoRoutines(t *testing.T) { const testName = "test-name" + repoFile := filepath.Join(ensure.TempDir(t), "repositories.yaml") + repoAddConcurrent(t, testName, repoFile) +} + +func TestRepoAddConcurrentDirNotExist(t *testing.T) { + const testName = "test-name-2" + repoFile := filepath.Join(ensure.TempDir(t), "foo", "repositories.yaml") + repoAddConcurrent(t, testName, repoFile) +} +func repoAddConcurrent(t *testing.T, testName, repoFile string) { ts, err := repotest.NewTempServer("testdata/testserver/*.*") if err != nil { t.Fatal(err) } defer ts.Stop() - repoFile := filepath.Join(ensure.TempDir(t), "repositories.yaml") - var wg sync.WaitGroup wg.Add(3) for i := 0; i < 3; i++ {