Skip to content

Commit

Permalink
chore(postrender): Adds unit tests for exec post renderer
Browse files Browse the repository at this point in the history
Signed-off-by: Taylor Thomas <taylor.thomas@microsoft.com>
  • Loading branch information
thomastaylor312 committed Feb 7, 2020
1 parent 08fc12a commit 7a3049a
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 8 deletions.
1 change: 1 addition & 0 deletions cmd/helm/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f.BoolVar(&client.IsUpgrade, "is-upgrade", false, "set .Release.IsUpgrade instead of .Release.IsInstall")
f.StringArrayVarP(&extraAPIs, "api-versions", "a", []string{}, "Kubernetes api versions used for Capabilities.APIVersions")
f.BoolVar(&client.UseReleaseName, "release-name", false, "use release name in the output-dir path.")
bindPostRenderFlag(cmd, &client.PostRenderer)

return cmd
}
25 changes: 17 additions & 8 deletions pkg/postrender/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,27 @@ func (p *execRender) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error)

// getFullPath returns the full filepath to the binary to execute. If the path
// does not contain any separators, it will search first in the plugins
// directory, then in $PATH, otherwise it will resolve any relative paths to a
// fully qualified path
// directory (or directories if multiple are specified. In which case, it will
// return the first result), then in $PATH, otherwise it will resolve any
// relative paths to a fully qualified path
func getFullPath(binaryPath string) (string, error) {
// Manually check the plugin dir first
if !strings.Contains(binaryPath, string(filepath.Separator)) {
// First check the plugin dir
pluginDir := helmpath.DataPath("plugins")
_, err := os.Stat(filepath.Join(pluginDir, binaryPath))
if err != nil && !os.IsNotExist(err) {
return "", err
} else if err == nil {
binaryPath = filepath.Join(pluginDir, binaryPath)
pluginDir := helmpath.DataPath("plugins") // Default location
// If location for plugins is explicitly set, check there
if v, ok := os.LookupEnv("HELM_PLUGINS"); ok {
pluginDir = v
}
// The plugins variable can actually contain multple paths, so loop through those
for _, p := range filepath.SplitList(pluginDir) {
_, err := os.Stat(filepath.Join(p, binaryPath))
if err != nil && !os.IsNotExist(err) {
return "", err
} else if err == nil {
binaryPath = filepath.Join(p, binaryPath)
break
}
}
}

Expand Down
152 changes: 152 additions & 0 deletions pkg/postrender/exec_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
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.
*/

package postrender

import (
"bytes"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"helm.sh/helm/v3/internal/test/ensure"
)

const testingScript = `#!/bin/sh
sed s/FOOTEST/BARTEST/g <&0
`

func TestGetFullPath(t *testing.T) {
is := assert.New(t)
t.Run("full path resolves correctly", func(t *testing.T) {
testpath, cleanup := setupTestingScript(t)
defer cleanup()

fullPath, err := getFullPath(testpath)
is.NoError(err)
is.Equal(testpath, fullPath)
})

t.Run("relative path resolves correctly", func(t *testing.T) {
testpath, cleanup := setupTestingScript(t)
defer cleanup()

currentDir, err := os.Getwd()
require.NoError(t, err)
relative, err := filepath.Rel(currentDir, testpath)
require.NoError(t, err)
fullPath, err := getFullPath(relative)
is.NoError(err)
is.Equal(testpath, fullPath)
})

t.Run("binary in PATH resolves correctly", func(t *testing.T) {
testpath, cleanup := setupTestingScript(t)
defer cleanup()

realPath := os.Getenv("PATH")
os.Setenv("PATH", filepath.Dir(testpath))
defer func() {
os.Setenv("PATH", realPath)
}()

fullPath, err := getFullPath(filepath.Base(testpath))
is.NoError(err)
is.Equal(testpath, fullPath)
})

t.Run("binary in plugin path resolves correctly", func(t *testing.T) {
testpath, cleanup := setupTestingScript(t)
defer cleanup()

realPath := os.Getenv("HELM_PLUGINS")
os.Setenv("HELM_PLUGINS", filepath.Dir(testpath))
defer func() {
os.Setenv("HELM_PLUGINS", realPath)
}()

fullPath, err := getFullPath(filepath.Base(testpath))
is.NoError(err)
is.Equal(testpath, fullPath)
})

t.Run("binary in multiple plugin paths resolves correctly", func(t *testing.T) {
testpath, cleanup := setupTestingScript(t)
defer cleanup()

realPath := os.Getenv("HELM_PLUGINS")
os.Setenv("HELM_PLUGINS", filepath.Dir(testpath)+string(os.PathListSeparator)+"/another/dir")
defer func() {
os.Setenv("HELM_PLUGINS", realPath)
}()

fullPath, err := getFullPath(filepath.Base(testpath))
is.NoError(err)
is.Equal(testpath, fullPath)
})
}

func TestExecRun(t *testing.T) {
if runtime.GOOS == "windows" {
// the actual Run test uses a basic sed example, so skip this test on windows
t.Skip("skipping on windows")
}
is := assert.New(t)
testpath, cleanup := setupTestingScript(t)
defer cleanup()

renderer, err := NewExec(testpath)
require.NoError(t, err)

output, err := renderer.Run(bytes.NewBufferString("FOOTEST"))
is.NoError(err)
is.Contains(output.String(), "BARTEST")
}

func setupTestingScript(t *testing.T) (filepath string, cleanup func()) {
t.Helper()

tempdir := ensure.TempDir(t)

f, err := ioutil.TempFile(tempdir, "post-render-test.sh")
if err != nil {
t.Fatalf("unable to create tempfile for testing: %s", err)
}

_, err = f.WriteString(testingScript)
if err != nil {
t.Fatalf("unable to write tempfile for testing: %s", err)
}

err = f.Chmod(0755)
if err != nil {
t.Fatalf("unable to make tempfile executable for testing: %s", err)
}

err = f.Close()
if err != nil {
t.Fatalf("unable to close tempfile after writing: %s", err)
}

return f.Name(), func() {
os.RemoveAll(tempdir)
}
}

0 comments on commit 7a3049a

Please sign in to comment.