Skip to content

Commit

Permalink
feat: add env subst command [CPE-1773] (#910)
Browse files Browse the repository at this point in the history
* feat: add env subst command

* chore: lint
  • Loading branch information
KyleTryon authored Apr 19, 2023
1 parent 66c2bfe commit 5b836ba
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 1 deletion.
47 changes: 47 additions & 0 deletions cmd/env.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package cmd

import (
"fmt"
"io"

"github.com/a8m/envsubst"
"github.com/spf13/cobra"
)

func newEnvCmd() *cobra.Command {
var envCmd = &cobra.Command{
Use: "env",
Short: "Manage environment variables",
}
var substCmd = &cobra.Command{
Use: "subst",
Short: "Substitute environment variables in a string",
RunE: substRunE,
}
envCmd.AddCommand(substCmd)
return envCmd
}

// Accepts a string as an argument, or reads from stdin if no argument is provided.
func substRunE(cmd *cobra.Command, args []string) error {
var input string
if len(args) > 0 {
input = args[0]
} else {
// Read from stdin
b, err := io.ReadAll(cmd.InOrStdin())
if err != nil {
return err
}
input = string(b)
}
if input == "" {
return nil
}
output, err := envsubst.String(input)
if err != nil {
return err
}
_, err = fmt.Fprint(cmd.OutOrStdout(), output)
return err
}
97 changes: 97 additions & 0 deletions cmd/env_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package cmd

import (
"bytes"
"os"
"testing"

"gotest.tools/v3/assert"
)

func TestSubstRunE(t *testing.T) {
// Set environment variables for testing
err := os.Setenv("ENV_NAME", "world")
if err != nil {
t.Fatal(err)
}

testCases := []struct {
name string
input string
output string
}{
{
name: "substitute variables",
input: "Hello $ENV_NAME!",
output: "Hello world!",
},
{
name: "no variables to substitute",
input: "Hello, world!",
output: "Hello, world!",
},
{
name: "empty input",
input: "",
output: "",
},
{
name: "no variables JSON",
input: `{"foo": "bar"}`,
output: `{"foo": "bar"}`,
},
{
name: "substitute variables JSON",
input: `{"foo": "$ENV_NAME"}`,
output: `{"foo": "world"}`,
},
{
name: "no variables key=value",
input: `foo=bar`,
output: `foo=bar`,
},
}

// Run tests for each test case as argument
for _, tc := range testCases {
t.Run("arg: "+tc.name, func(t *testing.T) {
// Set up test command
cmd := newEnvCmd()

// Capture output
outputBuf := bytes.Buffer{}
cmd.SetOut(&outputBuf)

// Run command
cmd.SetArgs([]string{"subst", tc.input})
err := cmd.Execute()

// Check output and error
assert.NilError(t, err)
assert.Equal(t, tc.output, outputBuf.String())
})
}
// Run tests for each test case as stdin
for _, tc := range testCases {
t.Run("stdin: "+tc.name, func(t *testing.T) {
// Set up test command
cmd := newEnvCmd()

// Set up input
inputBuf := bytes.NewBufferString(tc.input)
cmd.SetIn(inputBuf)

// Capture output
outputBuf := bytes.Buffer{}
cmd.SetOut(&outputBuf)

// Run command
cmd.SetArgs([]string{"subst"})
err = cmd.Execute()

// Check output and error
assert.NilError(t, err)
assert.Equal(t, tc.output, outputBuf.String())
})
}
}
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ func MakeCommands() *cobra.Command {
rootCmd.AddCommand(newSwitchCommand(rootOptions))
rootCmd.AddCommand(newAdminCommand(rootOptions))
rootCmd.AddCommand(newCompletionCommand())
rootCmd.AddCommand(newEnvCmd())

flags := rootCmd.PersistentFlags()

Expand Down
2 changes: 1 addition & 1 deletion cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ var _ = Describe("Root", func() {
Describe("subcommands", func() {
It("can create commands", func() {
commands := cmd.MakeCommands()
Expect(len(commands.Commands())).To(Equal(23))
Expect(len(commands.Commands())).To(Equal(24))
})
})

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ require (

require (
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/a8m/envsubst v1.4.2 // indirect
github.com/agnivade/levenshtein v1.1.1 // indirect
github.com/atotto/clipboard v0.1.4 // indirect
github.com/charmbracelet/bubbles v0.11.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nB
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/a8m/envsubst v1.4.2 h1:4yWIHXOLEJHQEFd4UjrWDrYeYlV7ncFWJOCBRLOZHQg=
github.com/a8m/envsubst v1.4.2/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY=
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
Expand Down

0 comments on commit 5b836ba

Please sign in to comment.