Files
kube-forge/internal/python/utils.go

162 lines
3.5 KiB
Go

package python
import (
"context"
"fmt"
"io"
"kube-forge/internal/python/data"
"kube-forge/internal/resources"
"os"
"os/exec"
"path/filepath"
executable "github.com/apenella/go-ansible/v2/pkg/execute/exec"
"github.com/kluctl/go-embed-python/embed_util"
"github.com/kluctl/go-embed-python/python"
)
type PythonExec struct {
ep *python.EmbeddedPython
PythonLibFsPath string
ResourcesFsPath string
}
type CmdWrapper struct {
*exec.Cmd
}
func (c *CmdWrapper) CombinedOutput() ([]byte, error) {
return c.Cmd.CombinedOutput()
}
func (c *CmdWrapper) Environ() []string {
return c.Cmd.Environ()
}
func (c *CmdWrapper) Output() ([]byte, error) {
return c.Cmd.Output()
}
func (c *CmdWrapper) Run() error {
return c.Cmd.Run()
}
func (c *CmdWrapper) Start() error {
return c.Cmd.Start()
}
func (c *CmdWrapper) StderrPipe() (io.ReadCloser, error) {
return c.Cmd.StderrPipe()
}
func (c *CmdWrapper) StdinPipe() (io.WriteCloser, error) {
return c.Cmd.StdinPipe()
}
func (c *CmdWrapper) StdoutPipe() (io.ReadCloser, error) {
return c.Cmd.StdoutPipe()
}
func (c *CmdWrapper) String() string {
return c.Cmd.String()
}
func (c *CmdWrapper) Wait() error {
return c.Cmd.Wait()
}
type ErrorCmd struct {
err error
}
func (e *ErrorCmd) CombinedOutput() ([]byte, error) {
return nil, e.err
}
func (e *ErrorCmd) Environ() []string {
return nil
}
func (e *ErrorCmd) Output() ([]byte, error) {
return nil, e.err
}
func (e *ErrorCmd) Run() error {
return e.err
}
func (e *ErrorCmd) Start() error {
return e.err
}
func (e *ErrorCmd) StderrPipe() (io.ReadCloser, error) {
return nil, e.err
}
func (e *ErrorCmd) StdinPipe() (io.WriteCloser, error) {
return nil, e.err
}
func (e *ErrorCmd) StdoutPipe() (io.ReadCloser, error) {
return nil, e.err
}
func (e *ErrorCmd) String() string {
return fmt.Sprintf("ErrorCmd: %v", e.err)
}
func (e *ErrorCmd) Wait() error {
return e.err
}
func NewPythonExec() *PythonExec {
tmpDir := filepath.Join(os.TempDir(), "go-ansible")
pythonDir := tmpDir + "-python"
pythonLibDir := tmpDir + "-python-lib"
resourcesDir := tmpDir + "-resources"
pythonLibFs, err := embed_util.NewEmbeddedFilesWithTmpDir(data.Data, pythonLibDir, true)
if err != nil {
panic(err)
}
pythonLibFsPath := pythonLibFs.GetExtractedPath()
resourcesFs, _ := embed_util.NewEmbeddedFilesWithTmpDir(resources.Kubespray, resourcesDir, true)
resourcesFsPath := resourcesFs.GetExtractedPath()
ep, _ := python.NewEmbeddedPythonWithTmpDir(pythonDir, true)
ep.AddPythonPath(pythonLibFs.GetExtractedPath())
ep.AddPythonPath(resourcesFs.GetExtractedPath())
return &PythonExec{
ep: ep,
PythonLibFsPath: pythonLibFsPath,
ResourcesFsPath: resourcesFsPath,
}
}
func (e *PythonExec) Command(name string, arg ...string) executable.Cmder {
cmd := append([]string{name}, arg...)
execCmd, err := e.ep.PythonCmd2(cmd)
if err != nil {
return &ErrorCmd{err: fmt.Errorf("failed to create python command: %w", err)}
}
return &CmdWrapper{Cmd: execCmd}
}
func (e *PythonExec) CommandContext(ctx context.Context, name string, arg ...string) executable.Cmder {
cmd := append([]string{name}, arg...)
execCmd, err := e.ep.PythonCmd2(cmd)
if err != nil {
return &ErrorCmd{err: fmt.Errorf("failed to create python command: %w", err)}
}
ctxCmd := exec.CommandContext(ctx, execCmd.Path, execCmd.Args[1:]...)
ctxCmd.Env = execCmd.Env
ctxCmd.Dir = execCmd.Dir
ctxCmd.Stdin = execCmd.Stdin
ctxCmd.Stdout = execCmd.Stdout
ctxCmd.Stderr = execCmd.Stderr
return &CmdWrapper{Cmd: ctxCmd}
}