From b068a813be1c0422f44802895da100ab6d1dee59 Mon Sep 17 00:00:00 2001 From: Miguel Angel Terron Santiago Date: Sat, 28 Sep 2019 23:39:47 +0100 Subject: [PATCH] major: Changed repos to use the new Helm 3 way, this breaks the use of repos with Helm 2! --- Makefile | 2 +- README.md | 26 +++---- cmd/push/main.go | 25 ++++--- cmd/push/main_test.go | 87 ++++++++++------------- go.mod | 8 ++- go.sum | 20 ++++-- pkg/artifactory/client.go | 2 +- pkg/artifactory/upload_test.go | 124 ++++++++++++--------------------- pkg/helm/chart.go | 29 +++----- pkg/repo/repo.go | 73 +++++++++++++++++++ pkg/tlsutil/tls.go | 80 +++++++++++++++++++++ pkg/version/version.go | 2 +- plugin.yaml | 2 +- 13 files changed, 301 insertions(+), 179 deletions(-) create mode 100644 pkg/repo/repo.go create mode 100644 pkg/tlsutil/tls.go diff --git a/Makefile b/Makefile index 048a4bd..bb1b850 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ vet: fmt: @set -e; \ - GO_FMT=$$(git ls-files *.go | grep -v 'vendor/' | xargs gofmt -d); \ + GO_FMT=$$(git ls-files *.go | grep -v 'vendor/' | xargs gofmt -d -s); \ if [ -n "$${GO_FMT}" ] ; then \ echo "Please run go fmt"; \ echo "$$GO_FMT"; \ diff --git a/README.md b/README.md index 85ea9e2..793e6d2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Helm push artifactory plugin +__WARNING: THIS VERSION IS FOR HELM 3, FOR HELM 2 PLEASE USE VERSION [v0.4.0](https://github.com/belitre/helm-push-artifactory-plugin/releases/tag/v0.4.0)__ + A Helm plugin to push helm charts to artifactory: * A version for artifactory of helm-push: https://github.com/chartmuseum/helm-push @@ -8,24 +10,16 @@ A Helm plugin to push helm charts to artifactory: ## Install -Based on the version in `plugin.yaml`, release binary will be downloaded from GitHub: - -``` -$ helm plugin install https://github.com/belitre/helm-push-artifactory-plugin -Downloading and installing helm-push-artifactory v0.4.0 ... -https://github.com/belitre/helm-push-artifactory-plugin/releases/download/v0.4.0/helm-push-artifactory_v0.4.0_darwin_amd64.tar.gz -Installed plugin: push-artifactory -``` +To install the version for Helm 3 you need to specify the version when installing using helm cli: -You can specify an specific version: ``` -$ helm plugin install https://github.com/belitre/helm-push-artifactory-plugin --version v0.3.0 -Downloading and installing helm-push-artifactory v0.3.0 ... -https://github.com/belitre/helm-push-artifactory-plugin/releases/download/v0.3.0/helm-push-artifactory_v0.3.0_darwin_amd64.tar.gz +$ helm plugin install https://github.com/belitre/helm-push-artifactory-plugin --version v1.0.0 +Downloading and installing helm-push-artifactory v1.0.0 ... +https://github.com/belitre/helm-push-artifactory-plugin/releases/download/v1.0.0/helm-push-artifactory_v1.0.0_darwin_amd64.tar.gz Installed plugin: push-artifactory ``` -You can also download on one of the compressed files from [here](https://github.com/belitre/helm-push-artifactory-plugin/releases) and just extract it in your `$HELM_HOME/plugins/` +You can also download on one of the compressed files from [here](https://github.com/belitre/helm-push-artifactory-plugin/releases/tag/v1.0.0) and just extract it in your `$HELM_HOME/plugins/` __Important for windows users: I really don't know how to make the `helm plugin install` command work on Windows :D so please just download the zip and extract it on your `$HELM_HOME/plugins/ folder :)__ @@ -86,6 +80,12 @@ Example: ## Usage +You can override the repositories file using the environment variable `HELM_REPOSITORY_CONFIG`, example: + +``` +export HELM_REPOSITORY_CONFIG=/home/myuser/my_repositories.yaml +``` + Example using URL: ```bash diff --git a/cmd/push/main.go b/cmd/push/main.go index d4d94ee..b547f2e 100644 --- a/cmd/push/main.go +++ b/cmd/push/main.go @@ -14,8 +14,8 @@ import ( "github.com/belitre/helm-push-artifactory-plugin/pkg/artifactory" "github.com/belitre/helm-push-artifactory-plugin/pkg/helm" + helmrepo "github.com/belitre/helm-push-artifactory-plugin/pkg/repo" "github.com/belitre/helm-push-artifactory-plugin/pkg/version" - helmpush "github.com/chartmuseum/helm-push/pkg/helm" "github.com/spf13/cobra" ) @@ -55,7 +55,7 @@ func getUsage() string { return strings.Replace(globalUsage, "%version%", version.GetVersion(), 1) } -func newPushCmd(args []string) *cobra.Command { +func newPushCmd(args []string) (*cobra.Command, error) { p := &pushCmd{} cmd := &cobra.Command{ Use: "helm push-artifactory", @@ -87,7 +87,7 @@ func newPushCmd(args []string) *cobra.Command { f.BoolVarP(&p.insecureSkipVerify, "insecure", "", false, "Connect to server with an insecure way by skipping certificate verification [$HELM_REPO_INSECURE]") f.BoolVarP(&p.skipReindex, "skip-reindex", "", false, "Avoid trigger reindex in the repository after pushing the chart [$HELM_REPO_SKIP_REINDEX]") f.Parse(args) - return cmd + return cmd, nil } func (p *pushCmd) setFieldsFromEnv() { @@ -124,7 +124,7 @@ func (p *pushCmd) setFieldsFromEnv() { } func (p *pushCmd) push() error { - var repo *helmpush.Repo + var repo *helmrepo.Repo var err error // If the argument looks like a URL, just create a temp repo object @@ -133,7 +133,7 @@ func (p *pushCmd) push() error { // Check valid URL _, err = url.ParseRequestURI(p.repository) } else { - repo, err = helmpush.GetRepoByName(p.repository) + repo, err = helmrepo.GetRepoByName(p.repository) } if err != nil { @@ -151,7 +151,10 @@ func (p *pushCmd) push() error { } if len(p.overrides) > 0 { - chart.OverrideValues(p.overrides) + err := chart.OverrideValues(p.overrides) + if err != nil { + return err + } } if repo != nil { @@ -201,7 +204,7 @@ func (p *pushCmd) push() error { return err } - resp, err := client.UploadChartPackage(chart.GetMetadata().GetName(), chartPackagePath) + resp, err := client.UploadChartPackage(chart.Metadata.Name, chartPackagePath) if err != nil { return err } @@ -222,6 +225,7 @@ func (p *pushCmd) push() error { } func handleReindexResponse(resp *http.Response) error { + defer resp.Body.Close() b, err := ioutil.ReadAll(resp.Body) if err != nil { return err @@ -235,6 +239,7 @@ func handleReindexResponse(resp *http.Response) error { } func handlePushResponse(resp *http.Response) error { + defer resp.Body.Close() if resp.StatusCode != 201 { b, err := ioutil.ReadAll(resp.Body) if err != nil { @@ -266,8 +271,12 @@ func getArtifactoryError(b []byte, code int) error { } func main() { - cmd := newPushCmd(os.Args[1:]) + cmd, err := newPushCmd(os.Args[1:]) + if err != nil { + fmt.Println(fmt.Sprintf("%v", err)) + } if err := cmd.Execute(); err != nil { + fmt.Println(fmt.Sprintf("%v", err)) os.Exit(1) } } diff --git a/cmd/push/main_test.go b/cmd/push/main_test.go index 07485f1..1e147cc 100644 --- a/cmd/push/main_test.go +++ b/cmd/push/main_test.go @@ -5,18 +5,18 @@ import ( "net/http" "net/http/httptest" "os" + "path" "testing" "github.com/stretchr/testify/assert" - "k8s.io/helm/pkg/getter" - helm_env "k8s.io/helm/pkg/helm/environment" - "k8s.io/helm/pkg/helm/helmpath" - "k8s.io/helm/pkg/repo" + "helm.sh/helm/pkg/cli" + "helm.sh/helm/pkg/getter" + "helm.sh/helm/pkg/repo" ) var ( - settings helm_env.EnvSettings + settings = &cli.EnvSettings{} testTarballPath = "../../testdata/charts/mychart/mychart-0.1.0.tgz" testCertPath = "../../testdata/tls/test_cert.crt" testKeyPath = "../../testdata/tls/test_key.key" @@ -50,8 +50,9 @@ func TestPushCmd(t *testing.T) { } defer os.RemoveAll(tmp) - home := helmpath.Home(tmp) - f := repo.NewRepoFile() + filepath := path.Join(tmp, "repositories.yaml") + + f := repo.NewFile() entry := repo.Entry{} entry.Name = "helm-push-test" @@ -63,88 +64,74 @@ func TestPushCmd(t *testing.T) { } f.Update(&entry) - os.MkdirAll(home.Repository(), 0777) - f.WriteFile(home.RepositoryFile(), 0644) + err = f.WriteFile(filepath, 0644) + assert.NoError(t, err) - os.Setenv("HELM_HOME", home.String()) + os.Setenv("HELM_REPOSITORY_CONFIG", filepath) os.Setenv("HELM_REPO_USERNAME", "myuser") os.Setenv("HELM_REPO_PASSWORD", "mypass") // Not enough args args := []string{} - cmd := newPushCmd(args) + cmd, err := newPushCmd(args) + assert.NoError(t, err) err = cmd.RunE(cmd, args) - if err == nil { - t.Error("expecting error with missing args, instead got nil") - } + assert.Error(t, err) // Bad chart path - args = []string{"/this/this/not/a/chart", "helm-push-test"} - cmd = newPushCmd(args) + args = []string{"/this/not/a/chart", "helm-push-test"} + cmd, err = newPushCmd(args) + assert.NoError(t, err) err = cmd.RunE(cmd, args) - if err == nil { - t.Error("expecting error with bad chart path, instead got nil") - } + assert.Error(t, err) // Bad repo name args = []string{testTarballPath, "wkerjbnkwejrnkj"} - cmd = newPushCmd(args) + cmd, err = newPushCmd(args) + assert.NoError(t, err) err = cmd.RunE(cmd, args) - if err == nil { - t.Error("expecting error with bad repo name, instead got nil") - } + assert.Error(t, err) // Happy path args = []string{testTarballPath, "helm-push-test"} - cmd = newPushCmd(args) + cmd, err = newPushCmd(args) + assert.NoError(t, err) err = cmd.RunE(cmd, args) - if err != nil { - t.Error("unexpecting error uploading tarball", err) - } + assert.NoError(t, err) // Happy path by repo URL args = []string{testTarballPath, ts.URL} - cmd = newPushCmd(args) + cmd, err = newPushCmd(args) + assert.NoError(t, err) err = cmd.RunE(cmd, args) - if err != nil { - t.Error("unexpecting error uploading tarball", err) - } + assert.NoError(t, err) // Trigger reindex error postStatusCode = 403 body = "{\"errors\": [{\"message\": \"Error\", \"status\": 403}]}" args = []string{testTarballPath, ts.URL} - cmd = newPushCmd(args) + cmd, err = newPushCmd(args) + assert.NoError(t, err) err = cmd.RunE(cmd, args) - if err == nil { - t.Error("expecting error with 403, instead got nil") - } else { - assert.Error(t, err, "403: Error") - } + assert.Error(t, err, "403: Error") // Trigger 409 putStatusCode = 409 body = "{\"errors\": [{\"message\": \"Error\", \"status\": 409}]}" args = []string{testTarballPath, ts.URL} - cmd = newPushCmd(args) + cmd, err = newPushCmd(args) + assert.NoError(t, err) err = cmd.RunE(cmd, args) - if err == nil { - t.Error("expecting error with 409, instead got nil") - } else { - assert.Error(t, err, "409: Error") - } + assert.Error(t, err, "409: Error") // Unable to parse JSON response body putStatusCode = 500 body = "qkewjrnvqejrnbvjern" args = []string{testTarballPath, ts.URL} - cmd = newPushCmd(args) + cmd, err = newPushCmd(args) + assert.NoError(t, err) err = cmd.RunE(cmd, args) - if err == nil { - t.Error("expecting error with bad response body, instead got nil") - } else { - assert.Error(t, err, "500: could not properly parse response JSON: qkewjrnvqejrnbvjern") - } + assert.Error(t, err, "500: could not properly parse response JSON: qkewjrnvqejrnbvjern") } @@ -203,7 +190,7 @@ func TestPushCmdWithTlsEnabledServer(t *testing.T) { os.MkdirAll(home.Repository(), 0777) f.WriteFile(home.RepositoryFile(), 0644) - os.Setenv("HELM_HOME", home.String()) + os.Setenv("HELM_REPOSITORY_CONFIG", home.String()) os.Setenv("HELM_REPO_USERNAME", "myuser") os.Setenv("HELM_REPO_PASSWORD", "mypass") diff --git a/go.mod b/go.mod index fcf70ed..d5e424c 100644 --- a/go.mod +++ b/go.mod @@ -10,10 +10,14 @@ require ( github.com/gobwas/glob v0.2.3 // indirect github.com/golang/protobuf v1.3.2 // indirect github.com/jfrog/jfrog-client-go v0.5.2 + github.com/pkg/errors v0.8.0 github.com/spf13/cobra v0.0.5 github.com/stretchr/testify v1.4.0 + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.1.0 // indirect gopkg.in/yaml.v2 v2.2.2 - k8s.io/apimachinery v0.0.0-20190925235427-62598f38f24e // indirect + helm.sh/helm v3.0.0-beta.3+incompatible + k8s.io/api v0.0.0-20190927115716-5d581ce610b0 // indirect k8s.io/client-go v11.0.0+incompatible // indirect - k8s.io/helm v2.14.3+incompatible ) diff --git a/go.sum b/go.sum index 4ba9260..827921f 100644 --- a/go.sum +++ b/go.sum @@ -8,7 +8,6 @@ github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/g github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/buger/jsonparser v0.0.0-20180910192245-6acdf747ae99/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/chartmuseum/helm-push v0.7.1 h1:PZpyEaKiZqexbXvFidmEC8UDl9+pRTtDv1cEBXOeZwE= github.com/chartmuseum/helm-push v0.7.1/go.mod h1:5ZGZxWAS+Nke4rc3c82laATE0n4vaTVKLFij1VnrTU4= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -38,6 +37,7 @@ github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1 github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -57,7 +57,6 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jfrog/gofrog v1.0.4/go.mod h1:4Caxvc8B2K1A798G1Ne+SsUICRPPre4GpgcFqj+EXJ8= -github.com/jfrog/jfrog-cli-go v1.22.0 h1:rD88IgDybo9sBDpNE4fjLHz3Ql1vSA559pcCOIlrxK0= github.com/jfrog/jfrog-client-go v0.5.2 h1:MGy1fonavEShjNGtN40XEx3eqdKvGbC8Cf2HGaEXt3s= github.com/jfrog/jfrog-client-go v0.5.2/go.mod h1:z0TT7uU1IcpkiEgySOE7UD/0f/Vzg85wEOixa5IQTas= github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -115,6 +114,12 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ulikunitz/xz v0.5.4/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.1.0 h1:ngVtJC9TY/lg0AA/1k48FYhBrhRoFlEmWzsehpNAaZg= +github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0= @@ -122,6 +127,7 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68= golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -147,13 +153,17 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -k8s.io/apimachinery v0.0.0-20190925235427-62598f38f24e h1:LYpiLXa8/G1bL7VPm3m5For0h/hsr3ZyD4ytutxTctQ= -k8s.io/apimachinery v0.0.0-20190925235427-62598f38f24e/go.mod h1:grJJH0hgilA2pYoUiJcPu2EDUal95NTq1vpxxvMLSu8= +helm.sh/helm v3.0.0-beta.3+incompatible h1:/U/yApDO3EL8dUqTfK+PYLLmAv22HzIhXUYPEzZSSNk= +helm.sh/helm v3.0.0-beta.3+incompatible/go.mod h1:0Xbc6ErzwWH9qC55X1+hE3ZwhM3atbhCm/NbFZw5i+4= +k8s.io/api v0.0.0-20190927115716-5d581ce610b0 h1:fwx2jAKNlXBQ8uiB3RNN5hVU/nEJTEBg/CfxoXEYri4= +k8s.io/api v0.0.0-20190927115716-5d581ce610b0/go.mod h1:l2ZHS8QbgqodGx7yrYsOSwIxOR76BpGiW1OywXo9PFI= +k8s.io/apimachinery v0.0.0-20190927035529-0104e33c351d h1:oYLB5Nk2IOm17BHdatnaWAgzNGzq/5dlWy7Bzo5Htdc= +k8s.io/apimachinery v0.0.0-20190927035529-0104e33c351d/go.mod h1:grJJH0hgilA2pYoUiJcPu2EDUal95NTq1vpxxvMLSu8= k8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/helm v2.14.3+incompatible h1:uzotTcZXa/b2SWVoUzM1xiCXVjI38TuxMujS/1s+3Gw= -k8s.io/helm v2.14.3+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= diff --git a/pkg/artifactory/client.go b/pkg/artifactory/client.go index 1c27206..2b0ed9d 100644 --- a/pkg/artifactory/client.go +++ b/pkg/artifactory/client.go @@ -4,7 +4,7 @@ import ( "fmt" "net/http" - "k8s.io/helm/pkg/tlsutil" + "github.com/belitre/helm-push-artifactory-plugin/pkg/tlsutil" ) type ( diff --git a/pkg/artifactory/upload_test.go b/pkg/artifactory/upload_test.go index 8d0c8fb..d63ba5a 100644 --- a/pkg/artifactory/upload_test.go +++ b/pkg/artifactory/upload_test.go @@ -6,6 +6,8 @@ import ( "net/http" "net/http/httptest" "testing" + + "github.com/stretchr/testify/assert" ) var ( @@ -43,29 +45,22 @@ func TestUploadChartPackage(t *testing.T) { Password("pass"), Path("/my/path"), ) - if err != nil { - t.Fatalf("[happy path] expect creating a client instance but met error: %s", err) - } + assert.NoError(t, err) + resp, err := cmClient.UploadChartPackage(chartName, testTarballPath) - if err != nil { - t.Error("error uploading chart package", err) - } - if resp.StatusCode != 201 { - t.Errorf("expecting 201 instead got %d", resp.StatusCode) - } + assert.NoError(t, err) + + assert.Equal(t, 201, resp.StatusCode) + resp.Body.Close() // Bad package path - resp, err = cmClient.UploadChartPackage(chartName, "/non/existant/path/mychart-0.1.0.tgz") - if err == nil { - t.Error("expecting error with bad package path, instead got nil") - } + _, err = cmClient.UploadChartPackage(chartName, "/non/existent/path/mychart-0.1.0.tgz") + assert.Error(t, err) // Bad URL cmClient, _ = NewClient(URL("jaswehfgew")) _, err = cmClient.UploadChartPackage(chartName, testTarballPath) - if err == nil { - t.Error("[bad URL] expecting error with bad package path, instead got nil") - } + assert.Error(t, err) // Bad context path cmClient, err = NewClient( @@ -75,17 +70,12 @@ func TestUploadChartPackage(t *testing.T) { Path("/my/crappy/context/path"), Timeout(5), ) - if err != nil { - t.Fatalf("[bad path] expect creating a client instance but met error: %s", err) - } + assert.NoError(t, err) resp, err = cmClient.UploadChartPackage(chartName, testTarballPath) - if err != nil { - t.Error("unexpected error with bad context path", err) - } - if resp.StatusCode != 404 { - t.Errorf("expecting 404 instead got %d", resp.StatusCode) - } + assert.NoError(t, err) + assert.Equal(t, 404, resp.StatusCode) + resp.Body.Close() // Unauthorized, invalid user/pass combo (basic auth) cmClient, err = NewClient( @@ -94,32 +84,24 @@ func TestUploadChartPackage(t *testing.T) { Password("badpass"), Path("/my/path"), ) - if err != nil { - t.Fatalf("[unauthorized: invalid user/pass] expect creating a client instance but met error: %s", err) - } + assert.NoError(t, err) + resp, err = cmClient.UploadChartPackage(chartName, testTarballPath) - if err != nil { - t.Error("unexpected error with invalid user/pass combo (basic auth)", err) - } - if resp.StatusCode != 401 { - t.Errorf("expecting 401 instead got %d", resp.StatusCode) - } + assert.NoError(t, err) + assert.Equal(t, 401, resp.StatusCode) + resp.Body.Close() // Unauthorized, missing user/pass combo (basic auth) cmClient, err = NewClient( URL(url), Path("/my/path"), ) - if err != nil { - t.Fatalf("[unauthorized: missing user/pass] expect creating a client instance but met error: %s", err) - } + assert.NoError(t, err) + resp, err = cmClient.UploadChartPackage(chartName, testTarballPath) - if err != nil { - t.Error("unexpected error with missing user/pass combo (basic auth)", err) - } - if resp.StatusCode != 401 { - t.Errorf("expecting 401 instead got %d", resp.StatusCode) - } + assert.NoError(t, err) + assert.Equal(t, 401, resp.StatusCode) + resp.Body.Close() } /* @@ -286,32 +268,24 @@ func TestReindexArtifactoryRepo(t *testing.T) { AccessToken("token"), Path("/my/path"), ) - if err != nil { - t.Fatalf("[basic auth token] expect creating a client instance but met error: %s", err) - } + assert.NoError(t, err) + resp, err := cmClient.ReindexArtifactoryRepo() - if err != nil { - t.Error("error reindexing repo", err) - } - if resp.StatusCode != 200 { - t.Errorf("expecting 200 instead got %d", resp.StatusCode) - } + assert.NoError(t, err) + assert.Equal(t, 200, resp.StatusCode) + resp.Body.Close() // auth header token cmClient, err = NewClient( URL(url), AccessToken("token"), ) - if err != nil { - t.Fatalf("[auth header token] expect creating a client instance but met error: %s", err) - } + assert.NoError(t, err) + resp, err = cmClient.ReindexArtifactoryRepo() - if err != nil { - t.Error("error reindexing repo", err) - } - if resp.StatusCode != 200 { - t.Errorf("expecting 200 instead got %d", resp.StatusCode) - } + assert.NoError(t, err) + assert.Equal(t, 200, resp.StatusCode) + resp.Body.Close() // basic auth apiKey cmClient, err = NewClient( @@ -319,30 +293,22 @@ func TestReindexArtifactoryRepo(t *testing.T) { Username("user"), ApiKey("apiKey"), ) - if err != nil { - t.Fatalf("[basic auth apiKey] expect creating a client instance but met error: %s", err) - } + assert.NoError(t, err) + resp, err = cmClient.ReindexArtifactoryRepo() - if err != nil { - t.Error("error reindexing repo", err) - } - if resp.StatusCode != 200 { - t.Errorf("expecting 200 instead got %d", resp.StatusCode) - } + assert.NoError(t, err) + assert.Equal(t, 200, resp.StatusCode) + resp.Body.Close() // auth header apiKey cmClient, err = NewClient( URL(url), ApiKey("apiKey"), ) - if err != nil { - t.Fatalf("[auth header apiKey] expect creating a client instance but met error: %s", err) - } + assert.NoError(t, err) + resp, err = cmClient.ReindexArtifactoryRepo() - if err != nil { - t.Error("error reindexing repo", err) - } - if resp.StatusCode != 200 { - t.Errorf("expecting 200 instead got %d", resp.StatusCode) - } + assert.NoError(t, err) + assert.Equal(t, 200, resp.StatusCode) + resp.Body.Close() } diff --git a/pkg/helm/chart.go b/pkg/helm/chart.go index 548ccb9..00577c1 100644 --- a/pkg/helm/chart.go +++ b/pkg/helm/chart.go @@ -3,11 +3,10 @@ package helm import ( "fmt" - yaml "gopkg.in/yaml.v2" - "k8s.io/helm/pkg/chartutil" - "k8s.io/helm/pkg/proto/hapi/chart" - cpb "k8s.io/helm/pkg/proto/hapi/chart" - "k8s.io/helm/pkg/strvals" + "helm.sh/helm/pkg/chart" + "helm.sh/helm/pkg/chart/loader" + "helm.sh/helm/pkg/chartutil" + "helm.sh/helm/pkg/strvals" ) type ( @@ -25,7 +24,11 @@ func (c *Chart) SetVersion(version string) { // GetChartByName returns a chart by "name", which can be // either a directory or .tgz package func GetChartByName(name string) (*Chart, error) { - cc, err := chartutil.Load(name) + chartLoader, err := loader.Loader(name) + if err != nil { + return nil, err + } + cc, err := chartLoader.Load() if err != nil { return nil, err } @@ -47,21 +50,11 @@ func (c *Chart) OverrideValues(overrides []string) error { } } - ovAsBytes, err := yaml.Marshal(ovMap) - if err != nil { - return fmt.Errorf("Error while marshal values: %s", err) - } - - cvals, err := chartutil.CoalesceValues(c.Chart, &cpb.Config{Raw: string(ovAsBytes)}) + cvals, err := chartutil.CoalesceValues(c.Chart, ovMap) if err != nil { return fmt.Errorf("Error while overriding chart values: %s", err) } - cvalsAsYaml, err := cvals.YAML() - if err != nil { - return fmt.Errorf("Error parsing values to yaml: %s", err) - } - - c.Values = &cpb.Config{Raw: cvalsAsYaml} + c.Values = cvals return nil } diff --git a/pkg/repo/repo.go b/pkg/repo/repo.go new file mode 100644 index 0000000..b138058 --- /dev/null +++ b/pkg/repo/repo.go @@ -0,0 +1,73 @@ +/* +Copyright The Helm-push Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package repo + +import ( + "fmt" + "os" + + "helm.sh/helm/pkg/helmpath" + "helm.sh/helm/pkg/repo" +) + +type ( + // Repo represents a collection of parameters for chart repository + Repo struct { + *repo.Entry + } +) + +// GetRepoByName returns repository by name +func GetRepoByName(name string) (*Repo, error) { + r, err := repoFile() + if err != nil { + return nil, err + } + entry, exists := findRepoEntry(name, r) + if !exists { + return nil, fmt.Errorf("no repo named %q found", name) + } + return &Repo{entry}, nil +} + +func repoFile() (*repo.File, error) { + repositoryFile := getRepositoryFile() + return repo.LoadFile(repositoryFile) +} + +func getRepositoryFile() string { + var helmRepoFilePath string + if v, ok := os.LookupEnv("HELM_REPOSITORY_CONFIG"); ok { + helmRepoFilePath = v + } else { + helmRepoFilePath = helmpath.ConfigPath("repositories.yaml") + } + return helmRepoFilePath +} + +func findRepoEntry(name string, r *repo.File) (*repo.Entry, bool) { + var entry *repo.Entry + exists := false + for _, re := range r.Repositories { + if re.Name == name { + entry = re + exists = true + break + } + } + return entry, exists +} diff --git a/pkg/tlsutil/tls.go b/pkg/tlsutil/tls.go new file mode 100644 index 0000000..6091453 --- /dev/null +++ b/pkg/tlsutil/tls.go @@ -0,0 +1,80 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/* + +Helm code, since it's an internal package in helm 3 you can't import it :( ) +*/ + +package tlsutil + +import ( + "crypto/tls" + "crypto/x509" + "io/ioutil" + + "github.com/pkg/errors" +) + +// NewClientTLS returns tls.Config appropriate for client auth. +func NewClientTLS(certFile, keyFile, caFile string) (*tls.Config, error) { + config := tls.Config{} + + if certFile != "" && keyFile != "" { + cert, err := CertFromFilePair(certFile, keyFile) + if err != nil { + return nil, err + } + config.Certificates = []tls.Certificate{*cert} + } + + if caFile != "" { + cp, err := CertPoolFromFile(caFile) + if err != nil { + return nil, err + } + config.RootCAs = cp + } + return &config, nil +} + +// CertPoolFromFile returns an x509.CertPool containing the certificates +// in the given PEM-encoded file. +// Returns an error if the file could not be read, a certificate could not +// be parsed, or if the file does not contain any certificates +func CertPoolFromFile(filename string) (*x509.CertPool, error) { + b, err := ioutil.ReadFile(filename) + if err != nil { + return nil, errors.Errorf("can't read CA file: %v", filename) + } + cp := x509.NewCertPool() + if !cp.AppendCertsFromPEM(b) { + return nil, errors.Errorf("failed to append certificates from file: %s", filename) + } + return cp, nil +} + +// CertFromFilePair returns an tls.Certificate containing the +// certificates public/private key pair from a pair of given PEM-encoded files. +// Returns an error if the file could not be read, a certificate could not +// be parsed, or if the file does not contain any certificates +func CertFromFilePair(certFile, keyFile string) (*tls.Certificate, error) { + cert, err := tls.LoadX509KeyPair(certFile, keyFile) + if err != nil { + return nil, errors.Wrapf(err, "can't load key pair from cert %s and key %s", certFile, keyFile) + } + return &cert, err +} diff --git a/pkg/version/version.go b/pkg/version/version.go index 123d5cd..118c93d 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -13,7 +13,7 @@ var ( func GetVersion() string { v := fmt.Sprintf("Version: %s", Version) if len(GitCommit) > 0 { - v = v + fmt.Sprintf("-%s", GitCommit) + v += fmt.Sprintf("-%s", GitCommit) } return v } diff --git a/plugin.yaml b/plugin.yaml index b8cbef4..0ff7eb8 100644 --- a/plugin.yaml +++ b/plugin.yaml @@ -1,5 +1,5 @@ name: "push-artifactory" -version: "0.4.0" +version: "1.0.0" usage: "Please see https://github.com/belitre/helm-push-artifactory-plugin for usage" description: "Push helm charts to artifactory" ignoreFlags: false