110 lines
3.6 KiB
Go
110 lines
3.6 KiB
Go
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
// handleDownloadUnifiedInstallScript serves the universal install.sh script
|
|
func (r *Router) handleDownloadUnifiedInstallScript(w http.ResponseWriter, req *http.Request) {
|
|
if req.Method != http.MethodGet && req.Method != http.MethodHead {
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
scriptPath := filepath.Join(r.config.AppRoot, "scripts", "install.sh")
|
|
|
|
// Check if file exists
|
|
if _, err := os.Stat(scriptPath); os.IsNotExist(err) {
|
|
log.Error().Str("path", scriptPath).Msg("Unified install script not found")
|
|
http.Error(w, "Install script not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "text/x-shellscript")
|
|
w.Header().Set("Content-Disposition", "inline; filename=\"install.sh\"")
|
|
http.ServeFile(w, req, scriptPath)
|
|
}
|
|
|
|
// handleDownloadUnifiedInstallScriptPS serves the universal install.ps1 script
|
|
func (r *Router) handleDownloadUnifiedInstallScriptPS(w http.ResponseWriter, req *http.Request) {
|
|
if req.Method != http.MethodGet && req.Method != http.MethodHead {
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
scriptPath := filepath.Join(r.config.AppRoot, "scripts", "install.ps1")
|
|
|
|
// Check if file exists
|
|
if _, err := os.Stat(scriptPath); os.IsNotExist(err) {
|
|
log.Error().Str("path", scriptPath).Msg("Unified PowerShell install script not found")
|
|
http.Error(w, "Install script not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "text/plain")
|
|
w.Header().Set("Content-Disposition", "inline; filename=\"install.ps1\"")
|
|
http.ServeFile(w, req, scriptPath)
|
|
}
|
|
|
|
// handleDownloadUnifiedAgent serves the pulse-agent binary
|
|
func (r *Router) handleDownloadUnifiedAgent(w http.ResponseWriter, req *http.Request) {
|
|
if req.Method != http.MethodGet && req.Method != http.MethodHead {
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
// For now, we only have the locally built binary.
|
|
// In production, this would look up the correct binary for the requested OS/Arch.
|
|
// Query params: ?os=linux&arch=amd64
|
|
|
|
osName := req.URL.Query().Get("os")
|
|
arch := req.URL.Query().Get("arch")
|
|
|
|
if osName == "" {
|
|
osName = "linux" // Default
|
|
}
|
|
if arch == "" {
|
|
arch = "amd64" // Default
|
|
}
|
|
|
|
// Normalize OS
|
|
osName = strings.ToLower(osName)
|
|
if osName == "darwin" {
|
|
osName = "macos"
|
|
}
|
|
|
|
// In dev mode, we just serve the binary we built in the root
|
|
// In prod, we'd look in a dist folder
|
|
binaryName := "pulse-agent"
|
|
if osName == "windows" {
|
|
binaryName = "pulse-agent.exe"
|
|
}
|
|
|
|
// Try to find the binary
|
|
// 1. Check root (dev)
|
|
binaryPath := filepath.Join(r.config.AppRoot, binaryName)
|
|
if _, err := os.Stat(binaryPath); os.IsNotExist(err) {
|
|
// 2. Check dist folder (prod/build)
|
|
binaryPath = filepath.Join(r.config.AppRoot, "dist", fmt.Sprintf("%s-%s", osName, arch), binaryName)
|
|
if _, err := os.Stat(binaryPath); os.IsNotExist(err) {
|
|
// Fallback for dev: just serve the root binary regardless of requested OS/Arch
|
|
// This allows testing the flow even if cross-compilation hasn't happened
|
|
binaryPath = filepath.Join(r.config.AppRoot, "pulse-agent")
|
|
if _, err := os.Stat(binaryPath); os.IsNotExist(err) {
|
|
log.Error().Str("path", binaryPath).Msg("Unified agent binary not found")
|
|
http.Error(w, "Agent binary not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/octet-stream")
|
|
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", binaryName))
|
|
http.ServeFile(w, req, binaryPath)
|
|
}
|