├── .gitignore ├── plugin.yaml ├── Gopkg.toml ├── Makefile ├── LICENSE ├── README.md ├── install-binary.sh ├── main.go └── Gopkg.lock /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | _dist/ 3 | vendor/ 4 | -------------------------------------------------------------------------------- /plugin.yaml: -------------------------------------------------------------------------------- 1 | name: "whatup" 2 | version: "0.2.1" 3 | usage: "checks if installed charts are out of date" 4 | description: "Checks if installed charts are out of date against the Helm repositories." 5 | command: "$HELM_PLUGIN_DIR/bin/helm-whatup" 6 | hooks: 7 | install: "$HELM_PLUGIN_DIR/install-binary.sh" 8 | useTunnel: true 9 | -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | [[constraint]] 2 | name = "github.com/spf13/cobra" 3 | branch = "master" 4 | 5 | [[constraint]] 6 | name = "k8s.io/helm" 7 | version = "v2.14.3" 8 | 9 | [[override]] 10 | name = "github.com/golang/protobuf" 11 | version = "1.2.0" 12 | 13 | [[override]] 14 | name = "github.com/spf13/pflag" 15 | version = "1.0.1" 16 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | HELM_HOME ?= $(shell helm home) 2 | HELM_PLUGIN_DIR ?= $(HELM_HOME)/plugins/helm-whatup 3 | HAS_GLIDE := $(shell command -v glide;) 4 | VERSION := $(shell sed -n -e 's/version:[ "]*\([^"]*\).*/\1/p' plugin.yaml) 5 | DIST := $(CURDIR)/_dist 6 | LDFLAGS := "-X main.version=${VERSION}" 7 | 8 | .PHONY: build 9 | build: 10 | go build -o bin/helm-whatup -ldflags $(LDFLAGS) ./main.go 11 | 12 | .PHONY: dist 13 | dist: 14 | mkdir -p $(DIST) 15 | GOOS=linux GOARCH=amd64 go build -o bin/helm-whatup ./main.go 16 | tar -zcvf $(DIST)/helm-whatup-$(VERSION)-linux-amd64.tar.gz bin/helm-whatup README.md LICENSE plugin.yaml 17 | GOOS=darwin GOARCH=amd64 go build -o bin/helm-whatup ./main.go 18 | tar -zcvf $(DIST)/helm-whatup-$(VERSION)-darwin-amd64.tar.gz bin/helm-whatup README.md LICENSE plugin.yaml 19 | 20 | 21 | .PHONY: bootstrap 22 | bootstrap: 23 | ifndef HAS_DEP 24 | go get -u github.com/golang/dep/cmd/dep 25 | endif 26 | dep ensure -v 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Helm Whatup Plugin 2 | Copyright (C) 2019, Matthew Fisher 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Helm Whatup 2 | 3 | This is a Helm plugin to help users determine if there's an update available for their installed charts. It works by reading your locally cached index files from the chart repositories (via `helm repo update`) and checking the version against the latest deployed version of your charts in the Kubernetes cluster. 4 | 5 | ## Usage 6 | 7 | ``` 8 | $ helm repo update 9 | $ helm whatup 10 | ``` 11 | 12 | ## Install 13 | 14 | ``` 15 | $ helm plugin install https://github.com/bacongobbler/helm-whatup 16 | ``` 17 | 18 | The above will fetch the latest binary release of `helm whatup` and install it. 19 | 20 | ### Developer (From Source) Install 21 | 22 | If you would like to handle the build yourself, instead of fetching a binary, 23 | this is how recommend doing it. 24 | 25 | First, set up your environment: 26 | 27 | - You need to have [Go](http://golang.org) installed. Make sure to set `$GOPATH` 28 | - If you don't have [Glide](http://glide.sh) installed, this will install it into 29 | `$GOPATH/bin` for you. 30 | 31 | Clone this repo into your `$GOPATH` using git. 32 | 33 | ``` 34 | cd $GOPATH/src/github.com/bacongobbler 35 | git clone https://github.com/bacongobbler/helm-whatup 36 | ``` 37 | 38 | Then run the following to get running. 39 | 40 | ``` 41 | $ cd helm-whatup 42 | $ make bootstrap build 43 | $ SKIP_BIN_INSTALL=1 helm plugin install $GOPATH/src/github.com/bacongobbler/helm-whatup 44 | ``` 45 | 46 | That last command will skip fetching the binary install and use the one you 47 | built. 48 | -------------------------------------------------------------------------------- /install-binary.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Combination of the Glide and Helm scripts, with my own tweaks. 4 | 5 | PROJECT_NAME="helm-whatup" 6 | PROJECT_GH="bacongobbler/$PROJECT_NAME" 7 | 8 | : ${HELM_PLUGIN_PATH:="$HELM_HOME/plugins/helm-whatup"} 9 | 10 | if [[ $SKIP_BIN_INSTALL == "1" ]]; then 11 | echo "Skipping binary install" 12 | exit 13 | fi 14 | 15 | # initArch discovers the architecture for this system. 16 | initArch() { 17 | ARCH=$(uname -m) 18 | case $ARCH in 19 | armv5*) ARCH="armv5";; 20 | armv6*) ARCH="armv6";; 21 | armv7*) ARCH="armv7";; 22 | aarch64) ARCH="arm64";; 23 | x86) ARCH="386";; 24 | x86_64) ARCH="amd64";; 25 | i686) ARCH="386";; 26 | i386) ARCH="386";; 27 | esac 28 | } 29 | 30 | # initOS discovers the operating system for this system. 31 | initOS() { 32 | OS=$(echo `uname`|tr '[:upper:]' '[:lower:]') 33 | 34 | case "$OS" in 35 | # Minimalist GNU for Windows 36 | mingw*) OS='windows';; 37 | esac 38 | } 39 | 40 | # verifySupported checks that the os/arch combination is supported for 41 | # binary builds. 42 | verifySupported() { 43 | local supported="linux-amd64\ndarwin-amd64" 44 | if ! echo "${supported}" | grep -q "${OS}-${ARCH}"; then 45 | echo "No prebuild binary for ${OS}-${ARCH}." 46 | exit 1 47 | fi 48 | 49 | if ! type "curl" > /dev/null && ! type "wget" > /dev/null; then 50 | echo "Either curl or wget is required" 51 | exit 1 52 | fi 53 | } 54 | 55 | # getDownloadURL checks the latest available version. 56 | getDownloadURL() { 57 | # Use the GitHub API to find the latest version for this project. 58 | local latest_url="https://api.github.com/repos/$PROJECT_GH/releases/latest" 59 | if type "curl" > /dev/null; then 60 | DOWNLOAD_URL=$(curl -s $latest_url | grep $OS | awk '/\"browser_download_url\":/{gsub( /[,\"]/,"", $2); print $2}') 61 | elif type "wget" > /dev/null; then 62 | DOWNLOAD_URL=$(wget -q -O - $latest_url | awk '/\"browser_download_url\":/{gsub( /[,\"]/,"", $2); print $2}') 63 | fi 64 | } 65 | 66 | # downloadFile downloads the latest binary package and also the checksum 67 | # for that binary. 68 | downloadFile() { 69 | PLUGIN_TMP_FILE="/tmp/${PROJECT_NAME}.tgz" 70 | echo "Downloading $DOWNLOAD_URL" 71 | if type "curl" > /dev/null; then 72 | curl -L "$DOWNLOAD_URL" -o "$PLUGIN_TMP_FILE" 73 | elif type "wget" > /dev/null; then 74 | wget -q -O "$PLUGIN_TMP_FILE" "$DOWNLOAD_URL" 75 | fi 76 | } 77 | 78 | # installFile unpacks and installs helm-whatup. 79 | installFile() { 80 | HELM_TMP="/tmp/$PROJECT_NAME" 81 | mkdir -p "$HELM_TMP" 82 | tar xf "$PLUGIN_TMP_FILE" -C "$HELM_TMP" 83 | echo "Preparing to install into ${HELM_PLUGIN_PATH}" 84 | cp -R "$HELM_TMP/bin" "$HELM_PLUGIN_PATH/" 85 | } 86 | 87 | # fail_trap is executed if an error occurs. 88 | fail_trap() { 89 | result=$? 90 | if [ "$result" != "0" ]; then 91 | echo "Failed to install $PROJECT_NAME" 92 | echo "\tFor support, go to https://github.com/bacongobbler/helm-whatup." 93 | fi 94 | exit $result 95 | } 96 | 97 | # testVersion tests the installed client to make sure it is working. 98 | testVersion() { 99 | set +e 100 | echo "$PROJECT_NAME installed into $HELM_PLUGIN_PATH/$PROJECT_NAME" 101 | $HELM_PLUGIN_PATH/bin/helm-whatup -h 102 | set -e 103 | } 104 | 105 | # Execution 106 | 107 | #Stop execution on any error 108 | trap "fail_trap" EXIT 109 | set -e 110 | initArch 111 | initOS 112 | verifySupported 113 | getDownloadURL 114 | downloadFile 115 | installFile 116 | testVersion 117 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/gosuri/uitable" 9 | "github.com/spf13/cobra" 10 | "gopkg.in/yaml.v2" 11 | 12 | "k8s.io/helm/pkg/helm" 13 | "k8s.io/helm/pkg/helm/environment" 14 | "k8s.io/helm/pkg/proto/hapi/release" 15 | "k8s.io/helm/pkg/repo" 16 | "k8s.io/helm/pkg/tlsutil" 17 | ) 18 | 19 | const globalUsage = ` 20 | Check to see if there is an updated version available for installed charts. 21 | ` 22 | 23 | var ( 24 | outputFormat string 25 | settings environment.EnvSettings 26 | devel bool 27 | tlsEnable bool 28 | tlsHostname string 29 | tlsCaCert string 30 | tlsCert string 31 | tlsKey string 32 | tlsVerify bool 33 | ) 34 | 35 | var version = "canary" 36 | 37 | const ( 38 | statusOutdated = "OUTDATED" 39 | statusUptodate = "UPTODATE" 40 | ) 41 | 42 | type ChartVersionInfo struct { 43 | ReleaseName string `json:"releaseName"` 44 | ChartName string `json:"chartName"` 45 | InstalledVersion string `json:"installedVersion"` 46 | LatestVersion string `json:"latestVersion"` 47 | Status string `json:"status"` 48 | } 49 | 50 | func main() { 51 | cmd := &cobra.Command{ 52 | Use: "whatup [flags]", 53 | Short: fmt.Sprintf("check if installed charts are out of date (helm-whatup %s)", version), 54 | RunE: run, 55 | } 56 | 57 | f := cmd.Flags() 58 | 59 | f.StringVarP(&outputFormat, "output", "o", "plain", "output format. Accepted formats: plain, json, yaml, table, short") 60 | f.BoolVarP(&devel, "devel", "d", false, "whether to include pre-releases or not") 61 | f.BoolVar(&tlsEnable, "tls", false, "enable TLS for requests to the server") 62 | f.StringVar(&tlsCaCert, "tls-ca-cert", "", "path to TLS CA certificate file") 63 | f.StringVar(&tlsCert, "tls-cert", "", "path to TLS certificate file") 64 | f.StringVar(&tlsKey, "tls-key", "", "path to TLS key file") 65 | f.StringVar(&tlsHostname, "tls-hostname", "", "the server name used to verify the hostname on the returned certificates from the server") 66 | f.BoolVar(&tlsVerify, "tls-verify", false, "enable TLS for requests to the server, and controls whether the client verifies the server's certificate chain and host name") 67 | 68 | if err := cmd.Execute(); err != nil { 69 | os.Exit(1) 70 | } 71 | } 72 | 73 | func newClient() (*helm.Client, error) { 74 | opts := []helm.Option{} 75 | 76 | helmHost := os.Getenv("TILLER_HOST") 77 | 78 | if helmHost == "" { 79 | return nil, fmt.Errorf("TILLER_HOST was not set by Helm") 80 | } 81 | 82 | opts = append(opts, helm.Host(helmHost)) 83 | 84 | // priority order for reading in configuration: 85 | // 86 | // 1. flags 87 | // 2. environment variables 88 | // 3. defaults 89 | 90 | if tlsHostname == "" { 91 | tlsHostname = os.Getenv("HELM_TLS_HOSTNAME") 92 | if tlsHostname == "" { 93 | tlsHostname = helmHost 94 | } 95 | } 96 | 97 | if tlsCaCert == "" { 98 | tlsCaCert = os.Getenv("HELM_TLS_CA_CERT") 99 | if tlsCaCert == "" { 100 | tlsCaCert = os.ExpandEnv(environment.DefaultTLSCaCert) 101 | } 102 | } 103 | 104 | if tlsCert == "" { 105 | tlsCert = os.Getenv("HELM_TLS_CERT") 106 | if tlsCert == "" { 107 | tlsCert = os.ExpandEnv(environment.DefaultTLSCert) 108 | } 109 | } 110 | 111 | if tlsKey == "" { 112 | tlsKey = os.Getenv("HELM_TLS_KEY") 113 | if tlsKey == "" { 114 | tlsKey = os.ExpandEnv(environment.DefaultTLSKeyFile) 115 | } 116 | } 117 | 118 | if !tlsEnable { 119 | tlsEnable = os.Getenv("HELM_TLS_ENABLE") != "" 120 | } 121 | 122 | if !tlsVerify { 123 | tlsVerify = os.Getenv("HELM_TLS_VERIFY") != "" 124 | } 125 | 126 | if tlsEnable || tlsVerify { 127 | tlsopts := tlsutil.Options{ 128 | ServerName: tlsHostname, 129 | CaCertFile: tlsCaCert, 130 | CertFile: tlsCert, 131 | KeyFile: tlsKey, 132 | InsecureSkipVerify: !tlsVerify, 133 | } 134 | 135 | tlscfg, err := tlsutil.ClientConfig(tlsopts) 136 | if err != nil { 137 | return nil, err 138 | } 139 | 140 | opts = append(opts, helm.WithTLS(tlscfg)) 141 | } 142 | 143 | return helm.NewClient(opts...), nil 144 | } 145 | 146 | func run(cmd *cobra.Command, args []string) error { 147 | client, err := newClient() 148 | if err != nil { 149 | return err 150 | } 151 | 152 | releases, err := fetchReleases(client) 153 | if err != nil { 154 | return err 155 | } 156 | 157 | repositories, err := fetchIndices(client) 158 | if err != nil { 159 | return err 160 | } 161 | 162 | if len(releases) == 0 { 163 | if outputFormat == "plain" { 164 | fmt.Println("No releases found. All up to date!") 165 | } 166 | return nil 167 | } 168 | 169 | if len(repositories) == 0 { 170 | if outputFormat == "plain" { 171 | fmt.Println("No repositories found. Did you run `helm repo update`?") 172 | } 173 | return nil 174 | } 175 | 176 | var result []ChartVersionInfo 177 | 178 | for _, release := range releases { 179 | for _, idx := range repositories { 180 | if idx.Has(release.Chart.Metadata.Name, release.Chart.Metadata.Version) { 181 | // fetch latest release 182 | constraint := "" 183 | // Include pre-releases 184 | if devel { 185 | constraint = ">= *-0" 186 | } 187 | chartVer, err := idx.Get(release.Chart.Metadata.Name, constraint) 188 | if err != nil { 189 | return err 190 | } 191 | 192 | versionStatus := ChartVersionInfo{ 193 | ReleaseName: release.Name, 194 | ChartName: release.Chart.Metadata.Name, 195 | InstalledVersion: release.Chart.Metadata.Version, 196 | LatestVersion: chartVer.Version, 197 | } 198 | 199 | if versionStatus.InstalledVersion == versionStatus.LatestVersion { 200 | versionStatus.Status = statusUptodate 201 | } else { 202 | versionStatus.Status = statusOutdated 203 | } 204 | result = append(result, versionStatus) 205 | } 206 | } 207 | } 208 | 209 | switch outputFormat { 210 | case "plain": 211 | for _, versionInfo := range result { 212 | if versionInfo.LatestVersion != versionInfo.InstalledVersion { 213 | fmt.Printf("There is an update available for release %s (%s)!\nInstalled version: %s\nAvailable version: %s\n", versionInfo.ReleaseName, versionInfo.ChartName, versionInfo.InstalledVersion, versionInfo.LatestVersion) 214 | } else { 215 | fmt.Printf("Release %s (%s) is up to date.\n", versionInfo.ReleaseName, versionInfo.LatestVersion) 216 | } 217 | } 218 | fmt.Println("Done.") 219 | case "short": 220 | for _, versionInfo := range result { 221 | if versionInfo.LatestVersion != versionInfo.InstalledVersion { 222 | fmt.Printf("%s (%s): %s --> %s\n", versionInfo.ReleaseName, versionInfo.ChartName, versionInfo.InstalledVersion, versionInfo.LatestVersion) 223 | } 224 | } 225 | case "json": 226 | outputBytes, err := json.MarshalIndent(result, "", " ") 227 | if err != nil { 228 | return err 229 | } 230 | fmt.Println(string(outputBytes)) 231 | case "yml": 232 | fallthrough 233 | case "yaml": 234 | outputBytes, err := yaml.Marshal(result) 235 | if err != nil { 236 | return err 237 | } 238 | fmt.Println(string(outputBytes)) 239 | case "table": 240 | table := uitable.New() 241 | table.AddRow("RELEASE", "CHART", "INSTALLED_VERSION", "LATEST_VERSION", "STATUS") 242 | for _, versionInfo := range result { 243 | table.AddRow(versionInfo.ReleaseName, versionInfo.ChartName, versionInfo.InstalledVersion, versionInfo.LatestVersion, versionInfo.Status) 244 | } 245 | fmt.Println(table) 246 | 247 | default: 248 | return fmt.Errorf("invalid formatter: %s", outputFormat) 249 | } 250 | 251 | return nil 252 | } 253 | 254 | func fetchReleases(client *helm.Client) ([]*release.Release, error) { 255 | res, err := client.ListReleases() 256 | if err != nil { 257 | return nil, err 258 | } 259 | if res == nil { 260 | return []*release.Release{}, nil 261 | } 262 | return res.Releases, nil 263 | } 264 | 265 | func fetchIndices(client *helm.Client) ([]*repo.IndexFile, error) { 266 | indices := []*repo.IndexFile{} 267 | rfp := os.Getenv("HELM_PATH_REPOSITORY_FILE") 268 | repofile, err := repo.LoadRepositoriesFile(rfp) 269 | if err != nil { 270 | return nil, fmt.Errorf("could not load repositories file '%s': %s", rfp, err) 271 | } 272 | for _, repository := range repofile.Repositories { 273 | idx, err := repo.LoadIndexFile(repository.Cache) 274 | if err != nil { 275 | return nil, fmt.Errorf("could not load index file '%s': %s", repository.Cache, err) 276 | } 277 | indices = append(indices, idx) 278 | } 279 | return indices, nil 280 | } 281 | -------------------------------------------------------------------------------- /Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | digest = "1:289dd4d7abfb3ad2b5f728fbe9b1d5c1bf7d265a3eb9ef92869af1f7baba4c7a" 6 | name = "github.com/BurntSushi/toml" 7 | packages = ["."] 8 | pruneopts = "" 9 | revision = "b26d9c308763d68093482582cea63d69be07a0f0" 10 | version = "v0.3.0" 11 | 12 | [[projects]] 13 | digest = "1:1355ed70fb12d3ae86828e65c35748269d1c8a20ab8c6c2f03107279c1e0bd90" 14 | name = "github.com/Masterminds/semver" 15 | packages = ["."] 16 | pruneopts = "" 17 | revision = "15d8430ab86497c5c0da827b748823945e1cf1e1" 18 | version = "v1.4.0" 19 | 20 | [[projects]] 21 | digest = "1:aec6720081aad903219cf427bb9acdefc9c440743add4d02df38ff387c69886a" 22 | name = "github.com/Masterminds/sprig" 23 | packages = ["."] 24 | pruneopts = "" 25 | revision = "15f9564e7e9cf0da02a48e0d25f12a7b83559aa6" 26 | version = "v2.16.0" 27 | 28 | [[projects]] 29 | digest = "1:24cff84fefa06791f78f9bc6e05c2a3a90710c81ae6b76225280daf33b267d36" 30 | name = "github.com/aokoli/goutils" 31 | packages = ["."] 32 | pruneopts = "" 33 | revision = "3391d3790d23d03408670993e957e8f408993c34" 34 | version = "v1.0.1" 35 | 36 | [[projects]] 37 | digest = "1:a9854984bc40330dde2125537b7f46d0a8d7860b3750de2e7cd0a6f904506212" 38 | name = "github.com/cyphar/filepath-securejoin" 39 | packages = ["."] 40 | pruneopts = "" 41 | revision = "a261ee33d7a517f054effbf451841abaafe3e0fd" 42 | version = "v0.2.2" 43 | 44 | [[projects]] 45 | digest = "1:e988ed0ca0d81f4d28772760c02ee95084961311291bdfefc1b04617c178b722" 46 | name = "github.com/fatih/color" 47 | packages = ["."] 48 | pruneopts = "" 49 | revision = "5b77d2a35fb0ede96d138fc9a99f5c9b6aef11b4" 50 | version = "v1.7.0" 51 | 52 | [[projects]] 53 | digest = "1:b13707423743d41665fd23f0c36b2f37bb49c30e94adb813319c44188a51ba22" 54 | name = "github.com/ghodss/yaml" 55 | packages = ["."] 56 | pruneopts = "" 57 | revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" 58 | version = "v1.0.0" 59 | 60 | [[projects]] 61 | digest = "1:9ab1b1c637d7c8f49e39d8538a650d7eb2137b076790cff69d160823b505964c" 62 | name = "github.com/gobwas/glob" 63 | packages = [ 64 | ".", 65 | "compiler", 66 | "match", 67 | "syntax", 68 | "syntax/ast", 69 | "syntax/lexer", 70 | "util/runes", 71 | "util/strings", 72 | ] 73 | pruneopts = "" 74 | revision = "5ccd90ef52e1e632236f7326478d4faa74f99438" 75 | version = "v0.2.3" 76 | 77 | [[projects]] 78 | digest = "1:b852d2b62be24e445fcdbad9ce3015b44c207815d631230dfce3f14e7803f5bf" 79 | name = "github.com/golang/protobuf" 80 | packages = [ 81 | "proto", 82 | "ptypes", 83 | "ptypes/any", 84 | "ptypes/duration", 85 | "ptypes/timestamp", 86 | ] 87 | pruneopts = "" 88 | revision = "6c65a5562fc06764971b7c5d05c76c75e84bdbf7" 89 | version = "v1.3.2" 90 | 91 | [[projects]] 92 | digest = "1:5247b135b5492aa232a731acdcb52b08f32b874cb398f21ab460396eadbe866b" 93 | name = "github.com/google/uuid" 94 | packages = ["."] 95 | pruneopts = "" 96 | revision = "d460ce9f8df2e77fb1ba55ca87fafed96c607494" 97 | version = "v1.0.0" 98 | 99 | [[projects]] 100 | digest = "1:0e0cf21ac3608548f53172bbd6d95078f99ef4d97a9fc2403b584a2243d69bbc" 101 | name = "github.com/gosuri/uitable" 102 | packages = [ 103 | ".", 104 | "util/strutil", 105 | "util/wordwrap", 106 | ] 107 | pruneopts = "" 108 | revision = "2cf933346b8370a3a3d8867ef5cf54b2129d8ecf" 109 | version = "v0.0.3" 110 | 111 | [[projects]] 112 | digest = "1:35979179658d20a73693589e67bdc3baf4dc0ef9f524b1dfd3cc55fb5f6ae384" 113 | name = "github.com/huandu/xstrings" 114 | packages = ["."] 115 | pruneopts = "" 116 | revision = "f02667b379e2fb5916c3cda2cf31e0eb885d79f8" 117 | version = "v1.2.0" 118 | 119 | [[projects]] 120 | digest = "1:7ab38c15bd21e056e3115c8b526d201eaf74e0308da9370997c6b3c187115d36" 121 | name = "github.com/imdario/mergo" 122 | packages = ["."] 123 | pruneopts = "" 124 | revision = "9f23e2d6bd2a77f959b2bf6acdbefd708a83a4a4" 125 | version = "v0.3.6" 126 | 127 | [[projects]] 128 | digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" 129 | name = "github.com/inconshreveable/mousetrap" 130 | packages = ["."] 131 | pruneopts = "" 132 | revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" 133 | version = "v1.0" 134 | 135 | [[projects]] 136 | digest = "1:9ea83adf8e96d6304f394d40436f2eb44c1dc3250d223b74088cc253a6cd0a1c" 137 | name = "github.com/mattn/go-colorable" 138 | packages = ["."] 139 | pruneopts = "" 140 | revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072" 141 | version = "v0.0.9" 142 | 143 | [[projects]] 144 | digest = "1:dbfae9da5a674236b914e486086671145b37b5e3880a38da906665aede3c9eab" 145 | name = "github.com/mattn/go-isatty" 146 | packages = ["."] 147 | pruneopts = "" 148 | revision = "1311e847b0cb909da63b5fecfb5370aa66236465" 149 | version = "v0.0.8" 150 | 151 | [[projects]] 152 | digest = "1:84c28d9899cc4e00c38042d345cea8819275a5a62403a58530cac67022894776" 153 | name = "github.com/mattn/go-runewidth" 154 | packages = ["."] 155 | pruneopts = "" 156 | revision = "3ee7d812e62a0804a7d0a324e0249ca2db3476d3" 157 | version = "v0.0.4" 158 | 159 | [[projects]] 160 | digest = "1:1d7e1867c49a6dd9856598ef7c3123604ea3daabf5b83f303ff457bcbc410b1d" 161 | name = "github.com/pkg/errors" 162 | packages = ["."] 163 | pruneopts = "" 164 | revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4" 165 | version = "v0.8.1" 166 | 167 | [[projects]] 168 | branch = "master" 169 | digest = "1:5fcbd0f98cf026018a68eb14a42cf6ca4f404b60d960bc265f6d4396ebd72039" 170 | name = "github.com/spf13/cobra" 171 | packages = ["."] 172 | pruneopts = "" 173 | revision = "1c9c46d5c1cc2aaebdd1898c0680e85e8a44b36d" 174 | 175 | [[projects]] 176 | digest = "1:cbaf13cdbfef0e4734ed8a7504f57fe893d471d62a35b982bf6fb3f036449a66" 177 | name = "github.com/spf13/pflag" 178 | packages = ["."] 179 | pruneopts = "" 180 | revision = "298182f68c66c05229eb03ac171abe6e309ee79a" 181 | version = "v1.0.3" 182 | 183 | [[projects]] 184 | branch = "master" 185 | digest = "1:295363031beef7eb063d53138806b43f26c38d8a3e2543324ce2af3c766069de" 186 | name = "golang.org/x/crypto" 187 | packages = [ 188 | "cast5", 189 | "openpgp", 190 | "openpgp/armor", 191 | "openpgp/clearsign", 192 | "openpgp/elgamal", 193 | "openpgp/errors", 194 | "openpgp/packet", 195 | "openpgp/s2k", 196 | "pbkdf2", 197 | "scrypt", 198 | ] 199 | pruneopts = "" 200 | revision = "5119cf507ed5294cc409c092980c7497ee5d6fd2" 201 | 202 | [[projects]] 203 | branch = "master" 204 | digest = "1:b6c2b04cb0d9f13f17753062d6cc38295513565bc7012deb14b9492d97a79084" 205 | name = "golang.org/x/net" 206 | packages = [ 207 | "context", 208 | "http2", 209 | "http2/hpack", 210 | "idna", 211 | "internal/timeseries", 212 | "lex/httplex", 213 | "trace", 214 | ] 215 | pruneopts = "" 216 | revision = "f5dfe339be1d06f81b22525fe34671ee7d2c8904" 217 | 218 | [[projects]] 219 | branch = "master" 220 | digest = "1:022f4bd6739cc585724b670eb38b3fbd3efe60d45cd6b279c990e434f8a8f6ea" 221 | name = "golang.org/x/sys" 222 | packages = ["unix"] 223 | pruneopts = "" 224 | revision = "cbf593c0f2f39034e9104bbf77e2ec7c48c98fc5" 225 | 226 | [[projects]] 227 | branch = "master" 228 | digest = "1:31985a0ed491dba5ba7fe92e18be008acd92ca9435ed9b35b06f3e6c00fd82cb" 229 | name = "golang.org/x/text" 230 | packages = [ 231 | "collate", 232 | "collate/build", 233 | "internal/colltab", 234 | "internal/gen", 235 | "internal/tag", 236 | "internal/triegen", 237 | "internal/ucd", 238 | "language", 239 | "secure/bidirule", 240 | "transform", 241 | "unicode/bidi", 242 | "unicode/cldr", 243 | "unicode/norm", 244 | "unicode/rangetable", 245 | ] 246 | pruneopts = "" 247 | revision = "4e4a3210bb54bb31f6ab2cdca2edcc0b50c420c1" 248 | 249 | [[projects]] 250 | branch = "master" 251 | digest = "1:2d833b53e432cd69645da559b822661ebc5c0a13c571dee1c1f80fb1a0241330" 252 | name = "google.golang.org/genproto" 253 | packages = ["googleapis/rpc/status"] 254 | pruneopts = "" 255 | revision = "2b5a72b8730b0b16380010cfe5286c42108d88e7" 256 | 257 | [[projects]] 258 | digest = "1:1c1ce3d4783796c0922d16dec8b0e9be02d383888e9126718e5a5db8baa3fe6d" 259 | name = "google.golang.org/grpc" 260 | packages = [ 261 | ".", 262 | "balancer", 263 | "balancer/base", 264 | "balancer/roundrobin", 265 | "codes", 266 | "connectivity", 267 | "credentials", 268 | "encoding", 269 | "grpclb/grpc_lb_v1/messages", 270 | "grpclog", 271 | "health/grpc_health_v1", 272 | "internal", 273 | "keepalive", 274 | "metadata", 275 | "naming", 276 | "peer", 277 | "resolver", 278 | "resolver/dns", 279 | "resolver/passthrough", 280 | "stats", 281 | "status", 282 | "tap", 283 | "transport", 284 | ] 285 | pruneopts = "" 286 | revision = "6b51017f791ae1cfbec89c52efdf444b13b550ef" 287 | version = "v1.9.2" 288 | 289 | [[projects]] 290 | branch = "v2" 291 | digest = "1:4b4e5848dfe7f316f95f754df071bebfb40cf4482da62e17e7e1aebdf11f4918" 292 | name = "gopkg.in/yaml.v2" 293 | packages = ["."] 294 | pruneopts = "" 295 | revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4" 296 | 297 | [[projects]] 298 | branch = "master" 299 | digest = "1:5935b656ca95587725df6f2d912ba9abcd3bf6c84a3744559346edeae6e4b572" 300 | name = "k8s.io/apimachinery" 301 | packages = ["pkg/version"] 302 | pruneopts = "" 303 | revision = "8259d997cf059cd83dc47e5f8074b7a7d7967c09" 304 | 305 | [[projects]] 306 | digest = "1:e0cde0b53f1a353cc5fe6d86e9d41a41280b6395ab11d6c4f8f2f82593154ed6" 307 | name = "k8s.io/client-go" 308 | packages = ["util/homedir"] 309 | pruneopts = "" 310 | revision = "78700dec6369ba22221b72770783300f143df150" 311 | version = "v6.0.0" 312 | 313 | [[projects]] 314 | digest = "1:c35e91a5a3af23a68b1440fc1a9c5a713853b5447bf4e0606def69cbc84148ef" 315 | name = "k8s.io/helm" 316 | packages = [ 317 | "pkg/chartutil", 318 | "pkg/engine", 319 | "pkg/getter", 320 | "pkg/helm", 321 | "pkg/helm/environment", 322 | "pkg/helm/helmpath", 323 | "pkg/ignore", 324 | "pkg/manifest", 325 | "pkg/plugin", 326 | "pkg/proto/hapi/chart", 327 | "pkg/proto/hapi/release", 328 | "pkg/proto/hapi/services", 329 | "pkg/proto/hapi/version", 330 | "pkg/provenance", 331 | "pkg/releaseutil", 332 | "pkg/renderutil", 333 | "pkg/repo", 334 | "pkg/storage/errors", 335 | "pkg/sympath", 336 | "pkg/tlsutil", 337 | "pkg/urlutil", 338 | "pkg/version", 339 | ] 340 | pruneopts = "" 341 | revision = "0e7f3b6637f7af8fcfddb3d2941fcc7cbebb0085" 342 | version = "v2.14.3" 343 | 344 | [solve-meta] 345 | analyzer-name = "dep" 346 | analyzer-version = 1 347 | input-imports = [ 348 | "github.com/gosuri/uitable", 349 | "github.com/spf13/cobra", 350 | "gopkg.in/yaml.v2", 351 | "k8s.io/helm/pkg/helm", 352 | "k8s.io/helm/pkg/proto/hapi/release", 353 | "k8s.io/helm/pkg/repo", 354 | ] 355 | solver-name = "gps-cdcl" 356 | solver-version = 1 357 | --------------------------------------------------------------------------------