d090f67bff
- Use Windows named pipe \.\pipe\studioe5-tailscaled instead of Unix socket - Apply hideWindow to all child processes (tailscale, podman, docker, browser) - Redirect agent logs to <data-dir>/agent.log and tailscaled logs to tailscaled.log - Fix double tailscale/ tailscale dir path in startTailscaleAndReport - Remove --operator=root on Windows - Bump agent version to 0.3.1
157 lines
4.9 KiB
Go
157 lines
4.9 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
func instanceDir(dataDir, instanceID string) string {
|
|
return filepath.Join(dataDir, "instances", instanceID)
|
|
}
|
|
|
|
func getContainerEngine() string {
|
|
if _, err := exec.LookPath("podman"); err == nil {
|
|
return "podman"
|
|
}
|
|
return "docker"
|
|
}
|
|
|
|
func writeCompose(dataDir, instanceID, compose string, port int) error {
|
|
dir := instanceDir(dataDir, instanceID)
|
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Ensure the studioE5 mu-plugin is available and substitute its path
|
|
muDir, err := writeMUPlugin(dataDir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
compose = strings.ReplaceAll(compose, "{MU_PLUGINS_DIR}", filepath.Dir(muDir))
|
|
compose = strings.ReplaceAll(compose, "{INSTANCE_ID}", instanceID)
|
|
compose = strings.ReplaceAll(compose, "{PORT}", fmt.Sprintf("%d", port))
|
|
|
|
f := filepath.Join(dir, "docker-compose.yml")
|
|
return os.WriteFile(f, []byte(compose), 0644)
|
|
}
|
|
|
|
func configureEngineCmd(cmd *exec.Cmd, dir string) {
|
|
hideWindow(cmd)
|
|
logPath := filepath.Join(dir, "compose.log")
|
|
if f, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644); err == nil {
|
|
cmd.Stdout = f
|
|
cmd.Stderr = f
|
|
}
|
|
}
|
|
|
|
func dockerComposeUp(dataDir, instanceID string) error {
|
|
dir := instanceDir(dataDir, instanceID)
|
|
cmd := exec.Command(getContainerEngine(), "compose", "-f", filepath.Join(dir, "docker-compose.yml"), "up", "-d")
|
|
configureEngineCmd(cmd, dir)
|
|
return cmd.Run()
|
|
}
|
|
|
|
func dockerComposeDown(dataDir, instanceID string) error {
|
|
dir := instanceDir(dataDir, instanceID)
|
|
cmd := exec.Command(getContainerEngine(), "compose", "-f", filepath.Join(dir, "docker-compose.yml"), "down")
|
|
configureEngineCmd(cmd, dir)
|
|
return cmd.Run()
|
|
}
|
|
|
|
func dockerComposeRm(dataDir, instanceID string) error {
|
|
dir := instanceDir(dataDir, instanceID)
|
|
cmd := exec.Command(getContainerEngine(), "compose", "-f", filepath.Join(dir, "docker-compose.yml"), "down", "-v")
|
|
configureEngineCmd(cmd, dir)
|
|
if err := cmd.Run(); err != nil {
|
|
return err
|
|
}
|
|
return os.RemoveAll(dir)
|
|
}
|
|
|
|
// extractPublicURL tries to find the public URL from a WordPress compose config.
|
|
func extractPublicURL(composeConfig string) string {
|
|
re := regexp.MustCompile(`define\('WP_HOME',\s*'([^']+)'\);`)
|
|
m := re.FindStringSubmatch(composeConfig)
|
|
if len(m) > 1 {
|
|
return m[1]
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// updateWordPressURLs patches wp-config.php inside the WordPress container
|
|
// so that WP_HOME and WP_SITEURL point to the public URL.
|
|
func updateWordPressURLs(dataDir, instanceID, publicURL string) error {
|
|
if publicURL == "" {
|
|
return nil
|
|
}
|
|
dir := instanceDir(dataDir, instanceID)
|
|
composeFile := filepath.Join(dir, "docker-compose.yml")
|
|
engine := getContainerEngine()
|
|
|
|
script := fmt.Sprintf(`#!/bin/sh
|
|
CONFIG=/var/www/html/wp-config.php
|
|
if [ -f "$CONFIG" ]; then
|
|
sed -i "s|define('WP_HOME',[^;]*);|define('WP_HOME', '%s');|" "$CONFIG"
|
|
sed -i "s|define('WP_SITEURL',[^;]*);|define('WP_SITEURL', '%s');|" "$CONFIG"
|
|
if ! grep -q "define('WP_HOME'" "$CONFIG"; then
|
|
sed -i "/That's all, stop editing/i define('WP_HOME', '%s');\ndefine('WP_SITEURL', '%s');" "$CONFIG"
|
|
fi
|
|
fi
|
|
`, publicURL, publicURL, publicURL, publicURL)
|
|
|
|
scriptPath := filepath.Join(dir, "update-wp-urls.sh")
|
|
if err := os.WriteFile(scriptPath, []byte(script), 0755); err != nil {
|
|
return err
|
|
}
|
|
defer os.Remove(scriptPath)
|
|
|
|
cpCmd := exec.Command(engine, "compose", "-f", composeFile, "cp", scriptPath, "app:/tmp/update-wp-urls.sh")
|
|
configureEngineCmd(cpCmd, dir)
|
|
if err := cpCmd.Run(); err != nil {
|
|
return err
|
|
}
|
|
|
|
execCmd := exec.Command(engine, "compose", "-f", composeFile, "exec", "-T", "app", "sh", "/tmp/update-wp-urls.sh")
|
|
configureEngineCmd(execCmd, dir)
|
|
return execCmd.Run()
|
|
}
|
|
|
|
// stripWordPressHardcodedURLs removes hardcoded WP_HOME/WP_SITEURL defines
|
|
// from wp-config.php so the studioE5 mu-plugin can compute them from the Host
|
|
// header. This is useful when repairing older instances created before the
|
|
// mu-plugin existed.
|
|
func stripWordPressHardcodedURLs(dataDir, instanceID string) error {
|
|
dir := instanceDir(dataDir, instanceID)
|
|
composeFile := filepath.Join(dir, "docker-compose.yml")
|
|
engine := getContainerEngine()
|
|
|
|
script := `#!/bin/sh
|
|
CONFIG=/var/www/html/wp-config.php
|
|
if [ -f "$CONFIG" ]; then
|
|
# Remove hardcoded WP_HOME / WP_SITEURL defines so the mu-plugin controls them
|
|
sed -i "/define('WP_HOME',/d" "$CONFIG"
|
|
sed -i "/define('WP_SITEURL',/d" "$CONFIG"
|
|
fi
|
|
`
|
|
|
|
scriptPath := filepath.Join(dir, "strip-wp-urls.sh")
|
|
if err := os.WriteFile(scriptPath, []byte(script), 0755); err != nil {
|
|
return err
|
|
}
|
|
defer os.Remove(scriptPath)
|
|
|
|
cpCmd := exec.Command(engine, "compose", "-f", composeFile, "cp", scriptPath, "app:/tmp/strip-wp-urls.sh")
|
|
configureEngineCmd(cpCmd, dir)
|
|
if err := cpCmd.Run(); err != nil {
|
|
return err
|
|
}
|
|
|
|
execCmd := exec.Command(engine, "compose", "-f", composeFile, "exec", "-T", "app", "sh", "/tmp/strip-wp-urls.sh")
|
|
configureEngineCmd(execCmd, dir)
|
|
return execCmd.Run()
|
|
}
|