Skip to content

Commit

Permalink
feat: Add systemd support for contributoor service启
Browse files Browse the repository at this point in the history
  • Loading branch information
mattevans committed Dec 20, 2024
1 parent baa2374 commit 06a4f1c
Show file tree
Hide file tree
Showing 11 changed files with 407 additions and 19 deletions.
3 changes: 3 additions & 0 deletions cmd/cli/commands/config/config_contributoor.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ func (p *ContributoorSettingsPage) initPage() {
// Available run modes
runModes := []string{
sidecar.RunMethodDocker,
sidecar.RunMethodSystemd,
sidecar.RunMethodBinary,
}

Expand Down Expand Up @@ -106,6 +107,8 @@ func (p *ContributoorSettingsPage) initPage() {
form.AddDropDown("Run Mode", runModes, currentRunModeIndex, func(option string, index int) {
if option == sidecar.RunMethodDocker {
p.description.SetText("Run using Docker containers (recommended)")
} else if option == sidecar.RunMethodSystemd {
p.description.SetText("Run using systemd")
} else {
p.description.SetText("Run directly as a binary on your system")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ func (p *OutputServerCredentialsPage) initPage() {
p.form = form

// Get existing credentials if any
if currentCreds := p.display.sidecarCfg.Get().OutputServer.Credentials; currentCreds != "" {
if cfg := p.display.sidecarCfg.Get(); cfg.OutputServer != nil && cfg.OutputServer.Credentials != "" {
currentCreds := cfg.OutputServer.Credentials
if decoded, err := base64.StdEncoding.DecodeString(currentCreds); err == nil {
parts := strings.Split(string(decoded), ":")
if len(parts) == 2 {
Expand Down
10 changes: 9 additions & 1 deletion cmd/cli/commands/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,17 @@ func RegisterCommands(app *cli.App, opts *options.CommandOpts) {
return fmt.Errorf("error creating docker sidecar service: %w", err)
}

systemdSidecar, err := sidecar.NewSystemdSidecar(log, sidecarCfg, installerCfg)
if err != nil {
return fmt.Errorf("error creating systemd sidecar service: %w", err)
}

binarySidecar, err := sidecar.NewBinarySidecar(log, sidecarCfg, installerCfg)
if err != nil {
return fmt.Errorf("error creating binary sidecar service: %w", err)
}

return startContributoor(c, log, sidecarCfg, dockerSidecar, binarySidecar)
return startContributoor(c, log, sidecarCfg, dockerSidecar, systemdSidecar, binarySidecar)
},
})
}
Expand All @@ -47,6 +52,7 @@ func startContributoor(
log *logrus.Logger,
config sidecar.ConfigManager,
docker sidecar.DockerSidecar,
systemd sidecar.SystemdSidecar,
binary sidecar.BinarySidecar,
) error {
var (
Expand All @@ -60,6 +66,8 @@ func startContributoor(
switch cfg.RunMethod {
case sidecar.RunMethodDocker:
runner = docker
case sidecar.RunMethodSystemd:
runner = systemd
case sidecar.RunMethodBinary:
runner = binary
default:
Expand Down
10 changes: 9 additions & 1 deletion cmd/cli/commands/status/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ func RegisterCommands(app *cli.App, opts *options.CommandOpts) {
return fmt.Errorf("error creating docker sidecar service: %w", err)
}

systemdSidecar, err := sidecar.NewSystemdSidecar(log, sidecarCfg, installerCfg)
if err != nil {
return fmt.Errorf("error creating systemd sidecar service: %w", err)
}

binarySidecar, err := sidecar.NewBinarySidecar(log, sidecarCfg, installerCfg)
if err != nil {
return fmt.Errorf("error creating binary sidecar service: %w", err)
Expand All @@ -43,7 +48,7 @@ func RegisterCommands(app *cli.App, opts *options.CommandOpts) {
return fmt.Errorf("error creating github service: %w", err)
}

return showStatus(c, log, sidecarCfg, dockerSidecar, binarySidecar, githubService)
return showStatus(c, log, sidecarCfg, dockerSidecar, systemdSidecar, binarySidecar, githubService)
},
})
}
Expand All @@ -53,6 +58,7 @@ func showStatus(
log *logrus.Logger,
config sidecar.ConfigManager,
docker sidecar.DockerSidecar,
systemd sidecar.SystemdSidecar,
binary sidecar.BinarySidecar,
github service.GitHubService,
) error {
Expand All @@ -65,6 +71,8 @@ func showStatus(
switch cfg.RunMethod {
case sidecar.RunMethodDocker:
runner = docker
case sidecar.RunMethodSystemd:
runner = systemd
case sidecar.RunMethodBinary:
runner = binary
default:
Expand Down
10 changes: 9 additions & 1 deletion cmd/cli/commands/stop/stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ func RegisterCommands(app *cli.App, opts *options.CommandOpts) {
return fmt.Errorf("error creating binary sidecar service: %w", err)
}

return stopContributoor(c, log, sidecarCfg, dockerSidecar, binarySidecar)
systemdSidecar, err := sidecar.NewSystemdSidecar(log, sidecarCfg, installerCfg)
if err != nil {
return fmt.Errorf("error creating systemd sidecar service: %w", err)
}

return stopContributoor(c, log, sidecarCfg, dockerSidecar, systemdSidecar, binarySidecar)
},
})
}
Expand All @@ -47,6 +52,7 @@ func stopContributoor(
log *logrus.Logger,
config sidecar.ConfigManager,
docker sidecar.DockerSidecar,
systemd sidecar.SystemdSidecar,
binary sidecar.BinarySidecar,
) error {
var (
Expand All @@ -60,6 +66,8 @@ func stopContributoor(
switch cfg.RunMethod {
case sidecar.RunMethodDocker:
runner = docker
case sidecar.RunMethodSystemd:
runner = systemd
case sidecar.RunMethodBinary:
runner = binary
default:
Expand Down
48 changes: 45 additions & 3 deletions cmd/cli/commands/update/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ func RegisterCommands(app *cli.App, opts *options.CommandOpts) {
return fmt.Errorf("error creating docker sidecar service: %w", err)
}

systemdSidecar, err := sidecar.NewSystemdSidecar(log, sidecarCfg, installerCfg)
if err != nil {
return fmt.Errorf("error creating systemd sidecar service: %w", err)
}

binarySidecar, err := sidecar.NewBinarySidecar(log, sidecarCfg, installerCfg)
if err != nil {
return fmt.Errorf("error creating binary sidecar service: %w", err)
Expand All @@ -50,7 +55,7 @@ func RegisterCommands(app *cli.App, opts *options.CommandOpts) {
return fmt.Errorf("error creating github service: %w", err)
}

return updateContributoor(c, log, sidecarCfg, dockerSidecar, binarySidecar, githubService)
return updateContributoor(c, log, sidecarCfg, dockerSidecar, systemdSidecar, binarySidecar, githubService)
},
})
}
Expand All @@ -60,6 +65,7 @@ func updateContributoor(
log *logrus.Logger,
sidecarCfg sidecar.ConfigManager,
docker sidecar.DockerSidecar,
systemd sidecar.SystemdSidecar,
binary sidecar.BinarySidecar,
github service.GitHubService,
) error {
Expand Down Expand Up @@ -111,25 +117,61 @@ func updateContributoor(
cfg = sidecarCfg.Get()

// Update the sidecar.
success, err = updateSidecar(log, cfg, docker, binary)
success, err = updateSidecar(log, cfg, docker, systemd, binary)
if err != nil {
return err
}

return nil
}

func updateSidecar(log *logrus.Logger, cfg *sidecar.Config, docker sidecar.DockerSidecar, binary sidecar.BinarySidecar) (bool, error) {
func updateSidecar(log *logrus.Logger, cfg *sidecar.Config, docker sidecar.DockerSidecar, systemd sidecar.SystemdSidecar, binary sidecar.BinarySidecar) (bool, error) {
switch cfg.RunMethod {
case sidecar.RunMethodDocker:
return updateDocker(log, cfg, docker)
case sidecar.RunMethodSystemd:
return updateSystemd(log, cfg, systemd)
case sidecar.RunMethodBinary:
return updateBinary(log, cfg, binary)
default:
return false, fmt.Errorf("invalid sidecar run method: %s", cfg.RunMethod)
}
}

func updateSystemd(log *logrus.Logger, cfg *sidecar.Config, systemd sidecar.SystemdSidecar) (bool, error) {
// Check if sidecar is currently running.
running, err := systemd.IsRunning()
if err != nil {
log.Errorf("could not check sidecar status: %v", err)

return false, err
}

// If the sidecar is running, we need to stop it before we can update the binary.
if running {
if err := systemd.Stop(); err != nil {
return false, fmt.Errorf("failed to stop sidecar: %w", err)
}
}

if err := systemd.Update(); err != nil {
log.Errorf("could not update sidecar: %v", err)

return false, err
}

fmt.Printf("%sContributoor updated successfully to version %s%s\n", tui.TerminalColorGreen, cfg.Version, tui.TerminalColorReset)

// If it was running, start it again for them.
if running {
if err := systemd.Start(); err != nil {
return true, fmt.Errorf("failed to start sidecar: %w", err)
}
}

return true, nil
}

func updateBinary(log *logrus.Logger, cfg *sidecar.Config, binary sidecar.BinarySidecar) (bool, error) {
// Check if sidecar is currently running.
running, err := binary.IsRunning()
Expand Down
70 changes: 70 additions & 0 deletions install.bats
Original file line number Diff line number Diff line change
Expand Up @@ -573,4 +573,74 @@ EOF
run check_docker
[ "$status" -eq 0 ]
[ -z "$output" ]
}

@test "setup_systemd_contributoor creates service file correctly" {
# Mock sudo to capture commands.
function sudo() {
case "$1" in
"tee")
# Capture service file content
cat > "$TEST_DIR/contributoor.service"
;;
*) return 0 ;;
esac
}
export -f sudo

# Run the setup.
run setup_systemd_contributoor

# Check status.
[ "$status" -eq 0 ]

# Verify service file was created and has correct content.
[ -f "$TEST_DIR/contributoor.service" ]
grep -q "Description=Contributoor Service" "$TEST_DIR/contributoor.service"
grep -q "User=$USER" "$TEST_DIR/contributoor.service"
grep -q "ExecStart=$CONTRIBUTOOR_BIN/sentry" "$TEST_DIR/contributoor.service"
}

@test "setup_systemd_contributoor removes any existing systemd service before installing" {
# Mock sudo and systemctl.
function sudo() {
case "$1" in
"systemctl")
case "$2" in
"list-unit-files") echo "contributoor.service enabled" ;;
*) return 0 ;;
esac
;;
*) return 0 ;;
esac
}
export -f sudo

run setup_systemd_contributoor

# Check status.
[ "$status" -eq 0 ]

# Verify it detected and handled existing service.
echo "$output" | grep -q "Stopped and disabled existing systemd service"
}

@test "check_systemd validates systemd availability" {
# Mock commands to simulate working systemd.
function pidof() { echo "1"; }
function systemctl() { return 0; }
export -f pidof systemctl

run check_systemd
[ "$status" -eq 0 ]
}

@test "check_systemd fails when systemd not available" {
# Mock pidof to simulate no systemd.
function pidof() { return 1; }
export -f pidof

run check_systemd
[ "$status" -eq 1 ]
echo "$output" | grep -q "Systemd is not available on this system. Please choose a different installation mode."
}
Loading

0 comments on commit 06a4f1c

Please sign in to comment.