fix: installer issues found during testing
- Remove invalid --config flag from exporter service template - Change ReadOnlyPaths to ReadWritePaths for catalog access - Add copyBinary() to install binary to /usr/local/bin (ProtectHome compat) - Fix exporter status detection using direct systemctl check - Add os/exec import for status check
This commit is contained in:
Binary file not shown.
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
@@ -198,13 +199,14 @@ func runInstallStatus(ctx context.Context) error {
|
|||||||
|
|
||||||
// Check for exporter
|
// Check for exporter
|
||||||
if _, err := os.Stat("/etc/systemd/system/dbbackup-exporter.service"); err == nil {
|
if _, err := os.Stat("/etc/systemd/system/dbbackup-exporter.service"); err == nil {
|
||||||
exporterStatus, err := inst.Status(ctx, "exporter")
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println("🔹 Metrics Exporter:")
|
fmt.Println("🔹 Metrics Exporter:")
|
||||||
if err == nil && exporterStatus != nil {
|
// Check if exporter is active using systemctl
|
||||||
fmt.Printf(" Service: %s\n", formatStatus(true, exporterStatus.Active))
|
cmd := exec.CommandContext(ctx, "systemctl", "is-active", "dbbackup-exporter")
|
||||||
|
if err := cmd.Run(); err == nil {
|
||||||
|
fmt.Printf(" Service: ✅ active\n")
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf(" Service: installed (status unknown)\n")
|
fmt.Printf(" Service: ⚪ inactive\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package installer
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/user"
|
"os/user"
|
||||||
@@ -105,6 +106,11 @@ func (i *Installer) Install(ctx context.Context, opts InstallOptions) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy binary to /usr/local/bin (required for ProtectHome=yes)
|
||||||
|
if err := i.copyBinary(&opts); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Write service and timer files
|
// Write service and timer files
|
||||||
if err := i.writeUnitFiles(opts); err != nil {
|
if err := i.writeUnitFiles(opts); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -428,6 +434,46 @@ func (i *Installer) createDirectories(opts InstallOptions) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copyBinary copies the binary to /usr/local/bin for systemd access
|
||||||
|
// This is required because ProtectHome=yes blocks access to home directories
|
||||||
|
func (i *Installer) copyBinary(opts *InstallOptions) error {
|
||||||
|
const installPath = "/usr/local/bin/dbbackup"
|
||||||
|
|
||||||
|
// Check if binary is already in a system path
|
||||||
|
if opts.BinaryPath == installPath {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.dryRun {
|
||||||
|
i.log.Info("Would copy binary", "from", opts.BinaryPath, "to", installPath)
|
||||||
|
opts.BinaryPath = installPath
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read source binary
|
||||||
|
src, err := os.Open(opts.BinaryPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to open source binary: %w", err)
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
|
||||||
|
// Create destination
|
||||||
|
dst, err := os.OpenFile(installPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create %s: %w", installPath, err)
|
||||||
|
}
|
||||||
|
defer dst.Close()
|
||||||
|
|
||||||
|
// Copy
|
||||||
|
if _, err := io.Copy(dst, src); err != nil {
|
||||||
|
return fmt.Errorf("failed to copy binary: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
i.log.Info("Copied binary", "from", opts.BinaryPath, "to", installPath)
|
||||||
|
opts.BinaryPath = installPath
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// writeUnitFiles renders and writes the systemd unit files
|
// writeUnitFiles renders and writes the systemd unit files
|
||||||
func (i *Installer) writeUnitFiles(opts InstallOptions) error {
|
func (i *Installer) writeUnitFiles(opts InstallOptions) error {
|
||||||
// Prepare template data
|
// Prepare template data
|
||||||
|
|||||||
@@ -21,14 +21,14 @@ RestrictRealtime=yes
|
|||||||
LockPersonality=yes
|
LockPersonality=yes
|
||||||
RemoveIPC=yes
|
RemoveIPC=yes
|
||||||
|
|
||||||
# Read-only access to catalog and backups
|
# Read-write access to catalog for metrics collection
|
||||||
ReadOnlyPaths=/var/lib/dbbackup
|
ReadWritePaths=/var/lib/dbbackup
|
||||||
|
|
||||||
# Network for HTTP server
|
# Network for HTTP server
|
||||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||||
|
|
||||||
# Execution
|
# Execution
|
||||||
ExecStart={{.BinaryPath}} metrics serve --port {{.MetricsPort}} --config {{.ConfigPath}}
|
ExecStart={{.BinaryPath}} metrics serve --port {{.MetricsPort}}
|
||||||
ExecReload=/bin/kill -HUP $MAINPID
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|||||||
Reference in New Issue
Block a user