Skip to content

Commit

Permalink
Reorder push command operations
Browse files Browse the repository at this point in the history
Narrow down the window of opportunity for race conditions

Reference issue: #18
The idea was presented in this PR: #19
  • Loading branch information
hypnoglow committed Dec 19, 2017
1 parent c535f50 commit 737a82c
Showing 1 changed file with 26 additions and 19 deletions.
45 changes: 26 additions & 19 deletions cmd/helms3/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path/filepath"
"time"

"github.com/pkg/errors"
"k8s.io/helm/pkg/chartutil"
Expand All @@ -16,7 +17,15 @@ import (
"github.com/hypnoglow/helm-s3/pkg/index"
)

const (
pushCommandDefaultTimeout = time.Second * 15
)

func runPush(chartPath string, repoName string) error {
// Just one big timeout for the whole operation.
ctx, cancel := context.WithTimeout(context.Background(), pushCommandDefaultTimeout)
defer cancel()

fpath, err := filepath.Abs(chartPath)
if err != nil {
return errors.WithMessage(err, "get chart abs path")
Expand All @@ -36,7 +45,8 @@ func runPush(chartPath string, repoName string) error {

storage := awss3.NewStorage(awsConfig)

// Load chart and calculate required params like hash.
// Load chart, calculate required params like hash,
// and upload the chart right away.

chart, err := chartutil.LoadFile(fname)
if err != nil {
Expand All @@ -48,15 +58,26 @@ func runPush(chartPath string, repoName string) error {
return err
}

fchart, err := os.Open(fname)
if err != nil {
return errors.Wrap(err, "open chart file")
}

if _, err := storage.Upload(ctx, repoEntry.URL+"/"+fname, fchart); err != nil {
return errors.WithMessage(err, "upload chart to s3")
}

// Next, update the repository index.
// The gap between index fetching and uploading should be as small as
// possible to make the best effort to avoid race conditions.
// See https://github.com/hypnoglow/helm-s3/issues/18 for more info.

hash, err := provenance.DigestFile(fname)
if err != nil {
return errors.WithMessage(err, "get chart digest")
}

// Fetch current index.

ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
defer cancel()
// Fetch current index, update it and upload it back.

b, err := storage.FetchRaw(ctx, repoEntry.URL+"/index.yaml")
if err != nil {
Expand All @@ -68,28 +89,14 @@ func runPush(chartPath string, repoName string) error {
return errors.WithMessage(err, "load index from downloaded file")
}

// Update index.

idx.Add(chart.GetMetadata(), fname, repoEntry.URL, hash)
idx.SortEntries()

// Finally, upload both chart file and index.

fchart, err := os.Open(fname)
if err != nil {
return errors.Wrap(err, "open chart file")
}
idxReader, err := idx.Reader()
if err != nil {
return errors.WithMessage(err, "get index reader")
}

ctx, cancel = context.WithTimeout(context.Background(), defaultTimeout*2)
defer cancel()

if _, err := storage.Upload(ctx, repoEntry.URL+"/"+fname, fchart); err != nil {
return errors.WithMessage(err, "upload chart to s3")
}
if _, err := storage.Upload(ctx, repoEntry.URL+"/index.yaml", idxReader); err != nil {
return errors.WithMessage(err, "upload index to s3")
}
Expand Down

0 comments on commit 737a82c

Please sign in to comment.