@ -19,14 +19,10 @@ package postrender
import (
import (
"bytes"
"bytes"
"io"
"io"
"os"
"os/exec"
"os/exec"
"path/filepath"
"path/filepath"
"strings"
"github.com/pkg/errors"
"github.com/pkg/errors"
"helm.sh/helm/v3/pkg/helmpath"
)
)
type execRender struct {
type execRender struct {
@ -34,10 +30,9 @@ type execRender struct {
}
}
// NewExec returns a PostRenderer implementation that calls the provided binary.
// NewExec returns a PostRenderer implementation that calls the provided binary.
// It returns an error if the binary cannot be found. If the provided path does
// It returns an error if the binary cannot be found. If the path does not
// not contain any separators, it will search first in the plugins directory,
// contain any separators, it will search in $PATH, otherwise it will resolve
// then in $PATH, otherwise it will resolve any relative paths to a fully
// any relative paths to a fully qualified path
// qualified path
func NewExec ( binaryPath string ) ( PostRenderer , error ) {
func NewExec ( binaryPath string ) ( PostRenderer , error ) {
fullPath , err := getFullPath ( binaryPath )
fullPath , err := getFullPath ( binaryPath )
if err != nil {
if err != nil {
@ -72,30 +67,35 @@ func (p *execRender) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error)
}
}
// getFullPath returns the full filepath to the binary to execute. If the path
// 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
// does not contain any separators, it will search in $PATH, otherwise it will
// directory (or directories if multiple are specified. In which case, it will
// resolve any relative paths to a fully qualified path
// 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 ) {
func getFullPath ( binaryPath string ) ( string , error ) {
// NOTE(thomastaylor312): I am leaving this code commented out here. During
// the implementation of post-render, it was brought up that if we are
// relying on plguins, we should actually use the plugin system so it can
// properly handle multiple OSs. This will be a feature add in the future,
// so I left this code for reference. It can be deleted or reused once the
// feature is implemented
// Manually check the plugin dir first
// Manually check the plugin dir first
if ! strings . Contains ( binaryPath , string ( filepath . Separator ) ) {
// if !strings.Contains(binaryPath, string(filepath.Separator)) {
// First check the plugin dir
// // First check the plugin dir
pluginDir := helmpath . DataPath ( "plugins" ) // Default location
// pluginDir := helmpath.DataPath("plugins") // Default location
// If location for plugins is explicitly set, check there
// // If location for plugins is explicitly set, check there
if v , ok := os . LookupEnv ( "HELM_PLUGINS" ) ; ok {
// if v, ok := os.LookupEnv("HELM_PLUGINS"); ok {
pluginDir = v
// pluginDir = v
}
// }
// The plugins variable can actually contain multple paths, so loop through those
// // The plugins variable can actually contain multple paths, so loop through those
for _ , p := range filepath . SplitList ( pluginDir ) {
// for _, p := range filepath.SplitList(pluginDir) {
_ , err := os . Stat ( filepath . Join ( p , binaryPath ) )
// _, err := os.Stat(filepath.Join(p, binaryPath))
if err != nil && ! os . IsNotExist ( err ) {
// if err != nil && !os.IsNotExist(err) {
return "" , err
// return "", err
} else if err == nil {
// } else if err == nil {
binaryPath = filepath . Join ( p , binaryPath )
// binaryPath = filepath.Join(p, binaryPath)
break
// break
}
// }
}
// }
}
// }
// Now check for the binary using the given path or check if it exists in
// Now check for the binary using the given path or check if it exists in
// the path and is executable
// the path and is executable