Skip to content

Commit

Permalink
Add --force/-f option to force upload (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
jdolitsky committed Jul 18, 2018
1 parent d065ec4 commit c25eb42
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 8 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ Pushing mychart-0.3.2.tgz to chartmuseum...
Done.
```

### Force push
If your ChartMuseum install is configured with `ALLOW_OVERWRITE=true`, chart versions will be automatically overwritten upon re-upload.

Otherwise, unless your install is configured with `DISABLE_FORCE_OVERWRITE=true`, you can use the `--force`/`-f` option to to force an upload:
```
$ helm push --force mychart-0.3.2.tgz chartmuseum
Pushing mychart-0.3.2.tgz to chartmuseum...
Done.
```

### Pushing directly to URL
If the second argument provided resembles a URL, you are not required to add the repo prior to push:
```
Expand Down
4 changes: 3 additions & 1 deletion cmd/helmpush/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type (
accessToken string
authHeader string
contextPath string
forceUpload bool
useHTTP bool
}

Expand Down Expand Up @@ -87,6 +88,7 @@ func newPushCmd(args []string) *cobra.Command {
f.StringVarP(&p.accessToken, "access-token", "", "", "Send token in Authorization header [$HELM_REPO_ACCESS_TOKEN]")
f.StringVarP(&p.authHeader, "auth-header", "", "", "Alternative header to use for token auth [$HELM_REPO_AUTH_HEADER]")
f.StringVarP(&p.contextPath, "context-path", "", "", "ChartMuseum context path [$HELM_REPO_CONTEXT_PATH]")
f.BoolVarP(&p.forceUpload, "force", "f", false, "Force upload even if chart version exists")
f.Parse(args)
return cmd
}
Expand Down Expand Up @@ -207,7 +209,7 @@ func (p *pushCmd) push() error {
}

fmt.Printf("Pushing %s to %s...\n", filepath.Base(chartPackagePath), p.repoName)
resp, err := client.UploadChartPackage(chartPackagePath)
resp, err := client.UploadChartPackage(chartPackagePath, p.forceUpload)
if err != nil {
return err
}
Expand Down
7 changes: 6 additions & 1 deletion pkg/chartmuseum/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
)

// UploadChartPackage uploads a chart package to ChartMuseum (POST /api/charts)
func (client *Client) UploadChartPackage(chartPackagePath string) (*http.Response, error) {
func (client *Client) UploadChartPackage(chartPackagePath string, force bool) (*http.Response, error) {
u, err := url.Parse(client.opts.url)
if err != nil {
return nil, err
Expand All @@ -26,6 +26,11 @@ func (client *Client) UploadChartPackage(chartPackagePath string) (*http.Respons
return nil, err
}

// Add ?force to request querystring to force an upload if chart version already exists
if force {
req.URL.RawQuery = "force"
}

err = setUploadChartPackageRequestBody(req, chartPackagePath)
if err != nil {
return nil, err
Expand Down
39 changes: 33 additions & 6 deletions pkg/chartmuseum/upload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,22 @@ var (
)

func TestUploadChartPackage(t *testing.T) {
chartUploaded := false

basicAuthHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte("user:pass"))
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !strings.HasPrefix(r.URL.String(), "/my/context/path") {
w.WriteHeader(404)
} else if r.Header.Get("Authorization") != basicAuthHeader {
w.WriteHeader(401)
} else if chartUploaded {
if _, ok := r.URL.Query()["force"]; ok {
w.WriteHeader(201)
} else {
w.WriteHeader(409)
}
} else {
chartUploaded = true
w.WriteHeader(201)
}
}))
Expand All @@ -32,7 +41,25 @@ func TestUploadChartPackage(t *testing.T) {
Password("pass"),
ContextPath("/my/context/path"),
)
resp, err := cmClient.UploadChartPackage(testTarballPath)
resp, err := cmClient.UploadChartPackage(testTarballPath, false)
if err != nil {
t.Error("error uploading chart package", err)
}
if resp.StatusCode != 201 {
t.Errorf("expecting 201 instead got %d", resp.StatusCode)
}

// Attempt to re-upload without force, trigger 409
resp, err = cmClient.UploadChartPackage(testTarballPath, false)
if err != nil {
t.Error("error uploading chart package", err)
}
if resp.StatusCode != 409 {
t.Errorf("expecting 409 instead got %d", resp.StatusCode)
}

// Upload with force
resp, err = cmClient.UploadChartPackage(testTarballPath, true)
if err != nil {
t.Error("error uploading chart package", err)
}
Expand All @@ -41,14 +68,14 @@ func TestUploadChartPackage(t *testing.T) {
}

// Bad package path
resp, err = cmClient.UploadChartPackage("/non/existant/path/mychart-0.1.0.tgz")
resp, err = cmClient.UploadChartPackage("/non/existant/path/mychart-0.1.0.tgz", false)
if err == nil {
t.Error("expecting error with bad package path, instead got nil")
}

// Bad URL
cmClient = NewClient(URL("jaswehfgew"))
_, err = cmClient.UploadChartPackage(testTarballPath)
_, err = cmClient.UploadChartPackage(testTarballPath, false)
if err == nil {
t.Error("expecting error with bad package path, instead got nil")
}
Expand All @@ -61,7 +88,7 @@ func TestUploadChartPackage(t *testing.T) {
ContextPath("/my/crappy/context/path"),
Timeout(5),
)
resp, err = cmClient.UploadChartPackage(testTarballPath)
resp, err = cmClient.UploadChartPackage(testTarballPath, false)
if err != nil {
t.Error("unexpected error with bad context path", err)
}
Expand All @@ -76,7 +103,7 @@ func TestUploadChartPackage(t *testing.T) {
Password("badpass"),
ContextPath("/my/context/path"),
)
resp, err = cmClient.UploadChartPackage(testTarballPath)
resp, err = cmClient.UploadChartPackage(testTarballPath, false)
if err != nil {
t.Error("unexpected error with invalid user/pass combo (basic auth)", err)
}
Expand All @@ -89,7 +116,7 @@ func TestUploadChartPackage(t *testing.T) {
URL(ts.URL),
ContextPath("/my/context/path"),
)
resp, err = cmClient.UploadChartPackage(testTarballPath)
resp, err = cmClient.UploadChartPackage(testTarballPath, false)
if err != nil {
t.Error("unexpected error with missing user/pass combo (basic auth)", err)
}
Expand Down

0 comments on commit c25eb42

Please sign in to comment.