5
5
"fmt"
6
6
"os"
7
7
"path/filepath"
8
+ "time"
8
9
9
10
"github.com/pkg/errors"
10
11
"k8s.io/helm/pkg/chartutil"
@@ -16,7 +17,15 @@ import (
16
17
"github.com/hypnoglow/helm-s3/pkg/index"
17
18
)
18
19
20
+ const (
21
+ pushCommandDefaultTimeout = time .Second * 15
22
+ )
23
+
19
24
func runPush (chartPath string , repoName string ) error {
25
+ // Just one big timeout for the whole operation.
26
+ ctx , cancel := context .WithTimeout (context .Background (), pushCommandDefaultTimeout )
27
+ defer cancel ()
28
+
20
29
fpath , err := filepath .Abs (chartPath )
21
30
if err != nil {
22
31
return errors .WithMessage (err , "get chart abs path" )
@@ -36,7 +45,8 @@ func runPush(chartPath string, repoName string) error {
36
45
37
46
storage := awss3 .NewStorage (awsConfig )
38
47
39
- // Load chart and calculate required params like hash.
48
+ // Load chart, calculate required params like hash,
49
+ // and upload the chart right away.
40
50
41
51
chart , err := chartutil .LoadFile (fname )
42
52
if err != nil {
@@ -48,15 +58,26 @@ func runPush(chartPath string, repoName string) error {
48
58
return err
49
59
}
50
60
61
+ fchart , err := os .Open (fname )
62
+ if err != nil {
63
+ return errors .Wrap (err , "open chart file" )
64
+ }
65
+
66
+ if _ , err := storage .Upload (ctx , repoEntry .URL + "/" + fname , fchart ); err != nil {
67
+ return errors .WithMessage (err , "upload chart to s3" )
68
+ }
69
+
70
+ // Next, update the repository index.
71
+ // The gap between index fetching and uploading should be as small as
72
+ // possible to make the best effort to avoid race conditions.
73
+ // See https://github.com/hypnoglow/helm-s3/issues/18 for more info.
74
+
51
75
hash , err := provenance .DigestFile (fname )
52
76
if err != nil {
53
77
return errors .WithMessage (err , "get chart digest" )
54
78
}
55
79
56
- // Fetch current index.
57
-
58
- ctx , cancel := context .WithTimeout (context .Background (), defaultTimeout )
59
- defer cancel ()
80
+ // Fetch current index, update it and upload it back.
60
81
61
82
b , err := storage .FetchRaw (ctx , repoEntry .URL + "/index.yaml" )
62
83
if err != nil {
@@ -68,28 +89,14 @@ func runPush(chartPath string, repoName string) error {
68
89
return errors .WithMessage (err , "load index from downloaded file" )
69
90
}
70
91
71
- // Update index.
72
-
73
92
idx .Add (chart .GetMetadata (), fname , repoEntry .URL , hash )
74
93
idx .SortEntries ()
75
94
76
- // Finally, upload both chart file and index.
77
-
78
- fchart , err := os .Open (fname )
79
- if err != nil {
80
- return errors .Wrap (err , "open chart file" )
81
- }
82
95
idxReader , err := idx .Reader ()
83
96
if err != nil {
84
97
return errors .WithMessage (err , "get index reader" )
85
98
}
86
99
87
- ctx , cancel = context .WithTimeout (context .Background (), defaultTimeout * 2 )
88
- defer cancel ()
89
-
90
- if _ , err := storage .Upload (ctx , repoEntry .URL + "/" + fname , fchart ); err != nil {
91
- return errors .WithMessage (err , "upload chart to s3" )
92
- }
93
100
if _ , err := storage .Upload (ctx , repoEntry .URL + "/index.yaml" , idxReader ); err != nil {
94
101
return errors .WithMessage (err , "upload index to s3" )
95
102
}
0 commit comments