diff --git a/src/cmd/initialize.go b/src/cmd/initialize.go index 29a66ba60e..193ba0f0d4 100644 --- a/src/cmd/initialize.go +++ b/src/cmd/initialize.go @@ -80,11 +80,11 @@ func findInitPackage(initPackageName string) (string, error) { } // Next, look for the init package in the executable directory - zarfBinPath, err := utils.GetFinalExecutablePath() + binaryPath, err := utils.GetFinalExecutablePath() if err != nil { return "", err } - executableDir := path.Dir(zarfBinPath) + executableDir := path.Dir(binaryPath) if !utils.InvalidPath(filepath.Join(executableDir, initPackageName)) { return filepath.Join(executableDir, initPackageName), nil } diff --git a/src/cmd/tools/crane.go b/src/cmd/tools/crane.go index 2105ec5ed4..5e68f8f7e1 100644 --- a/src/cmd/tools/crane.go +++ b/src/cmd/tools/crane.go @@ -133,6 +133,7 @@ func zarfCraneCatalog(cranePlatformOptions *[]crane.Option) *cobra.Command { } if tunnel != nil { + message.Notef(lang.CmdToolsRegistryTunnel, registryEndpoint, zarfState.RegistryInfo.Address) defer tunnel.Close() } @@ -186,6 +187,8 @@ func zarfCraneInternalWrapper(commandToWrap func(*[]crane.Option) *cobra.Command } if tunnel != nil { + message.Notef(lang.CmdToolsRegistryTunnel, tunnel.Endpoint(), zarfState.RegistryInfo.Address) + defer tunnel.Close() givenAddress := fmt.Sprintf("%s/", zarfState.RegistryInfo.Address) @@ -229,6 +232,7 @@ func pruneImages(_ *cobra.Command, _ []string) error { } if tunnel != nil { + message.Notef(lang.CmdToolsRegistryTunnel, registryEndpoint, zarfState.RegistryInfo.Address) defer tunnel.Close() } diff --git a/src/config/lang/english.go b/src/config/lang/english.go index fa3178c15c..efcbe8b5b9 100644 --- a/src/config/lang/english.go +++ b/src/config/lang/english.go @@ -354,6 +354,7 @@ const ( CmdToolsRegistryShort = "Tools for working with container registries using go-containertools" CmdToolsRegistryZarfState = "Retrieving registry information from Zarf state" + CmdToolsRegistryTunnel = "Opening a tunnel from %s locally to %s in the cluster" CmdToolsRegistryCatalogExample = ` # list the repos internal to Zarf diff --git a/src/internal/api/packages/find.go b/src/internal/api/packages/find.go index c0a51fbf6a..5836542be9 100644 --- a/src/internal/api/packages/find.go +++ b/src/internal/api/packages/find.go @@ -56,8 +56,8 @@ func FindInitStream(w http.ResponseWriter, _ *http.Request) { done := make(chan bool) go func() { // stream init packages in the execution directory - if execBin, err := utils.GetFinalExecutablePath(); err == nil { - streamDirPackages(filepath.Dir(execBin), packager.ZarfInitPattern, w) + if binaryPath, err := utils.GetFinalExecutablePath(); err == nil { + streamDirPackages(filepath.Dir(binaryPath), packager.ZarfInitPattern, w) } else { streamError(err, w) } diff --git a/src/internal/cluster/data.go b/src/internal/cluster/data.go index f6746e5677..dea6471997 100644 --- a/src/internal/cluster/data.go +++ b/src/internal/cluster/data.go @@ -81,12 +81,12 @@ iterator: // Inject into all the pods for _, pod := range pods { // Try to use the embedded kubectl if we can - zarfBinPath, err := utils.GetFinalExecutablePath() + zarfCommand, err := utils.GetFinalExecutableCommand() kubectlBinPath := "kubectl" if err != nil { message.Warnf("Unable to get the zarf executable path, falling back to host kubectl: %s", err) } else { - kubectlBinPath = fmt.Sprintf("%s tools kubectl", zarfBinPath) + kubectlBinPath = fmt.Sprintf("%s tools kubectl", zarfCommand) } kubectlCmd := fmt.Sprintf("%s exec -i -n %s %s -c %s ", kubectlBinPath, data.Target.Namespace, pod.Name, data.Target.Container) diff --git a/src/pkg/packager/actions.go b/src/pkg/packager/actions.go index 13e6b32a36..a5e1ac9c43 100644 --- a/src/pkg/packager/actions.go +++ b/src/pkg/packager/actions.go @@ -7,13 +7,11 @@ package packager import ( "context" "fmt" - "os" "regexp" "runtime" "strings" "time" - "github.com/defenseunicorns/zarf/src/config" "github.com/defenseunicorns/zarf/src/internal/packager/template" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/utils" @@ -209,20 +207,13 @@ func convertWaitToCmd(wait types.ZarfComponentActionWait, timeout *int) (string, // Perform some basic string mutations to make commands more useful. func actionCmdMutation(cmd string, shellPref types.ZarfComponentActionShell) (string, error) { - binaryPath, err := os.Executable() + zarfCommand, err := utils.GetFinalExecutableCommand() if err != nil { return cmd, err } - binaryPath = fmt.Sprintf("%s %s", binaryPath, config.ActionsCommandZarfPrefix) - - // If a library user has chosen to override config to use system Zarf instead, reset the binary path. - if config.ActionsUseSystemZarf { - binaryPath = "zarf" - } - // Try to patch the zarf binary path in case the name isn't exactly "./zarf". - cmd = strings.ReplaceAll(cmd, "./zarf ", binaryPath+" ") + cmd = strings.ReplaceAll(cmd, "./zarf ", zarfCommand+" ") // Make commands 'more' compatible with Windows OS PowerShell if runtime.GOOS == "windows" && (exec.IsPowershell(shellPref.Windows) || shellPref.Windows == "") { diff --git a/src/pkg/utils/io.go b/src/pkg/utils/io.go index 5c204a5a5c..662e1891d2 100755 --- a/src/pkg/utils/io.go +++ b/src/pkg/utils/io.go @@ -17,6 +17,7 @@ import ( "regexp" "strings" + "github.com/defenseunicorns/zarf/src/config" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/utils/helpers" "github.com/defenseunicorns/zarf/src/types" @@ -254,7 +255,7 @@ func CreatePathAndCopy(source string, destination string) error { return CreateFile(destination) } -// GetFinalExecutablePath returns the absolute path to the Zarf executable, following any symlinks along the way. +// GetFinalExecutablePath returns the absolute path to the current executable, following any symlinks along the way. func GetFinalExecutablePath() (string, error) { message.Debug("utils.GetExecutablePath()") @@ -263,11 +264,31 @@ func GetFinalExecutablePath() (string, error) { return "", err } - // In case the binary is symlinked somewhere else, get the final destination!! + // In case the binary is symlinked somewhere else, get the final destination linkedPath, err := filepath.EvalSymlinks(binaryPath) return linkedPath, err } +// GetFinalExecutableCommand returns the final path to the Zarf executable including and library prefixes and overrides. +func GetFinalExecutableCommand() (string, error) { + // In case the binary is symlinked somewhere else, get the final destination + zarfCommand, err := GetFinalExecutablePath() + if err != nil { + return zarfCommand, err + } + + if config.ActionsCommandZarfPrefix != "" { + zarfCommand = fmt.Sprintf("%s %s", zarfCommand, config.ActionsCommandZarfPrefix) + } + + // If a library user has chosen to override config to use system Zarf instead, reset the binary path. + if config.ActionsUseSystemZarf { + zarfCommand = "zarf" + } + + return zarfCommand, err +} + // SplitFile splits a file into multiple parts by the given size. func SplitFile(path string, chunkSizeBytes int) (chunks [][]byte, sha256sum string, err error) { var file []byte diff --git a/src/pkg/utils/wait.go b/src/pkg/utils/wait.go index 976b93dce4..84b782906b 100644 --- a/src/pkg/utils/wait.go +++ b/src/pkg/utils/wait.go @@ -13,6 +13,7 @@ import ( "time" "github.com/defenseunicorns/zarf/src/pkg/utils/exec" + "github.com/defenseunicorns/zarf/src/types" "github.com/defenseunicorns/zarf/src/config/lang" "github.com/defenseunicorns/zarf/src/pkg/message" @@ -46,8 +47,8 @@ func ExecuteWait(waitTimeout, waitNamespace, condition, kind, identifier string, waitType = "condition=" } - // Get the Zarf executable path. - zarfBinPath, err := GetFinalExecutablePath() + // Get the Zarf command configuration. + zarfCommand, err := GetFinalExecutableCommand() if err != nil { message.Fatal(err, lang.CmdToolsWaitForErrZarfPath) } @@ -73,6 +74,9 @@ func ExecuteWait(waitTimeout, waitNamespace, condition, kind, identifier string, existMsg := fmt.Sprintf("Waiting for %s%s%s to exist.", kind, identifierMsg, namespaceMsg) spinner := message.NewProgressSpinner(existMsg) + // Get the OS shell to execute commands in + shell, shellArgs := exec.GetOSShell(types.ZarfComponentActionShell{Windows: "cmd"}) + defer spinner.Stop() for { @@ -86,8 +90,8 @@ func ExecuteWait(waitTimeout, waitNamespace, condition, kind, identifier string, default: spinner.Updatef(existMsg) // Check if the resource exists. - args := []string{"tools", "kubectl", "get", "-n", waitNamespace, kind, identifier} - if stdout, stderr, err := exec.Cmd(zarfBinPath, args...); err != nil { + zarfKubectlGet := fmt.Sprintf("%s tools kubectl get -n %s %s %s", zarfCommand, waitNamespace, kind, identifier) + if stdout, stderr, err := exec.Cmd(shell, shellArgs, zarfKubectlGet); err != nil { message.Debug(stdout, stderr, err) continue } @@ -101,12 +105,11 @@ func ExecuteWait(waitTimeout, waitNamespace, condition, kind, identifier string, spinner.Updatef(conditionMsg) // Wait for the resource to meet the given condition. - args = []string{"tools", "kubectl", "wait", "-n", waitNamespace, - kind, identifier, "--for", waitType + condition, - "--timeout=" + waitTimeout} + zarfKubectlWait := fmt.Sprintf("%s tools kubectl wait -n %s %s %s --for %s%s --timeout=%s", + zarfCommand, waitNamespace, kind, identifier, waitType, condition, waitTimeout) // If there is an error, log it and try again. - if stdout, stderr, err := exec.Cmd(zarfBinPath, args...); err != nil { + if stdout, stderr, err := exec.Cmd(shell, shellArgs, zarfKubectlWait); err != nil { message.Debug(stdout, stderr, err) continue }