diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 31298ea..e7e7077 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,4 +31,4 @@ jobs: version: latest args: release --rm-dist env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 92d253d..1c9ac3d 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,4 @@ go.work bin dist helm-set -releases/* \ No newline at end of file +releases/* diff --git a/.goreleaser.yml b/.goreleaser.yml index 0b52fc6..169146c 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -15,4 +15,4 @@ archives: format: tar.gz files: - LICENSE - - plugin.yaml \ No newline at end of file + - plugin.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..511c7f1 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,68 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-yaml + exclude: charts/ + - id: check-merge-conflict + - exclude: README.md + id: end-of-file-fixer + - exclude: README.md + id: trailing-whitespace + - id: mixed-line-ending + - id: check-added-large-files +- repo: https://github.com/norwoodj/helm-docs + rev: v1.11.0 + hooks: + - id: helm-docs + args: + - --output-file=README.md +- repo: https://github.com/antonbabenko/pre-commit-terraform + rev: v1.77.1 + hooks: + - id: terraform_fmt + - id: terraform_tflint + - id: terraform_docs + args: + - --hook-config=--add-to-existing-file=true # Boolean. true or false + - --hook-config=--create-file-if-not-exist=true # Boolean. true or false + - id: terraform_tfsec + args: + - --args=--exclude-downloaded-modules + # - id: terraform_providers_lock + # - id: terrascan + # args: + # - --args=--non-recursive + - id: terraform_validate + exclude: infrastructure/modules/([^/]*)/[^/].+$ +# - repo: https://github.com/bridgecrewio/checkov.git +# rev: '2.3.33' +# hooks: +# - id: checkov +# # verbose: true +# args: [ +# # '--download-external-modules', 'true', +# '--framework', 'terraform' +# ] +- repo: https://github.com/hadolint/hadolint + rev: v2.12.0 + hooks: + - id: hadolint-docker +- repo: https://github.com/commitizen-tools/commitizen + rev: v2.13.0 + hooks: + - id: commitizen + stages: + - commit-msg +- repo: https://github.com/dnephin/pre-commit-golang + rev: v0.4.0 + hooks: + - id: go-fmt + # - id: go-lint + # - id: go-vet + - id: go-mod-tidy +- repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.22.0 + hooks: + - id: check-github-workflows + - id: check-github-actions diff --git a/Makefile b/Makefile index defdf3a..7378f74 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ run: go build . helm plugin uninstall myplugin - helm plugin install . \ No newline at end of file + helm plugin install . diff --git a/README.md b/README.md index a668ce4..cde5e7b 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![GitHub release](https://img.shields.io/github/v/release/bery/helm-set.svg)](https://github.com/bery/helm-set/releases) [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/helm-helm-set)](https://artifacthub.io/packages/search?repo=helm-helm-set) -This Helm plugin allows you to substitute the environment variables specified in your helm values file with their respective values in the environment from within a CICD pipeline. +Helm-set plugin allows you to substitute the environment variables specified in your helm values file with their respective values in the environment from within a CICD pipeline. Heavily inspired by Terraform's [envsubst](https://developer.hashicorp.com/terraform/language/values/variables#environment-variables) feature. ## Install @@ -23,13 +23,59 @@ To use the plugin, you do not need any special dependencies. The installer will ### Simple usage ```bash +Use environment variables as helm values by taking all variables starting with HELM_VAR_ to --set values. + +Usage: + set [command] + +Available Commands: + completion Generate the autocompletion script for the specified shell + help Help about any command + install wrapper for helm install, decrypting secrets + upgrade wrapper for helm upgrade, decrypting secrets + +Flags: + -d, --debug enable verbose output + --dry-run parameter parsing mode (rename, copy) + -h, --help help for set + -v, --verbose enable verbose output +``` +### Examples +#### Basic usage +Set the `HELM_VAR_replicaCount` envrionment variable to `3` by: +```bash export HELM_VAR_replicaCount=3 -helm set upgrade --install --dry-run=false xxx ealenn/echo-server ``` -### Result +Replace `helm upgrade` with `helm set upgrade` and run: +```bash +helm set upgrade --install --dry-run=false +``` +This will replace the value of `replicaCount` in the `helm upgrade` command with the value of the environment variable `HELM_VAR_replicaCount`. +#### Result +```bash +helm upgrade upgrade --install --dry-run=false --set replicaCount=3 +``` +#### Nested values +Goal: set value of image.tag to `latest` and value of image.pullPolicy to `Always`. ```bash -helm upgrade upgrade --install --dry-run=false xxx ealenn/echo-server --set replicaCount=3 +export HELM_VAR_image__tag="latest" +export HELM_VAR_image__pullPolicy="Always" +helm set upgrade --install --dry-run=false ``` +#### Result +```bash +helm upgrade upgrade --install --set image.tag="latest" --set image.pullPolicy="Always" +``` +#### Lists values +```bash +export HELM_VAR_list__item___0___path="your_path" +helm set upgrade --install --dry-run=false +``` +#### Result +```bash +helm upgrade upgrade --install --set list.item[0].path="your_path" +``` + ## Uninstall ```bash helm plugin remove helm-set @@ -37,5 +83,4 @@ helm plugin remove helm-set ## License -[MIT](LICENSE) -# helm-set +[MIT](LICENSE) \ No newline at end of file diff --git a/cmd/helms.go b/cmd/helms.go index 524416b..04b34ab 100644 --- a/cmd/helms.go +++ b/cmd/helms.go @@ -10,11 +10,6 @@ import ( "github.com/spf13/cobra" ) -type CommandFlags struct { - DryRun bool - Install bool -} - // installCmd wraps the helm 'install' command. var installCmd = &cobra.Command{ Use: "install", @@ -22,13 +17,13 @@ var installCmd = &cobra.Command{ Long: `This command wraps the default helm install command, but decrypting any encrypted values file using Barbican. Available arguments are the same as for the default command.`, - Args: cobra.ArbitraryArgs, - DisableFlagParsing: true, + Args: cobra.ArbitraryArgs, + // DisableFlagParsing: true, FParseErrWhitelist: cobra.FParseErrWhitelist{ UnknownFlags: true, }, Run: func(cmd *cobra.Command, args []string) { - out, err := wrapHelmCommand("install", Mode, args) + out, err := wrapHelmCommand("install", Mode, args, DryRun) if err != nil { log.Fatalf("%v", string(out)) } @@ -43,13 +38,12 @@ var upgradeCmd = &cobra.Command{ Long: `This command wraps the default helm upgrade command, but decrypting any encrypted values file using Barbican. Available arguments are the same as for the default command.`, - Args: cobra.ArbitraryArgs, - DisableFlagParsing: true, + Args: cobra.ArbitraryArgs, FParseErrWhitelist: cobra.FParseErrWhitelist{ UnknownFlags: true, }, Run: func(cmd *cobra.Command, args []string) { - out, err := wrapHelmCommand("upgrade", Mode, args) + out, err := wrapHelmCommand("upgrade", Mode, args, DryRun) if err != nil { log.Fatalf("%v", string(out)) } @@ -57,21 +51,16 @@ var upgradeCmd = &cobra.Command{ }, } -func wrapHelmCommand(cmd string, mode string, args []string) ([]byte, error) { +func wrapHelmCommand(cmd string, mode string, args []string, dryRun bool) ([]byte, error) { var value string for _, pair := range os.Environ() { variable := strings.Split(pair, "=") if strings.HasPrefix(variable[0], Prefix) { log.Debugf("Found %s", variable[0]) - if mode == "rename" { - normalizedKey := normalizeName(strings.TrimPrefix(variable[0], Prefix)) - value = fmt.Sprintf("%s=%s", normalizedKey, variable[1]) - log.Debugf("Setting %s", value) - } else if mode == "copy" { - value = strings.TrimPrefix(pair, variable[0]+"=") - log.Debugf("Setting %s", value) - } - args = append(args, []string{"--set", fmt.Sprintf("'%s'", value)}...) + normalizedKey := normalizeName(strings.TrimPrefix(variable[0], Prefix)) + value = fmt.Sprintf("%s=%s", normalizedKey, variable[1]) + log.Debugf("Setting %s", value) + args = append(args, []string{"--set", value}...) } } helmArgs, err := getArgs(args) @@ -80,22 +69,16 @@ func wrapHelmCommand(cmd string, mode string, args []string) ([]byte, error) { } fullArgs := append([]string{cmd}, helmArgs...) helmCmd := exec.Command("helm", fullArgs...) + if dryRun { + log.Infof("Dry run result command: %s", helmCmd.String()) + return []byte{}, nil + } log.Infof("Running helm command: %s", helmCmd.String()) return helmCmd.CombinedOutput() } func getArgs(args []string) ([]string, error) { helmArgs := args - // for i, flag := range args { - // if flag == "--values" || flag == "-f" || flag == "--filename" { - // if len(helmArgs) > i+1 { - // fname := helmArgs[i+1] - - // // Update args to access the decrypt shm file instead - // helmArgs[i+1] = tmpf - // } - // } - // } return helmArgs, nil } @@ -105,7 +88,7 @@ func normalizeName(name string) string { replaceForBrackets := fmt.Sprintf("___%s___", match) pattern := "[%s]" if !strings.HasSuffix(name, replaceForBrackets) { - pattern = "\\[%s\\]." + pattern = "[%s]." } name = strings.ReplaceAll(name, replaceForBrackets, fmt.Sprintf(pattern, match)) } diff --git a/cmd/root.go b/cmd/root.go index edba73d..e2ba963 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -2,52 +2,36 @@ package cmd import ( "os" - "strings" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -func main() { - Execute() -} - -// RootCmd represents the base command when called without any subcommands -var RootCmd = &cobra.Command{ +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ Use: "set", - Short: "Use envrironment variables as helm values", - Long: `Use envrironment variables as helm values by taking all variables starting with HELM_VAR_ to --set values.`, + Short: "Use environment variables as helm values", + Long: `Use environment variables as helm values by taking all variables starting with HELM_VAR_ to --set values.`, FParseErrWhitelist: cobra.FParseErrWhitelist{ UnknownFlags: true, }, } -// ④ Now use the FooMode enum flag. If you want a non-zero default, then -// simply set it here, such as in "foomode = Bar". var Mode string +var DryRun bool var Debug bool var Verbose bool var Prefix string = "HELM_VAR_" -// Execute adds all child commands to the root command and sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the rootCmd. -func Execute() { - // Cleanup OpenStack environment for compatibility with the golang client - for _, v := range []string{ - "OS_IDENTITY_PROVIDER", "OS_AUTH_TYPE", "OS_MUTUAL_AUTH", "OS_PROTOCOL"} { - os.Unsetenv(v) - } - os.Setenv("OS_AUTH_URL", strings.Replace(os.Getenv("OS_AUTH_URL"), "krb/", "", 1)) - if err := RootCmd.Execute(); err != nil { - log.Fatal(err) - os.Exit(1) - } +func main() { + Execute() } -func init() { - RootCmd.PersistentFlags().BoolVarP(&Debug, "debug", "", false, "enable verbose output") - RootCmd.PersistentFlags().StringVarP(&Mode, "mode", "", "rename", "enable verbose output") +func Execute() { + rootCmd.PersistentFlags().BoolVarP(&Debug, "debug", "d", false, "enable verbose output") + rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "enable verbose output") + rootCmd.PersistentFlags().BoolVar(&DryRun, "dry-run", false, "parameter parsing mode (rename, copy)") log.SetFormatter(&log.TextFormatter{DisableTimestamp: true}) log.SetOutput(os.Stdout) @@ -58,6 +42,8 @@ func init() { log.SetLevel(log.InfoLevel) } - RootCmd.AddCommand(installCmd) - RootCmd.AddCommand(upgradeCmd) + rootCmd.AddCommand(installCmd) + rootCmd.AddCommand(upgradeCmd) + + rootCmd.Execute() } diff --git a/go.mod b/go.mod index 5fc9793..9811c10 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,11 @@ go 1.19 require ( github.com/sirupsen/logrus v1.9.0 - github.com/spf13/cobra v1.5.0 + github.com/spf13/cobra v1.7.0 ) require ( - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index fb3a7c9..0d6b228 100644 --- a/go.sum +++ b/go.sum @@ -2,15 +2,15 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= -github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -19,7 +19,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/helm-set.sh b/helm-set.sh index fad2bf2..5d82d04 100755 --- a/helm-set.sh +++ b/helm-set.sh @@ -28,7 +28,7 @@ version="$(cat plugin.yaml | grep "version" | cut -d '"' -f 2)" echo "Downloading and installing helm-helm-set v${version} ..." binary_url="" -if [ "$(uname)" == "Darwin" ]; then +if [ "$(uname)" == "Darwin" ]; then binary_url="https://github.com/bery/helm-set/releases/download/v${version}/helm-set_${version}_darwin_amd64.tar.gz" elif [ "$(uname)" == "Linux" ] ; then binary_url="https://github.com/bery/helm-set/releases/download/v${version}/helm-set_${version}_linux_amd64.tar.gz" @@ -74,4 +74,4 @@ checksums_filename="releases/v${version}_checksums.txt" # Unpack the binary. tar xzf "${binary_filename}" -C "releases/v${version}" mv "releases/v${version}/bin/helm-set" "bin/helm-set" -exit 0 \ No newline at end of file +exit 0 diff --git a/plugin.yaml b/plugin.yaml index 68d44c6..d43c419 100644 --- a/plugin.yaml +++ b/plugin.yaml @@ -1,5 +1,5 @@ name: "set" -version: "0.0.14" +version: "0.0.16" usage: "helm set install|upgrade" description: |- This plugin provides a way to translate environment variables @@ -7,4 +7,4 @@ description: |- command: "$HELM_PLUGIN_DIR/bin/helm-set" hooks: install: "cd $HELM_PLUGIN_DIR; ./helm-set.sh" - update: "cd $HELM_PLUGIN_DIR; ./helm-set.sh" \ No newline at end of file + update: "cd $HELM_PLUGIN_DIR; ./helm-set.sh" diff --git a/run.sh b/run.sh index b38f285..f01acdd 100644 --- a/run.sh +++ b/run.sh @@ -1,3 +1,3 @@ #! /bin/sh # run prog with some arguments -./helm-set "$@" \ No newline at end of file +./helm-set "$@"