mirror of
https://github.com/dokku/dokku.git
synced 2025-12-25 16:29:30 +01:00
This simplifies cache referencing and also paves the way for removing more from the app git directory. Refs #1558
154 lines
3.9 KiB
Go
154 lines
3.9 KiB
Go
package common
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/codeskyblue/go-sh"
|
|
)
|
|
|
|
// ShellCmd represents a shell command to be run for dokku
|
|
type ShellCmd struct {
|
|
Env map[string]string
|
|
Command *exec.Cmd
|
|
CommandString string
|
|
Args []string
|
|
ShowOutput bool
|
|
ExitError *exec.ExitError
|
|
}
|
|
|
|
// NewShellCmd returns a new ShellCmd struct
|
|
func NewShellCmd(command string) *ShellCmd {
|
|
items := strings.Split(command, " ")
|
|
cmd := items[0]
|
|
args := items[1:]
|
|
return NewShellCmdWithArgs(cmd, args...)
|
|
}
|
|
|
|
// NewShellCmdWithArgs returns a new ShellCmd struct
|
|
func NewShellCmdWithArgs(cmd string, args ...string) *ShellCmd {
|
|
commandString := strings.Join(append([]string{cmd}, args...), " ")
|
|
|
|
return &ShellCmd{
|
|
Command: exec.Command(cmd, args...),
|
|
CommandString: commandString,
|
|
Args: args,
|
|
ShowOutput: true,
|
|
}
|
|
}
|
|
|
|
func (sc *ShellCmd) setup() {
|
|
env := os.Environ()
|
|
for k, v := range sc.Env {
|
|
env = append(env, fmt.Sprintf("%s=%s", k, v))
|
|
}
|
|
sc.Command.Env = env
|
|
if sc.ShowOutput {
|
|
sc.Command.Stdout = os.Stdout
|
|
sc.Command.Stderr = os.Stderr
|
|
}
|
|
}
|
|
|
|
// Execute is a lightweight wrapper around exec.Command
|
|
func (sc *ShellCmd) Execute() bool {
|
|
sc.setup()
|
|
|
|
if err := sc.Command.Run(); err != nil {
|
|
exitError, ok := err.(*exec.ExitError)
|
|
if ok {
|
|
sc.ExitError = exitError
|
|
}
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// Start is a wrapper around exec.Command.Start()
|
|
func (sc *ShellCmd) Start() error {
|
|
sc.setup()
|
|
|
|
return sc.Command.Start()
|
|
}
|
|
|
|
// Output is a lightweight wrapper around exec.Command.Output()
|
|
func (sc *ShellCmd) Output() ([]byte, error) {
|
|
sc.setup()
|
|
return sc.Command.Output()
|
|
}
|
|
|
|
// CombinedOutput is a lightweight wrapper around exec.Command.CombinedOutput()
|
|
func (sc *ShellCmd) CombinedOutput() ([]byte, error) {
|
|
sc.setup()
|
|
return sc.Command.CombinedOutput()
|
|
}
|
|
|
|
// PlugnTrigger fire the given plugn trigger with the given args
|
|
func PlugnTrigger(triggerName string, args ...string) error {
|
|
LogDebug(fmt.Sprintf("plugn trigger %s %v", triggerName, args))
|
|
return PlugnTriggerSetup(triggerName, args...).Run()
|
|
}
|
|
|
|
// PlugnTriggerOutput fire the given plugn trigger with the given args
|
|
func PlugnTriggerOutput(triggerName string, args ...string) ([]byte, error) {
|
|
LogDebug(fmt.Sprintf("plugn trigger %s %v", triggerName, args))
|
|
rE, wE, _ := os.Pipe()
|
|
rO, wO, _ := os.Pipe()
|
|
session := PlugnTriggerSetup(triggerName, args...)
|
|
session.Stderr = wE
|
|
session.Stdout = wO
|
|
err := session.Run()
|
|
wE.Close()
|
|
wO.Close()
|
|
|
|
readStderr, _ := ioutil.ReadAll(rE)
|
|
readStdout, _ := ioutil.ReadAll(rO)
|
|
|
|
stderr := string(readStderr[:])
|
|
if err != nil {
|
|
err = fmt.Errorf(stderr)
|
|
}
|
|
|
|
if os.Getenv("DOKKU_TRACE") == "1" {
|
|
for _, line := range strings.Split(stderr, "\n") {
|
|
LogDebug(fmt.Sprintf("plugn trigger %s stderr: %s", triggerName, line))
|
|
}
|
|
for _, line := range strings.Split(string(readStdout[:]), "\n") {
|
|
LogDebug(fmt.Sprintf("plugn trigger %s stdout: %s", triggerName, line))
|
|
}
|
|
}
|
|
|
|
return readStdout, err
|
|
}
|
|
|
|
// PlugnTriggerSetup sets up a plugn trigger call
|
|
func PlugnTriggerSetup(triggerName string, args ...string) *sh.Session {
|
|
shellArgs := make([]interface{}, len(args)+2)
|
|
shellArgs[0] = "trigger"
|
|
shellArgs[1] = triggerName
|
|
for i, arg := range args {
|
|
shellArgs[i+2] = arg
|
|
}
|
|
return sh.Command("plugn", shellArgs...)
|
|
}
|
|
|
|
// PlugnTriggerExists returns whether a plugin trigger exists (ignoring the existence of any within the 20_events plugin)
|
|
func PlugnTriggerExists(triggerName string) bool {
|
|
pluginPath := MustGetEnv("PLUGIN_PATH")
|
|
pluginPathPrefix := filepath.Join(pluginPath, "enabled")
|
|
glob := filepath.Join(pluginPathPrefix, "*", triggerName)
|
|
exists := false
|
|
files, _ := filepath.Glob(glob)
|
|
for _, file := range files {
|
|
plugin := strings.Trim(strings.TrimPrefix(strings.TrimSuffix(file, "/"+triggerName), pluginPathPrefix), "/")
|
|
if plugin != "20_events" {
|
|
exists = true
|
|
break
|
|
}
|
|
}
|
|
return exists
|
|
}
|